1. 導言
想像你在寫一般的網頁服務。一切都很直觀:你有 URL /search,使用者按下按鈕,你呼叫控制器 searchController。 在 ChatGPT Apps 的世界中,使用者看不到任何 /search。他只會寫出一段自然語言:
«幫我替愛打電動的弟弟挑個不超過 50 美元的禮物»
接著會發生:
- 模型判斷:「喔,這是關於禮物的,我有 GiftGenius 可以做到這件事」;
- GPT 會自己「按按鈕」——呼叫你 App 的工具;
- 有時還會提示使用者:「要不要我打開 GiftGenius 給你看一些選項?」。
關鍵轉變:使用者表達意圖,而按哪個按鈕由模型決定。 如果不理解這個流程,很容易:
- 寫出毫無意義命名的工具(run_func、doStuff),
- 做出一個 從不被模型推薦或經常被誤用的 App,
- 創建會「突然跳出來」把對話打斷的 widget。
因此本講會建立一個心智模型:GPT 究竟如何得知你的 App,並在對話的哪些節點把它「嵌入」進來。
Insight:應用程式是 ChatGPT 的外掛
不同於手機上的 App 或 WeChat 的 mini-app,ChatGPT 裡的應用運作方式很不一樣。
ChatGPT 會自行決定何時啟動你的應用程式以及要呼叫哪個功能。 在 ChatGPT 中的應用可以(雖然有限制)主動介入聊天邏輯。 它們的核心目標與強項——是擴充 ChatGPT 本身的能力。
如果 ChatGPT 能完美解決使用者的問題——它就不需要呼叫你的應用。 如果 ChatGPT 完全無法解決——使用者通常也不會來問。 理想情況是:ChatGPT 僅能部分解決。 這代表需求存在且不少,但結果還不夠好。
就在這時,ChatGPT 會呼叫你的應用,而你們一起讓使用者變得更滿意。 使用者更開心,而你也更有價值。
2. 從使用者視角看啟動 ChatGPT App 的方式
使用者沒有「叫出 MCP 伺服器並 call_tool」的按鈕,他只有一個輸入框,以及(有時)應用選單。 從他的角度看有兩種基本啟動模式:顯式與隱式。
顯式啟動(explicit)
這是使用者刻意選擇你的 App的情境。
常見方式:
- 他在 ChatGPT 的 Store 中找到 App 並點擊「開啟」;
- 他在 Launcher 中選擇 App(例如透過輸入框(Composer)裡的 + 按鈕);
- 他以應用名稱開頭撰寫訊息:「GiftGenius,幫我挑個禮物…」 ——這稱為 named mention。 若 App 名稱位於提示詞開頭,ChatGPT 會自動把你的 App 混入回覆的上下文。
在顯式模式下,模型一開始就知道:使用者是為了這個 App 而來。因此:
- GPT 會更頻繁、也更積極地呼叫你的工具;
- 你的 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 能幫上忙,但資訊太模糊。常見模式是:
- GPT 先用文字問 1–2 個釐清問題。
- 接著再建議啟動 App: 「我有一個挑禮物的工具。要不要我打開它並展示一些選項?」
這是良好的 UX:使用者不會覺得被「強迫切換到另一個應用」。
3. Discovery:GPT 如何找到你的 App
現在換成模型本身的視角看看整件事。
在 Apps SDK 的文件中,這稱為 Discovery ——也就是使用者與模型如何得知你的 App 的所有路徑。 包含在聊天中的自然請求、應用目錄,以及像 Launcher 這樣的特殊「進入點」。
模型怎麼知道你的 App 存在
在註冊時,ChatGPT 會啟動你的 App,而你的 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。 這會考量:
- 對話脈絡(訊息歷史、先前工具的結果、使用者偏好);
- 文字中的明確品牌提及;
- 你的工具中繼資料——名稱、描述、參數文件;
- 「連結」狀態——使用者是否已連上 App(已授權、必要權限是否允許)。
開發者對此的影響是間接的:透過優質的中繼資料與 UX 模式,而不是在程式碼裡寫 if/else。
目錄與 Launcher
除了對話式的途徑之外,ChatGPT 內還有Store 與從 Composer 可開啟的Launcher。 透過它們,使用者可以明確選擇 App,就像在一般的應用商店。
這對我們的概念很重要:當我們設計 GiftGenius 的流程時,必須記住:
- 有人會從目錄進來,立刻就「在」App 裡;
- 也有人完全不會逛目錄,只會在對話中看見被建議的 App。
以上都是關於 App 本身的 discovery:模型決定是否要在當前對話中「載入」你的應用並把它推薦給使用者的那些時刻。
4. 互動循環的剖析:從一句話到小工具
是時候把前一講的所有層次——從 ChatGPT UI 與 widget,到 Apps SDK 與 MCP 伺服器——整合成一個容易理解的邏輯循環。
高階流程圖
從流程的角度,循環大致如下:
sequenceDiagram
participant U as 使用者
participant G as ChatGPT(模型)
participant A as App / MCP 伺服器
U->>G: 文字請求
G->>G: 分析請求 + 選擇工具
G->>A: 呼叫工具(call_tool)
A-->>G: 回應(資料 / structuredContent)
G->>U: 文字回覆 +(可選)App 小工具
白話版:
- 使用者在 ChatGPT 中輸入訊息。
- 模型分析請求與目前的上下文,並決定:
- 要不要自行回覆,
- 或是呼叫一個或多個工具。
- 若選中你的 App 的工具,ChatGPT 會形成一個結構化請求 (call_tool)並把它送到 MCP 伺服器。
- 你的 backend(或 MCP 伺服器)執行動作:查資料庫、外部 API、ACP 等等,並整理結果。
- 結果以結構化資料(也可能包含用於小工具的 JSON)返回。
- 模型使用這些資料來:
- 生成使用者可理解的文字,
- 必要時——在回覆中直接渲染 App 的小工具。
所有多步驟的規劃——「何時叫什麼」、「要不要先澄清」、「是否再多呼叫一次」——都在 AI 模型這一側。 Apps SDK 與 MCP 只是為工具提供統一的契約。
我們在哪些地方寫程式
在這個循環中,有三個點是你會真正寫 TypeScript/程式碼的地方:
- App 與工具的組態——工具的描述(名稱、描述、結構)與 App 中繼資料(名稱、圖示、分類)。 在你的專案裡,這很可能是像 openai/app-config.ts 這樣的檔案。
- MCP 伺服器 / backend——處理 call_tool:查資料庫、篩選商品、也可以呼叫其他 API 等。
- 小工具(UI)——Next.js 應用中的 React 元件,它會在聊天裡渲染,並透過 window.openai 或 Apps SDK 的 hooks 讀取工具結果。
其他一切都交給模型與平台處理。
5. GiftGenius 實戰:兩種使用者流程場景
接下來看更具體的情境,幫你「看見」這個流程。
情境 1:使用者顯式開啟 GiftGenius
情境:
- 使用者在 ChatGPT 打開 App 目錄並找到 GiftGenius。
- 點擊「開啟」。
- ChatGPT 在以 GiftGenius 為上下文的狀態下開始對話。
對話大概像這樣:
使用者:
從目錄開啟 GiftGenius。
並寫道:「嗨!我想幫朋友挑個禮物」
GPT:
«太好了,讓我來幫你挑禮物。請告訴我對象、預算以及場合?」
在這一步,GPT 可能立刻呼叫第一個工具,例如 start_gift_session, 用來在你的 backend 初始化一個 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 內部大致會發生:
- 模型分析請求與可用工具清單。
- 它看到 suggest_gifts 工具擁有相符的描述。
- 理解到 GiftGenius 就是為此類任務而設計。
- 檢查使用者是否已安裝該應用、是否曾授權、允許了哪些權限。
接著有幾種可能的行為:
- 如果請求已相當具體,GPT 可能會直接呼叫 suggest_gifts,並返回帶有小工具的回覆;
- 如果缺少資訊(例如沒說場合或年齡),GPT 可能先以文字詢問澄清,再建議使用 App。
這種彈性正是 Apps 與「死板的」表單式 UI 的差異:模型自己決定何時用工具、何時先聊聊。
6. 語義路由:「LLM 當調度員」
在 discovery 的層次,模型決定是否要將你的 App 接入當前請求。 而當 App 已被「載入」,且其工具在當前會話中已為模型所知時,第二個層次就啟動了—— 在這些工具之間進行語義路由:這一輪訊息究竟要用哪個工具處理。
在傳統的 Web 後端,路由靠 URL 選擇:/checkout 就會呼叫 checkout 控制器。 在 ChatGPT Apps 沒有 URL 路由,但有語義路由: 模型會將請求的語意與你工具的描述進行比對。
簡化後的流程:
- 在會話開始時,ChatGPT 會取得工具列表:它們的名稱、描述、結構。
- 這些資料會被嵌入模型的系統指令中。
- 當使用者發出請求,模型把請求語意與各工具描述比對: 哪個是「挑禮物」、哪個是「找飯店」、哪個是「畫圖表」。
- 若找到良好匹配——就會形成對應工具的結構化呼叫。
由此得出最重要的實務結論:
- 工具描述就是提供給模型的 API;請再讀一遍,然後再讀一遍。
- 如果你寫成「does stuff」,模型真的無法理解何時該使用它。
關於 discovery 的文件與最佳實踐一再強調:把中繼資料當成產品文案工作來做。 正是它們決定了模型會在什麼樣的對話裡想起你的 App。
7. 圍繞 App 的對話樣式(Patterns)
接下來看看 GPT 在同一段對話中與 App 互動時,常見的 UX 模式。 這很重要,避免你在不了解 GPT 角色的情況下把 App「造在真空裡」。
各種 Apps SDK 的實作指南都會指出幾個典型模式:
「精靈嚮導」(The Wizard)
GPT 逐步引導使用者,並經常依賴 App。
以 GiftGenius 為例:
- GPT:「請告訴我要送給誰?」
- 使用者:「弟弟,25 歲,喜歡桌遊。」
- GPT:「預算多少?」
- 使用者:「最多 50 美元。」
- GPT 呼叫 suggest_gifts,在小工具中顯示結果,並寫道: 「我幫你挑了幾個選項,請看下面的清單。」
這個模式中,App 與其小工具就像多步驟對話之上的視覺層。 使用者大多時間用文字交流,而小工具輔助視覺化挑選。
「自適應小工具」(The Adaptive Widget)
文字仍然是主要管道,而 App 只在特定任務時接入: 畫圖表、顯示表格、渲染商品卡片等。
範例:
- 使用者:「比較三種禮物:桌遊、書、體驗型禮物。」
- GPT 先用文字說明優缺點。
- 再呼叫工具返回結構化產品清單,並渲染小表格或卡片。
這裡 App 是視覺化的補充,而不是「預設的工作模式」。
「隱形代理」(Invisible Agent)
App 也可以完全不顯示 UI。它作為「底層資料來源」運作:
- 你實作一個 MCP 工具,從資料庫搜尋禮物;
- GPT 呼叫它、拿到清單,之後直接用文字轉述結果,不顯示任何小工具。
這很像傳統的「無 UI 外掛」:使用者只會發現 GPT 知道最新價格與庫存。
這個模式特別適合tool‑first 的 App,也就是 UI 並非關鍵者。
8. 流程如何影響 App 設計
理解流程不只是哲學問題,也會影響非常務實的決策: 要做哪些工具、如何描述它們、什麼時候顯示小工具、什麼時候改用文字回覆更好。
「chat‑first」原則
生態系的核心理念:聊天是主要互動管道,UI 元件是輔助。
這表示:
- 不要嘗試把「整個網站」塞進一個小工具;
- 小工具應該用在聊天不便之處:從清單中挑選、篩選、比較、複雜表單等。
以 GiftGenius 而言:
- 挑出一份禮物清單,讓使用者能「點點看」卡片;
- 視覺化篩選器(價格、類別、是否有貨);
- 協助以幾個清楚步驟完成下單(checkout)。
但在小工具裡寫一大段「如何挑選內向女生的禮物」——不是好主意,那是聊天該做的事。
什麼時候該啟動 App,什麼時候不該
另一個啟示:不要讓 App 變成「對話的侵入者」。
不佳的模式:
- 使用者正在進行嚴肅討論;
- App 啟動並在未通知的情況下打開巨大的全螢幕小工具;
- 使用者困惑:「我的聊天去哪了?」。
更好的做法:
- 先用文字把事情說清楚,問幾個澄清問題;
- 接著在確實能改善 UX(比較、設定、checkout)時,再溫和地建議開啟 App。
對工具設計的影響
由於模型是依據描述選擇工具,每個工具都應該:
- 解決一個清楚的任務;
- 以「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. 設計使用者流程的常見錯誤
錯誤一:期待完全控制——「我自己決定何時啟動 App」。
有些開發者以「我會攔下所有與禮物相關的請求,然後接入我的 App」的思維設計。在 ChatGPT Apps 的世界不是這樣:決策由模型做出。它會考量工具描述、對話脈絡、權限狀態,以及使用者對接入你 App 的滿意度。
錯誤二:工具名稱與描述含糊不清。
名稱為 run、main、tool1,描述為「Calls the main function」的工具,會造成完美風暴:模型不明白何時該呼叫它們,in‑conversation discovery 幾乎失效,你的 App 變得「隱形」。以「Use this when the user wants…」風格撰寫的好描述與清楚名稱——比你想像中重要得多。
錯誤三:試圖把「所有東西」塞進一個 App。
如果你的 App 同時「挑禮物、訂飯店、算稅金、秀貓咪」,模型將無法穩定地路由請求。官方建議與實務指南都強調「one clear job per tool/App」的原則:多個專精的小應用,勝過一個巨型單體。
錯誤四:過度激進地自動啟動沉重的 UI。
開發者對自己漂亮的全螢幕小工具很興奮,想「逮到機會就展示」。結果讓使用者覺得聊天被「破壞」成一個奇怪的網頁應用。更好的作法是讓 GPT 先以文字互動、提出幾個澄清問題,然後再解釋為何需要,最後才建議開啟 App。
錯誤五:忽視 GPT 作為 UX 層的角色。
你可以把 App 設計成一般 SPA:所有事都在小工具裡做,ChatGPT 就「安靜不打擾」。但這不會奏效。ChatGPT 可能不顯示你的小工具,或每次呼叫工具都顯示一個新的小工具。若想做出成功的產品——請配合平台,而不是期待平台配合你。
GO TO FULL VERSION