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}
两个实现细节值得注意:
- 选择性沙盒化:
CodeMode(tools=...)支持按名称 / 谓词 / 元数据选择哪些工具有资格进沙盒。shell 类工具故意留在外面—— 这样模型不用在生成的 Python 字符串里再 quote 一遍 shell 命令。 - 缓存感知:新工具被发现时会增长
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 的三条规则
- 选模型本来就会的 surface。JS、SQL、bash、Python,不是你的 DSL。流畅度是免费的,你付不起放弃它的代价。
- 把每个「不需要 agent 做的逐次决策」搬进 bootstrap。认证、重试、分页、限流、base URL、请求头、编码、错误格式 —— 这些都不是 agent 的工作。如果你的 agent 代码看起来像初级工程师的任务单,你就做对了;如果看起来像 SDK 的 README,你就还没做完。
- 加发现机制,而不是加目录。别把整个 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 说的只有一句话:
别占地方。等我要的时候,再出现。
参考资料
- Cloudflare Blog — Code Mode: the better way to use MCP(Kenton Varda & Sunil Pai)
- Anthropic Engineering — Code execution with MCP: Building more efficient agents(2025-11-04)
- Pi Changelog — Pi 0.99.0(2026-09-29)
- Pi Package Docs — pi-codemode-extension
- Pydantic AI Docs — Code Mode
- Michael Livs — Ergonomic coding surfaces for agents (a.k.a Code Mode)
- Scalekit Benchmark — CLI vs MCP