视频加载失败

《AI Agents in Depth》学习笔记(四):工具

11550 字
58 分钟
《AI Agents in Depth》学习笔记(四):工具

工具是连接 Agent 语言”大脑”与真实数字世界的”手脚和感官”(如《Her》中的 Samantha)。本章围绕两个核心挑战展开:一是工具选择——当数千个工具的说明足以撑爆上下文窗口时,如何准确找到所需工具、从被动”选择”进化为主动”发现”;二是异步与事件——如何管理耗时任务、处理随时到来的中断与外部事件,而不陷入同步等待的僵局。全章先给出五类工具分类与通用设计原则,再讲 MCP 如何统一工具生态及其安全风险,逐类深入感知、执行、协作工具,然后进入事件驱动的异步架构(事件触发工具与用户沟通工具依托其上),以”主动工具发现”收尾。工具的自主创造与淘汰留待第八章,代码元能力在第五章,多 Agent 架构在第十章。

4.1 工具的分类#

从两个特征审视五类工具:调用方向(交互由谁发起)与作用对象(作用于什么)。两列不构成交叉分类框架,只为快速把握定位。

表4-1 五类工具的调用方向与作用对象

工具类型调用方向作用对象
感知工具Agent 主动调用获取信息
执行工具Agent 主动调用改变世界
协作工具Agent 主动调用驱动其他 Agent 或人类
用户沟通工具Agent 主动调用向用户传递信息
事件触发工具Agent 注册、外部触发驱动 Agent 开始执行

各类要点:感知工具(web_search、grep_file、read_file 等)设计关键在粒度权衡与输出信息量控制;执行工具(shell_exec、code_interpreter、send_email 等)错误代价可能极高,安全约束是核心;协作工具(spawn_subagent、list_agents 等)支撑并行执行与”用不同模型/工具/上下文各司其职”;用户沟通工具(reply_to_user、send_user_notification 等)——沟通扩展到多渠道异步消息时,“说话”本身也要成为显式工具调用;事件触发工具(set_timer、monitor_shell、connect_channel)涉及注册(Agent 主动声明关心什么事件)与触发(外部事件异步回调唤醒 Agent)两个时刻,没有它 Agent 只能被动响应对话。

4.2 工具设计的通用原则#

4.2.1 能力表达形式:专用工具还是 Skill + 通用执行器#

  • 专用代码工具:结构化函数调用,确定性高、可测试;但每个工具占数百 token,数量膨胀会破坏 KV Cache。
  • Skill + 通用执行器:自然语言 Skill 文档描述流程(如”1. npm run build;2. docker build;3. kubectl apply”),Agent 经终端/代码解释器执行,少量通用工具覆盖大量场景。

三维决策:参数复杂度(嵌套对象、多字段联合校验适合结构化 schema 引导;简单参数走 CLI 同样可靠)、变更频率(频变能力用 Skill——改文本远比改代码+测试+部署轻松;稳定底层操作做专用工具)、模型能力(SOTA 模型可用 Skill + 执行器表达更多能力;弱模型需要 schema 引导)。

4.2.2 工具粒度:整合与分离#

粒度过细→数量激增(超过约 100 个工具时最先进的 LLM 也易选错);过粗→单个工具过于复杂。整合标准是功能相似性使用场景重叠度extract_pdf_text/extract_docx_content/extract_pptx_content 应整合为 read_documentfile_type 参数区分)——降低认知负担、描述更清晰、便于扩展。但参数形态、延迟特性差异大的功能(图片 OCR vs 视频关键帧提取)强行合并反而语义模糊;参数集差异大或使用频率极高的保持独立。

4.2.3 通用性设计#

**通用工具优于专用工具,除非存在明确的安全、权限或性能理由。**与其做四则运算计算器,不如提供沙盒中装好 sympy/numpy/pandas 的 code_interpreter——LLM 本身有强大的思考与代码生成能力,应利用而非限制;一个 Python 解释器可代替数十个专用工具,还能处理预先没想到的边缘场景。边界:需特殊权限、复杂配置或有安全风险的操作仍需封装良好的专用工具(生产库写操作要精细权限与审计;各 OS grep 语法不同,专门的 grep 工具更好)。

4.2.4 工具描述的艺术#

  • 核心是让 LLM 知道**“什么时候用”**而非只是”能做什么”:“当需要获取实时信息或查找未知事实时使用”胜过”搜索相关内容”。
  • 边界比能力更重要:明确做不到什么、不接受什么输入。多数调用失败的根因不是不知道工具能做什么,而是不知道不能做什么。
  • 参数用具体例子代替抽象规范:“phone:E.164 格式(国家代码+号码,无空格),例如 +8613888888888”——复杂任务中确认格式只占模型注意力一小部分,可套用的例子省去额外思考。
  • 描述返回值结构(“JSON 数组,每元素含 title、url、snippet”)与执行代价(“大型网站需 5-10 秒;只要元信息请用 get_page_metadata”)。
  • 1-5 个真实调用示例:JSON Schema 表达不了调用方式与典型参数组合(时间戳秒还是毫秒、过滤条件如何嵌套);加示例后调用准确率在一些基准上可从约 72% 提升到 90%。
调试原则:先查描述,再怀疑模型

Agent 频繁选错工具时,优先检查工具描述而非怀疑模型能力——多数错误根因是描述不准确(边界不清、缺反例、参数含义模糊)。修正描述的投入产出比通常远高于换更强的模型。

4.2.5 参数传递的保真性#

两种隐蔽反模式:静默输入转换——工具悄悄”修正”输入。案例:Cursor 某版本把中文弯引号静默转成英文直引号,模型读文件看到弯引号、原样传入 old_string,替换却报”未找到匹配”;写入方向同样被篡改。模型反复失败且无法自行诊断。静默参数注入——某 IDE 的 bash 工具给所有 git commit 自动附加”AI 生成”标记参数,旧版 Git 不支持时怎么改提交信息都报错。

保真性底线

模型感知到的世界与工具操作的世界之间,不能存在系统性偏差。参数传递必须透明;确需规范化(如统一编码),必须写入工具描述并在返回中明确告知,否则”智能修正”制造的是模型无法自行诊断的系统性故障。

4.2.6 工具设计的三代演进#

第一代:直接封装 API,每个端点一个工具,粒度过细。第二代ACI(Agent-Computer Interface)原则——对标 HCI,研究 Agent 如何与计算机交互,核心是让工具对 Agent 友好:工具对应 Agent 的目标而非底层 API 操作(粒度、通用性、描述规范皆属此阶段)。第三代:优化工具被调用(示例驱动)、发现(动态工具发现)与串联代码编排执行)的方式——LLM 一次性生成脚本,中间变量留在执行环境,只返回最终结果(像领导一次写好操作手册而非每步邮件往返);抓取多网页批量提取字段时页面全文不进上下文,token 消耗可降约两个数量级,属第五章”代码作为通用 Agent 元能力”范式。

4.3 工具生态:MCP 与工具选择的挑战#

各框架工具定义格式互不兼容(OpenAI function calling、Anthropic tool use、LangChain Tool),如同各国插座标准不一。Model Context Protocol(MCP)是 Anthropic 于 2024 年底发布的开放标准——AI 工具生态的通用”插座标准”。关键设计:客户端-服务器架构(服务器暴露工具,客户端为 Agent 框架/IDE);JSON Schema 标准化工具描述传输层灵活(本地 stdio,远程 Streamable HTTP,早期 SSE 已弃用);价值是一次开发、处处可用

MCP 的三类原语

工具(模型可执行的操作)、资源(应用可读取的只读数据,如文件、数据库记录)、提示模板(prompts,用户可选用的提示词模板)。资源与工具分离,使 Agent 区分”获取信息”与”执行操作”。

modelcontextprotocol
/
servers
Repository details unavailable
Unavailable

MCP 实践中的三个递进挑战:

**1. 同步调用的局限。**MCP 主体是请求-响应式。扩展原语——通知(notifications)、进度(progress)、采样(sampling,服务器反向请求客户端模型补全)、征询(elicitation,执行中向用户请求补充输入)——都只作用于保持连接的单个会话内:没有标准方式触发 Agent 思考循环,更无法唤醒未运行的 Agent。跨会话、多事件源、离线唤醒需分层构建:MCP 管单次调用的标准化,Agent 框架在其上用事件队列管调度、并发与外部事件源接入。

2. 上下文开销。仅 5 个 MCP 服务器就可能引入约 55,000 token 的工具定义——200K 窗口未开始对话就用掉近三成。Cursor 方案:工具描述同步到文件夹,默认只见名称索引、按需查询定义,A/B 测试总 token 消耗减少 46.9%(“默认少给,按需加载”,与 KV Cache 友好设计、渐进式披露一脉相承)。Pi Coding Agent 更激进:核心不内置 MCP,优先 CLI + README + Skills 按需加载;社区扩展 pi-mcp-adapter 用约 200 token 的代理工具”搜索→查看定义→调用”按需发现,MCP 服务器延迟到首次使用才启动。启示:是否用 MCP 作互操作协议是否在会话开始暴露全部工具定义是两个独立决策。

**3. 层次化组织与动态发现。**上百工具时按信息源性质分类优于扁平列表:搜索(主动查找)、读取(从已知位置提取)、解析(处理非结构化数据)、查询(访问结构化数据源),并在系统提示词中显式说明分类结构。更进一步是动态工具发现:Anthropic 实验显示按需检索使 Opus 4 工具使用基准准确率从 49% 提升到 74%(详见 4.8)。

从 MCP 到 Skills:MCP 解决互操作,Skills 解决选择过载——少量通用工具+可按需加载的知识文档替代大量专用工具,把”工具选择”转化为 LLM 擅长的”知识检索”。具体能力选哪种形态,仍用 4.2.1 三维框架。

接入 MCP 服务器 = 引入新的信任边界

每接入一个服务器,等于把一段不受控文本注入上下文,往往还交出一份凭证。四类风险:工具描述投毒(description 原样进入上下文可夹带指令——提示注入(Prompt Injection)的变种,且每次会话生效);恶意或被劫持的服务器(供应链攻击、更新引入恶意行为);同名工具遮蔽(tool shadowing,把携带敏感参数的调用路由给攻击者);凭证管理风险(代持的 OAuth token/API key 被诱导滥用)。缓解:把 description 当不可信输入审计、锁定版本拒绝静默更新、最小权限凭证;运行时靠 Sidecar 兜底。第五章”致命三要素”(访问私有数据、暴露于不可信内容、对外通信能力)提供整体评估框架——服务器越多,三要素齐备概率越高。

4.4 感知工具#

共同挑战:返回信息量远超处理能力(一次搜索数万字符、一份 PDF 上百页)。通用应对是工具层集成上下文感知压缩——输出超阈值(如 10000 字符)时按 Agent 当前查询意图自动压缩(机制见第二章)。特有设计:

  • 搜索类:返回结构化候选列表(标题、位置、摘要片段)而非全文拼接;结果多时提供分页/游标参数,注明总数与翻页方式,由 Agent 自主决定。
  • 读取类:支持 offset/limit 按需读大文件片段;截断显式可见(“已显示第 1-200 行,共 5000 行,可用 offset 继续读取”)。
  • 只读性红利:结果可安全缓存、多个感知调用可放心并行——执行工具没有这种自由。
  • 多模态形态:直接给图像(保留布局但耗 token)还是 OCR/解析转文本(精简但可能丢失空间结构)?纯文字用文本提取,布局敏感内容(UI、复杂表格、设计稿)保留图像。
静默截断的危险

截断而不告知,Agent 会误以为看到了全部内容,基于不完整信息做出错误判断。任何截断都应注明省略了多少、如何读取剩余部分。

实验 4-1(★★)构建感知工具 MCP 服务器:搜索、多模态理解、文件系统、公开数据源、私有数据源五类场景。

4.5 执行工具#

执行工具错误代价极高(误删无法恢复、命令致服务中断、API 调用致真实财务损失),设计核心是能力开放安全约束的平衡。

层次化安全防护。第一层输入验证:检查路径遍历(../../etc/passwd)、命令注入(分号/管道拼接)、参数类型格式,关键是快速失败、不”智能”修正。其上是权限控制:文件操作限定工作目录、命令黑名单(rm -rf /dd if=/dev/zero)、API 配额限速。黑名单只是最基础防护——变形命令可绕过字符串匹配,更健壮的是语义解析(第五章)。

提议者-审核者(Proposer-Reviewer):独立第二视角检验第一视角产出,两种机制。①事前审批:一个模型提议、另一独立模型审批(银行双签)。要点:模型应来自不同家族但能力相近(理想如 Claude Opus 与 GPT-5 互审)——不同来源带来认知多样性,同家族易犯相同错误;能力悬殊(Haiku 审 Opus)则审查者跟不上被审者思路。提示词底层规则须完全一致(否则互相扯皮),关注点差异化(提议者重行动、审核者重风险)。审批失败不简单重试,而是把拒绝理由作为工具调用结果加入轨迹(对提议模型如同一次带修正建议的工具失败)。可做风险分级审批、不确定时升级人类。适用一切不可逆、影响重大的操作(收费、发邮件、改关键配置、建外部资源)。②事后验证:要诀是模态切换——不是第二个模型重读一遍,而是换模态检验(文档渲染为视觉输出查排版、配置在沙盒实际运行验证生效),单一模态易陷相同盲区。

Sidecar 机制:解决”执行时如何实时校验”。借鉴微服务边车模式,轻量级 LLM 调用伴随主 Agent 思考循环,对主 Agent 的行为做独立判断:与主模型流式输出并行(省的是审查排队时间),但对被审查的工具调用起门控作用——放行前不真正执行。关键设计:只看结构化的工具调用数据(工具名、参数),不看主模型自由文本——堵住提示注入话术经主模型复述操纵权限判断的通道。轻量模型即可胜任:审查对象是结构化数据上的分类问题(“这条命令是否越界”),而非需能力相近模型的开放式思考;通常数百毫秒(亚秒级)完成。另一应用是上下文丰富(并行筛选记忆相关性、摘要大型工具输出、预判权限)。安全 Sidecar 需配拒绝熔断器:连续多次拒绝时回退到人工判断而非无限重试。

表4-2 提议者-审核者与 Sidecar 对比

维度提议者-审核者Sidecar
执行时机操作前(事前审批)或操作后(事后验证)与主模型流式输出并行,门控单次工具调用
审查对象操作的合理性或结果操作本身(工具调用)
审查视角独立模型审批、模态切换验证安全性/可靠性校验
输入隔离提议者与审查者看到相似信息Sidecar 刻意隔离主模型自由文本
典型用途不可逆操作审批、文档生成、配置修改权限分类、记忆相关性判断、工具输出摘要

自动验证与反馈闭环:结果可验证就应自动验证——write_file 写代码后立即跑 linter,结构化错误列表随返回值给 Agent,形成”执行-验证-反馈”闭环,下轮即可修正。

长输出截断与持久化:超阈值(如 200 行或 10000 字符)只返回头尾各 50 行(头含初始输出/错误上下文,尾含最终错误或成功标志),注明”[省略 8523 行,完整输出已保存至 /tmp/…]”并引导用 read_file 读取。

执行环境隔离,按强度递增:OS 级(macOS Seatbelt、Linux seccomp/namespaces——限文件访问、禁网、屏蔽危险系统调用,本地轻量首选)→容器(Docker 独立文件系统与网络栈,但共享内核,内核漏洞可逃逸)→microVM/虚拟机(Firecracker,独立内核硬件级隔离,跑完全不可信代码的最强层级);任一层级之上都设 CPU/内存/磁盘/网络资源配额

venv 不是沙盒

Python 虚拟环境只隔离包依赖,对文件系统、网络、进程没有任何安全约束——venv 中的代码照样能删任意文件、访问任意网络。真正的隔离依靠操作系统及更底层机制。

可观测性(Observability):详细日志(时间、参数、结果、耗时)、审计追踪、性能指标、告警机制。

幂等性与取消语义:必须回答”调用被取消/超时后副作用到底发生了没有”(转账超时返回失败,钱可能已转出,盲目重试即重复转账)。核心是幂等性——执行一次与多次影响相同,可安全重试。两条手段:客户端生成唯一标识(idempotency key)供服务端去重;先查询后变更。不可幂等操作(发邮件、拨电话、对外转账——每次执行都产生不可撤销的真实世界事件)用**“预检-确认”两段式**:第一段只校验预演并返回确认令牌,第二段凭令牌执行,失败不就地重发而是交回上层重走预检。

实验 4-2(★★)构建执行工具服务器:文件写入+linter、终端命令(超时/危险命令检测)、沙盒代码解释器、数据操作、外部系统对接、图形界面操作(browser-use 虚拟浏览器、Computer Use 虚拟桌面、Android World 虚拟手机)。

4.6 协作工具#

核心价值是专业化分工:与其构建”全能” Agent,不如构建一组各自专精的 Agent,各自独立优化提示词、工具集和知识库。

子 Agent 提示词四要素:角色定义清晰(开门见山”你是专门负责 XXX 的助手”);上下文来源明确标注[FROM_MAIN_AGENT] 主 Agent 指令 / [FROM_USER] 用户补充 / [TOOL_RESULT] 工具返回——防混淆来源与提示注入);任务边界明确(何时转交上报);输出格式标准化(统一 JSON 降低解析负担)。

协作机制三组原语:①启动与取消(spawn_subagent;cancel_subagent 在任务失去意义时及时止损省 token);②消息传递(运行期双向补充指令、追问、汇报、请求澄清);③发现(list_agents 列出可用 Agent 及职责与状态,与 MCP tools/list 同一思路)。其上承载四种协作形态:同步调用异步调用(返回任务 ID+完成时事件通知)、流式协作(持续增量消息)、多轮交互。拓扑与分工属第十章。

人工介入(HITL,Human-In-The-Loop,人在回路):有些判断本质上需要人类的价值观、常识或领域知识。要点:超时和降级策略(“5 分钟无响应则采用保守策略”;优先级队列——紧急多渠道通知、普通只发邮件);反馈循环——批准/拒绝及理由构成带证据的反馈数据:可归纳的原则进入经验知识或 Skill,隐式偏好形成后训练数据;但不能把一次人工判断未经归纳直接推广为普遍规则(第八章)。

实验 4-3(★★):协作工具服务器,要求对比至少两种子 Agent 上下文传递方式(最小化传递 vs LLM 从主轨迹提炼交接上下文)、实现 HITL 识别与超时、多渠道通知。

4.7 事件驱动的异步 Agent#

4.7.1 为什么需要异步#

同步 Agent 像只会排队的柜台,真正的助手像灵活的秘书——多个事项按紧急程度决定先后、可暂停切换。同步模式撑不起三项核心能力:异步执行是常态(长任务不应阻塞交互)、事件优先级动态判断(取消当前操作/入队/并行)、中断与恢复的流畅性

“训练同步 / 部署异步”的根本矛盾

LLM 的训练范式假设同步——发出工具调用后,下一条消息必须是工具结果;真实部署却是异步——用户随时打断、多任务并发、外部事件在工具未返回时抵达。这一矛盾贯穿本节所有工程取舍,根本解法有待模型在异步环境中通过强化学习进化(见 4.7.8)。

事件驱动架构:不轮询”有没有新消息”,而是新消息到达自动触发处理;所有输入、输出、思考与外部交互统一建模为事件流(原书图4-2 展示事件源→事件队列→Agent 处理流程的整体架构)。

4.7.2 从 OpenClaw 看事件驱动的现实需求#

OpenClaw 经 Gateway 控制平面接收多渠道消息并路由到 Agent 运行时,内置三种自动化机制:Hooks(响应 Agent 生命周期事件,类似 GitHub Actions 触发器)、Cron(按 cron 表达式执行周期任务)、Heartbeat(每隔 N 分钟唤醒检查,凭判断力避免警报疲劳)。但真正让 Agent 在无用户消息时”自己动起来”的只有 Cron 和 Heartbeat,而二者都是时间驱动;Hooks 只被动响应框架内部事件。短板:对内置渠道之外的第三方事件源(新邮件、API 回调、紧急通知)缺乏即时接入通道,只能等下一个周期才察觉。

PineClaw(Pine AI 的 OpenClaw 插件;Pine 代替用户打真实电话:协商账单、取消订阅、保险理赔)不容此延迟:通话中随时需要用户立即提供 OTP 验证码、几秒内接听三方通话、确认降价方案。5 分钟心跳轮询下客服早已挂断,秒级轮询又造成大量无效请求。解法是 Channel 机制——在 Gateway 与 Pine API 间建实时事件通道,关键事件即时推送,响应延迟从分钟级降到秒级。核心结论:真正的”主动服务”不仅需要 Agent 能定时检查世界,更需要世界能主动通知 Agent。

4.7.3 事件触发工具#

  • 定时器(set_timer):处理依赖物理时间的事件。一次性定时器用于明确时间点(周六收到”给 DMV 打电话”,设”下周一上午 10<00> 致电”);循环定时器用于周期任务与对不支持推送的服务定时轮询——Heartbeat 即其系统化。
  • 后台任务监控(monitor_shell):长后台命令若不断轮询浪费 token,等完全结束又无法及时发现问题、卡死时无法介入;Claude Code 的 monitor 工具允许监控新增输出或含特定关键词的输出。
  • 外部事件通道(connect_channel):把新邮件、API 回调、IM 消息实时推送给 Agent(PineClaw Channel 即典型实现)。

设计要点:清晰的触发条件与过滤规则(防无关事件唤醒浪费算力);事件载荷(payload)含足够上下文(减少唤醒后的额外查询)。

4.7.4 用户沟通工具#

多数 Agent(Claude Code、Manus 等)的 assistant 消息直接发给用户,用户必须打开指定 session 对话。OpenClaw 打破此范式:session 对用户透明,双方随时互发消息而非一问一答——“活人感”如秘书异步沟通。此时消息用专门的工具发送,可附图片文件、按紧急程度附推送提醒;进一步有结构化卡片、提醒邮件乃至生成式 UI(HTML 交互界面)。设计上支持异步消息(用户不一定在线)、已读/未读追踪、多渠道消息一致性。

类别边界:同样是”发通知”,对象是审批者/协作者归协作工具,是最终用户本人才归用户沟通工具——区别不在渠道,在”通知谁、为什么通知”。通知机制同时是用户召回机制:扩展到 IM、短信、邮件、电话、推送多渠道,按紧急程度、用户状态、内容性质、用户偏好综合选择;长任务完成时主动召回注意力,定期任务帮助用户建立交互习惯。

4.7.5 虚拟身份与隔离执行环境#

(本质是执行环境基础设施,与沙盒一脉相承;放在此节因独立常驻、随时代表用户行动的 Agent 最需要它。)

架构选择:直接管理用户个人账号,还是独立虚拟身份?直接管理便捷,但 Agent 出错或被攻破时用户全部数字身份暴露。更稳妥的是独立虚拟身份——专属通讯账号、存储、计算环境(如秘书有自己的办公电话和邮箱);身份的明确性反而增强沟通真实性。落地在虚拟电脑(VM/容器)与虚拟手机(Android 模拟器):Agent 有自己的账号、家目录、凭证,操作可追溯可审计,出错不影响宿主与真实设备——沙盒隔离代码执行,虚拟设备隔离整个数字身份。

两个现实挑战:①反自动化机制——CAPTCHA 与 IP 信誉检测拦截数据中心 IP,实践中常需住宅代理网络(真实家庭 IP);②必须以用户本人身份登录时——用 HITL 认证:VNC/RDP 远程桌面让用户在可视化环境中亲自登录(可看到 Agent 操作的完整界面),会话令牌有效期内复用,平衡自主性与安全性。主 Agent 与虚拟环境的数据交换用共享文件系统(卷挂载如 /workspace/shared):传递文件路径引用而非内容拷贝,避免占用上下文窗口。

4.7.6 事件处理机制#

骨架是事件循环(event loop):每轮从队列取事件→追加轨迹→调用一次 LLM→执行工具→回到循环(同 Go 的 for-select 结构)。关键性质:事件只在每轮循环的边界被消费——LLM 推理、工具执行期间新事件先排队,到安全点(一段推理结束、一次工具返回)再统一处理;取消也在安全点检查(如 Go 的 ctx.Done())。三种策略的区别只在对待安全点的方式:等下一个自然安全点(队列式)、主动提前制造安全点(取消式)、另起循环不等安全点(并行式)。

结构化事件建模:输入不只来自用户,每个输入按四维建模——来源(用户/联系人/陌生人/系统)、渠道(电话、短信、邮件、定时器、异步工具结果等)、内容(文本、情感、紧急度、是否需回复)、上下文(是否回复既有对话、与当前任务关联):

{
"source": {"type": "email", "sender": "client@example.com"},
"channel": "gmail_webhook",
"content": {"subject": "退款请求", "body": "订单 #12345 希望退款..."},
"context": {"priority": "high", "customer_tier": "vip", "related_orders": ["#12345"]}
}

统一建模使 Agent 在多方通信中保持清晰认知,避免把用户输入误当工具结果、或把藏指令的工具结果误当用户指令(提示注入)。

三种处理策略(原书图4-3):

  • 取消式(Cancellation-Based):紧急事件,本质是提前制造安全点——停止当前操作(取消流式响应/发取消信号)→清空队列→队列事件与紧急事件一起追加轨迹→立即重新调用 LLM 评估局势(例:用户喊”停止!我说错了”)。
  • 队列式(Queued):常规事件——入队不打断→等当前操作完成→工具返回时检查队列、一次性追加→LLM 综合处理。批量提效:搜索期间用户补充”只看最近一个月”,结果返回时两事件一起呈现,省一次往返。
  • 并行(Parallel):独立轻量查询(主任务分析数据时用户问天气)。三特征:与主任务无关、需快速响应、执行成本低。在并行推理会话中独立执行并立即返回,查询与响应追加主轨迹并明确标记”与主任务并行执行”防混淆。

紧急度判定:紧急——user.interrupt、supervisor.instruction、agent.interrupt、标记紧急的外部触发(系统告警、支付失败);非紧急——常规输入、tool.result、timer.trigger 等。硬编码规则有局限,语义决定策略(“马上停下”取消式、“天气怎么样”并行式、“报告用中文发我”队列式),建议用轻量级分类 LLM 作事件路由器

实验 4-4(★★★):事件驱动邮件处理 Agent——邮件、IM/短信、GitHub、定时器、Webhook、系统事件统一入队,每个事件触发一次独立思考循环。验证:会议邀请自动查日历冲突并起草回复、客户投诉标高优并通知、营销广告归档,全程无需用户介入。

4.7.7 工程实现:让同步模型支持异步打断#

核心思想:常态下让 LLM 看到标准同步轨迹,只在打断时插入占位符修复格式。五条规则:

  1. LLM 输出时立即记录 assistant message(thinking、content、tool call)。
  2. 工具完成时才记录 tool result(执行中轨迹处于”部分完成”状态)。
  3. 工具执行中被打断→为未完成工具生成占位符响应(“工具正在后台执行,请优先处理新事件”),追加打断事件、重新调用 LLM——LLM 视角里 assistant message 仍有配对的 tool result。
  4. LLM 思考中被打断→直接丢弃当前思考,不写入轨迹,新事件追加后开新一轮。
  5. 非打断事件入队等批处理,当前周期完成后一次性追加。

示例:起草邮件时 search_contacts 未返回、用户问天气→生成占位符→处理天气→联系人结果到达后作为新事件追加→继续起草。优势:常态轨迹完美同步,对同步训练的 LLM 最友好。残留风险:模型可能”编造”未返回的工具结果——训练数据里工具调用后几乎总跟着真实结果,模型没学过”结果还没回来”。故实践中只在真正紧急时打断,非紧急一律排队。

用异步语义命名工具:解耦”启动”与”完成”

传统命名隐含”调用即完成”(phone_call 暗示等通话结束返回记录)。异步范式下应解耦:initiate_phone_call 立即返回任务 ID 与初始状态,进展经事件通知(phone_call_connected、phone_call_ended)。工具名称和描述本身就要传达异步语义——模型看到 initiate 会自然推断这是”发起”而非”完成”。

批量事件的注意力分散:模型被训练为对最新输入做反应,批量事件时往往只关注最后一个。两层干预——提示词声明”确保全面考虑所有信息”;Agent 状态栏为每个事件加显式标记并在末尾汇总:

[未处理事件 1/4] Tool result from database_query:...
[未处理事件 2/4] User 补充说明:只看北京地区的数据
[未处理事件 3/4] 系统提醒:报告截止时间还有 30 分钟
[未处理事件 4/4] User 询问:进度如何?
(末尾汇总:上面有 4 个未处理事件……请确保回应涵盖所有信息。)

4.7.8 深层矛盾与未来方向#

占位符、异步接口、状态栏标记本质都是用提示工程弥补训练不足的过渡方案。真正解法需训练范式转变——类似机器人领域 VLA(Vision-Language-Action,视觉-语言-动作)模型面对感知-动作延迟的路径。下一代模型需经异步环境强化学习获得三种能力:①理解轨迹中事件的异步穿插(tool call 之后可能是新 user 消息而非 tool result;被打断的思考中间状态保留、处理完继续而非重来);②恢复被打断的任务与思考(记得未完成任务,尤其避免误以为被打断的工具已完成的幻觉);③批量事件的综合处理。配套基础设施:异步环境模拟器(工具延迟、随机打断)+异步能力专项奖励。

“持续思考”不必等下一代模型:约两百行编排逻辑即可让现成文本思考模型变成持续思考(continuous-time)Agent——规则 4 的升级版:不丢弃半截思考,而是把交互建成一条不间断思维流——随时强行合上 <think> 块、把新观察作为普通消息注入、让模型接着解码。它利用被浪费的资源:模型每秒生成上千 token,而工具调用/用户说话要几秒——等待都是”白赚的算力”。由此长出边等边想(基于半截信息提前思考、甚至抢先调工具,多个模型家族零样本复现)与边做边想(输出中途纠正自己)。更关键的发现在训练侧:用”LLM 当裁判”式奖励,模型学会藏起思考换好评、客观指标反而变差;只有可验证、保信息覆盖度的目标才有实打实收益——编排让行为成为可能,训练让行为变好

实验 4-5(★★★):并行执行+打断——异步工具执行(长命令期间即答”现在几点”)、事件批处理(连发”用日语回复""整理成网页”完成时一并处理)、打断取消、并行任务状态查询(三个每秒 3%/2%/1% 的脚本,最快者完成后查其余进度、取消未过 50% 的那个)。

4.8 主动工具发现#

4.8.1 现有工具发现方法#

全量注入在上千工具时失效;检索式预筛选的内在局限是按初始查询做一次性匹配——“Debug the file”实际可能牵出文件访问、代码分析、命令执行等多步跨领域工具链,开始时无法预见。

从被动选择到主动发现:Agent 在执行中意识到能力缺口时,主动用自然语言声明”我需要什么能力”,系统动态匹配注入。代表工作 MCP-Zero:系统提示词不预置任何工具 schema,Agent 在思考中生成结构化请求块(“GitHub 服务器:搜索仓库并返回元数据”),经服务器级→工具级两层语义路由匹配注入,约 2800 个工具上比全量注入节省约 98% token。工程等价方案:系统提示词只留少数基础工具+一个”工具搜索工具”(Anthropic 的 Tool Search Tool 属此类)。共同点:Agent 声明缺口、系统按需注入

层次化匹配与降级:工具按服务器分组(类似手机 App),先定位服务器再匹配工具,搜索空间从”数千工具”缩为”数十服务器×每个数十工具”。依赖离线构建、增量更新的嵌入索引;两层相似度都低于阈值时明确返回”未找到”,让 Agent 改写需求、用基础工具手工实现或创造新工具(第八章)。

动态加载与 KV Cache:若全部工具定义放静态前缀,每加载新工具整段缓存失效。破解:新 schema 追加到上下文末尾,静态前缀保持稳定、缓存完全复用,状态栏只维护简短工具名列表。已成主流默认架构:OpenAI Responses API 的 tool_search + defer_loading: true(schema 以 tool_search_output 追加末尾);Claude Code 对 MCP 工具默认延迟加载(tool_reference blocks 按需注入);Codex CLI 的 tool_search(BM25 检索)默认开启。澄清易误解处:“追加到末尾”只发生在发现那一轮——此后 schema 块固定在轨迹原位置、成为普通历史消息,后续轮次持续命中缓存;真正导致重算的只有 Prompt Cache TTL 过期和修改/移除/重排已加载的工具集。原书图4-9 展示多轮发现后的上下文全貌:静态前缀只含系统提示词+核心工具+搜索元工具,历次发现的 schema 散落轨迹各处、固定于首次注入位置——“工具定义必须在上下文最前面”不再是铁律;代价是模型须在后训练中学会理解散落各处的定义,弱模型还易生成非法调用格式,需 RL 专门训练(第七章)。

实验 4-6(★★★):Qwen3-4B + 120+ 工具。对照组全量注入(超 50K tokens)——4B 模型指令遵循严重退化:查股价错选 Web Search 而非 Yahoo Finance 工具、“忘记”工具导致失败。实验组:system prompt 仅留 web_searchcode_interpreterdiscover_tools 元工具;discover_tools 按嵌入相似度返回 3-5 个候选及完整 schema,新定义追加对话历史、状态栏更新工具名列表。预期:准确率与完成率显著提升——主动发现让小模型在上百工具场景保持可用。

4.8.2 Skills:把工具发现变成”按需查阅”#

与上节最大不同:不需要”嵌入索引+语义匹配”基础设施

  • 一层层查而非一次性全暴露:启动时只见薄薄的目录(每个 skill 的 name + description,合计数百 token);当前上下文真需要某能力时才读对应 sub-skill,再顺引用往下读脚本/子文档。“发现”由上下文里的实际需要驱动,而非任务开始时的一次性预匹配——即渐进式披露(Progressive Disclosure)
  • 像查工具书/维基百科:没人从头读到尾,顺索引按需精确查阅。Agent 靠通用文件阅读能力(grep、读文件)翻阅目录即可,不必把”发现工具”建模为特殊的语义检索。
  • KV Cache 新问题与解法:同一批 skill 会跨会话、跨用户、在不同位置反复加载,每次随历史从头 prefill 成本不小。解法是第二章的”可编辑、可组合的 KV Cache”:每个 skill 的 KV 表示预编译缓存一次,RoPE 重定位”粘贴”到任意位置,以 O(L) 而非 O(L²) 代价拼接;小改动以”勘误笔记”增量修正——skill 从”每次重新 prefill 的文本”升级为”可复用、可组合的缓存对象”。

本章小结#

  1. 核心结论:工具设计的质量决定 Agent 的能力上限,异步架构决定 Agent 能否在真实世界可靠运行。
  2. 五类工具按调用方向与作用对象区分:感知、执行、协作、用户沟通由 Agent 主动调用,事件触发工具”Agent 注册、外部触发”。
  3. 能力表达两形态(专用代码工具 vs Skill+通用执行器),三维决策:参数复杂度、变更频率、模型能力。
  4. ACI 原则:粒度按功能相似性整合(工具超约 100 个时最强模型也易选错);通用优于专用,除非有安全/权限/性能理由;描述讲”什么时候用”、写清边界反例、附 1-5 个真实示例(准确率约 72%→90%);选错工具先查描述再怀疑模型。
  5. 保真性底线:模型感知的世界与工具操作的世界不能有系统性偏差——严禁静默输入转换与静默参数注入。
  6. MCP 统一互操作(客户端-服务器、JSON Schema、stdio/Streamable HTTP、工具/资源/提示三原语),但请求-响应范式与单会话扩展原语覆盖不了跨会话、离线唤醒的事件驱动需求,需分层构建。
  7. 工具过多的应对:按需加载描述(Cursor 省 46.9% token)、层次化组织(搜索/读取/解析/查询)、动态发现(Opus 4 准确率 49%→74%)、Skills 把选择过载转化为知识检索。
  8. MCP 安全四风险:描述投毒、恶意/被劫持服务器、同名工具遮蔽、凭证风险;接入前审计、锁版本、最小权限,运行时靠 Sidecar。
  9. 感知工具:结构化候选+分页、offset/limit+显式截断(静默截断危险)、只读带来缓存与并行红利、多模态按内容类型选形态。
  10. 执行工具多层防护:输入验证(快速失败)→权限控制(黑名单只是底线)→提议者-审核者(不同家族相近能力互审、拒绝理由入轨迹、事后验证靠模态切换)→Sidecar(并行门控、只看结构化数据、拒绝熔断器)。
  11. 执行工具还需:写后自动验证闭环、长输出头尾保留+持久化、分级沙盒(OS 级→容器→microVM,venv 不是沙盒)、可观测性、幂等性与不可幂等操作的”预检-确认”两段式。
  12. 协作工具:spawn/message/cancel/discover 原语承载同步、异步、流式、多轮四种形态;子 Agent 提示词标注上下文来源;HITL 需超时降级与反馈学习循环。
  13. 事件驱动异步架构:结构化事件建模+事件循环安全点;取消式/队列式/并行三策略按紧急度选用,轻量分类 LLM 作路由器;OpenClaw 的 Cron/Heartbeat 是时间驱动,PineClaw 的 Channel 补上”世界主动通知 Agent”的事件驱动能力。
  14. “训练同步/部署异步”矛盾的过渡解法:占位符五规则、异步语义命名(initiate_*)、状态栏标记;根本解法是异步环境的 RL——持续思考研究表明”编排让行为成为可能,训练让行为变好”。
  15. 主动工具发现:“声明缺口—语义匹配—动态注入”(MCP-Zero 约省 98% token),KV Cache 靠”追加末尾、原位固定”保命中;Skills 的渐进式披露把发现变成免索引的”按需查阅”。

思考题#

  1. ★★ MCP 标准将工具定义从 Agent 框架中解耦了出来。但标准化也意味着复杂的工具交互模式(如流式输出、双向通信、有状态会话)可能难以在标准协议中表达。你认为 MCP 未来最需要扩展的能力是什么?
  2. ★★ 在异步 Agent 架构中,事件队列的优先级策略需要在设计时确定。但如果优先级判断本身需要语义理解(比如判断一条新消息是否比当前任务更紧急),这个判断应该由谁来做——规则引擎还是另一个 LLM 调用?各有什么代价?
  3. ★★ 在 MCP 生态中,不同的 MCP 服务器可能提供功能高度重叠的工具。当 Agent 面对多个来源不同但功能相似的工具时,应该如何选择?如果不同来源的同名工具在行为上略有差异(比如一个返回摘要,另一个返回全文),Agent 是否有能力感知并利用这种差异?
  4. ★★★ Agent 代表用户与外部世界交互时,本质上面临一个身份选择:是用独立的虚拟身份(专属邮箱和电话号码)以第三方身份行动,还是直接以用户本人的身份操作其个人账号?前者可以在后台自主操作,但第三方可能不信任一个非真人的身份;后者拥有更完整的上下文和权限,但引入了信任授权和安全边界的问题。你认为在什么场景下应该选择哪种模式?
  5. ★★ 在队列式事件处理中,模型倾向于只关注最后一个事件,本章通过 Agent 状态栏标记和汇总来缓解。但如果队列中积压了 20 个事件(10 个工具结果 + 5 条用户消息 + 5 个系统提醒),你会如何组织这些事件的呈现顺序和格式,使模型不遗漏关键信息?
  6. ★★ 本章提出了”执行-验证-反馈”闭环(如写代码后自动运行 linter)。这种”操作后立即自动验证”的模式还可以应用到哪些工具场景?是否存在某些操作,其验证本身的成本或风险超过了操作本身,导致这种模式不可行?
  7. ★★ 本章提出了”工具爆炸”问题——Agent 面对数千个工具时选择精度下降。除了主动工具发现,还有哪些方案?可以参考人类专家在面对大量可用工具时的策略。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

《AI Agents in Depth》学习笔记(四):工具
https://lingluoa.icu/posts/ai-agent-notes-04-tools/
作者
lingluoa
发布于
2026-08-07
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
lingluoa
Hello, I'm lingluoa.
公告
欢迎来到我的博客!不定期更新中。
文章目录
标签
站点统计
文章
61
分类
9
标签
75
总字数
282,985
运行时长
0
最后活动
0 天前
站点信息
构建平台
ESA Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC-SA 4.0