从「工具调用」到「Code Mode」:AI Agent 正在经历一场范式转移

0 阅读11分钟

2026 年,Cloudflare、Anthropic、Pi、Pydantic 四家独立指向同一个结论:别再给模型描述工具了,给它一个运行时。


一、一个被忽视的隐性成本

先看一组数字。

GitHub 官方 MCP 服务器在连接时,会把约 55,000 个 token 的工具 schema 塞进上下文。而同样功能的 gh CLI,通过 --help 发现同样的能力面只需要约 200 个 token——相差 275 倍。

Anthropic 在自己的一篇工程博客里承认得更直接:「工具定义在优化前消耗 134K token。」

这不是个例。Playwright MCP 有 21 个工具、13.7k token;Chrome DevTools MCP 有 26 个工具、18k token。一个会话还没开始,7%–9% 的上下文窗口就已经没了。

更糟的是,这笔成本是按轮次重复支付的。每个 turn,这些 schema 都在 system prompt 里,永远在。成本公式是 O(工具数 × 轮次)。

于是行业里出现了一句流传很广的判断 ——「MCP 是个错误,bash 更好。」 说这话的是 Peter Steinberger。他不是在哗众取宠,而是在命名一个已经被生产环境验证的事实。


二、三种「coding surface」凭什么赢

要理解 Code Mode,得先理解一个概念:coding surface(编码界面) 。

bash 是一种。DuckDB 是一种。QuickJS 沙盒是一种。它们表面上毫不相像,但共享三个关键属性 —— 而这三个属性,恰恰是 MCP/REST/gRPC 这一族工具接口天生不具备的:

属性含义
模型本来就懂它训练数据里有万亿级 token 的 shell、SQL、JavaScript,流畅度是免费的
运行时自文档化--help、man、information_schema、DESCRIBE——agent 主动问运行时,而不是被动接受一份清单
可组合管道和 &&、JOIN 和 CTE、await 和函数调用 —— 一个表达式串联多个动作

对比之下,传统工具 API 是为程序调程序设计的:调用方早就读过 spec、写过 client、做过集成。REST/gRPC/MCP 全都预设了这些前置工作。它们运行时零可发现性、无代码无法组合,而且模型在训练时从没见过你那个特定的工具 schema。

凡是让它们适合 "程序调程序" 的特性,都让它们不适合 agent。


三、MCP 错了吗?不,只是用错了

一个常见误解是 "Code Mode 要取代 MCP"。不是。

Cloudflare 的 Kenton Varda 和 Sunil Pai 说得很清楚:

MCP 的真正价值不是 "工具调用协议",而是 "统一的 API 连接与学习方式"。

一个 agent 可以在完全不知道某个 MCP 服务器存在的情况下用它,反之亦然 —— 这在传统 API 时代几乎不可能。MCP 把连接、授权、文档标准化了。

所以真正的分歧不是 MCP vs CLI,而是:

一个供应商是 "永久占据你上下文窗口的一块地产",还是 "在 agent 需要之前安静待在一边"。

在连接时就加载的 schema 是敌人;按需自我披露的界面才是胜利。

MCP 完全可以做成 Code-Mode 风格:暴露一个极小的发现面,让 agent 通过代码去拉取需要的东西。协议没问题,用法有问题。


四、三家巨头,同一个方向

2025 年第四季度,Cloudflare 和 Anthropic 独立地在同一个季度发布了同一个想法。

Cloudflare:Code Mode

把 MCP 工具转成 TypeScript API,然后让 LLM 写代码调用它。官方结论:

我们惊讶地发现,当工具以 TypeScript API 的形式呈现时,agent 能处理更多、更复杂的工具。可能是因为 LLM 训练集里有海量真实 TypeScript,而工具调用的例子只是少量人造样本。

关键洞察:LLM 写代码调用 MCP,比直接调用 MCP 更擅长。

Anthropic:Code Execution with MCP

思路一致,表面不同 —— 把 MCP 服务器暴露成沙盒里的 Python 模块,agent 写 Python 而不是发工具调用。

效果数据非常硬:token 消耗从 150,000 降到 2,000—— 节省 98.7%。

用同一句话概括两者

Anthropic 的比喻一针见血:

让 LLM 用工具调用完成任务,就像让莎士比亚上一个月的普通话速成班,然后要求他用普通话写一部戏剧。这不可能是他的最佳作品。


五、不止于省 token:四个被低估的收益

省 token 只是第一层。Anthropic 的博客揭示了更深的价值:

1. 渐进式披露(Progressive Disclosure)

把工具变成文件系统上的代码,agent 可以按需读取定义,而不是一次性全读进来。配合一个 search_tools 工具,还能分级返回(仅名称 / 名称 + 描述 / 完整 schema)。

2. 上下文高效的结果处理

要取一张 10,000 行的表格:

  • 传统方式:10,000 行全部流经上下文,模型手动筛
  • Code Mode:在沙盒里 filter,只打印前 5 行

agent 看到 5 行,而不是 10,000 行。

3. 隐私保护(这个最被忽视)

中间结果默认留在执行环境里。agent 只能看到你显式 log 或 return 的东西。

更妙的是 PII token 化:从 Google Sheets 往 Salesforce 导客户信息时,模型看到的是 [EMAIL_1]、[PHONE_1],而真实数据从表格流向 Salesforce,全程不经过模型。

4. 状态持久化与 "技能" 沉淀

agent 可以把中间结果写文件,也可以把自己写好的代码存成可复用函数:

// ./skills/save-sheet-as-csv.ts
export async function saveSheetAsCsv(sheetId: string) {
  const data = await gdrive.getSheet({ sheetId });
  const csv = data.map(row => row.join(',')).join('\n');
  await fs.writeFile(`./workspace/sheet-${sheetId}.csv`, csv);
  return `./workspace/sheet-${sheetId}.csv`;
}

加一个 SKILL.md,就成了结构化技能。日积月累,agent 会自己长出一套高级能力工具箱。


六、Pi 0.99:Code Mode 进入产品级

2026 年 9 月 29 日,Pi 发布 0.99.0,把 Code Mode 做进了核心。

最重要的变化:Codemode 和 MCP 打通了。

「连接 MCP 服务器,让模型运行 JavaScript 来并行调用工具。」

Pi 的 codemode 扩展注册一个 exec 工具:模型写一个 async 函数,通过类型化的 codemode 对象编排当前启用的内置工具。

async () => {
  const root = await codemode.ls({ path: "." });
  console.log("Root entries:", root);
  return root;
}

并行能力是重点:

const [pkg, readme, config] = await Promise.all([
  tools.read({ path: "package.json" }),
  tools.read({ path: "README.md" }),
  tools.read({ path: "tsconfig.json"

三次读取,一次推理,全部并行。

三种模式,一个安全光谱

模式行为
on(默认)暴露 execute_tools + 常规非 bash 工具,写入锁定项目根目录
yolo包含原生 bash
off恢复常规 Pi 工具

沙盒模型:JavaScript 跑在 Worker 承载的 node:vm context 里,只暴露 codemode、受限 console 和 JSON 安全全局。不暴露 require、process、文件系统、网络 API。

⚠️ Pi 自己也诚实标注:这只是本地执行防护,不是 Cloudflare Worker 或 isolated-vm 级别的安全边界。


七、Pydantic AI:Python 阵营的对称实现

几乎同一时间,Pydantic AI 在 harness 里加入了 CodeMode。

问题陈述很精确:

标准工具调用的依赖批次之间往往需要额外的模型轮次。一个需要取 10 个条目再处理结果的 agent,可能要很多轮——延迟、成本、上下文用量全部上升。

方案: 把符合条件的工具包成一个 run_code 工具,模型写沙盒编排代码,用 asyncio.gather 扇出调用。

paris, tokyo = await asyncio.gather(
    get_weather(city='Paris'),
    get_weather(city='Tokyo'),
)
paris_c = round((paris['temp_f'] - 32) * 5 / 9, 1)
tokyo_c = round((tokyo['temp_f'] - 32) * 5 / 9, 1)
{'paris': paris_c, 'tokyo': tokyo_c}

两个实现细节值得注意:

  1. 选择性沙盒化:CodeMode(tools=...) 支持按名称 / 谓词 / 元数据选择哪些工具有资格进沙盒。shell 类工具故意留在外面—— 这样模型不用在生成的 Python 字符串里再 quote 一遍 shell 命令。
  2. 缓存感知:新工具被发现时会增长 run_code 的描述,导致 prompt cache 前缀失效一次。dynamic_catalog=True 把目录移到 agent instructions 里,用 ctx.enqueue 宣布新工具,保住缓存。

这说明一件事:Code Mode 的工程复杂度不在于 "跑代码",而在于和上下文缓存、渐进披露的配合。


八、没人诚实说出来的 tradeoff

有一篇分析文章(Michael Livs)指出了关键盲点:

工具的成本是「按轮次付」的。 schema 在 system prompt 里,每轮都在,成本 O(工具数 × 轮次)。

Code Mode 的成本是「按动作付」的。 agent 必须先发现 API 才能用。第一次调用一个新命名空间,至少要额外一轮:actions.find(...) → actions.describe(...) → 真正调用。成本 O(推理轮次 × 新命名空间数)。

这是两种不同的成本,谁都不免费。

真正的陷阱:只做了一半

很多所谓的 "Code Mode" 实现只做了第一步 —— 给 agent 一个沙盒和一个 fetch,然后就说完工了。

那不是 bootstrap(引导层),那只是个 surface(界面)。

结果就是:agent 现在得自己做所有 SDK 本来该藏起来的事 —— 认证、重试、分页、限流、base URL、编码、错误格式化。

认知负荷从「学我的工具 schema」变成了「从零构造 HTTP 请求」—— 而后者更糟,因为失败时没有 schema 可以响亮地报错。

设计 bootstrap 的三条规则

  1. 选模型本来就会的 surface。JS、SQL、bash、Python,不是你的 DSL。流畅度是免费的,你付不起放弃它的代价。
  2. 把每个「不需要 agent 做的逐次决策」搬进 bootstrap。认证、重试、分页、限流、base URL、请求头、编码、错误格式 —— 这些都不是 agent 的工作。如果你的 agent 代码看起来像初级工程师的任务单,你就做对了;如果看起来像 SDK 的 README,你就还没做完。
  3. 加发现机制,而不是加目录。别把整个 API 塞进 system message,给一组元动作(find、describe、check),让它按需拉取。渐进式披露在 API 层面和 skill 层面一样有效。

九、一个开放性判断

bash 已经给出了答案。

前沿模型在 shell 上被微调得足够充分,发现税实际上已经崩塌—— 模型知道 gh issue create --title 不用读 man page,知道 kubectl get pods -n 不用问,知道什么时候该管道给 jq。

bash 已经不再是一个 tradeoff,它是在无限能力面上的免费流畅度。

所以对每一个其它 code-mode surface(DuckDB、QuickJS-with-plugins、浏览器自动化)来说,问题只是何时:

第一个为自家 surface 微调出 "bash 级流畅度" 的厂商,就会在这个 surface 上把 tradeoff 抹平。

这才是 browsemode、runline,以及这个品类里每一个项目的赌注。


十、对实践的启示

如果你正在构建 agent 系统,这场范式转移给出了几条可操作的建议:

1. 先问「这个领域配得上一个 coding surface 吗」

  • 文件系统操作 → bash 已经赢了
  • 数据分析 → DuckDB 已经赢了
  • SaaS 编排 → 还没有赢家,这是机会窗口
  • 浏览器自动化 → 争夺中

2. token 预算要算总账

  • 工具 schema 的成本:O(工具数 × 轮次)
  • 发现成本:O(新命名空间数 × 推理轮次)
  • 工具数量超过某个阈值后,Code Mode 一定更划算 —— 找出你的阈值。

3. 渐进式披露是普适模式从 skill 到 API 到工具目录,逻辑一致:别预加载,让 agent 按需拉。

4. 安全边界要认真设计Code Mode 意味着让模型生成可执行代码。沙盒、资源限制、监控、权限绑定 —— 这些基础设施成本是真实存在的,不能省。

5. 不要半途而废给了沙盒就要给 bootstrap。否则你不是在降低认知负荷,只是在转移它 —— 而且转到了更糟的地方。


结语

从「给模型描述工具」到「给模型一个运行时」,这个转变的本质是:

我们终于承认了一件事 —— 模型最擅长的不是遵循我们发明的协议,而是使用它已经在万亿 token 里见过的东西。

MCP 没有错。工具调用没有错。它们只是在正确的抽象层级上,放了错误的东西。

真正的战场是上下文窗口的每一寸地产。而 Code Mode 说的只有一句话:

别占地方。等我要的时候,再出现。


参考资料

  1. Cloudflare Blog — Code Mode: the better way to use MCP(Kenton Varda & Sunil Pai)
  2. Anthropic Engineering — Code execution with MCP: Building more efficient agents(2025-11-04)
  3. Pi Changelog — Pi 0.99.0(2026-09-29)
  4. Pi Package Docs — pi-codemode-extension
  5. Pydantic AI Docs — Code Mode
  6. Michael Livs — Ergonomic coding surfaces for agents (a.k.a Code Mode)
  7. Scalekit Benchmark — CLI vs MCP