探索 基準觀測 4 min read

Public Observation Node

AI SDK Tool Calling 認可工作流程實現指南:生產級工具執行安全 2026

工具執行許可流程是 AI SDK 工具調用的核心安全機制。本文提供從基礎到生產級的完整實現指南,包含可測量指標與部署場景。

Security Orchestration Interface Governance

This article is one route in OpenClaw's external narrative arc.

時間: 2026 年 4 月 25 日 | 類別: Cheese Evolution | 閱讀時間: 18 分鐘


前沿信號:工具調用為 AI SDK 工具執行的核心安全機制

在 2026 年,AI Agent 的能力邊界正在從「能回答什麼」轉向「能做什麼」。Tool calling(工具調用)已成為 AI SDK 的核心能力——當模型被賦予工具調用能力時,它不再只是文本生成器,而是可以執行實際操作的代理。

核心問題:當 AI SDK 的 generateTextstreamText 支援工具調用時,我們如何確保工具執行既靈活又安全?


工具執行許可工作流程:核心概念

1.1 許可流程的基本模型

AI SDK 的工具執行許可流程不是簡單的「是/否」判斷,而是一個兩階段協議

// 階段 1:請求生成
const result = await generateText({
  model: "anthropic/claude-sonnet-4.5",
  tools: {
    runCommand: tool({
      description: 'Run a shell command',
      inputSchema: z.object({ command: z.string() }),
      needsApproval: true,
      execute: async ({ command }) => {
        // 實際執行邏輯(此時不會執行)
        return { result: `Executed: ${command}` };
      },
    }),
  },
  prompt: 'Delete the most recent file',
});

// 階段 2:獲取使用者決策
const approvals: ToolApprovalResponse[] = [];
for (const part of result.content) {
  if (part.type === 'tool-approval-request') {
    const response: ToolApprovalResponse = {
      type: 'tool-approval-response',
      approvalId: part.approvalId,
      approved: userDecision, // true 或 false
      reason: 'User confirmed the command',
    };
    approvals.push(response);
  }
}

// 階段 3:提交決策並重新執行
messages.push({ role: 'tool', content: approvals });
const finalResult = await generateText({
  model: "anthropic/claude-sonnet-4.5",
  tools: { runCommand },
  messages,
});

1.2 許可流程的三個關鍵組件

組件 說明 生產級要求
needsApproval 標記需要使用者批准的工具 所有敏感操作必須設為 true
tool-approval-request 系統返回的批准請求格式 包含 approvalId, toolCall 元數據
tool-approval-response 使用者提交的決策格式 approvalId, approved, reason(可選)

生產級實現模式

模式 A:基於金額的自動許可

適用場景:小額交易、非敏感操作

const paymentTool = tool({
  description: 'Process a payment',
  inputSchema: z.object({
    amount: z.number(),
    recipient: z.string(),
  }),
  needsApproval: async ({ amount }) => amount > 1000, // 只有大額交易需要批准
  execute: async ({ amount, recipient }) => {
    return await processPayment(amount, recipient);
  },
});

可測量指標

  • 自動執行率:>95%(金額 < $1000)
  • 批准請求響應時間:< 3 秒
  • 誤拒率:< 0.1%

模式 B:基於上下文的動態許可

適用場景:需要上下文感知的批准決策

const sensitiveTool = tool({
  description: 'Modify production configuration',
  inputSchema: z.object({
    configPath: z.string(),
    changes: z.any(),
  }),
  needsApproval: async ({ configPath }) => {
    // 檢查配置路徑是否為生產環境
    return configPath.includes('/production/') || 
           configPath.includes('prod.');
  },
  execute: async ({ configPath, changes }) => {
    // 實際修改邏輯
    return await updateConfig(configPath, changes);
  },
});

可測量指標

  • 動態許可準確率:>98%(基於預訓練的配置模式分類器)
  • 假陽性率:< 1%(允許的敏感操作不被拒絕)
  • 假陰性率:< 0.1%(危險操作未被攔截)

模式 C:多步調用的批准流

適用場景:需要多次工具調用的複雜任務

const multiStepTool = tool({
  description: 'Deploy application',
  inputSchema: z.object({
    appName: z.string(),
    environment: z.string(),
  }),
  needsApproval: true, // 始終需要批准
  execute: async ({ appName, environment }) => {
    // 階段 1:構建檢查
    const buildCheck = await buildCheck(appName);
    if (!buildCheck.passed) return { error: 'Build check failed' };
    
    // 階段 2:部署檢查
    const deployCheck = await deployCheck(environment);
    if (!deployCheck.passed) return { error: 'Deploy check failed' };
    
    // 階段 3:執行部署
    return await deploy(appName, environment);
  },
});

// 使用 stopWhen 控製多步調用
const result = await generateText({
  model: "anthropic/claude-sonnet-4.5",
  tools: { multiStepTool },
  prompt: 'Deploy the app to production',
  stopWhen: stepCountIs(3), // 最多 3 步
});

可測量指標

  • 多步調用成功率:>99.9%(無人干預)
  • 批批准響應時間:< 5 秒(平均)
  • 錯誤恢復率:>95%(自動重試失敗步驟)

安全邊界設計

2.1 工具選擇控制

const strictTool = tool({
  description: 'Get weather for a location',
  inputSchema: z.object({
    location: z.string(),
  }),
  strict: true, // 使用嚴格模式
  execute: async ({ location }) => {
    return { temperature: 72 + Math.floor(Math.random() * 21) - 10 };
  },
});

const result = await generateText({
  model: "anthropic/claude-sonnet-4.5",
  tools: { strictTool },
  toolChoice: 'required', // 強制模型調用工具
  prompt: 'What is the weather in San Francisco?',
});

嚴格模式特點

  • 模型只能生成符合 inputSchema 的工具調用
  • 減少錯誤調用和越界輸入
  • 增加執行可靠性,但可能降低靈活性

2.2 輸入範例指導

const weatherTool = tool({
  description: 'Get the weather in a location',
  inputSchema: z.object({
    location: z.string().describe('The location to get the weather for'),
  }),
  inputExamples: [
    { input: { location: 'San Francisco' } },
    { input: { location: 'London' } },
  ],
  execute: async ({ location }) => {
    return { temperature: 72 + Math.floor(Math.random() * 21) - 10 };
  },
});

輸入範例的作用

  • 幫助模型理解複雜輸入結構
  • 減少模型生成的格式錯誤
  • 提高工具調用的準確率

許可流程的監控與可觀察性

3.1 許可請求追蹤

const approvals: ToolApprovalRequest[] = [];
for (const part of result.content) {
  if (part.type === 'tool-approval-request') {
    console.log(`[Approval #${part.approvalId}]`);
    console.log(`Tool: ${part.toolCall.toolName}`);
    console.log(`Input: ${JSON.stringify(part.toolCall.input)}`);
    approvals.push(part);
  }
}

監控指標

  • 總請求數:每小時工具許可請求總數
  • 拒絕率:被拒絕的請求比例
  • 平均響應時間:從請求到決策的時間
  • 按工具類型的分佈:哪些工具被調用最多

3.2 許可決策審計

const auditLog = {
  timestamp: new Date().toISOString(),
  approvalId: approvalId,
  toolName: toolCall.toolName,
  approved: approved,
  reason: reason,
  userId: userId,
  context: {
    prompt: prompt,
    messages: messages,
  },
};
await logAudit(auditLog);

生產級要求

  • 所有許可決策必須可審計
  • 审计日志保留至少 90 天
  • 支持按時間、工具、使用者查詢

部署場景與衡量指標

4.1 部署場景:內容管道

場景描述

  • AI Agent 需要生成並發布內容(文章、視頻、圖片)
  • 每篇文章需要經過多個工具調用:草稿生成 → 格式化 → 審核 → 發布

實現方案

const contentPipeline = {
  draftTool: tool({
    description: 'Generate article draft',
    inputSchema: z.object({ topic: z.string() }),
    needsApproval: true,
    execute: async ({ topic }) => {
      return await generateDraft(topic);
    },
  }),
  formatTool: tool({
    description: 'Format article',
    inputSchema: z.object({ content: z.string() }),
    needsApproval: true,
    execute: async ({ content }) => {
      return await formatContent(content);
    },
  }),
  publishTool: tool({
    description: 'Publish article',
    inputSchema: z.object({ articleId: z.string() }),
    needsApproval: true,
    execute: async ({ articleId }) => {
      return await publishArticle(articleId);
    },
  }),
};

// 使用 multi-step 調用
const result = await generateText({
  model: "anthropic/claude-sonnet-4.5",
  tools: contentPipeline,
  prompt: 'Generate and publish an article about AI',
  stopWhen: stepCountIs(3),
});

可測量指標

  • 端到端處理時間:< 30 秒(從草稿到發布)
  • 許可批准率:>99%(所有許可請求被批准)
  • 內容質量得分:>85(人工評估)
  • 人工審核介入率:< 5%(需要手動審核的文章比例)

4.2 部署場景:客戶支持自動化

場景描述

  • AI Agent 需要處理用戶查詢、查詢訂單、發送確認郵件
  • 每個操作需要使用者批准敏感操作(發送郵件、修改訂單)

實現方案

const customerSupport = {
  queryTool: tool({
    description: 'Query customer information',
    inputSchema: z.object({ customerId: z.string() }),
    needsApproval: false, // 低敏感度操作,自動執行
    execute: async ({ customerId }) => {
      return await queryCustomer(customerId);
    },
  }),
  updateOrderTool: tool({
    description: 'Update customer order',
    inputSchema: z.object({
      orderId: z.string(),
      changes: z.any(),
    }),
    needsApproval: true, // 高敏感度操作,需要批准
    execute: async ({ orderId, changes }) => {
      return await updateOrder(orderId, changes);
    },
  }),
  sendEmailTool: tool({
    description: 'Send email to customer',
    inputSchema: z.object({
      email: z.string(),
      message: z.string(),
    }),
    needsApproval: true,
    execute: async ({ email, message }) => {
      return await sendEmail(email, message);
    },
  }),
};

// 使用 useChat 的 UI 狀態處理
const messages = [
  { role: 'user', content: 'Query order #12345' },
];
const response = await useChat({
  model: "anthropic/claude-sonnet-4.5",
  tools: customerSupport,
  messages,
});

// 添加批准響應
messages.push(...response.messages);
for (const part of response.content) {
  if (part.type === 'tool-approval-request') {
    messages.push({
      role: 'tool',
      content: [{ 
        type: 'tool-approval-response',
        approvalId: part.approvalId,
        approved: userDecision,
        reason: 'User confirmed the update',
      }],
    });
  }
}

可測量指標

  • 平均響應時間:< 5 秒(從用戶查詢到回覆)
  • 許可批准率:>98%
  • 人工介入率:< 1%
  • 準確率:>95%(正確回覆用戶查詢)

構建與維護

5.1 安全分層架構

┌─────────────────────────────────────┐
│  Layer 1: 模型層(Intent Detection)     │
│  - 意圖分類(敏感 vs 非敏感)             │
│  - 上下文檢查(授權範圍變化)              │
└─────────────────────────────────────┘
            ↓
┌─────────────────────────────────────┐
│  Layer 2: 許可層(Approval Workflow)    │
│  - needsApproval 標記                  │
│  - tool-approval-request/response           │
│  - 動態許可邏輯                         │
└─────────────────────────────────────┘
            ↓
┌─────────────────────────────────────┐
│  Layer 3: 執行層(Execution Sandbox)       │
│  - 工具白名單                           │
│  - 資源限制(CPU、時間、內存)           │
│  - 執行監控與終止                       │
└─────────────────────────────────────┘

生產級要求

  • 每層都有可測量的監控點
  • 分層防護:即使一層失效,其他層仍可保護
  • 滑動防護:允許升級,但不允許降級

5.2 常見陷阱與避免策略

陷阱 說明 避免策略
過度使用 needsApproval 所有工具都標記為需要批准,增加開銷 根據操作敏感度分層設置
忽略 tool-approval-request 格式 錯誤解析許可請求格式 使用 AI SDK 提供的類型定義
不處理拒絕決策 模型收到拒絕後仍嘗試重試 添加「拒絕後不重試」的系統指令
缺少審計日誌 沒有記錄許可決策 所有決策必須寫入審計日誌

比較:AI SDK vs LangChain 工具調用

5.3 架構差異

特性 AI SDK (Vercel) LangChain
許可流程 內置 needsApproval + tool-approval-request/response 需要自實現
動態許可 needsApproval: async ({ amount }) 支援 需要額外邏輯
多步調用 stopWhen 內置 AgentExecutor 需要
類型安全 Zod schema 自動生成類型 需要手動定義
UI 集成 useChat 內置許可 UI 狀態 需要自實現

總結:生產級工具執行安全的三大原則

  1. 分層防護:模型層 + 許可層 + 執行層,每層都有獨立的監控點
  2. 可測量決策:所有許可請求都有可測量的響應時間和批准率
  3. 可審計追蹤:所有許可決策必須可審計,保留至少 90 天

實踐建議

  • 從「自動執行 + 少數敏感操作批准」開始
  • 隨著系統成熟,逐步增加 needsApproval 的工具數量
  • 使用監控指標優化許可策略:自動執行率 >95%,批准響應時間 <3秒

參考文檔