跳到主要内容
非官方简体中文翻译,内容版权归 Mastra 所有,遵循 Apache-2.0 许可。

Human-in-the-loop

当 agents 调用处理敏感操作的工具(例如删除资源或运行长时间进程)时,有时需要与 workflows 相同的 human-in-the-loop (HITL) 监督机制。借助 human-in-the-loop,你可以在工具调用执行前将其挂起,以便人工批准或拒绝;也可以让工具自行挂起,以向用户请求额外上下文。

何时使用 human-in-the-loop
何时使用 human-in-the-loop的直接链接

  • 破坏性或不可逆的操作,例如删除记录或发送电子邮件,或者处理付款。
  • 成本高昂的操作,例如调用昂贵的第三方 API,你希望先验证参数。
  • 条件确认,即工具开始执行后才发现需要用户确认或提供额外数据才能完成。

快速开始
快速开始的直接链接

为工具标记 requireApproval: true,然后在流中检查 tool-call-approval 片段,以批准或拒绝该操作:

src/mastra/agents/index.ts
import { Agent } from '@mastra/core/agent'
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

const deleteTool = createTool({
id: 'delete-record',
description: 'Delete a record by ID',
inputSchema: z.object({ id: z.string() }),
outputSchema: z.object({ deleted: z.boolean() }),
requireApproval: true,
execute: async ({ id }) => {
await db.delete(id)
return { deleted: true }
},
})

const agent = new Agent({
id: 'my-agent',
name: 'My Agent',
model: 'openai/gpt-5-mini',
tools: { deleteTool },
})

const stream = await agent.stream('Delete record abc-123')

for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-approval') {
const approved = await agent.approveToolCall({ runId: stream.runId })
for await (const c of approved.textStream) process.stdout.write(c)
}
}
备注

Human-in-the-loop 使用快照来捕获请求状态。请在你的 Mastra 实例上配置存储提供器,否则你会看到 "snapshot not found" 错误。

Agent 运行的快照是精简的恢复产物:它们只保存恢复挂起运行所需的内容,并在运行结束后删除。执行记录请使用链路追踪,对话历史请使用记忆。

审批如何工作
审批如何工作的直接链接

Mastra 提供两种不同的机制来暂停工具调用:执行前审批和运行时挂起。

执行前审批
执行前审批的直接链接

执行前审批在工具的 execute 函数运行之前暂停工具调用。LLM 仍然决定调用哪个工具并提供参数,但 execute 只有在你明确批准后才会运行。

以下标志通过 OR 逻辑组合控制此行为。只要任意一个为 true,调用就会暂停:

标志设置位置作用域
requireToolApproval: truestream() / generate() 选项暂停该请求的每一次工具调用
requireApproval: truecreateTool() 定义暂停对该特定工具的调用

流会发出一个 tool-call-approval 片段,包含 toolCallId、toolName 和 args。使用流的 runId 调用 approveToolCall() 或 declineToolCall() 以继续:

const stream = await agent.stream("What's the weather in London?", {
requireToolApproval: true,
})

for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-approval') {
console.log('Tool:', chunk.payload.toolName)
console.log('Args:', chunk.payload.args)

// Approve
const approved = await agent.approveToolCall({ runId: stream.runId })
for await (const c of approved.textStream) process.stdout.write(c)

// Or decline
const declined = await agent.declineToolCall({ runId: stream.runId })
for await (const c of declined.textStream) process.stdout.write(c)
}
}

解释拒绝原因
解释拒绝原因的直接链接

declineToolCall()、declineToolCallGenerate() 和 declineNetworkToolCall() 接受一个可选的 reason。该原因会代替工具结果返回给模型,使模型可以调整策略,而不是盲目重试。它还会存储在工具调用的 approval 元数据中,因此对话被召回时仍然存在。

const declined = await agent.declineToolCall({
runId: stream.runId,
toolCallId,
reason: 'Reading other users PII is not allowed, ask the user for their own email instead',
})

如果不提供 reason,模型会收到默认消息 Tool call was not approved by the user。

使用函数进行条件审批
使用函数进行条件审批的直接链接

requireToolApproval 也可以接受一个函数而不是布尔值,该函数会针对每次工具调用做出决定。它接收 toolName、模型传入的 args、requestContext 和 workspace。返回 true 表示该调用需要审批,返回 false 表示允许。这样你就可以在运行时控制审批,例如仅对名称匹配某个模式的工具要求审批:

const stream = await agent.stream('Clean up old records', {
requireToolApproval: ({ toolName }) => /^delete_/.test(toolName),
})

该函数可以是异步的。对于依赖工具名称和参数的决定,可以使用 classifier 来估计调用是否需要人工审核:

src/mastra/agents/run-with-approval.ts
import { Classifier } from '@mastra/core/classifier'
import { typeSafeAi } from '@ai-sdk/typesafe-ai'
import { agent } from './agent'

const approvalClassifier = new Classifier({
id: 'tool-approval-classifier',
model: typeSafeAi.decisionModel('jev-latest'),
questions: {
requiresApproval: {
type: 'boolean',
instructions:
'Does this tool call need human approval because it is destructive, irreversible, expensive, or handles sensitive data?',
},
},
})

const stream = await agent.stream('Clean up old records', {
requireToolApproval: async ({ toolName, args }) => {
const result = await approvalClassifier.decide({
state: {
toolName,
argumentNames: Object.keys(args),
},
})

// A refused question has no probability, so it falls back to requiring approval.
return (result.answers.requiresApproval.probability ?? 1) >= 0.7
},
})

该示例发送的是参数名而不是参数值,因为 classifier 会将其状态转发给配置的决策模型。如果决策需要参数值,请先脱敏敏感数据,或使用满足受保护工具数据处理要求的决策模型和提供器。

返回 true 会暂停工具调用以等待人工审批,它不会自动批准或拒绝调用。请选择与 agent 可用工具的风险相匹配的阈值。如果该 requireToolApproval 函数抛出异常,则默认要求审批。

随后运行时会将此结果与工具的 requireApproval 设置组合。布尔值 true 表示要求审批,而 false 不会禁用由 requireToolApproval 要求的审批。工具级别的 requireApproval 函数具有权威性,会替换该工具的组合结果。

备注

基于函数的 requireToolApproval 仅适用于常规的 stream() / generate() 调用。持久化 agents 和存储型 agents 会持久化其选项,而函数无法序列化,因此它们只接受布尔值。如果在这些上下文中传入函数,则回退为对每次工具调用都要求审批。

将审批绑定到确切的工具参数
将审批绑定到确切的工具参数的直接链接

对于敏感工具,请将审批绑定到展示给审核者的确切工具名称和参数。如果这些参数在执行前发生变化,工具就不应在旧审批下运行。

tool-call-approval 片段已经包含 toolName、toolCallId 和 args。你可以在展示审批请求时对这些字段进行指纹计算。下面的示例使用 JSON 字符串作为指纹,但在生产环境中,你应该使用工具名称和参数的稳定哈希:

src/mastra/agents/approval-bound-agent.ts
import { Agent } from '@mastra/core/agent'

// For your production usecase, build a stable hash of the tool name and args
function actionFingerprint(toolName: string, args: unknown) {
const payload = JSON.stringify({ toolName, args })
return `fingerprint-${payload}`
}

const sensitiveTools = new Set(['issue_refund', 'delete_record'])
const approvedFingerprints = new Set<string>()

export const approvalBoundAgent = new Agent({
id: 'approval-bound-agent',
name: 'Approval Bound Agent',
model: 'openai/gpt-5.6-sol',
tools: { issueRefundTool, deleteRecordTool },
hooks: {
beforeToolCall: ({ toolName, input }) => {
if (!sensitiveTools.has(toolName)) return

const fingerprint = actionFingerprint(toolName, input)
if (!approvedFingerprints.delete(fingerprint)) {
return {
proceed: false,
output: `Tool call blocked: approval did not match ${toolName} arguments.`,
}
}
},
},
})
const stream = await approvalBoundAgent.stream('Refund order ord-1042', {
requireToolApproval: ({ toolName }) => sensitiveTools.has(toolName),
})

async function consumeApprovalStream(currentStream: typeof stream) {
for await (const chunk of currentStream.fullStream) {
if (chunk.type === 'tool-call-approval') {
const { toolName, toolCallId, args } = chunk.payload
const fingerprint = actionFingerprint(toolName, args)

// Present toolName, args, and fingerprint to your approval UI.
const approved = await showApprovalDialog({ toolName, args, fingerprint })

const nextStream = approved
? await approveReviewedToolCall(currentStream.runId, toolCallId, fingerprint)
: await approvalBoundAgent.declineToolCall({ runId: currentStream.runId, toolCallId })

await consumeApprovalStream(nextStream)
}
}
}

async function approveReviewedToolCall(runId: string, toolCallId: string, fingerprint: string) {
approvedFingerprints.add(fingerprint)
return approvalBoundAgent.approveToolCall({ runId, toolCallId })
}

await consumeApprovalStream(stream)

在生产环境中,请将批准的指纹存储到持久化存储中,并按用户、运行、工具调用和策略版本划分作用域。上面的 Set 有意保持简单,以便边界清晰:审批只会被消费一次,且仅针对经过审核的相同的规范化工具参数。

使用 suspend() 进行运行时挂起
使用-suspend-进行运行时挂起的直接链接

工具也可以在其 execute 函数执行期间调用 suspend() 来暂停。当工具开始运行后才发现需要额外的用户输入或确认才能完成时,这很有用。

流会发出一个 tool-call-suspended 片段,其自定义 payload 由工具的 suspendSchema 定义。你可以调用 resumeStream() 并提供匹配工具 resumeSchema 的数据来恢复。

const weatherTool = createTool({
id: 'get-weather',
inputSchema: z.object({
location: z.string().optional(),
}),
suspendSchema: z.object({
question: z.string(),
}),
resumeSchema: z.object({
location: z.string(),
}),
execute: async ({ location }, context) => {
if (!location) {
return await context?.agent?.suspend({
question: 'Which city would you like the weather for?',
})
}
return await fetchWeather(location)
},
})
备注

suspend() 不会抛出异常,请在调用后立即返回(例如 return await suspend({ ... }))。await suspend(...) 之后的代码仍会在工具暂停前运行。

当工具需要用户提供结构化答案,并且还会在 subagent 中运行时,请使用 suspend() 而不是没有 execute 的工具:subagents 无法运行客户端工具,但挂起状态会通过 supervisor 传播。要从 AI SDK 的 useChat() 恢复,请参阅从 useChat() 恢复挂起的工具。

使用 generate() 进行工具审批
使用-generate-进行工具审批的直接链接

工具审批也适用于非流式场景的 generate()。当工具需要审批时,generate() 会立即返回,带有 finishReason: 'suspended'、包含工具调用详情(toolCallId、toolName、args)的 suspendPayload,以及 runId:

const output = await agent.generate('Find user John', {
requireToolApproval: true,
})

if (output.finishReason === 'suspended') {
console.log('Tool requires approval:', output.suspendPayload.toolName)

// Approve
const result = await agent.approveToolCallGenerate({
runId: output.runId,
toolCallId: output.suspendPayload.toolCallId,
})
console.log('Final result:', result.text)

// Or decline
const result = await agent.declineToolCallGenerate({
runId: output.runId,
toolCallId: output.suspendPayload.toolCallId,
})
}

stream 与 generate 对比
stream 与 generate 对比的直接链接

方面stream()generate()
响应类型流式片段完整响应
审批检测tool-call-approval 片段finishReason: 'suspended'
批准方法approveToolCall({ runId })approveToolCallGenerate({ runId, toolCallId })
拒绝方法declineToolCall({ runId })declineToolCallGenerate({ runId, toolCallId })
结果可迭代的流完整输出对象
备注

toolCallId 在所有四个方法中都是可选的。当可能有多个工具调用待处理时(在 supervisor agents 中很常见),请传入它。省略时,agent 会恢复最近挂起的工具调用。

工具级审批
工具级审批的直接链接

除了在 agent 级别暂停每次工具调用,你还可以将单个工具标记为需要审批。这样你就能获得细粒度控制:只有特定工具会暂停,其他工具则立即执行。

使用 requireApproval 审批
使用-requireapproval-审批的直接链接

在工具定义上设置 requireApproval: true。无论 agent 上是否设置了 requireToolApproval,该工具都会在执行前暂停:

src/mastra/tools/test-tool.ts
export const testTool = createTool({
id: 'test-tool',
description: 'Fetches weather for a location',
inputSchema: z.object({
location: z.string(),
}),
outputSchema: z.object({
weather: z.string(),
}),
resumeSchema: z.object({
approved: z.boolean(),
}),
execute: async inputData => {
const response = await fetch(`https://wttr.in/${inputData.location}?format=3`)
const weather = await response.text()

return { weather }
},
requireApproval: true,
})

当 requireApproval 为 true 时,流会以与 agent 级审批相同的方式发出 tool-call-approval 片段。使用 approveToolCall() 或 declineToolCall() 继续:

const stream = await agent.stream("What's the weather in London?")

for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-approval') {
console.log('Approval required for:', chunk.payload.toolName)
}
}

const handleApproval = async () => {
const approvedStream = await agent.approveToolCall({ runId: stream.runId })

for await (const chunk of approvedStream.textStream) {
process.stdout.write(chunk)
}
process.stdout.write('\n')
}

使用 suspend() 审批
使用-suspend-审批的直接链接

使用这种方法时,agent 和工具都不使用 requireApproval。相反,工具的 execute 函数调用 suspend() 在特定位置暂停,并向用户返回上下文或确认提示。当审批取决于运行时条件而不是无条件要求时,这很有用。

src/mastra/tools/test-tool-b.ts
export const testToolB = createTool({
id: 'test-tool-b',
description: 'Fetches weather for a location',
inputSchema: z.object({
location: z.string(),
}),
outputSchema: z.object({
weather: z.string(),
}),
resumeSchema: z.object({
approved: z.boolean(),
}),
suspendSchema: z.object({
reason: z.string(),
}),
execute: async (inputData, context) => {
const { resumeData: { approved } = {}, suspend } = context?.agent ?? {}

if (!approved) {
return suspend?.({ reason: 'Approval required.' })
}

const response = await fetch(`https://wttr.in/${inputData.location}?format=3`)
const weather = await response.text()

return { weather }
},
})

使用这种方法时,流中会包含一个 tool-call-suspended 片段,suspendPayload 包含工具 suspendSchema 定义的 reason。使用 resumeSchema 数据和 runId 调用 resumeStream 以继续:

const stream = await agent.stream("What's the weather in London?")

for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-suspended') {
console.log(chunk.payload.suspendPayload)
}
}

const handleResume = async () => {
const resumedStream = await agent.resumeStream({ approved: true }, { runId: stream.runId })

for await (const chunk of resumedStream.textStream) {
process.stdout.write(chunk)
}
process.stdout.write('\n')
}

当挂起的或需要审批的工具调用恢复时,流会在该调用的 tool-result 之前发出一个具有相同 toolCallId 的 tool-call-resumed 片段。其 payload.kind 为 'suspension' 或 'approval',payload 会重复原始的 args、suspendPayload 和 resumeSchema。仅当真实的挂起或审批请求被清除时,才会发出该片段。

使用 @mastra/ai-sdk 时,它会以 data-tool-call-suspended 部分(审批则为 data-tool-call-approval 部分)到达,并带有 resumed: true,这会替换原始部分并保留其 payload。使用此信号将问题标记为已回答。不要从工具输出的形状推断这一点:当挂起来自 sub-agent 时,委派调用的输出是 sub-agent 的结果,而不是你的答案。

自动恢复工具
自动恢复工具的直接链接

使用调用 suspend() 的工具时,你可以启用自动恢复,让 agent 根据用户的下一条消息恢复挂起的工具。在 agent 的默认选项中或每次请求时设置 autoResumeSuspendedTools 为 true:

src/mastra/agents/my-agent.ts
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'

const agent = new Agent({
id: 'my-agent',
name: 'My Agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5-mini',
tools: { weatherTool },
memory: new Memory(),
defaultOptions: {
autoResumeSuspendedTools: true,
},
})

启用后,agent 会在下一条用户消息时从消息历史中检测挂起的工具。它会根据工具的 resumeSchema 提取 resumeData,然后自动恢复工具。

自动恢复适用于携带数据的 suspend() 流程。它不会批准使用 requireApproval 的工具;这些工具会保持挂起,直到通过 approveToolCall()、declineToolCall()、resumeStream({ approved: boolean }) 或等效的 UI 或 API 操作提交明确的批准或拒绝。

以下示例展示了一个完整的对话流程:

src/mastra/tools/weather-tool.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

const weatherTool = createTool({
id: 'weather-tool',
description: 'Fetches weather for a city',
inputSchema: z.object({
city: z.string(),
}),
outputSchema: z.object({
weather: z.string(),
}),
suspendSchema: z.object({
message: z.string(),
}),
resumeSchema: z.object({
city: z.string(),
}),
execute: async (inputData, context) => {
const { resumeData, suspend } = context?.agent ?? {}

// If no city provided, ask the user
if (!inputData.city && !resumeData?.city) {
return suspend?.({ message: 'What city do you want to know the weather for?' })
}

const city = resumeData?.city ?? inputData.city
const response = await fetch(`https://wttr.in/${city}?format=3`)
const weather = await response.text()

return { weather: `${city}: ${weather}` }
},
})
const stream = await agent.stream("What's the weather like?")

for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-suspended') {
console.log(chunk.payload.suspendPayload)
}
}

// User sends follow-up on the same thread
const resumedStream = await agent.stream('San Francisco')
for await (const chunk of resumedStream.textStream) {
process.stdout.write(chunk)
}
Console output
User: "What's the weather like?"
Agent: "What city do you want to know the weather for?"

User: "San Francisco"
Agent: "The weather in San Francisco is: San Francisco: ☀️ +72°F"

第二条消息会自动恢复挂起的工具。agent 会从用户消息中提取 { city: "San Francisco" } 并将其作为 resumeData 传入。

要求
要求的直接链接

要使自动工具恢复正常工作:

  • 已配置 memory:agent 需要 memory 来跨消息跟踪挂起的工具
  • 同一 thread:后续消息必须使用相同的 memory thread 和 resource 标识符
  • 已定义 resumeSchema:工具必须定义 resumeSchema,以便 agent 知道要从用户消息中提取什么数据结构

手动与自动恢复
手动与自动恢复的直接链接

方式使用场景
手动(resumeStream())编程控制、webhooks、按钮点击、外部触发
自动(autoResumeSuspendedTools)用户以自然语言提供恢复数据的对话式流程

两种方式都适用于相同的工具定义。自动恢复仅在消息历史中存在挂起的工具且用户在同一 thread 上发送新消息时触发。

重启后恢复
重启后恢复的直接链接

上面的示例在挂起和审批之间一直持有 stream.runId。这在进程保持存活时有效,但在生产环境中,审批往往来得更晚,例如页面刷新、服务器重启之后,或者位于负载均衡器后面的不同服务器实例上。

使用 listSuspendedRuns() 从存储中重新发现某个对话的待处理运行:

// In the request handler that receives the user's decision
const { runs } = await agent.listSuspendedRuns({
threadId: 'thread-123',
resourceId: 'user-456',
})

const run = runs[0]
const toolCall = run?.toolCalls[0]

if (run && toolCall) {
let stream
if (toolCall.requiresApproval) {
// Suspended by requireApproval — approve or decline the tool call
stream = await agent.approveToolCall({ runId: run.runId, toolCallId: toolCall.toolCallId })
} else {
// Suspended by suspend() — resume with the data the tool asked for
console.log('Tool asked:', toolCall.suspendPayload)
stream = await agent.resumeStream({ name: 'San Francisco' }, { runId: run.runId })
}
for await (const chunk of stream.textStream) process.stdout.write(chunk)
}

每个返回的运行都包含挂起的工具调用(toolCallId、toolName、args 和 requiresApproval)。审批挂起(requiresApproval: true)通过 approveToolCall() / declineToolCall() 应答,而基于 suspend() 的挂起带有其 suspendPayload,并期望使用恢复数据调用 resumeStream(),因此你可以为任一流程重建正确的 UI,而无需在内存中保留任何状态。

sendToolApproval() 会自动使用相同的基于存储的发现机制。如果 memory 中该 thread 没有活动运行,它会在失败前搜索存储中的挂起运行。当多个挂起的运行匹配该 thread 时,请传入 toolCallId。

相同的发现机制也通过 HTTP 以 GET /agents/:agentId/suspended-runs 提供,在客户端 SDK 中为 agent.listSuspendedRuns(),因此基于浏览器的审批 UI 可以直接重新发现待处理的运行。

备注

只有当你的 Mastra 实例配置了持久化存储提供器时,挂起的运行才能在重启后存活。默认的内存存储会在进程退出时丢失快照。

工具审批:Supervisor agents
工具审批:Supervisor agents的直接链接

supervisor agent 使用 .stream() 或 .generate() 协调多个 subagents。当 subagent 调用需要审批的工具时,请求会通过委派链向上传播,并在 supervisor 层出现:

  1. supervisor 将任务委派给 subagent。
  2. subagent 调用具有 requireApproval: true 或使用 suspend() 的工具。
  3. 审批请求冒泡到 supervisor。
  4. 你在 supervisor 层批准或拒绝。
  5. 决定向下传播回 subagent。

工具审批也会通过多层委派传播。如果 supervisor 委派给 subagent A,A 又委派给拥有 requireApproval: true 工具的 subagent B,审批请求仍会出现在顶层 supervisor。

在 supervisor agents 中批准和拒绝
在 supervisor agents 中批准和拒绝的直接链接

下面的示例创建了一个带有需要审批工具的 subagent。当工具触发审批请求时,它会在 supervisor 的流中作为 tool-call-approval 片段出现:

import { Agent } from '@mastra/core/agent'
import { createTool } from '@mastra/core/tools'
import { Memory } from '@mastra/memory'
import { z } from 'zod'

const findUserTool = createTool({
id: 'find-user',
description: 'Finds user by ID in the database',
inputSchema: z.object({
userId: z.string(),
}),
outputSchema: z.object({
user: z.object({
id: z.string(),
name: z.string(),
email: z.string(),
}),
}),
requireApproval: true,
execute: async input => {
const user = await database.findUser(input.userId)
return { user }
},
})

const dataAgent = new Agent({
id: 'data-agent',
name: 'Data Agent',
description: 'Handles database queries and user data retrieval',
model: 'openai/gpt-5-mini',
tools: { findUserTool },
})

const supervisorAgent = new Agent({
id: 'supervisor',
name: 'Supervisor Agent',
instructions: `You coordinate data retrieval tasks.
Delegate to data-agent for user lookups.`,
model: 'openai/gpt-5.6-sol',
agents: { dataAgent },
memory: new Memory(),
})

const stream = await supervisorAgent.stream('Find user with ID 12345')

for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-approval') {
console.log('Tool requires approval:', chunk.payload.toolName)
console.log('Arguments:', chunk.payload.args)

// Approve the tool call
const resumeStream = await supervisorAgent.approveToolCall({
runId: stream.runId,
toolCallId: chunk.payload.toolCallId,
})

for await (const resumeChunk of resumeStream.textStream) {
process.stdout.write(resumeChunk)
}

// To decline instead, use:
const declineStream = await supervisorAgent.declineToolCall({
runId: stream.runId,
toolCallId: chunk.payload.toolCallId,
})
}
}

在 supervisor agents 中使用 suspend()
在-supervisor-agents-中使用-suspend的直接链接

工具也可以使用 suspend() 暂停执行并向用户返回上下文。此方法通过 supervisor 委派链的工作方式与 requireApproval 相同:挂起状态会在 supervisor 层出现:

src/mastra/tools/conditional-tool.ts
const conditionalTool = createTool({
id: 'conditional-operation',
description: 'Performs an operation that may require confirmation',
inputSchema: z.object({
operation: z.string(),
}),
suspendSchema: z.object({
message: z.string(),
}),
resumeSchema: z.object({
confirmed: z.boolean(),
}),
execute: async (input, context) => {
const { resumeData } = context?.agent ?? {}

if (!resumeData?.confirmed) {
return context?.agent?.suspend({
message: `Confirm: ${input.operation}?`,
})
}

// Proceed with operation
return await performOperation(input.operation)
},
})
// When using this tool through a subagent in supervisor agents
for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-suspended') {
console.log('Tool suspended:', chunk.payload.suspendPayload.message)

// Resume with confirmation
const resumeStream = await supervisorAgent.resumeStream(
{ confirmed: true },
{ runId: stream.runId },
)

for await (const resumeChunk of resumeStream.textStream) {
process.stdout.write(resumeChunk)
}
}
}

使用 generate() 的 supervisor 审批
使用-generate-的-supervisor-审批的直接链接

工具审批传播也适用于 supervisor agents 中的 generate():

const output = await supervisorAgent.generate('Find user with ID 12345', {
maxSteps: 10,
})

if (output.finishReason === 'suspended') {
console.log('Tool requires approval:', output.suspendPayload.toolName)

// Approve
const result = await supervisorAgent.approveToolCallGenerate({
runId: output.runId,
toolCallId: output.suspendPayload.toolCallId,
})

console.log('Final result:', result.text)
}

相关内容
相关内容的直接链接