Skip to content

工具调用:一次动作从请求到执行 ​

对应 CS329Z · 2026-10-05 · Tool Use & Function Calling。日期为校方课表日期,可能调整。核对官方课表。

资料状态

核对日期:2026-09-19。对应课程尚未开课;本文是基于公开课纲与文中原始资料的原创预习技术解读,不是课堂实录、讲义翻译或官方作业答案。本文于 2026-09-20 深度修订。示例为原创教学设计;离线实验与真实模型实验的边界分别说明,不以推演冒充模型实测。

研究助手从 D2 得知需要核查部署配置,提出调用 read。这一步看似只是函数调用,实际上跨越了模型决策、用户身份、外部服务和执行结果四个边界。工具设计决定系统能否从失败中恢复。

本讲先完善只读工具,再用“创建核查工单”这一扩展场景推演有副作用的操作。创建工单仅在获得相应任务授权后开放;前面的研究任务默认仍只有只读权限。

工具返回值应该表达世界发生了什么 ​

[] 不能同时表示零结果、无权限和服务故障。模型若收到空结果,可能更换查询;权限不足时继续尝试猜文档 ID 则毫无意义。使用带标签的结果:

typescript
type ReadResult =
  | { status: 'ok'; document: Evidence }
  | { status: 'not_found' }
  | { status: 'forbidden' }
  | { status: 'unavailable'; retryable: boolean }

对外是否区分 not_found 与 forbidden 取决于信息泄漏策略;即使向模型合并,服务端日志也应保留真实原因。错误分类的目的,是帮助正确恢复,同时不暴露无权知道的资源存在性。

输入同样需要契约:查询范围从可信会话派生,结果数量有上限,字符串长度受限。不要让模型用参数重新指定自己的身份。

连接协议不承担业务决策 ​

MCP 架构描述宿主、客户端与服务器的协作。它让工具接入具有统一结构,但不会替应用决定某个用户是否可以读取某份报告。

因此我们把协议适配放在外层,把业务授权保留在执行器和服务端。无论工具来自本地函数、HTTP 还是 MCP,都经过同样的资源检查与结果记录。这样的分层允许替换接线方式而不改变任务的信任规则。

超时后,最重要的状态是“未知” ​

扩展场景中,助手被授权创建一张核查工单。执行顺序为:服务端写入工单,响应在网络中丢失,客户端超时。客户端不能根据没有收到响应就断言操作失败。

text
客户端:提交 op-17 ───────────────→ 服务端:创建 ticket-8
客户端:等待超时 ←── 响应丢失 ─── 服务端:返回 ticket-8

此时立即用新操作 ID 重试,会创建另一张工单。正确策略是按原操作 ID 查询;或使用服务端支持的幂等键重试,使相同业务意图返回同一结果。

幂等键需要与请求内容绑定。若 op-17 最初创建 A 的核查单,后来改成 B 却复用该键,服务端应报告冲突,而不是悄悄返回 A 的工单。键的有效范围、保留时长和并发行为也要有契约。

同一个幂等键同时到达时怎么办 ​

只在动作完成后保存结果还不够。两个请求可能同时发现“没有完成记录”,随后各创建一张工单。服务端需要先原子登记操作意图,例如借助唯一约束创建 IN_PROGRESS 记录,再由获胜者执行。

同键重入时先比较请求内容摘要:内容不同返回冲突;内容相同且已完成返回原结果;仍在执行时返回处理中或等待。不要将处理中当成失败,随后换新键再试。

还要处理执行者在登记后崩溃的情形。租约或恢复任务可以帮助接管,但外部副作用是否已经发生仍需要对账。若副作用不在同一事务内,单靠唯一键表并不能解决所有窗口。

因此“幂等工具”应该附明确故障语义,而不只是声明用了 UUID。客户端、操作登记与最终业务服务各自承担哪部分保证,需要写进接口契约。

为什么一个本地去重集合不够 ​

教学内存集合可以演示重复调用,但进程重启后集合丢失;多个实例之间也不能共享。若本地记录成功与远端写入不是同一事务,还会出现先后提交的窗口。

真正保证业务不重复,通常需要最终产生副作用的服务参与:唯一约束、事务内登记操作 ID,或下游本身支持幂等。客户端只能降低风险,不能凭空保证跨系统的恰好一次。

这也回扣最初的延时任务比较:消息不丢与业务不重复,需要调度器和处理端共同设计。

一次完整故障演练 ​

在模拟服务中安排“首次创建成功但不返回”,第二次提交使用相同 ID。应观察到两次请求、一张工单、一个稳定结果。再用同一 ID 提交不同正文,预期冲突。最后模拟服务不支持幂等且无法查询,预期停在结果未知,不能自动无限重试。

只读工具可以采用有上限的退避重试,但仍要计入任务总预算。重试应该由执行器统一安排,避免模型与 SDK 各重试三次,最终放大为九次请求。

至此,动作接口、证据接口与执行语义都有了明确边界。下一讲讨论框架能够接管哪些责任,以及迁移时该怎样证明这些语义没有丢失。继续阅读框架与编排。


本课程逐讲目录 · 两门课程映射与资料边界 · 离线实验与验证边界