内容提要
文章梳理了Agent从ReAct到CodeAct的演进:ReAct是在循环中交替推理与行动的行为模式,CodeAct则让模型用可执行代码表达行动,便于实现循环、并发和数据处理。Pi Codemode是CodeAct在Pi中的具体实现,通过QuickJS沙箱限制权限。Pi从拒绝MCP转向内置MCP,借助Codemode和按需发现控制上下文成本。核心结论是:程序工作流负责确定性,Agent Loop负责决策,CodeAct表达复杂行动,MCP连接工具,上下文管理保障长任务。
延伸解读
控制流归属:先分清程序、模型与代码
文章把 Agent 设计的关键问题归结为控制流交给谁:固定工作流由程序掌握,适合步骤明确、失败代价高、需要复现的任务;Agent Loop 把决策交给模型,适合路径难以穷举的探索;CodeAct 则让模型生成代码来表达循环、并发和数据处理。三者并非替代关系,生产系统常在工作流中嵌入少量 Agent 环节,再以确定性测试收尾。
CodeAct 的收益有边界,不能直接外推
文章引用 CodeAct 论文在 M³ToolEval 上的结果:17 个模型中最高提升 20 个百分点成功率,行动次数最多下降约 30%。但作者明确提醒,这是特定模型与基准组合的“最高”值,不能推成所有任务都有同等增益。CodeAct 的优势集中在多工具循环、并发调用、结构化数据传递和结果裁剪等场景,单次查询或需逐次确认的高风险操作仍适合直接工具调用。
Pi Codemode 是更窄的实现,沙箱边界值得注意
Pi Codemode 与 CodeAct 共享“写代码编排工具”的思路,但运行在 QuickJS 沙箱中,没有 Node API、文件系统、网络和计时器,只能通过注入的工具访问外部,且只有脚本主动输出的内容回到模型上下文。这比论文中的通用 Python 解释器更保守,便于把权限和审计留在宿主层。不过脚本失败不会撤销已发生的工具调用,写入型工具仍需幂等键、权限检查和超时。
Pi 接纳 MCP 的方式:连接标准与上下文成本分开
Pi 曾公开表示不支持 MCP,但 0.99.0 已加入内置 MCP、Codemode 和 tool_search,0.99.2 又把默认 MCP 工具改为按需发现。文章指出,这并非放弃极简思路,而是拒绝把大量工具 schema 一次性塞进提示词。当前提供 codemode、deferred、direct、hidden 四种暴露方式,MCP 负责工具注册与调用,Codemode 负责组合与裁剪结果,二者互补。
Q&A
ReAct 和 CodeAct 到底有什么区别?
ReAct 是模型在 Agent Loop 中交替进行推理、行动和观察的行为模式,行动通常表现为一次结构化工具调用(如 JSON)。CodeAct 则改变行动的表达方式:模型可以生成一小段可执行代码,在代码中组合、并发和处理多次工具调用。两者层级不同:ReAct 描述循环如何推进,CodeAct 描述行动如何编码。
CodeAct 适合处理什么样的任务?
CodeAct 适合:同类工具需循环调用多次;多个独立调用可并发;一个工具的结构化结果要传给另一个工具;原始返回很大,只需过滤、聚合后的少量结果;中间步骤需要条件、重试、排序或统计。反之,单次简单调用、需逐次确认的高风险操作、需清晰审计每一步的任务,直接工具调用更合适。
Pi Codemode 和 CodeAct 是一回事吗?
不是。Pi Codemode 是 CodeAct 思想在 Pi 中的具体实现,共享“用可执行代码编排工具”的核心思路,但实现边界更窄:语言用 JavaScript,运行在 QuickJS 沙箱中,不能直接访问网络、文件系统、Node API 和计时器,只能通过注入的工具与模型能力访问外部;只有脚本主动输出的内容(如 text()、return)才回到模型上下文。
Pi 之前不是拒绝 MCP 吗,为什么后来内置了?
Pi 团队曾公开表示不支持 MCP,担心服务器连接后大量工具 schema 塞入上下文、长文本结果持续携带、单次 JSON 调用不便组合工具、常驻工具分散注意力并增加提示词成本。2026 年 9 月 29 日官方文章回顾了转向,0.99.0 加入内置 MCP、Codemode 和 tool_search,0.99.2 将默认 MCP 工具改为按需发现,1.0 继续压缩 Codemode 常驻提示并加强 MCP OAuth。核心思路未变:接纳 MCP 作为连接标准,但拒绝一次性灌入所有工具。
Pi 的 MCP 工具暴露方式有哪几种?
当前 Pi MCP 文档提供 4 种 exposure:codemode(默认值,工具不直接声明给模型,在 Codemode 脚本里发现和调用)、deferred(先由 tool_search 找到,后续模型调用再加载声明)、direct(直接声明给模型,也能从 Codemode 调用)、hidden(注册但不可达)。
CodeAct 能解决上下文过长的问题吗?
能部分解决。Codemode 可以在工具结果进入模型以前做一次程序化过滤,例如 MCP 返回 1000 条记录时,脚本内部完成筛选、排序和聚合,只把最后 20 条候选及统计结果交给模型,避免模型阅读全部原始数据。但它不能替代任务记忆、历史压缩和状态恢复,长程 Agent 仍需区分不可丢失的事件、当前回合需要的信息、只需保存到文件或数据库的结果,以及可按需发现的工具说明。
用 CodeAct 写代码操作工具,有什么风险需要注意?
脚本可能语法错误、陷入低效循环,或在后半段失败时已经完成前面的外部操作;Pi 文档明确说明脚本失败不会撤销已经发生的工具调用。因此写入型工具仍需设计幂等键、权限检查、超时和调用记录,不能只依赖 JavaScript 沙箱。此外,稳定重复的业务流程直接写成普通程序更可靠,模型每次现场生成 CodeAct 脚本会引入额外不确定性。
实际项目中应该怎么选择工作流、Agent Loop 和 CodeAct?
建议顺序:先判断任务能否用固定工作流完成(步骤清楚、失败代价高、结果需复现时优先程序控制);再判断开放环节是否需要 Agent Loop(路径难以预先穷举、需根据环境反馈持续探索时交给模型决策);遇到多工具、多数据和动态控制流时引入 CodeAct;接入 MCP 时再决定工具应该 direct、deferred 还是只通过 Codemode 暴露。这样能获得代码动作的灵活性,也不会把所有控制权和上下文成本一起交给模型。