跳至主要內容

AI 工具呼叫授權 TypeScript 教學

實作

工具呼叫:模型提案,應用程式決定是否執行

只給模型一個窄的帳戶查詢工具,並證明身分、租戶、參數驗證、執行與稽核都由應用程式負責。

難度
中階
預估時間
120 分鐘
更新日期
2026-10-02
文案複核
speak-human-tw
兩輪
本課內容
  1. 01先把定義說清楚
  2. 02現場情境
  3. 03實作範例
  4. 04照著做,每一步都有檢查點
  5. 05實務脈絡
  6. 06動手實作
  7. 07故障診間
  8. 08正式上線前的邊界
  9. 09資料來源與主張限制

這一課會完成什麼

  • 替單一用途工具設計嚴格 schema
  • 不依賴模型產生的參數,另外驗證呼叫端與租戶
  • 回傳精簡有型別的觀察紀錄與可處理的錯誤碼
  • 測錯誤的工具、偽造參數、逾時、超出大小限制的結果與重複呼叫

開始前先準備

  • • 模組 01 的結果聯集型別與執行環境驗證模式
  • • 基本授權概念與本機 TypeScript 測試執行器

先把定義說清楚

工具呼叫與權限

工具呼叫(function 呼叫)讓模型以結構化參數提出請求,例如查詢某個帳戶。收到請求後,主應用程式先驗格式與權限,再用受限身分執行,記錄結果,將有型別的觀察資料交給下一輪模型。參數合法只代表格式正確,並不授予資料存取權。使用者、租戶與角色都由可信的執行環境提供,模型不能自行填入身分來擴大權限。

工具 schema 只能限制參數形態。它無法證明目前使用者可讀這個帳戶、帳戶屬於登入中的租戶,或這個動作符合規則。這些條件必須從可信工作階段與伺服器端規則得到。

工具結果會變成模型脈絡。把整包 CRM 傳送資料、內部 UUID 或呼叫堆疊塞回去,既浪費 token,也讓模型更難復原。介面應回傳下一步真正用得到的語意欄位、大小限制與具名錯誤。

現場情境

Meridian account lookup

具名合成情境。Meridian CRM、租戶 ID、帳戶紀錄、執行軌跡與規則全是本實作虛構資料,不代表真實環境的系統。

負責人
你是 API 工程師,正在替研究助理加入唯讀帳戶查詢。
要做的決策
設計能回答分析師問題的最小工具介面,同時不暴露原始 SQL、任意 HTTP 或跨租戶資料。
目前狀態
助理會先摘要已核准的帳戶脈絡,再由分析師研究公司。兩個合成租戶共用同一個資料庫;早期原型直接相信模型提出的帳戶 ID,也允許模型傳 tenantId。這讓跨租戶讀取成為實際風險。
預期成果
授權查詢回傳精簡觀察紀錄;偽造租戶、unknown 紀錄、schema 錯誤與逾時各有不洩密的具名錯誤,也不回傳帳戶資料。

限制條件

  • • 工具只能讀取公司 name、分類、已核准的筆記與紀錄版本。
  • • 租戶身分來自已驗證身分的工作階段,絕不從模型參數取得。
  • • 回應最多 5 則筆記、2,000 個 UTF-8 字元。
  • • 每次請求記錄呼叫端、租戶、工具、已驗證的參數、結果碼、耗時與關聯 ID。

實作範例

帳戶 ID 合法,租戶檢查仍然擋下

證據類型: 具名模擬情境

進行中的工作階段屬於 meridian-eu。使用者詢問 Northwind Labs,但檢索到的公開文字夾帶指令,要模型用 accountId acct_us_204 呼叫 lookup_account。這筆帳戶確實存在,卻屬於 meridian-us。模型看不到資料庫責任歸屬規則,因此輸出符合 schema 的呼叫。

主應用程式忽略自動產生的文字裡所有租戶值,從工作階段綁定 meridian-eu,驗證 accountId,再用租戶與帳戶兩個條件查詢。結果回傳 NOT_FOUND,不透露 acct_us_204 是否存在於別處。執行軌跡記為 denied_at_data_boundary,只保存已驗證的參數雜湊,不存原始帳戶筆記。

EU 呼叫端拿不到任何 US 欄位,稽核紀錄保留已驗證身分的租戶,模型只收到能處理的精簡錯誤,對抗測試資料才算通過。這是確定性的應用程式行為,不宣稱供應商有任何可靠度百分比。

主張限制

範例在記憶體中模擬資料儲存區,採簡單角色規則。正式系統可能還需資料列層級安全、委派 OAuth、依屬性授權、欄位遮蔽與法定保存規則。OpenAI 和 Anthropic 文件描述工具迴圈,實際授權仍由應用程式負責。

做法

照著做,每一步都有檢查點

模型提出 lookup_account,主應用程式綁定可信租戶身分,通過授權與驗證後才查限定租戶範圍的程式庫,最後寫稽核並回傳有上限的結果。

現場情境

設計能回答分析師問題的最小工具介面,同時不暴露原始 SQL、任意 HTTP 或跨租戶資料。

  1. 01拆開身分與參數
  2. 02先驗證,再讀資料
  3. 03縮小觀察紀錄

驗收條件

工具 schema 協助模型提出有用請求;身分、授權、執行、傳送資料、重試與稽核仍由應用程式控制。跨租戶或未授權情境不會因模型參數看似合理而漏資料。

這張圖要幫你看懂什麼從來源產生確定性的順序圖解,精確畫出使用者、主應用程式、模型、授權層、限定租戶範圍的程式庫、稽核接收端與觀察紀錄。拒絕點不能模糊。
  1. 01

    拆開身分與參數

    工作階段由可信的中介層建立,Args 只來自模型呼叫。從工具 schema 移除 tenantId、userId、角色、URL 與查詢,模型不需要知道也不能控制。

    檢查點 · 模型可見的 schema 只有 accountId;執行器必須由主應用程式額外傳入可信工作階段才能執行。

  2. 02

    先驗證,再讀資料

    依序做嚴格 schema、角色規則與限定租戶範圍的查詢,通過後才組回應。不存在與屬於其他租戶的帳戶一律用相同 NOT_FOUND 形態。

    檢查點 · meridian-eu 查 acct_us_204 得到 NOT_FOUND,紀錄與工具結果都沒有任何資料列欄位。

  3. 03

    縮小觀察紀錄

    只回傳 name、最多 5 則筆記、穩定版本及受大小限制的資料。失敗用明確代號指出下一步,不回堆疊或內部查詢;另測超出上限時是否完整拒絕,避免洩漏部分筆記。

    檢查點 · 正常結果少於 2,000 字元;超大結果回 RESULT_TOO_LARGE,不洩漏部分筆記。

  4. 04

    控制逾時與重複呼叫

    資料存取層呼叫到期限就取消;成功讀取依執行與已驗證的參數雜湊快取。暫時逾時最多再讀 1 次,之後直接轉交人工。

    檢查點 · 逾時測試資料結束於 TIMEOUT;同一執行的 3 次相同呼叫,在成功後最多執行資料存取層 1 次。

  5. 05

    寫對抗性測試與稽核斷言

    涵蓋額外參數、格式錯誤 ID、缺漏角色、跨租戶 ID、unknown 紀錄、逾時、超出大小限制的回應與重複呼叫,逐一檢查稽核。

    檢查點 · 每個測試都記關聯 ID、可信租戶、工具名稱、結果碼與耗時,不存帳戶筆記。

實務脈絡

展示版之後

G1

實作拆解

工具宣告只描述模型可提出的請求,授權紀錄由應用程式建立。中介層從工作階段取得 userId、tenantId 與 roles,以伺服器端型別傳給執行器;模型不必自行填租戶。資料存取層只提供 findByTenantAndId,避免先做全域查詢再補權限判斷。CI 固定測跨租戶呼叫,回應、紀錄、快取鍵值和時間差都不得透露其他租戶是否有該帳戶。

只回傳下一個決策需要的欄位。分析師需要名稱(name)、分類(分類)、已核准筆記與版本時,就省去內部分數、負責人電子郵件、後端鍵值與完整變更歷史。5 則筆記及 2,000 UTF-8 字元的限制,要用多位元字元測清楚位元組與字元的算法。超出上限回完整錯誤碼,不能截掉後半段又讓模型當成完整資料。

驗證前建立關聯 ID,稽核紀錄最後補上可信租戶、已驗證參數雜湊、權限判定、資料存取結果碼、耗時與實作版本,省去原始帳戶筆記。逾時、取消與完成狀態未知分開處理;唯讀操作可依固定規則有限重試。未來若允許寫入,先設計冪等性與結果核對。模型收到可採取下一步的錯誤,操作人員取得可定位原因的軌跡,兩者都不直接暴露內部呼叫堆疊。

G2

營運檢查

工具介面審查要從最壞情境開始:攻擊者能控制使用者文字、檢索內容與模型提出的參數,但不能控制已驗證的工作階段。沿著一次呼叫把信任來源標出來,帳號識別碼來自模型所以要驗格式;租戶、角色與使用者來自中介層所以仍要檢查有效期;資料列來自資料庫,但回傳前還要投影與遮蔽。接著用八個離線測試逐一證明,格式不正確時資料庫呼叫次數為零、跨租戶與不存在都回同一外觀、逾時不會無限重送、成功後相同輸入不重做查詢、過大結果不回半套資料。測試除了看回傳值,也要對稽核事件與儲存庫呼叫計數做斷言。

工具說明不是行銷文案,應明講用途、不能做的事與回傳限制。名稱要能和其他工具區分,參數使用穩定的業務語意,不暴露任意查詢、網址或後端欄位。錯誤結果也要設計:找不到不能透露其他租戶是否存在;權限不足不回內部政策;結果過大要告訴協調器改走分頁或縮小範圍,而不是讓模型自己猜。準備新增第二個工具前,先用保留的真實任務評估選擇正確率、無效參數、呼叫次數、回傳長度與失敗復原。若兩個工具功能重疊到工程師都難以說明差別,模型只會更難選。

G3

驗證與上線

部署前的權限檢查由兩個人分工:一人只看公開工具格式,嘗試塞入額外租戶、任意網址、萬用查詢與過長字串;另一人只看執行器與資料存取,確認可信身分從哪裡來、每個拒絕發生在查詢前還是查詢後。兩邊的結果合併後,工具文件才算完整。這種分工能抓出常見落差:格式很嚴格,執行器卻先查全域資料;或資料層有租戶條件,工具回傳與稽核卻洩漏不該看的欄位。

工具升級也要保留相容性策略。欄位更名、結果增大、錯誤碼新增或權限收緊,都可能讓既有模型與協調器走錯路。先用版本化宣告與保留任務重跑,再決定是否同時支援舊版;不可默默放寬額外欄位,讓舊呼叫『先能跑再說』。移除工具前,搜尋所有提示、允許清單、測試、儀表板與操作手冊的引用,確認舊名稱呼叫會得到明確不可用狀態,而不是轉到一個權限更大的替代工具。

G4

補強練習

再加一個工具登錄測試:程式啟動時逐一確認每個工具都有風險類別、參數格式、執行身分、逾時、回傳上限、負責人與稽核版本。缺一項就不註冊。這能避免後來加入的工具繞過本模組建立的嚴格邊界。

G5

交付前最後檢查

最後用一個完全沒有帳號資料的工作階段執行正常查詢,確認拒絕發生在任何資料讀取之前;再以合法角色執行不存在與跨租戶識別碼,兩者外觀一致。這三筆稽核足以讓審查者確認格式、授權與防枚舉不是同一道檢查。

G6

延伸實作

安全評審另做一張欄位級資料表,列每個回傳欄位的業務用途、原始資料位置、可見角色、遮蔽規則、最長保留與是否進模型。欄位沒有明確下一步用途就移除。工具錯誤也套同樣原則:模型只需要知道能否縮小查詢、稍後再試或交人工,內部堆疊、資料庫名稱與其他租戶線索不應回傳。這張表日後能直接用來審新增欄位,避免後端物件擴張時,模型介面跟著無意放寬。

動手實作

建立 Meridian 唯讀工具邊界

對兩個租戶的記憶體內測試資料實作 lookup_account,跑允許、denied、不合法、逾時與超出大小限制的回應。

準備項目

  • • 沿用模組 01 的封閉結果模式。
  • • 工作階段與工具參數使用不同型別,不能合併成模型可見的物件。
  • • 帳戶筆記只用合成資料,不放姓名、Email 或機密。
  • • 資料儲存模擬器回固定結果,驗收可離線執行。

本課產出

嚴格工具宣告、綁定工作階段的執行器、合成程式庫、精簡結果契約、稽核事件型別,以及至少 8 個離線測試。

起始模板: 有授權檢查的帳戶工具

TypeScript
type Session = { userId: string; tenantId: string; roles: string[] };
type Args = { accountId: string };
type ToolResult =
  | { ok: true; account: { id: string; name: string; segment: string; notes: string[]; version: number } }
  | { ok: false; code: "FORBIDDEN" | "NOT_FOUND" | "INVALID_ARGS" | "TIMEOUT" | "RESULT_TOO_LARGE" };

const TOOL = {
  type: "function",
  name: "lookup_account",
  description: "Read one account in the authenticated tenant. Never searches other tenants or updates records.",
  strict: true,
  parameters: {
    type: "object",
    additionalProperties: false,
    required: ["accountId"],
    properties: { accountId: { type: "string", pattern: "^acct_[a-z0-9_]+$" } }
  }
} as const;

export async function executeLookup(session: Session, args: Args): Promise<ToolResult> {
  if (!session.roles.includes("account:read")) return { ok: false, code: "FORBIDDEN" };
  if (!/^acct_[a-z0-9_]+$/.test(args.accountId)) return { ok: false, code: "INVALID_ARGS" };
  const row = await repository.findByTenantAndId(session.tenantId, args.accountId);
  if (!row) return { ok: false, code: "NOT_FOUND" };
  const account = { ...row, notes: row.notes.slice(0, 5) };
  if (JSON.stringify(account).length > 2000) return { ok: false, code: "RESULT_TOO_LARGE" };
  return { ok: true, account };
}

預期結果

工具 schema 協助模型提出有用請求;身分、授權、執行、傳送資料、重試與稽核仍由應用程式控制。跨租戶或未授權情境不會因模型參數看似合理而漏資料。

留給下一課

保留工作階段、ToolResult、稽核欄位與雙租戶測試資料。模組 05 會用同樣窄的讀取能力封裝成 MCP 伺服器。

驗收條件

  1. 01跨租戶與未授權測試資料不回帳戶欄位,錯誤形態也不能協助枚舉資料。
  2. 02額外或格式錯誤參數在程式庫呼叫前失敗。
  3. 03工具結果不超過文件列出的欄位與大小上限。
  4. 04同一執行的重複成功呼叫不重做程式庫工作,所有路徑都有稽核紀錄。

常見故障

故障診間

F1呼叫端只要提供 ID,就能讀到另一個租戶的帳戶。
先檢查
追查租戶身分來源,並確認程式庫判定條件同時包含 tenantId 與 accountId。
可能原因
授權由模型參數推測,或先做全域 ID 查詢才檢查租戶。
修復方式
租戶只能從已驗證身分的工作階段綁定,工具僅可使用限定租戶範圍的程式庫方法。
下次怎麼避免
CI 保留跨租戶測試資料;資料儲存區支援時再加資料列規則。
F2模型一直呼叫正確工具,卻反覆帶入無效可選欄位。
先檢查
檢查原始呼叫、schema 嚴格程度、參數 name、工具說明與驗證錯誤。
可能原因
Schema 太寬,或參數命名模糊,模型無法區分用途。
修復方式
移除沒用欄位,additionalProperties 設不成立,INVALID_ARGS 回一個可處理範例。
下次怎麼避免
擴大工具面前,先對保留評測貼近實際情況的集合評估工具選擇與參數。
F3查詢成功,原始 CRM 傳送資料卻塞滿脈絡,後續判斷變差。
先檢查
量測結果 token,找出下一步從未使用的欄位。
可能原因
工具直接鏡射後端回應,沒有設計 Agent 看到的觀察紀錄。
修復方式
改回精簡語意欄位選取;真的需要才透過分頁或詳細模式取更多資料。
下次怎麼避免
設定回應預算,評測報告要包含工具結果 token 總量。
F4逾時引發重複呼叫,執行軌跡不一致或後端過載。
先檢查
檢查期限、嘗試計數器、執行層級的快取鍵值與完成狀態未知處理。
可能原因
重試留給模型自由決定,沒有冪等性或去重邊界。
修復方式
用確定性的任務協調限制重試,成功結果依已驗證的輸入快取。
下次怎麼避免
工具串接測試主動注入緩慢、已遺漏的與重複回應。

展示版之後

正式上線前的邊界

  1. 01身分、租戶與角色從可信的中介層取得,不放在模型可見的參數。
  2. 02每個工具只做一件事,schema 嚴格且最小。
  3. 03能力逐一標成唯讀、可復原寫入、外部通訊或不可復原操作。
  4. 04使用短效、最小權限憑證,網路目的地明列允許清單。
  5. 05結果有大小限制、穩定錯誤碼,也不回內部呼叫堆疊。
  6. 06期限、重試、速率限制與去重全在模型外執行。
  7. 07稽核要有發起者、可信的租戶、參數雜湊、決策、結果、延遲與版本。
  8. 08加新工具前,先跑保留評測選擇測試與對抗性授權測試。

證據類型

資料來源與主張限制

資料來源只支撐本課標示的主張,不代表換一個系統也會得到相同結果。

  1. [1]
    Function calling

    OpenAI · 官方文件 · 2026-08-20

    strict function schema · 平行呼叫 · tool-call 狀態機
  2. [2]
    Claude tool use

    Anthropic · 官方文件 · 2026-08-20

    工具定義 · tool result 迴圈 · 使用者端執行責任
  3. [3]
    為 agent 設計有效工具

    Anthropic · 官方文件 · 2026-08-20

    工具介面設計 · 保留集工具評測 · 節省 token 的結果格式
  4. [4]
    建置 agent 的安全指引

    OpenAI · 官方文件 · 2026-08-20

    prompt injection · 結構化資料邊界 · MCP 核准

延伸的 Tenten 資源

實作準備進正式環境時

帶著實作證據來,不用從空白摘要開始。

有效的實作審查,起點應該是任務測試資料、權限地圖、執行軌跡、評測報告、失敗案例與成本上限。Tenten 可以根據這些資料檢查整合與營運缺口,不必把課程裡已經證明過的決策全部重開。