Appearance
工具调用
这一组文章把语言模型和外部世界连接起来:先理解工具描述,再掌握循环和协议。
| 文章 | 重点 |
|---|---|
| Function Calling:工具的定义与触发 | 工具 schema、触发决策和参数生成 |
| 工具调用循环(Tool Loop)—— Agent 的心跳 | 调用、执行、回传和继续 |
| MCP(Model Context Protocol) | 用标准协议接入外部工具 |
文章学习清单
清单集中放在这里,练习时仍可回到对应文章查看上下文。每个问题后面都给出验收时应达到的程度,不只检查“代码能跑”。
Function Calling:工具的定义与触发
定义一个工具,故意把
description写得含糊,观察模型是否乱调或漏调- 参考答案:准备“应该调用”“不应该调用”和“边界模糊”三类问题,记录模型是否调用、选了哪个工具以及参数。含糊描述通常让模型分不清触发条件、能力边界和参数含义,可能在本该直接回答时调用,也可能在需要实时数据时漏调。最后要能指出是用途、触发条件还是限制描述缺失导致错误,并确认服务端没有因误调用执行危险操作。
把同一工具的
description写清楚,对比触发准确率- 参考答案:清晰描述应包含能力、触发时机、返回内容、适用范围、不可处理的情况和参数示例。保持模型、系统提示、工具集合和测试集不变,统计调用准确率、参数完整率、无效调用率以及新增描述的 token 成本;触发率变高不等于所有问题都该强制调用。
给字段加上
enum,再引导模型传一个范围外的值- 参考答案:
enum会给模型明确的合法值提示,但不能替代服务端校验。分别测试合法值、大小写变化、自然语言别名、越界值和缺失值,区分 Schema 不合法、业务不允许和权限不足三类失败;执行层应在真正调用前拦截非法参数。
- 参考答案:
打印模型返回的
tool_calls,确认arguments是字符串并处理一轮多个调用- 参考答案:每个调用通常包含唯一
id、工具名和 JSON 字符串形式的arguments,需要先解析再做 Schema 与业务校验。一轮可能有多个互不依赖的调用,结果必须按各自tool_call_id回传。验收应覆盖合法/非法 JSON、缺字段、未知工具和两个并行调用,确保不会串结果。
- 参考答案:每个调用通常包含唯一
用
tool_choice强制调用某个工具,观察行为变化- 参考答案:
none禁止调用,auto交给模型决定,required要求至少调用一个,指定函数则固定目标。强制调用不代表用户提供了合法参数,模型可能编造缺失信息。实验要为每种模式找到合理场景,并在执行前加参数校验、权限检查和必要的用户追问,说明固定流程与无关强制调用的风险。
- 参考答案:
工具调用循环(Tool Loop)
不用框架,纯 SDK 写通一次完整循环
- 参考答案:程序应跑通“用户问题 → tool call → 本地执行 → 追加 tool 结果 → 模型总结”,模型直接回答时也能正常退出。保留 assistant 工具调用消息、
tool_call_id、原始参数和每轮 usage;用只读工具与失败工具覆盖正常结束、非法参数、未知工具和 API 错误,并设置最大轮数、超时和总预算。
- 参考答案:程序应跑通“用户问题 → tool call → 本地执行 → 追加 tool 结果 → 模型总结”,模型直接回答时也能正常退出。保留 assistant 工具调用消息、
让模型完成一个需要连续调用两个工具的任务
- 参考答案:设计“先查订单,再用订单号查物流”这种有依赖的任务,trace 中应能看出第二步使用了第一步结果。说明为什么第二个调用不能提前执行,并记录每轮延迟、输入/输出 token、工具耗时和最终结果;结果缺失时应停止或追问,不能编造。无依赖的两个工具可能在同一轮并行,不能把两个工具误认为两个循环。
打印每轮
messages,观察它如何增长- 参考答案:每轮会追加 assistant 消息和一个或多个 tool 消息,历史重发会推高输入 token、延迟和成本。日志需脱敏,并记录角色、调用 id、摘要、token 数和 trace id;验收时要能还原链路,并提出摘要、裁剪旧消息、压缩结果或外置状态的方案,同时保留仍会影响决策的约束和工具结果。
用本地 mock 工具诱导死循环,理解终止条件
- 参考答案:让工具持续返回相同或无效结果,观察模型重复调用导致费用和延迟失控。实验只用本地 mock、极小预算和短超时;恢复保护后至少有最大轮数、总 token/费用预算、单工具超时、重复调用检测和取消机制,达到限制时返回可解释的失败状态并保存 trace。
处理工具执行报错,把错误回传给模型并验证自我纠正
- 参考答案:网络超时、参数校验失败、业务拒绝应转换成结构化结果,说明错误类型、是否可重试和需要补充什么;不能把堆栈、密钥或内部路径暴露给模型或用户。至少区分可重试、不可重试、需人工确认和权限不足,验证不会重复执行非幂等操作,最终回答如实说明工具是否成功。
MCP(Model Context Protocol)
说清 2026-07-28 为何取消
initialize握手,以及如何兼容 legacy Server- 参考答案:现代 MCP 是无协议级 session 的逐请求模型,每个请求通过
_meta自描述,HTTP 另带MCP-Protocol-Version;服务端不支持版本时返回版本错误,客户端选择支持版本重试。兼容旧 Server 时,STDIO 可先探测server/discover,HTTP 可检查 400 响应体,只有确认 legacy 才回退initialize与notifications/initialized。
- 参考答案:现代 MCP 是无协议级 session 的逐请求模型,每个请求通过
写出
server/discover请求和DiscoverResult的关键字段- 参考答案:请求方法为
server/discover,业务参数为空但带标准_meta;结果至少检查resultType: "complete"、supportedVersions和capabilities,通常还包含serverInfo、instructions、ttlMs、cacheScope。serverInfo只是服务端自报身份,不能作为安全决策依据。
- 参考答案:请求方法为
区分 Tools、Resources、Prompts 的驱动方和安全入口
- 参考答案:Tools 由模型提出调用,但 Host 负责确认、参数校验、鉴权、超时和审计;Resources 由 Host/用户选择读取,重点防 URI 越权和数据传播;Prompts 由用户主动选择,重点检查模板来源、参数和 prompt injection。三者都可能承载不可信文本,不能直接当系统指令。
解释
tools/call的协议错误与工具执行错误- 参考答案:未知方法、未知工具和参数结构非法属于 JSON-RPC
error;工具已找到但下游 API、业务校验或执行失败,应返回正常result并设置isError: true,让模型得到可行动反馈。Host 仍要限制重试次数和副作用。
- 参考答案:未知方法、未知工具和参数结构非法属于 JSON-RPC
说清
resultType、structuredContent与outputSchema的关系- 参考答案:现代结果使用
resultType,普通完成为complete,需要客户端补充输入为input_required。outputSchema描述结构化结果,Server 必须让structuredContent符合它,Client 应验证;这不是模型供应商的 Structured Outputs。为兼容旧 Client,最好同时返回可读的 TextContent。
- 参考答案:现代结果使用
描述 MRTR 往返以及
requestState安全要求- 参考答案:Server 在工具、资源或提示词结果中返回
InputRequiredResult,inputRequests携带 elicitation、sampling 或 roots 请求;Client 完成输入后用新的 JSON-RPC id 重试原方法并带inputResponses。requestState必须原样回显,Server 应做完整性保护、绑定用户和原请求、设置 TTL 并防重放。
- 参考答案:Server 在工具、资源或提示词结果中返回
对比
resources/subscribe与subscriptions/listen- 参考答案:旧版通过
resources/subscribe/unsubscribe(HTTP 还可能有独立 GET SSE);2026-07-28 用subscriptions/listen建立长生命周期响应流,由 Client 选择资源或列表变更类型,Server 用订阅 id 关联推送。请求级 progress/log 仍在原请求响应流中。
- 参考答案:旧版通过
说清 Streamable HTTP 与 HTTP+SSE 的差异和部署安全点
- 参考答案:当前 Streamable HTTP 使用单一 POST endpoint,每个请求独立 POST,响应可为 JSON 或该请求范围内的 SSE;没有独立 GET 流、
Mcp-Session-Id、Last-Event-ID和独立 Server Request。必须校验 Origin、认证、协议版本及Mcp-*头体一致性,本地只监听 localhost;HTTP+SSE 已弃用。
- 参考答案:当前 Streamable HTTP 使用单一 POST endpoint,每个请求独立 POST,响应可为 JSON 或该请求范围内的 SSE;没有独立 GET 流、
解释 MCP 授权发现链路和 token passthrough 风险
- 参考答案:受保护 Server 发布 RFC 9728 Protected Resource Metadata,Client 由此发现授权服务器;授权服务器至少支持 RFC 8414 或 OIDC Discovery,Client 使用 OAuth 2.1、PKCE、state 和严格重定向校验。Client 凭据按 issuer 隔离,MCP Server 不能把 Client token 原样转发给第三方 API,下游凭据应由 Server 独立 OAuth 流程取得并绑定用户。
对比 form mode 与 URL mode elicitation,列出禁止事项
- 参考答案:form mode 只适合可查看、可修改的非敏感结构化输入,禁止密码、API Key、访问令牌和支付凭据;URL mode 让用户在 Server 安全页面处理敏感信息,URL 不能放秘密、PII 或预认证链接。Client 要展示 Server 和完整 URL、征得同意、禁止预取或让 LLM 读取页面,并处理取消、拒绝和身份绑定。
设计一个无协议 session 的有状态工具
- 参考答案:创建工具生成高熵 opaque handle,在
structuredContent返回;后续工具把 handle 当普通参数,每次根据认证主体校验,设置 TTL、权限和一次性约束。过期返回isError: true的可行动错误,不能依赖 HTTP 连接或Mcp-Session-Id保存状态,也不能把 handle 当成无需鉴权的 bearer token。
- 参考答案:创建工具生成高熵 opaque handle,在
判断什么时候用 MCP、什么时候用本地 function 或 A2A
- 参考答案:能力需要跨多个 Host/Agent/IDE 复用、统一发现和权限边界、或由独立团队维护时,MCP 更合适;单应用内稳定小函数、极低延迟路径可直接写 function;需要委派自治 Agent、持续任务、产物和状态时考虑 A2A。三者都不能替代授权、幂等、数据最小化和审计。