人工参与¶
Agent 在执行工具前请求 审批,也会向用户请求只有用户才能提供的 输入。各协议映射到同一个中立模型,由相同组件处理。
| Agent 的请求 | AI SDK 6 | AG-UI | MCP | ACP | 设备端 |
|---|---|---|---|---|---|
| 执行工具 | tool-approval-request |
带 toolCallId 的 interrupt |
—(宿主的 McpApproval) |
session/request_permission |
requiresApproval |
| 接收理由 | approval.reason |
resume reason |
— | — | 告知模型 |
| 接收修改后的参数 | — | resume editedArgs |
— | — | 执行修改后的调用 |
| 向用户提选择题 | 客户端工具 ask_user_question |
前端工具 ask_user_question |
— | — | AskUser |
| 请求用户输入 | — | 带 responseSchema 的 interrupt |
form 或 URL elicitation | — | 通过 MCP 工具 |
向用户提问¶
AskUser 是设备端的 Pydantic AI Harness AskUser:同一个 ask_user_question 工具,schema、限制、说明和结果相同。模型一次提出 1–10 个问题,每题 2–6 个选项(标签及含义),允许多选时使用 multi_select。用户可选择或自行填写;工具按问题 header 返回选中标签,或告知模型用户拒绝回答。
- 应用内 Agent:添加
AskUser()能力。 - 服务端 Agent:将
AskUser.tool作为设备工具传入。AG-UI 通过RunAgentInput.tools发送;AI SDK 服务端声明不带execute的客户端工具(Pydantic AI 中使用含 Harness 工具定义的ExternalToolset),应用返回工具输出。无需协议扩展。
问题以标准 JSON Schema 的 InputRequest 到达 UI:每题一个 property,选项为 {const, title, description} 的 anyOf,用户自填答案为 {"type": "string"}。表单以类似 Question 的列表显示这些选项。
UI 接入¶
Chat 会连接全部交互:
- 审批显示在工具调用内,有 Deny 和 Allow。其“⋯”菜单按协议支持程度提供 附理由拒绝、修改并批准,以及 始终允许。后者通过
ToolDecision.remember由ChatController保存,当前会话内不再询问;ACP Agent 收到自己的allow_always选项。Backend 用ApprovalAnswers声明支持的回答,UI 不会提供无法传回 Agent 的选项。 - 提问显示为
InputRequestCard:按 JSON Schema 构建文本、格式、带边界的数字、布尔、带描述的单选/多选与自填答案表单,或 URL elicitation 链接。
自定义页面时,将回调传给 Conversation:
Conversation(
state = state,
onToolApproval = chat::respondToApproval, // yes / no
onToolDecision = chat::respondToApproval, // with a reason or edited arguments
onInputResponse = chat::respondToInput, // forms
)
也可以从代码回答:
chat.respondToApproval("call-1", approved = true)
chat.respondToApproval("call-2", ToolDecision(approved = false, reason = "Not on the production database"))
chat.respondToInput("booking-1", InputResponse.Accept(buildJsonObject { put("guests", 2) }))
待处理请求保存在 ChatState(工具 part 的 APPROVAL_REQUESTED 状态及 inputRequests);停止本轮会取消这些请求。
Backend 接入¶
通过传入的 ToolApprover 请求交互:
decide(toolCallId)返回ToolDecision(approved, reason, editedInput)。input(InputRequest)返回InputResponse.Accept(content)、Decline或Cancel。
询问前发出 ChatEvent.ToolApprovalRequest(id, answers) 显示审批,之后发出 ToolApproved / ToolDenied。ChatController 通过显示请求并等待用户来实现 approver。
默认安全策略¶
改变数据的工具需要审批,除非用户选择关闭。MCP annotation 是不可信提示,只有 readOnlyHint 放宽默认要求。