跳到主要内容

工具:Agent 的手,以及手的安全规程

这一章讲三件事: 一件工具怎么描述才能被模型用对;一个工具生态(MCP) 怎么既省钱又防毒;一双「手」(执行工具)怎么在不烧掉生产环境的前提下干活。 全章的暗线是同一个矛盾:模型按同步训练,世界按异步运转

1. 这一章讲什么

第 01 章把工具分成五类,这一章讲「怎么把工具做好」。书里开篇给了两个核心挑战: 工具选择(数千工具怎么不撑爆上下文、不错选)与异步事件(外部世界不会 排队等 Agent 想完)1。前者的答案在描述与生态(3.1-3.4 节),后者的答案在 事件驱动架构(3.6 节),中间夹着本章最重的部分:执行工具的安全(3.5 节)。

2. 顶层全景

模型:「我要调 shell_exec,参数 rm -rf /tmp/data」

┌──────▼───────────────────────────────────────┐
│ 第 1 层 输入验证:路径合法?参数注入? │
│ 第 2 层 权限控制:工作目录内?黑名单外? │
│ 第 3 层 提议者-审核者:不可逆?另一个模型审 │
│ 第 4 层 Sidecar:执行瞬间,轻量模型门控 │
│ 第 5 层 沙盒:就算执行了,也炸在隔离区里 │
│ 第 6 层 幂等/两段式:万一重复执行,也无害 │
└──────────────────────────────────────────────┘
图说:没有哪一层是万能的;设计假设是「每一层都会漏」。

3. 核心原理

3.1 能力用什么形态表达:专用工具还是 Skill+通用执行器

先于一切粒度讨论,书里摆了一个更基本的选择。专用代码工具:结构化函数调用(模型按固定格式报「函数名+参数」), 行为可复现、可测试,但每个工具占数百 token,数量膨胀还会破坏缓存。

Skill+通用 执行器:用自然语言文档描述操作流程(如「部署应用」:npm run build → docker build → kubectl apply 三步),Agent 用少量通用工具照着执行。三维决策: 参数复杂度(参数有多五花八门)、变更频率、模型能力2

粒度上,书里给了个数量级判据:工具超过 100 个,即使最先进的模型也会在 选择上出错——所以 extract_pdf/docx/pptx 这类应整合成统一的 read_document, 而 OCR(图片转文字)与视频解析不该合并(参数形态与延迟差异太大)3。通用性上,通用优于 专用,除非有明确的安全、权限或性能理由:code_interpreter 强过十几个专用计算器, 但生产数据库写操作要专用工具的精细权限4

3.2 描述的艺术:核心是「什么时候用」

工具描述的质量直接决定使用准确性。书里最承重的一句:描述的核心是让模型知道 「什么时候用」,而不只是「能做什么」——「搜索相关内容」远不如「当需要获取 实时信息或查找未知事实时使用」5

比描述能力更重要的,是列边界——做不到什么、不接受什么。文件搜索工具应 明说「只能按文件名匹配,不能搜文件内容」;缺了反例,模型就会去猜。大多数 调用失败的根因,不是模型不知道工具能做什么,而是不知道它不能做什么6

其余要点打包:参数用具体例子(「RFC3339 格式,例如 2024-03-15T14:30:00Z」 胜过单写格式名);返回值说明字段;长耗时注明代价(「大型网站可能 5-10 秒; 若只需元信息,改用 get_page_metadata」);附 1-5 个真实调用示例——书里 引用的对照数据是准确率从 72% 提升到 90%,因为 JSON Schema(描述参数类型与取值约束的规范)能说清参数怎么填, 说不清「时间戳是秒还是毫秒」这类调用方式7。调试原则也随之而来:Agent 频繁选错工具,先查描述再怀疑模型——修描述的投入产出比,通常远高于换更强的 模型8

3.3 主走查:一次静默改写,两个世界失配

事故来自原书引用的 Cursor 2026 年初版本;对话死循环的展开是我们按机制还原的。

工具设计里比功能缺失更隐蔽的反模式:静默输入转换——工具在执行前悄悄 「修正」模型的输入参数9

模型读到文件:……他说「你好」…… (文件里是中文弯引号)
模型发起编辑:
old_string = 他说「你好」 ← 模型如实传参
(参数传递层悄悄把「 」换成 " ")
工具在文件里找:他说"你好" ← 找不到,文件里没有直引号
工具返回:未找到匹配字符串

模型:我明明看到了这段内容,再试一次…… ← 还是弯引号,还是被换,还是找不到

死循环

写入方向同样遭殃:模型想写中文弯引号(排版的正确选择),传参层换成直引号; 模型回读验证,看到的是被篡改后的内容——模型陷入「我写的和我看到的不一样、 我以为的世界和真实世界对不上」10。姊妹问题是静默参数注入:某 IDE 的 bash 工具自动给所有 git commit 追加一个标记参数,用户的 Git 版本旧、不认识 它,于是每次提交都失败,而模型完全不知道自己发出的命令被改过11

书里从这些事故提炼出一条基础原则,值得全文记下:模型感知到的世界与工具操作 的世界之间,不能存在系统性的偏差;确实需要规范化(如统一编码),必须写进 工具描述、并在返回中明确告知12

3.4 MCP:一次开发、处处可用,以及它的代价

各家框架工具格式互不相通,工具开发者为每个框架重写绑定。MCP(模型上下文 协议,Anthropic 2024 年底开放的标准)就是为了终结这种重复:用「两端分工」的 架构统一接口——提供工具的一方按标准暴露能力,调用工具的一方按标准接入。

关键设计有三。其一,标准化的工具描述:工具用 JSON Schema 描述,确保不同 客户端(发起调用的一方)都能正确理解用法。

其二,传输层的灵活性:本地连接走标准输入输出(进程之间最朴素的字节通道, 行话 stdio)。

远程则走 Streamable HTTP(基于 HTTP 的流式传输,早期的 SSE 方案已淘汰)。

其三,三原语(三类最基础的构件)分离——工具(可执行)、资源(只读)、prompts (可复用的提示模板)。生态价值一句话:一次开发,处处可用13

代价也明码标价。三个递进的挑战14:

  1. 同步限制:MCP 的调用主体仍是请求-响应式;notifications、progress、 sampling 这些扩展都活在单次会话内——跨会话唤醒不在协议的管辖区, 事件队列要框架自己在上层建;
  2. 上下文开销:仅 5 个 MCP 服务器(提供工具的那一端)就可能引入约 55,000 token 的工具定义 开销——200K 的窗口还没开口就用掉近三成。Cursor 的解法是把工具描述同步到 文件夹按需读取(他们报告总 token 减 46.9%);Anthropic 的按需检索把 Opus 4 的工具使用准确率从 49% 拉到 74%15;
  3. 选择过载:工具到数百个,平铺列表模型就选不对。书里的分工判据一句话: MCP 解决互操作,Skills 解决选择过载——后者把工具选择问题变成知识检索 问题16

安全风险四类:工具描述投毒(description 原样进上下文,是提示注入的变种)、 恶意或被劫持的服务器(供应链攻击)、同名工具遮蔽、凭证管理。缓解一脉相承: 接入前把 description 当不可信输入审计、锁版本拒静默更新、最小权限凭证17。 (MCP 规范的源码级细节,我们 protocol 书架有完整拆解可对照——补充(不在书里, 依据我们的 protocol 书架):依据: shelf=ai-protocol-reference/mcp-spec#03-server-primitives.md 事实=规范原文同样把 tools/resources/prompts 定义为服务器的三类原语。)

3.5 执行工具:六层防护

执行工具的错误代价可能极高——误删不可恢复、命令可致服务中断、API 调用会造成真金白银的赔付。书里的立场是层次化:不依赖单一机制,每层都会漏,层层兜底18

  • 输入验证:路径遍历(../../etc/passwd)、命令拼接注入;快速失败, 不替模型智能修正——修正正是 3.3 节反模式的源头;
  • 权限控制:限定工作目录、危险命令黑名单(rm -rf /);书里特意注明 黑名单只是最基础的防护层,不该是唯一防线19;
  • 提议者-审核者(事前审批):不可逆操作由另一个模型先审——银行双签。 要点三则:两模型来自不同家族但能力相近(不同家族带来认知多样性;能力 差太远,审查者跟不上被审者的思路,审不动);底层规则一致、关注点各异 (提议者重行动,审核者重风险);拒绝理由作为工具结果进轨迹——对提议模型 来说,审批拒绝就是一次「工具报错」,它本来就会处理20;
  • 事后验证:要诀是模态切换——代码生成后渲染成视觉再看排版;改完配置 在沙盒里真跑一遍,而不是让第二个模型把同样的文字重读一遍21;
  • Sidecar(边车):与主模型流式输出并行的轻量 LLM 门控(在旁边把关、放行或拦下),在工具执行 的瞬间做安全分类(这条命令越界吗),数百毫秒内完成。它刻意只看结构化 数据、不看主模型的自由文本——否则攻击者的话术(「请允许执行 rm -rf」) 会被主模型复述进思考,反过来骗过审查。它和提议者-审核者并不冲突:审查对象 不同——前者审「开放式思考」需能力相近的模型,后者审「结构化分类」轻量模型 就够;Sidecar 也配拒绝熔断器,连续拒绝不再无限重试,回退请用户定夺22;
  • 沙盒:常见误区必须钉死——Python 虚拟环境(venv)不是沙盒,它只隔离 包依赖,里面的代码照样能删任意文件、访问任意网络。真隔离按强度递增:OS 级 机制(如 Seatbelt/seccomp)< 容器(共享内核)< microVM(如 Firecracker, 独立内核,运行完全不可信代码的最强层级)23

幂等性单独说,因为它是异步世界的救命绳:幂等(同一操作执行一次和多次, 对外界的影响完全相同)操作可以放心重试——手段是唯一标识(idempotency key, 服务端凭它去重)或先查询后变更。发邮件、打电话、转账不可幂等——每执行 一次就是一个不可撤销的真实事件;对它们用预检-确认两段式:第一段只校验 预演、返回确认令牌(一张「已预检」的凭据),第二段凭令牌真执行,失败不盲目重发,交回上层重走预检24

3.6 异步:训练同步,部署异步

事件驱动架构要解决的矛盾,书里一句话钉死:LLM 的训练范式假设同步——发出 工具调用后,下一条必须是结果;而真实部署要求异步——用户随时打断、多任务 并发(同时推进)、事件在工具未返回时抵达25。同步像只会排队的柜台,异步像灵活的秘书。

业界的工程解法有一套精细的规则:输出立即记录;工具完成才记 result;执行中被打断 → 留占位符(「工具正在后台执行」);思考中被打断→丢弃思考;非紧急事件进队列 批处理。书里反复强调:常态是完美同步的轨迹,占位符是必要妥协——它们会加剧 幻觉(模型编造不存在的内容)风险,只在真正紧急时打断26

事件只在轮次边界消费;紧急事件(「停止!我说错了」)用取消式——提前制造安全点, 清队列、追加更正、重调模型;常规事件用队列式;独立轻量问题用并行式27

这一节还有一个惊喜:「持续思考」不必等下一代模型。用约两百行编排,就能让 现成模型边等边想——工具调用、用户说话的几秒「等待」,对每秒能生成上千 token 的模型是白赚的算力;随时强行合上正在写的思考块,把新观察注入,接着往下写。 但书里同时给了关键的另一半:训练信号决定这事有没有用——用「LLM 当裁判」式 奖励,模型学会把思考藏起来换好评,客观指标反而更差;只有可验证、保信息覆盖度 的目标才有效。一句话:编排让行为成为可能,训练让行为变好28

3.7 工具发现:从全量注入到按需声明

工具到成百上千,发现成了新问题。检索预筛选的局限:按初始查询一次性匹配, 任务中途需要的新工具它不知道。MCP-Zero 的思路让 Agent 主动声明缺口 (「我需要查询股票价格的能力」),系统两层语义路由(服务器级→工具级)从数千 候选中匹配注入——论文报告约 2800 个工具上比全量注入省约 98% 的 token; 工程上更常见的等价物是「工具搜索工具」:系统提示词只留少数基础工具加一个 discover_tools,按需返回 3-5 个候选及完整 schema29

配套的缓存纪律沿用第 03 章:新工具的 schema 追加到轨迹末尾、只在被发现那轮 追加、此后固定原位;状态栏同步维护工具名列表。书里的实验还给了小模型的 教训:全量注入 120 工具(约 50K token)时指令遵循直接退化;只留 3 个基础工具 加 discover_tools 后恢复。书末不忘点题:Skills 是更轻的替代思路——把工具库 变成「目录+按需查阅」,像查维基百科词条30

4. 作者的判断与证据

书里给了证据的: 1-5 个示例 72%→90%、MCP 5 服务器约 55,000 token、Cursor 减 46.9%、Opus 4 49%→74%、MCP-Zero 省 98%、120 工具退化实验、持续思考的 编排与训练对照——都有出处(多为作者团队或注明来源的实验)。

是作者的判断: 「模型感知的世界与工具操作的世界不能有系统性偏差」是从 事故归纳的设计公理(合理,但「静默转换永远弊大于利」是可证伪的强主张); 「通用工具优于专用工具,除非……」是带明确例外的默认值,不是铁律。

5. 边界与局限

  • 工具描述、审批、Sidecar 的具体阈值(100 个工具、10000 字符、5-10 秒)都是 经验数,不是常数;
  • MCP 的接口形态在快速演化(书中已记 SSE 弃用一例),细节以各版本规范为准;
  • 「训练同步/部署异步」的工程补丁(占位符、事件队列)是权宜之计——书里明说 根本解法在下一代模型的异步 RL 训练,那还不存在;
  • Sidecar 与提议者-审核者的分工基于当前模型的能力分布(轻量模型能做分类、 做不了开放审查),能力分布变了分工也要重划。

6. 可带走的

  1. 工具描述写「什么时候用」和「做不到什么」——边界比能力更重要;
  2. 选错工具先查描述,别急着怀疑模型;
  3. 参数带例子(「RFC3339,例如 2024-03-15T14:30:00Z」),附 1-5 个真实示例;
  4. 静默输入转换是最阴险的反模式:模型看到的世界必须等于工具操作的世界;
  5. 工具超 100 个,先想整合与按需发现,别指望模型在长列表里不选错;
  6. MCP 管互操作,Skills 管选择过载——两个问题,两把钥匙;
  7. 执行安全靠分层:验证/权限/双审/Sidecar/沙盒/幂等,每层都会漏,层层数减;
  8. venv 不是沙盒——只隔离包依赖,不隔离文件、网络、进程;
  9. 不可逆操作两段式:先预检发确认令牌,再凭令牌执行;
  10. 异步矛盾的工程补丁要克制:常态保持同步轨迹,占位符只在真正紧急时用。

7. 原文地图

主题原书章原文位置
两个核心挑战4 工具text/06-ch04.txt:7(搜「两个核心挑战」)
专用 vs Skill+通用执行器4 工具text/06-ch04.txt:61(搜「表达形态」) · text/06-ch04.txt:63(搜「专用代码工具」) · text/06-ch04.txt:65(搜「通用执行器」) · text/06-ch04.txt:67(搜「npm run build」)
粒度与 100 个4 工具text/06-ch04.txt:79(搜「100 个」)
通用性4 工具text/06-ch04.txt:87(搜「code_interpreter」)
描述核心与边界4 工具text/06-ch04.txt:97(搜「什么时候用」) · text/06-ch04.txt:99(搜「不知道工具」)
参数例子与示例 72%→90%4 工具text/06-ch04.txt:101(搜「RFC3339」) · text/06-ch04.txt:105(搜「72%」)
调试原则4 工具text/06-ch04.txt:107(搜「怀疑模型能力」)
静默输入转换4 工具text/06-ch04.txt:111(搜「静默输入转换」) · text/06-ch04.txt:113(搜「弯引号」) · text/06-ch04.txt:115(搜「写入方向」)
静默参数注入与保真原则4 工具text/06-ch04.txt:117(搜「git commit」) · text/06-ch04.txt:119(搜「系统性的偏差」)
三代演进4 工具text/06-ch04.txt:123(搜「三个阶段」) · text/06-ch04.txt:125(搜「示例驱动调用」)
MCP 架构与三原语4 工具text/06-ch04.txt:133(搜「客户端-服务器」) · text/06-ch04.txt:137(搜「stdio」) · text/06-ch04.txt:139(搜「资源与工具的分离」) · text/06-ch04.txt:141(搜「处处可用」)
MCP 三挑战4 工具text/06-ch04.txt:143(搜「三个递进的挑战」) · text/06-ch04.txt:145(搜「请求-响应式」) · text/06-ch04.txt:147(搜「55,000」) · text/06-ch04.txt:161(搜「选择过载」)
层次化与 49%→74%4 工具text/06-ch04.txt:149(搜「层次化」) · text/06-ch04.txt:159(搜「49%」)
MCP 信任模型4 工具text/06-ch04.txt:163(搜「信任模型」) · text/06-ch04.txt:165(搜「工具描述投毒」) · text/06-ch04.txt:167(搜「供应链」)
感知工具与截断4 工具text/06-ch04.txt:175(搜「10000 个字符」) · text/06-ch04.txt:177(搜「分页」)
执行工具多层安全4 工具text/06-ch04.txt:205(搜「手脚」) · text/06-ch04.txt:211(搜「路径遍历」) · text/06-ch04.txt:213(搜「黑名单」)
提议者-审核者4 工具text/06-ch04.txt:219(搜「双签」) · text/06-ch04.txt:221(搜「认知多样性」) · text/06-ch04.txt:223(搜「互相扯皮」) · text/06-ch04.txt:225(搜「拒绝理由」) · text/06-ch04.txt:227(搜「风险分级」)
事后验证与模态切换4 工具text/06-ch04.txt:229(搜「模态切换」)
Sidecar4 工具text/06-ch04.txt:235(搜「边车」) · text/06-ch04.txt:237(搜「话术」) · text/06-ch04.txt:239(搜「轻量模型」) · text/06-ch04.txt:269(搜「上下文丰富」) · text/06-ch04.txt:271(搜「拒绝熔断器」)
自动验证闭环4 工具text/06-ch04.txt:275(搜「linter」) · text/06-ch04.txt:277(搜「执行-验证-反馈」)
沙盒与 venv 误区4 工具text/06-ch04.txt:293(搜「venv」) · text/06-ch04.txt:299(搜「Firecracker」) · text/06-ch04.txt:303(搜「隔离层级」)
幂等与两段式4 工具text/06-ch04.txt:313(搜「幂等性」) · text/06-ch04.txt:315(搜「预检-确认」)
训练同步部署异步4 工具text/06-ch04.txt:397(搜「训练同步」) · text/06-ch04.txt:389(搜「柜台」)
占位符与常态同步4 工具text/06-ch04.txt:554(搜「工程解法」) · text/06-ch04.txt:616(搜「提示工程弥补」)
持续思考4 工具text/06-ch04.txt:632(搜「两百行」) · text/06-ch04.txt:634(搜「编排让行为成为可能」)
工具发现与 MCP-Zero4 工具text/06-ch04.txt:13(搜「主动工具发现」) · text/06-ch04.txt:658(搜「MCP-Zero」) · text/06-ch04.txt:674(搜「更轻的思路」) · text/06-ch04.txt:690(搜「discover_tools」)

Footnotes

  1. 出处:「4 工具」第 7 段(text/06-ch04.txt:7,搜「两个核心挑战」)。

  2. 出处:「4 工具」第 61-67 段(text/06-ch04.txt:61,搜「表达形态」;text/06-ch04.txt:63,搜「专用代码工具」;text/06-ch04.txt:65,搜「通用执行器」)。

  3. 出处:「4 工具」第 79 段(text/06-ch04.txt:79,搜「100 个」)。

  4. 出处:「4 工具」第 87 段(text/06-ch04.txt:87,搜「code_interpreter」)。

  5. 出处:「4 工具」第 97 段(text/06-ch04.txt:97,搜「什么时候用」)。

  6. 出处:「4 工具」第 99 段(text/06-ch04.txt:99,搜「不知道工具」)。

  7. 出处:「4 工具」第 101-105 段(text/06-ch04.txt:101,搜「RFC3339」;text/06-ch04.txt:105,搜「72%」)。

  8. 出处:「4 工具」第 107 段(text/06-ch04.txt:107,搜「怀疑模型能力」)。

  9. 出处:「4 工具」第 111 段(text/06-ch04.txt:111,搜「静默输入转换」)。

  10. 出处:「4 工具」第 113-115 段(text/06-ch04.txt:113,搜「弯引号」;text/06-ch04.txt:115,搜「写入方向」)。

  11. 出处:「4 工具」第 117 段(text/06-ch04.txt:117,搜「git commit」)。

  12. 出处:「4 工具」第 119 段(text/06-ch04.txt:119,搜「系统性的偏差」)。

  13. 出处:「4 工具」第 133-141 段(text/06-ch04.txt:133,搜「客户端-服务器」;text/06-ch04.txt:137,搜「stdio」;text/06-ch04.txt:139,搜「资源与工具的分离」;text/06-ch04.txt:141,搜「处处可用」)。

  14. 出处:「4 工具」第 143-145 段(text/06-ch04.txt:143,搜「三个递进的挑战」;text/06-ch04.txt:145,搜「请求-响应式」)。

  15. 出处:「4 工具」第 147 段(text/06-ch04.txt:147,搜「55,000」)与第 159 段(text/06-ch04.txt:159,搜「49%」)。

  16. 出处:「4 工具」第 161 段(text/06-ch04.txt:161,搜「选择过载」)。

  17. 出处:「4 工具」第 163-167 段(text/06-ch04.txt:165,搜「工具描述投毒」;text/06-ch04.txt:167,搜「供应链」)。

  18. 出处:「4 工具」第 205-209 段(text/06-ch04.txt:205,搜「手脚」;text/06-ch04.txt:209,搜「多层的防护体系」)。

  19. 出处:「4 工具」第 211-213 段(text/06-ch04.txt:211,搜「路径遍历」;text/06-ch04.txt:213,搜「黑名单」)。

  20. 出处:「4 工具」第 219-225 段(text/06-ch04.txt:219,搜「双签」;text/06-ch04.txt:221,搜「认知多样性」;text/06-ch04.txt:225,搜「拒绝理由」)。

  21. 出处:「4 工具」第 229 段(text/06-ch04.txt:229,搜「模态切换」)。

  22. 出处:「4 工具」第 235-271 段(text/06-ch04.txt:235,搜「边车」;text/06-ch04.txt:237,搜「话术」;text/06-ch04.txt:239,搜「轻量模型」;text/06-ch04.txt:271,搜「拒绝熔断器」)。

  23. 出处:「4 工具」第 293-303 段(text/06-ch04.txt:293,搜「venv」;text/06-ch04.txt:299,搜「Firecracker」;text/06-ch04.txt:303,搜「隔离层级」)。

  24. 出处:「4 工具」第 313-315 段(text/06-ch04.txt:313,搜「幂等性」;text/06-ch04.txt:315,搜「预检-确认」)。

  25. 出处:「4 工具」第 397 段(text/06-ch04.txt:397,搜「训练同步」)。

  26. 出处:「4 工具」第 554 段(text/06-ch04.txt:554,搜「工程解法」)与第 616 段(text/06-ch04.txt:616,搜「提示工程弥补」)。

  27. 出处:「4 工具」第 471-518 段的事件处理三策略;事件只在轮次边界消费、取消式的「停止!我说错了」机制见该节(text/06-ch04.txt:427,搜「事件循环」)。

  28. 出处:「4 工具」第 632-634 段(text/06-ch04.txt:632,搜「两百行」;text/06-ch04.txt:634,搜「编排让行为成为可能」)。

  29. 出处:「4 工具」第 658 段(text/06-ch04.txt:658,搜「MCP-Zero」)。

  30. 出处:「4 工具」第 674 段(text/06-ch04.txt:674,搜「更轻的思路」)与第 690 段(text/06-ch04.txt:690,搜「discover_tools」)。