SDK 教學 · 8 / 10

處理核准流程

Approval 是產品 policy boundary,不只是一個 confirmation dialog。Heddle 路由 gated call 並記錄 decision;產品端則知道 user、tenant、trust model 與真實 side effects。

客製化深度

層級 4 · 產品端政策

託管深度

Process 內 callback 或 hosted approval lifecycle

文件狀態

支援的 SDK 邊界

前置假設

  • 至少一個 tool 或 policy 可能在執行前要求 decision。
  • Host 能辨識 authenticated approver 與即將變更的 product resource。
  • 無法提供 decision surface 時,產品有明確的 deny behavior。
Heddle 負責
  • 評估設定好的 policy chain,並把需要決策的 request 路由到 host callback。
  • 在 turn lifecycle 與 trace 中記錄 approval-requested 和 approval-resolved activity。
  • 當 approval-gated call 沒有設定 handler 時拒絕執行。
產品端負責
  • 驗證 approver 身分、授權 target action,並呈現 decision context。
  • 根據產品資料與 trust model 定義 allow、deny 與 request policies。
  • 當 user 或 tenant 永遠不該使用某 capability 時,直接讓它不可見。

標記需要決策的 tool

TypeScript
import type { ToolDefinition } from '@roackb2/heddle'

const publishRecord: ToolDefinition = {
  name: 'publish_record',
  description: 'Publish a reviewed product record.',
  requiresApproval: true,
  parameters: {
    type: 'object',
    properties: {
      recordId: { type: 'string' },
    },
    required: ['recordId'],
    additionalProperties: false,
  },
  execute: async (input) => publishAuthorizedRecord(input),
}

requiresApproval 會要求 default policy chain 向 host 取得 decision。它不會取代 publishAuthorizedRecord 內的 authorization。

此範例刻意省略 application-defined capability tag。若要加入,host policy 必須明確解讀它;built-in read-only profile 只理解 Heddle 文件列出的 capability vocabulary。

提供 approval surface

TypeScript
import type { ConversationEngineHost } from '@roackb2/heddle'

const host: ConversationEngineHost = {
  approvals: {
    async requestToolApproval(request) {
      const allowed = await productPolicy.canApprove({
        authenticatedUser,
        tool: request.call.tool,
        input: request.call.input,
      })

      if (!allowed) {
        return {
          approved: false,
          reason: 'The current user cannot approve this action.',
        }
      }

      return {
        approved: true,
        reason: 'Approved through product policy.',
      }
    },
  },
}

const result = await engine.turns.submit({
  sessionId,
  prompt,
  host,
})

Callback 會收到 requested call 與已註冊的 tool definition。請回傳 boolean decision 與 operator 可理解的 reason。不要在 reason 中暴露 credential 或敏感的 internal policy diagnostics。

理解 policy resolution

ToolApprovalPolicy 可以 allow、deny、request human decision 或 abstain。Policy 會依宣告順序執行;第一個具決定性的 allowdeny 會結束判斷。request 會先被記住並繼續評估後續 policy;只有後面沒有 policy 做出具決定性的判斷時,才會進入設定的 approval surface。若最後仍需要 request 但沒有 handler,Heddle 會 deny;若所有 policy 都 abstain,則直接執行。

用 tool profile 與 capability filter 移除永遠不該被看見的 tools;用 approval policy 處理依 context 變化的 decisions;最後在 domain operation 內再次執行產品 authorization。

遠端核准流程

上面的 callback 可以等待 process 內的 product decision。若 browser 可能在 approval pending 時中斷,請使用 hosted run service 的 pending-approval lifecycle,不要在 route layer 另存一個彼此無關的 promise 或 event bus。

驗證兩條路徑

用 deterministic policy input 測試 approve 與 deny。確認 denied call 不會執行、兩種 decision 都出現在 trace/activity,且 gated call 缺少 handler 時會 fail closed。

權威來源