CodeGym /课程 /ChatGPT Apps /用户流程:GPT 如何推荐 App 并调用其功能

用户流程:GPT 如何推荐 App 并调用其功能

ChatGPT Apps
第 1 级 , 课程 2
可用

1. 引言

想象你在写一个普通的 Web 服务。一切都很直观:你有 URL /search,用户点按钮,你调用控制器 searchController。 在 ChatGPT Apps 的世界里,用户根本看不到 /search。他只会写自然语言:

“给爱打游戏的哥哥挑一份不超过 50 美元的礼物”

接下来会发生:

  • 模型判断:“哦,这是关于礼物的。我有 GiftGenius,它能处理这个。”;
  • GPT 自己“按按钮”——调用你 App 的工具;
  • 有时还会向用户提议:“要不要打开 GiftGenius 给你展示候选?”

关键转变:用户表达意图,按按钮的是模型。 如果不理解这个流程,很容易:

  • 写出一堆名字莫名其妙的工具(如 run_funcdoStuff),
  • 得到一个 模型从不推荐或总是用错场景的 App,
  • 做出一个“小组件从草丛里跳出来”打断对话的 UI。

因此本讲要建立一套心智模型:GPT 到底如何“得知”你的 App,并在对话的哪些节点将其“嵌入”进来。

洞见:App 是 ChatGPT 的插件

不同于手机上的应用或 WeChat 的 mini-app,ChatGPT 里的应用工作方式截然不同。

ChatGPT 会自行决定何时启动你的应用以及要调用它的哪一个功能。 ChatGPT 中的应用可以(有一定限制地)主动影响聊天逻辑。 它们的核心目标与强项——是扩展 ChatGPT 本身的能力

如果 ChatGPT 能完美解决用户问题——它就不需要调用你的应用。 如果 ChatGPT 完全解决不了——用户大概率也不会来问。 理想情况是 ChatGPT 只能部分解决用户请求。 这意味着请求确实存在、数量可观,但结果还不够好。

就在这时,ChatGPT 会调用你的应用,你们一起把用户变得更开心。 用户更开心,而你——也更富有。

2. 从用户视角看 ChatGPT App 的启动方式

用户没有“调用 MCP 服务器并 call_tool”的按钮,但有输入框和(有时)应用菜单。 从他的视角看,有两种基本方式:显式隐式

显式启动(explicit)

这是用户有意识地选择你的 App的场景。

典型方式:

  • 他在 ChatGPT 的 Store 里找到 App 并点击“打开”;
  • 他在启动器中选择 App(例如通过输入框(Composer)里的 + 按钮);
  • 他以应用名开头撰写消息:“GiftGenius,帮我挑个礼物……” ——这叫做 named mention。 如果 App 名在提示开头,ChatGPT 会自动把你的 App 混入回复上下文。

在显式模式下,模型从一开始就知道:用户就是为这个 App 而来。因此:

  • GPT 会更频繁、更积极地调用你的 tools;
  • 你的 App 的 UI 小组件完全可能在第一条回复里就出现;
  • GPT 更少会“忽略”App 并“靠自己”回答。

一个常见示例:用户直接打开 GiftGenius,因为他想“玩一玩”礼物筛选。 他在列表里点开 App,GPT 展示类似的问候语:

“你好!我是 GiftGenius,我能帮你挑选礼物。请告诉我送给谁、预算大概多少?”

接着它会积极地使用你的工具进行搜索。

隐式启动(implicit / suggested)

完全不同的场景:用户压根没想过 App。他只是在普通聊天里写道:

“帮我挑一份给妈妈的生日礼物,她喜欢园艺,预算不超过 100 美元”

GPT 分析请求并发现:

  • 生态里有个 App GiftGenius,其工具描述为 “Use this when the user wants to get gift recommendations”;
  • 任务与约束(礼物、预算、兴趣)与该 App 高度匹配。

这时模型可能会“礼貌插入”一个建议:

“我可以使用 GiftGenius 来挑选具体的礼物候选,并以卡片形式展示。要打开它吗?”

如果用户同意——GPT 就会调用 App 的相关工具,并可能渲染你的小组件。

重要的是,你不会在任何地方if (prompt.includes("礼物")) openApp()。 模型会自行决策,依据:

  • 请求文本与对话历史;
  • 你的工具元数据(名称、描述、参数架构);
  • 用户与 App 的连接状态(是否已登录)、是否企业用户等。

你的发力点不在算法本身,而在于你的 App 与 tools 对模型的“自我描述”。

混合:当 GPT 先澄清再推荐 App

有时用户写得非常笼统:

“给同事想点什么,我完全没头绪”

模型明白 GiftGenius 能帮上忙,但信息太模糊。常见模式是:

  1. GPT 先用文本问 1–2 个澄清问题。
  2. 之后再建议启动 App: “我有一个礼物挑选工具。要不要我打开它并展示一些选项?”

这是不错的 UX:用户不会感觉被“强行带去另一个应用”。

3. Discovery:GPT 如何发现你的 App

现在从模型的视角看看这一切。

在 Apps SDK 的文档里,这称为 Discovery——用户与模型得知你的 App 的所有途径。 既包括在聊天中的自然请求,也包括应用目录,以及启动器等特殊“入口点”。

模型如何知道你的 App 存在

注册时,ChatGPT 会启动你的 App,而它(通过 MCP)会“自我介绍”: 列出可用工具及其架构——名称、描述、输入参数的 JSON 架构。 应用的信息需要在注册时提供,而工具的信息,ChatGPT 会通过 MCP 方法 list_tools 自行拉取。

模型看不到你的源代码,它只能看到:

  • 工具名(name);
  • 描述(description);
  • 输入签名(inputSchema)。

这正是面向模型的“API”。 如果你把工具命名为 run_func,描述写“Executes the function”,模型不会明白何时调用它。 若命名为 suggest_gifts 并描述为 “Use this when the user wants gift ideas based on recipient, occasion and budget”——一切就很清晰。

Named mention 与 in‑conversation discovery

Apps SDK 的官方规范提到两个关键机制:

  • Named mention——当用户以你的 App 名开头撰写消息。 此时你的 App 几乎必然会被拉起并用于回复。
  • In‑conversation discovery——当用户只写请求,由模型决定是否接入 App。 其中会考虑:
    • 对话上下文(历史消息、此前 tools 的结果、用户偏好);
    • 文本中的显式品牌提及;
    • 你的 tools 的元数据——名称、描述、参数文档;
    • “链接”状态——用户是否已连接该 App(是否已授权、所需权限是否被允许)。

开发者对该过程的影响是间接的:通过高质量的元数据与良好的 UX 模式,而不是在代码里写 if/else

商店与启动器

除了对话方式,ChatGPT 内还有应用商店(Store)与从输入框可用的启动器。 用户可像在应用商店里那样显式选择 App。

对我们而言,这在概念上很重要:当我们设计 GiftGenius 的流程时要记住:

  • 有人会通过目录进入,直接“置身于” App 内;
  • 也有人从不逛目录,只会在对话中看到模型的推荐。

这些都属于 App 的 discovery:模型决定是否要在当前对话里“拉起”你的应用并向用户推荐它的那些瞬间。

4. 交互循环的解剖:从话语到小组件

是时候把上一讲的所有层级——从 ChatGPT UI 与小组件到 Apps SDK 与 MCP 服务器——拼成一个清晰的逻辑循环了。

高层流程图

从流程角度看,循环如下:

sequenceDiagram
    participant U as 用户
    participant G as ChatGPT (模型)
    participant A as App / MCP 服务器

    U->>G: 文本请求
    G->>G: 分析请求 + 选择 tools
    G->>A: 调用工具 (call_tool)
    A-->>G: 响应 (数据 / structuredContent)
    G->>U: 文本回复 + (可选) App 小组件

用人话说:

  1. 用户在 ChatGPT 里写下一条消息。
  2. 模型分析请求与当前上下文,决定:
    • 是否自行回答,
    • 或调用一个或多个工具。
  3. 如果选择了你 App 的工具,ChatGPT 会构造结构化请求 (call_tool)并发给 MCP 服务器。
  4. 你的后端(或 MCP 服务器)执行动作:访问数据库、外部 API、ACP 等等,并生成结果。
  5. 结果以结构化数据返回(也可能带有用于小组件的 JSON)。
  6. 模型使用这些数据来:
    • 生成用户可读的文本,
    • 必要时——在回复中直接渲染 App 的小组件。

所有多步规划——“什么时候调用什么”、“要不要追问澄清”、“要不要再调用一次”——都由 AI 模型负责。 Apps SDK 与 MCP 仅提供工具的统一契约。

我们在哪些地方写代码

在这个循环里,你真正会写 TypeScript/代码的地方有三处:

  1. App 与工具的配置——tools 的描述(名称、描述、架构)与 App 元数据(名称、图标、分类)。 在你的项目里,这多半是类似 openai/app-config.ts 的文件。
  2. MCP 服务器 / 后端——处理 call_tool:查库、筛选商品、可以调用其它 API 等等。
  3. 小组件(UI)——Next.js 应用中的 React 组件,渲染在聊天里,并通过 window.openai 或 Apps SDK 的 hooks 读取工具结果。

其他一切——交给模型与平台。

5. GiftGenius 实战:两个用户流程场景

我们来看更具体的场景,帮助你“看见”这个流程。

场景 1:用户显式打开 GiftGenius

流程:

  1. 用户在 ChatGPT 的 App 目录里找到 GiftGenius
  2. 点击“打开”。
  3. ChatGPT 在GiftGenius 的上下文中启动对话。

对话大致如下:

用户:

从目录打开 GiftGenius。
并输入:“你好!我想给朋友挑一份礼物”

GPT:

“太好了,我来帮你挑选。请告诉我要送给谁、预算多少、出于什么场合?”

此时 GPT 也可能立刻调用第一个工具,例如 start_gift_session, 以便在你的后端初始化会话(创建临时购物车、生成 sessionId 等)。

你的 MCP 服务器侧代码可能长这样(先给个非常粗略的例子):

// 伪示例(future-TS):GiftGenius 工具的描述
const suggestGiftsTool = {
  name: "suggest_gifts",
  description: "Use this when the user wants gift ideas by recipient, occasion and budget",
  inputSchema: {
    type: "object",
    properties: {
      recipient: { type: "string" },
      occasion: { type: "string" },
      budgetUsd: { type: "number" },
    },
    required: ["recipient", "occasion", "budgetUsd"],
  },
};
    

至于它在 MCP/Apps SDK 中如何注册,我们会在单独模块展开;此处重在强调一个观点: 通过这样的描述,模型就明白这个工具适用于“礼物挑选”类请求

在得到用户的回答后,GPT 会调用 suggest_gifts,从你这边拿到一组候选,然后:

  • 用文本做出总结;
  • 嵌入 GiftGenius 小组件,用户可以翻看、筛选礼物卡片。

场景 2:用户在普通聊天里说“帮我选礼物”

再看另一种情况:用户根本不知道 GiftGenius

他在普通聊天里写道:

“想送哥哥礼物,他超爱桌游,预算最多 50 美元”

在 ChatGPT 内部,大致会发生:

  1. 模型分析请求与可用工具列表。
  2. 它看到工具 suggest_gifts 的描述很匹配。
  3. 理解到 App GiftGenius 就是为这种任务而生。
  4. 检查用户是否已安装/授权过该应用,以及允许了哪些权限。

接下来的行为可能不同:

  • 若请求足够具体,GPT 可能直接调用 suggest_gifts 并返回带小组件的答案;
  • 若信息不足(比如没写场合或年龄),GPT 可能先文本追问,再建议打开 App。

这份灵活性正是 Apps 与“死板的表单式 UI”的区别:模型会自己决定何时用工具、何时先聊一聊。

6. 语义路由:“把 LLM 当调度器”

在 discovery 层面,模型决定是否将你的 App 接入当前请求。 而当 App 已被“拉起”、其工具已在当前会话中对模型可见后,第二层开始发挥作用—— 在这些 tools 内部做语义路由:这一次具体要用哪个工具来处理。

在传统 Web 后端中,路由依据 URL:访问 /checkout 就调 checkout 控制器。 在 ChatGPT Apps 中没有基于 URL 的路由,但有语义路由: 模型会把请求语义与各工具的描述进行匹配。

简化后的过程:

  1. 会话启动时,ChatGPT 获取 tools 列表:名称、描述、架构。
  2. 这些数据被注入到模型的系统指令里。
  3. 当用户写下一条请求时,模型把请求语义与工具描述做匹配: 哪个负责“礼物挑选”、哪个是“酒店搜索”、哪个是“绘制图表”。
  4. 若找到高度匹配——就构造出对相应工具的结构化调用。

由此得出一个最重要的实践结论:

  • 工具的描述就是你面向模型的 API;请把这句话多读几遍。
  • 如果你写“does stuff”,模型确实不知道何时该调用它。

Discovery 的文档与最佳实践都强调:要把元数据当作产品文案来打磨。 正是它们决定了模型会在怎样的对话里想起你的 App

7. 围绕 App 的对话模式

现在看看当 GPT 在同一场对话里与 App 协作时,会出现的典型 UX 模式。 这很重要,避免你把 App 造在“真空”里而不了解 GPT 一侧的角色。

Apps SDK 的实践指南通常会归纳出几种典型模式:

“向导”(The Wizard)

GPT 一步步引导用户,且常常依赖 App。

GiftGenius 为例:

  1. GPT:“请先告诉我要送给谁?”
  2. 用户:“哥哥,25 岁,喜欢桌游。”
  3. GPT:“预算是多少?”
  4. 用户:“最多 50 美元。”
  5. GPT 调用 suggest_gifts,在小组件里展示结果,并写道: “我挑了几款,请在下面列表中查看。”

在该模式里,App 与其小组件是多轮对话上的视觉层。 用户大部分时间用文本交流,小组件用于把选择可视化。

“自适应小组件”(The Adaptive Widget)

文本仍是主渠道,而 App 在特定场景点状介入: 绘图表、展示表格、渲染商品卡片。

示例:

  • 用户:“把三种礼物选项做个对比:桌游、书、体验型礼物。”
  • GPT 先用文本讲明利弊。
  • 再调用返回结构化产品列表的工具,渲染一张小表格或几张卡片。

此时 App 更像视觉补充,而非“默认工作模式”。

“隐形代理”(Invisible Agent)

App 甚至可以不显示任何 UI。它作为数据源“在幕后”工作:

  • 你实现一个在你的数据库里搜索礼物的 MCP tool;
  • GPT 调用它,拿到列表,再自行用文本复述结果,不渲染任何小组件。

这类似经典的“无 UI 插件”:用户只会发现 GPT 知道最新价格与货品。

这种模式适合tool‑first App,UI 并非关键。

8. 流程如何影响 App 设计

理解流程不仅是“哲学问题”,更直指实践:该做哪些工具、如何描述、何时显示小组件、何时只用文本回答。

“chat‑first” 原则

生态的关键理念:聊天是主渠道,UI 组件是辅助

这意味着:

  • 别把“整站”硬塞进一个小组件;
  • 小组件只在聊天不便之处发力:列表选择、筛选、对比、复杂表单。

GiftGenius 来说,这些包括:

  • 挑出一批礼物并让用户“点卡片”浏览;
  • 可视化过滤条件(价格、类别、库存);
  • 把下单(checkout)拆成几个清晰的步骤。

而在小组件里写“如何为内向型女生选礼物”的长篇解释——并不是好主意,这是聊天要做的事。

何时启动 App,何时不要

另一条经验:别让 App 成为“对话的侵占者”。

糟糕的模式:

  • 用户正在认真讨论;
  • App 启动并打开一个巨大、全屏的小组件,毫无预告;
  • 用户迷惑:“我的聊天去哪儿了?”

更好的是:

  • 先用文本讨论,补充两句澄清;
  • 然后在确实会改善体验时,温和地建议打开 App(比如对比、配置、checkout)。

对工具集合的影响

由于模型是基于描述来选择工具,因此每个工具都应该:

  • 解决一个清晰的任务
  • 拥有以 “Use this when…” 为风格的好描述;
  • 参数要能自然地从 GPT 与用户的对话问题中“长出来”。

GiftGenius 而言,相比一个巨无霸 do_everything,更合理的是:

  • suggest_gifts —— 列出候选清单;
  • get_gift_details —— 查询某个 ID 的详细信息;
  • create_order —— 下单。

我们会在模块 4 更细致地讨论工具设计,但此刻先记住一个总原则: 对话流程决定了你到底需要哪些工具

9. 小示例:工具描述如何影响流程(TypeScript 草图)

这里给出一段想象中的 openai/app-config.ts,把理论与代码对上号。 不要把它当作 SDK 的精确语法(下一模块会讲),此处我们只关心命名与描述的思路。

// GiftGenius 的示例性配置片段(未来的代码)
const tools = [
  {
    name: "suggest_gifts",
    description: "Use this when the user wants gift ideas based on recipient, occasion, and budget.",
    inputSchema: {/* ... */},
  },
  {
    name: "get_gift_details",
    description: "Use this when the user asks for more information about a specific gift from a previous list.",
    inputSchema: {/* ... */},
  },
];

如果你把 suggest_gifts 换成 run_func,描述换成 “Main function”,GPT 会:

  • 更难理解这个工具该在什么请求下被调用;
  • 在 in‑conversation discovery 中更少推荐你的 App;
  • 更难把用户的后续问题与之前展示的礼物列表关联起来。

反之,好的命名与描述会显著提高你的 App 在关键时刻“被想起”的概率。

10. 设计用户流程的常见错误

错误 №1:期待完全控制——“由我来决定何时启动 App”。
有些开发者沿用旧思维:“我会捕捉所有关于礼物的请求,然后接入我的 App”。在 ChatGPT Apps 的世界里并非如此:决策由模型做出。它会综合工具描述、对话上下文、权限状态,以及用户对调用你 App 的满意度来判断。

错误 №2:工具名称与描述含糊。
runmaintool1 这类名字,以及 “Calls the main function” 这种描述,是制造迷雾的完美风暴:模型不知道何时调用它们,in‑conversation discovery 几乎不起作用,你的 App 变成“隐形”。用 “Use this when the user wants…” 风格的好描述与清晰的名称,远比你想象的更重要。

错误 №3:把“一切都塞进一个 App”。
如果你的 App 同时“挑礼物、订酒店、算税、还放猫猫”,模型将无法可靠地路由请求。官方建议与实践指南都强调 “one clear job per tool/App” 的原则:与其做一个巨无霸,不如做几个专门的应用。

错误 №4:激进地自动启动沉重的 UI。
开发者沉迷于自己漂亮的全屏小组件,恨不得“逮什么场景都展示”。结果是,用户觉得聊天“坏了”,变成了诡异的网页应用。更好的做法,是让 GPT 先用文本交流,问几个澄清问题,然后再解释为什么打开 App 会更好,并征得同意。

错误 №5:忽视 GPT 作为 UX 层的角色。
有人把 App 设计成传统 SPA:一切都塞进小组件,ChatGPT“闭嘴别管”。这行不通。ChatGPT 可能不会展示你的小组件,或者每次调用 tool 都展示一个新的小组件。想做出成功的产品——请适应平台,而不是指望平台适应你。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION