乐于分享
好东西不私藏

AI Agent 工具调用:一个关于"意识如何控制世界"的故事

AI Agent 工具调用:一个关于"意识如何控制世界"的故事

AI Agent 工具调用:一个关于"意识如何控制世界"的故事

一句话说清本质:

AI 从来没有"碰到"过文件系统。它只是在文本空间里描述了一个动作,Runtime 替它实现了这个动作,再把结果翻译回文本喂给它。这个循环就是 Tool Calling 的全部秘密,也是唯一秘密。

你有没有想过一个问题:一个 AI,它活在纯文本里,看不见摸不着,它是怎么"动手"去读你的文件、执行你的命令的?

我第一次接触 Agent 时,最震撼的不是它多聪明,而是这个问题的答案——它根本没有"动手"。它从始至终都在做同一件事:接龙文字。

那它是怎么控制电脑的?从头说起。


一、三句话讲清楚原理

先不绕弯子,直接上答案——

你:帮我查一下服务器的配置

AI(纯文本空间):思考 → 输出一个 JSON

→ {"tool":"ssh","params":{"host":"192.168.x.x","cmd":"free -h"}}

Runtime(框架):看到这个 JSON → 真的去执行 ssh

操作系统:跑命令 → 把结果还给 Runtime

Runtime:转成文本 → 塞回给 AI

AI:哦,内存是 15G → 写成答案回复你

就是这样一个循环:AI 描述想法 → JSON → Runtime 执行 → 结果回传 → AI 再看 → 再想 → 再到下一个想法……

关键在哪里?

Runtime 没有任何智能。它就是个机械的 JSON 解析器。整个系统的"智商"全靠 AI 输出格式的准确性撑着。AI 输出格式一乱,Runtime 直接报错,AI 必须自己发现并修正。

这不是玄学,纯工程。


二、这件事的源头:四条思想脉络

这个循环不是凭空冒出来的,它有四条清晰的传承线。

🌀 控制论(1940s)

诺伯特·维纳在 1948 年写了一本书,叫《控制论》。核心思想就一句话:系统通过观察自身行为的结果来调整下一步行动。

你房间里的恒温器就是最简单的例子——温度低了就加热,到了就停。传感器、控制器、执行器、反馈,四个组件构成一个闭环。

Agent 的 Tool Calling 本质上就是同一个结构:

  • 传感器 = AI 收到用户消息 + 工具返回的结果
  • 控制器 = AI 的推理层
  • 执行器 = Runtime 执行工具调用
  • 反馈 = 工具结果回传

🔧 Unix 管道(1970s)

这条线是工程层面的。Unix 的设计哲学是:每个程序只做一件事,通过文本流串联起来,组合成更复杂的功能。

cmd1 | cmd2 | cmd3

映射到 Agent 上:

  • 每个 Tool 聚焦一个能力(读文件、查天气、发邮件)
  • JSON 作为通用的调用格式(类比 Unix 的文本流)
  • 多个 Tool 串联完成复杂任务

🧠 ReAct 论文(2022,Google)

这是直接的学术源头。在这之前,AI 做推理有两种主流方式:

  • Chain of Thought(CoT):思考 → 思考 → 思考 → 答案。只推理,不行动。
  • 单纯行动:直接调工具,但不思考为什么调。

Yao 等人在 2022 年 10 月发表的 ReAct 论文(ICLR 2023),把这两件事合在了一起:

  • CoT: 思考 → 思考 → 思考 → 答案
  • ReAct: 思考 → 行动 → 观察 → 再思考 → 再行动 → 观察 → … → 答案

举个例子:

问:"纽约到东京的时差是多少?"

CoT 模式: "纽约在东五区?不对,纽约是西五区,东京是东九区,差 14 个小时……"(纯推理,全靠模型知识,错了就是错了)

ReAct 模式:

思考:我需要查纽约和东京的时区

行动:[搜索 "New York timezone UTC offset"]

观察:UTC-5

思考:再查东京

行动:[搜索 "Tokyo timezone UTC offset"]

观察:UTC+9

思考:相差 14 小时,纽约比东京晚 14 小时

答案:纽约比东京晚 14 个小时

今天所有 Agent 的工具调用机制——OpenAI Function Calling、Claude Tool Use、MCP——都是在 ReAct 这个模式上的工程化包装。

🚀 OpenAI Function Calling(2023.6)

ReAct 提出了模式,但留给开发者一个问题:"我怎么知道 AI 想调用什么工具?"

答案是。开发者得自己解析 AI 的输出文本,试图从中理解"它是想查天气还是想发邮件"。

2023 年 6 月 13 日,OpenAI 用 API 解决了这个问题。他们在 GPT-4 的接口里加了一个 functions 参数:

{
  "functions": [{
    "name": "get_weather",
    "description": "查天气",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {"type": "string"}
      }
    }
  }]
}

然后 AI 的回复里就可能出现标准化的 tool_calls JSON。这是第一次在商用 API 层面定义了"AI 输出结构化行动指令"的标准格式。开发者不需要猜了,直接拿到结构化的调用参数。

再后来(2023.11),OpenAI 支持了一次返回多个 tool_calls——单步可以并行调用多个工具。参数名也从 functions 改成了 tools(2024),反映了从"函数调用"到"通用工具"的概念升级。


三、真实项目拆解:三个例子

☁️ MCP Weather Server

社区中最常见的 MCP 入门示例——一个只有 50 行代码的天气查询服务。

class WeatherServer:
    @tool()
    def get_forecast(self, city: str) -> str:
        """获取指定城市未来 7 天的天气预报"""
        data = requests.get(f"https://api.weather.com/{city}")
        return data.text

    @tool()
    def get_alerts(self, region: str) -> list:
        """获取指定地区的天气预警"""
        return alert_service.query(region)

接入流程:启动 Server → 在 Claude/Hermes 配置里加上这个 server → AI 自动发现工具 → 用户说"北京明天天气怎么样" → AI 输出 {"tool":"get_forecast","args":{"city":"北京"}} → Runtime 调用 → 结果返回。

这个项目展示了 MCP 协议的核心设计:工具和 Runtime 之间加了一层标准化接口。开发者只需要实现 @tool() 装饰器,不用关心 AI 端的细节。

📊 drawio-mcp(真·实战)

这是另一个真实的 MCP Server,把 draw.io 的图表生成能力封装成了 AI 可调用的工具。

当我想画架构图时,整个流程是这样的:

你:帮我画个架构图

AI:理解需求 → 写出 Mermaid 代码

输出 tool_call:{"tool": "open_drawio_mermaid", "args": {"content": "..."}}

Runtime:看到 tool_call → 调用 drawio-mcp

drawio-mcp:生成 SVG → 打开浏览器窗口

结果回传 → AI 告诉你:"画好了,你窗口里能看到"

这就是每天都在用的流程。没有魔法,全是工程。

🧰 Headroom(55.6K Star 的 Token 压缩工具)

Headroom 是 Netflix 高级工程师 Tejas Chopra 的个人开源项目,2026 年 1 月发布,至今已在 GitHub 收获超过 55,600 Star。虽然并非 Netflix 公司官方出品,但 Netflix 内部已有多个团队在用。

它号称可节省 60%-95% 的 Token 消耗(README 第一句:"60–95% fewer tokens, same answers")。仓库自带可复现的评测套件,分场景数据如下:

场景 压缩前 Token 压缩后 Token 节省率
代码搜索(100 结果) 17,765 1,408 92%
SRE 事故调试 65,694 5,118 92%
GitHub Issue 分类 54,174 14,761 73%
代码库探索 78,502 41,254 47%

它通过 MCP 服务器模式暴露三个工具:

工具 功能
headroom_compress 压缩发给 LLM 的内容(工具输出、日志、RAG 检索片段等)
headroom_retrieve CCR 机制——从本地缓存(Redis/SQLite)取回压缩前的原文
headroom_stats 查询压缩统计与节省金额(按当前提供商定价计算)

当一个 Agent 跑长任务时,调用链可能是这样的:

Agent 调用 headroom_compress(压缩日志)

→ Runtime 执行压缩

→ 返回压缩后的文本

→ Agent 继续推理

→ 需要看细节时,调用 headroom_retrieve(取回原文)

→ Runtime 从缓存读取

→ 返回原文

Chopra 在近期的开源峰会上分享了一组数据:Headroom 累计已为用户节省约 70 万美元、释放超过 2000 亿 Token

他的起因是一张 $287 的 Claude Sonnet API 账单——仔细分析后发现,大量成本并非来自他手写的提示词,而是嵌套的 JSON 结构、重复的 API 响应和冗余的数据库字段。有研究指出,AI 应用中约 76% 的 Token 消耗仅用于读取用户输入。

关键洞察:工具之间也可以互相调用。 一个工具的输出可以成为另一个工具的输入。这已经不是"AI 调工具"了,这是"工具调工具"——A2A(Agent-to-Agent)协议的雏形。


四、各家的实现差异

虽然底层原理一样,但各家在细节上有明显区别。

厂商 特色 一句话总结
OpenAI Structured Outputs 强制格式正确,并行调用最成熟 亲爹优势,格式最标准
Claude 每次调用前会说"我要调 XX 工具了,因为……" 可解释性强,复杂任务表现出色
Gemini 200 万 token 超长上下文 你不需要拆分任务,一次全告诉我
Hermes Skill 系统按需加载工具 不一次性注册,根据任务暴露最相关工具集

Hermes 的按需加载尤其值得一提——它不是在每个对话里把 60 个工具全塞给模型,而是根据当前任务上下文,只暴露最相关的几个。这减少了 AI 的选择负担,提高了工具调用的准确率。我现在写这篇文章,就在用这个机制。


五、加餐:工业级框架的代码到底长什么样

这部分稍微硬核一些。理解了它,你就理解了为什么工业级 Agent 框架和玩具 Demo 之间隔着一个太平洋。

(对代码不感兴趣可以跳到第六节看瓶颈和总结。)

🌀 双层循环,不是一层

大多数人脑子里 Agent 是这样的:

LLM 回复 → 解析工具 → 执行 → 结果返回 → 下一轮

实际代码是两层 while:

外层 while(true):                  ← 处理你中途插话、发新指令
    内层 while(有工具调用):         ← LLM→工具→结果→再调 LLM 的自动链
        1. 把消息发给 LLM,拿到回复
        2. 解析回复中的 tool_calls
        3. 并行执行所有工具
        4. 把结果塞回上下文
        5. 回到步骤 1(内层继续)
    对话泡完了,检查有没有新消息
没有 → 退出外层

为什么分两层? 因为用户可能中途插话。你在 Agent 跑一半时发消息,外层循环负责把这条消息注入到下一轮推理中。内层只负责"装弹→开枪→装弹→开枪"的自动循环。

🗣️ Provider 系统——最大的设计亮点

这是 pi-agent 最独特的设计。大多数框架依赖 LLM 提供商的原生 tool calling API,但 pi-agent 多了一个文本编码层。它不用提供商的 tool calling,而是把工具描述写成提示语塞给模型,让模型以文本格式回应,自己再解析出来。

看 DeepSeek 的格式:

<|tool▁calls▁begin|>
  <|tool▁call▁begin|>
    {"name": "read", "arguments": {"path": "/tmp/x"}}
  <|tool▁call▁end|>
<|tool▁calls▁end|>

pi 的 packages/ai/src/providers/ 目录目前覆盖了超过 25 个独立 Provider(含区域变体共 36 个 .ts 文件),从 Anthropic、DeepSeek、Google、OpenAI 到国内的 Kimi、MiniMax、Moonshot、小米,再到 Amazon Bedrock、Azure、Cerebras、Cloudflare、Fireworks、Groq、HuggingFace、Mistral、NVIDIA、Together、OpenRouter 等海外平台,一应俱全:

Provider 说明
anthropic Anthropic Claude
deepseek DeepSeek
google Google Gemini
google-vertex Google Vertex AI
kimi-coding Kimi(Moonshot)编程版
minimax / minimax-cn MiniMax 及中国区
moonshotai / moonshotai-cn Moonshot AI 及中国区
openai OpenAI GPT 系列
openai-codex OpenAI Codex
openrouter OpenRouter 路由
xai xAI Grok
amazon-bedrock Amazon Bedrock
azure-openai-responses Azure OpenAI
cerebras Cerebras
cloudflare-ai-gateway Cloudflare AI Gateway
cloudflare-workers-ai Cloudflare Workers AI
fireworks Fireworks AI
github-copilot GitHub Copilot
groq Groq
huggingface Hugging Face
mistral Mistral AI
nvidia NVIDIA NIM
together Together AI
opencode / opencode-go OpenCode
vercel-ai-gateway Vercel AI Gateway
ant-ling Ant Ling
xiaomi(含 ams/cn/sgp 变体) 小米系列
zai / zai-coding-cn ZAI 及中国区变体

三个好处:

  • 兼容任何模型——只要模型会生成文本,就能走这套流程
  • 流式解析——模型一边生成,一边就能识别出工具调用
  • 统一处理——所有模型都走同一套工具执行逻辑

🧩 工具注册——工厂模式 + 条件加载

omp 有 32 个内置工具,但不是全部注册。下面是完整列表:

文件与搜索(7 个)

工具 功能
read 读取文件、目录、归档、SQLite、PDF、notebook、URL 及内部 :// 方案
write 创建或覆盖文件、归档条目、SQLite 行
edit Hashline 修补,使用内容哈希锚点与过期锚点恢复
ast_edit 通过 ast-grep 预览后执行结构化重写
ast_grep 基于 50+ tree-sitter 语法的结构化代码查询
search 正则搜索文件、glob 及内部 URL
find glob 路径查找;需要内容匹配时用 search

运行时(3 个)

工具 功能
bash 工作区 shell,可选 PTY 或后台任务派发
eval 持久化 Python/JS cell,共享 prelude 且支持工具重入
ssh 对配置主机执行一条远程命令

代码智能(2 个)

工具 功能
lsp 诊断、导航、符号、重命名、代码动作、原始请求
debug 驱动 DAP 会话——断点、步进、线程、栈、变量

协调(5 个)

工具 功能
task 并行派出子代理,可选工作区隔离
irc 本进程内活跃代理间的短文本通信
todo 会话 todo 列表的有序变更与阶段追踪
job 等待或取消后台任务
ask 交互式运行的结构化追问

外部能力(6 个)

工具 功能
browser Puppeteer 标签页,支持无头 Chromium 或 CDP 附接
web_search 跨配置提供商的一次查询,返回答案+引用
github GitHub CLI 操作——repo、PR、issues、代码搜索、Actions 运行监控
generate_image 通过 Gemini/GPT/xAI Grok 图像模型生成或编辑图像
inspect_image 视觉模型分析本地图像文件
tts xAI Grok Voice 文转语——5 种内置语音,WAV 或 MP3

记忆与状态(5 个)

工具 功能
checkpoint 标记对话状态以便后续折叠并生成报告
rewind 修剪探索性上下文,保留精炼报告
retain 向活跃 Hindsight bank 队列持久事实
recall 搜索 Hindsight bank 中的原始记忆
reflect 让 Hindsight 综合 bank 中的答案

杂项(2 个)

工具 功能
resolve 应用或丢弃排队中的预览动作
search_tool_bm25 BM25 搜索隐藏工具索引;会话中期激活匹配工具

其中 8 个为设置门控、默认关闭:github、inspect_image、tts、checkpoint、rewind、search_tool_bm25、retain、recall、reflect。需按项目配置手动开启。

每个工具分三个等级:

  • essential(核心): read、bash、edit、write、find、eval——始终可用
  • conditional(条件): SSH 工具只在有 SSH 配置时才注册,GitHub 工具只在有 Token 时
  • discovery(按需): web_search、search_tool_bm25 等,模型通过搜索工具名来激活

好处: 上下文只包含当前可用的工具,模型不会在几十个工具中挑花了眼。

💡 软工具要求——一种缓存优化

当 Agent 框架想让模型务必使用某个工具时,通常的做法是设 tool_choice 强制调用。但有一个问题:强制 tool_choice 会让 prompt 缓存失效。 很多 LLM API 的 prompt caching 在 tool_choice 改变时会重新计算缓存。

pi-agent 的做法是先软后硬

注入一条 remind 消息,tool_choice 保持 auto → 缓存保留
模型没调 → 再来一次 → 缓存继续保留
超过阈值 → 强制 tool_choice(忍痛丢弃缓存)
最多试 3 次,不行就报错

🛡️ 错误恢复不只一种

Agent 跑着跑着挂掉是常态。工业级框架处理了多种异常:

故障 处理方式
输出被拦截 保留部分输出,发射可见错误事件
流中断 保留已完成工具,丢弃失败的
参数校验失败 宽容模式继续执行或发射错误 tool_result

🏗️ 整体架构一览

omp (CLI 层)
  工具工厂 (32 built-in + MCP + Extensions + Custom)
  │
  ↓
pi-agent-core (Agent 层)
  AgentLoop (双层循环: 外 steering + 内 LLM→Tools)
  normalizeTools → 工具 schema 标准化
  convertToLlm → AgentMessage → Message 格式转换
  │
  ↓
pi-ai (LLM 层)
  Provider 系统 (25+ providers, 文本协议编解码)
  streamSimple → 流式 LLM 调用
  EventStream → 逐事件处理
  │
  ↓
Provider API (DeepSeek / Anthropic / OpenAI / Gemini …)

📌 从代码中学到的四条原则

  • 抽象一层自己的工具协议——不直接依赖 LLM 提供商的函数调用格式,换模型基本不用改代码
  • 错误恢复是第一要务——Agent 跑长任务一定会出各种错,分层恢复策略比一次重试更靠谱
  • 上下文管理比推理更重要——工具描述太长就裁剪、频繁的 tool_choice 会破坏缓存、软要求比硬强制更省 token
  • 可观测性要内建——每一种事件都是可订阅的,上层可以实时渲染

这就是从概念到代码之间的鸿沟——原理看似简单,但要让它稳定地跑在 25+ 个模型提供商、32 个内置工具、几十个 MCP 插件的组合爆炸中,必须有一套健壮的抽象层。


六、演化全景图

从思想源头到今天的生态,整条脉络如下:

1940s 控制论 → 反馈循环概念
     ↓
1970s Unix 管道 → 工具链哲学
     ↓
2022.10 ReAct 论文 → 推理+行动的学术奠基(ICLR 2023)
     ↓
2023.06 OpenAI Function Calling → 第一次商用 API 级标准
     ↓
2023.11 并行函数调用 → 单步多工具并行
     ↓
2023-2024 生态爆发 → LangChain / Claude / Gemini / Hermes
     ↓
2024.11 MCP 协议 → 工具接口标准化
     ↓
2025.04 A2A 协议 → Agent 互联标准
     ↓
2026.01 Headroom → Token 压缩层(60-95% fewer tokens, same answers)
     ↓
2026 pi-agent → Provider 系统(25+ providers)+ 32 内置工具

七、瓶颈在哪里

工具调用这个机制已经基本成熟了。当前真正的瓶颈不在工具本身,而在三个地方:

1️⃣ 格式稳定性

Runtime 是瞎的——你输出格式错了它就报错,它不会帮你修正。Agent 能不能稳定输出正确的 JSON,决定了这个系统靠不靠谱。这也是为什么 OpenAI 的 Structured Outputs 和 omp 的 Hashline 编辑本质上在解决同一个问题:让 AI 的输出格式不再随机波动。

(关于 Hashline 如何把编辑成功率从 6.7% 提到 68.3%,之前在 oh-my-pi 的文章里聊过)

2️⃣ 多步推理

简单问题(查天气)调一个工具就够了。复杂问题("帮我做一个竞品分析报告")可能需要调用十几个工具,每一步的推理质量都会影响最终结果。

一步错,步步错。

3️⃣ Token 效率

每调一次工具,工具的描述、参数、返回结果都要写进上下文。步数一多,上下文就炸了。这也是为什么 Headroom 之类的 Token 压缩工具会在 2026 年火起来——Chopra 在开源峰会上分享的数据显示,Headroom 累计已为用户节省约 70 万美元、释放超过 2000 亿 Token

这个数字说明:Token 效率不是锦上添花,是刚需。


写在最后

AI 从来没有"碰到"过文件系统。它只是在文本空间里描述了一个动作,Runtime 替它实现了这个动作,再把结果翻译回文本喂给它。

这个循环就是"意识控制世界"的全部秘密。没有魔法,纯工程。

但正因为没有魔法,它才可靠,才可预测,才能被我们拿来踏踏实实地干活。

这就是 Tool Calling 的本质——一个接口加一个反馈环


参考来源

  • Wiener (1948). Cybernetics.
  • Salus (1994). A Quarter-Century of Unix.
  • Yao et al. (2022). ReAct: Synergizing Reasoning and Acting in Language Models. ICLR 2023.
  • Patil et al. (2023). Gorilla: Large Language Model Connected with Massive APIs.
  • OpenAI (2023). Function Calling 官方文档.
  • Anthropic (2024). Tool Use 官方文档 / MCP 协议.
  • Google (2025). Agent-to-Agent (A2A) Protocol.
  • Hermes Agent 官方文档. https://hermes-agent.nousresearch.com/docs[1]
  • IT之家 (2026.6.20). Netflix 工程师开源项目 Headroom,可节省 60%-95% Token 消耗.
  • InfoQ / Joab Jackson (2026.6). 砍掉 90% 冗余词元,省下 70 万美元:Netflix 开源工具狙击 AI 账单黑洞.
  • andrew.ooo (2026). Headroom Review: 60-95% LLM Token Compression.
  • earendil-works/pi 仓库. https://github.com/earendil-works/pi[2]
  • can1357/oh-my-pi 仓库. https://github.com/can1357/oh-my-pi[3]
  • headroomlabs-ai/headroom 仓库. https://github.com/headroomlabs-ai/headroom[4]

引用链接

[1]https://hermes-agent.nousresearch.com/docs

[2]https://github.com/earendil-works/pi

[3]https://github.com/can1357/oh-my-pi

[4]https://github.com/headroomlabs-ai/headroom