CodeAct代码优先智能体为何还没赢?深度剖析范式困境

一个更优雅的范式,为何没有胜出?
2024年,Wang等人发表的CodeAct论文提出了一个看似简单却颇具颠覆性的观点:与其让大模型输出JSON格式的工具调用(tool call),不如让它直接生成可执行代码作为自己的行动。在这种范式下,工具不再是被逐个调用的API,而是变成了你可以在代码里直接调用的函数。
CodeAct的理论根基可以追溯到程序合成(Program Synthesis)领域的长期研究。早在深度学习时代之前,研究者就探索过让AI系统通过生成程序来解决问题的路径。CodeAct的创新在于将这一思想与大语言模型的代码生成能力相结合,利用LLM在大规模代码语料上预训练获得的编程能力,将其从「辅助编程」提升为「以编程作为行动」。
CodeAct的核心创新在于重新定义了LLM Agent的「行动空间」(action space)。传统的ReAct框架中,模型的行动被限制为从预定义工具集中选择一个工具并填入参数——这本质上是一个离散的、受限的决策空间。而CodeAct将行动空间扩展为整个编程语言的表达能力——理论上是图灵完备的表达空间,可以表达任意可计算的操作序列。模型可以在一次行动中完成变量赋值、条件判断、循环迭代、异常处理等复杂逻辑。论文中的实验数据显示,在多步骤任务中,CodeAct相比传统JSON工具调用方式,平均减少了约30%的交互轮次,同时在需要数据处理和逻辑组合的任务上表现显著优于基线。
这个思路的好处显而易见:代码天然支持嵌套调用、循环以及各种表达能力更强的逻辑结构;更关键的是,中间数据不必再经过上下文窗口(context window)——它们可以留在执行环境里,而不是作为文本反复塞进对话历史。这一点的深层含义在于:当前LLM Agent架构中,对话历史是模型的唯一「记忆」载体,所有信息必须以文本形式实体化才能被模型访问,这迫使系统采用低效的传值(pass-by-value)模式。而代码优先范式通过引入独立的执行环境(如Python解释器),天然支持变量引用和内存中的对象持久化,避免了反复序列化大型数据的开销。

然而,两年过去了,一位Reddit开发者发出了灵魂拷问:几乎所有人实际在用的智能体框架,仍然是「聊天优先」(chat-first)、基于ReAct、基于JSON工具调用的。对话历史进去,工具调用出来,执行,再提交,如此循环往复。即便CodeAct风格的代码执行有所渗透(比如微软的Agent Framework提供了code-act provider),它也往往是以一个execute_code工具的形式,被「螺栓」式地拧到一个对话式智能体上。Bash成了关键工具,但通常只是众多工具中的一个。
ReAct聊天优先框架为何率先赢得市场?
ReAct(Reasoning + Acting)框架由Yao等人于2022年提出,其核心思想是让LLM交替进行推理(Thought)和行动(Action),并观察行动结果(Observation)形成闭环。ReAct的提出解决了一个关键问题:纯推理(Chain-of-Thought)缺乏与外部世界交互的能力,而纯行动(直接工具调用)缺乏推理透明性。通过交替的Thought-Action-Observation循环,模型的决策过程变得可解释、可追踪。
在实际工程实现中,ReAct通常依赖于结构化的工具调用协议:模型输出一个包含工具名称和参数的JSON对象,框架层解析该对象并路由到对应的工具执行器,执行结果再以文本形式注入对话历史供模型下一轮参考。LangChain、LlamaIndex等框架将ReAct抽象为标准化的Agent执行循环,开发者只需定义工具集和系统提示即可快速搭建Agent应用——这种低门槛的开发体验是ReAct范式快速普及的关键因素之一。这种模式的工程优势在于确定性强、易于调试和监控,但其代价是每一步都需要完整的模型推理循环,即便是简单的数据传递也要经过序列化-反序列化-再注入上下文的过程。
这位Reddit开发者的分析相当中肯。2022年底ChatGPT大获成功之后,行业在2023到2024年间的下一步自然是给模型加上推理能力和工具调用能力。「聊天优先」是阻力最小的路径——它顺着已有的对话交互模式往前走,工程改造成本最低。
换句话说,Chat-first的胜出并非因为它在技术上更优越,而是因为它在时间线上占了先机,符合当时整个生态演进的惯性。这是一个典型的路径依赖问题。
制度性摩擦:代码优先范式如何输给「先来的」
作者对CodeAct没能占据主流的核心判断是:制度性摩擦(Institutional Friction)。即便我们才进入LLM浪潮短短几年,这种摩擦已经足够强大。他列举了几个层层递进的原因:
模型训练偏向聊天式工具调用
巨量的RLHF投入,都花在了让模型输出格式良好的结构化工具调用上。RLHF(Reinforcement Learning from Human Feedback)是当前对齐LLM行为的核心技术之一,在工具调用场景中,模型需要学会在恰当的时机决定调用工具、选择正确的工具、并生成格式严格的参数JSON。这一能力的训练涉及大量精心构造的训练数据:包括人工标注的工具调用示例、合成的多步骤工具使用轨迹、以及针对格式正确性的奖励信号。
具体而言,RLHF在工具调用场景中的应用比通常理解的更为复杂。除了基本的格式正确性(JSON语法合法、参数类型匹配),奖励模型还需要评估工具选择的恰当性(是否选择了最合适的工具)、参数语义的准确性(参数值是否正确反映了用户意图)、以及调用时机的合理性(是否在需要时才调用工具,而非过度调用)。此外,DPO(Direct Preference Optimization)等更新的对齐技术也被广泛应用于工具调用能力的微调,进一步巩固了模型在结构化输出方面的行为模式。OpenAI、Anthropic等公司在这一方向上的投入是巨大的——据估计仅GPT-4的工具调用能力就经历了数千小时的人工标注和数轮迭代优化。
这意味着,一个结构上更优越的范式,完全可能输给一个结构上更差、但背后有上万小时调优的范式。这是最根本的一点——不是范式不行,而是模型的「肌肉记忆」被训练成了另一个样子。改变输出范式意味着大量训练基础设施和数据管线需要重新设计,这种投入形成的惯性极其难以逆转。
通信协议本身假定了聊天优先架构
主流API的请求结构messages: [...]加上tools: [...]的schema列表,本身就是聊天优先的。这种假设直接编码进了协议层,不是应用层能轻易绕过的。从OpenAI的Chat Completions API到Anthropic的Messages API,请求体的顶层结构都预设了「一段对话历史 + 可用工具列表」的范式,模型的输出也被强制归类为「assistant message」或「tool_calls」——这套类型系统中根本没有「一段需要被执行的程序」这个语义槽位。
这种协议层的锁定效应是深远的。当数以万计的应用都构建在这套API之上时,任何对协议的根本性修改都会引发大规模的兼容性问题。即便API提供方想要支持代码优先范式,也只能以向后兼容的方式逐步引入,而非进行破坏性变更。这就是为什么代码执行往往只能以一个execute_code工具的形式被「塞入」现有框架,而非作为一等公民获得原生支持。
MCP协议的设计局限
这是作者一个很尖锐的观察。Model Context Protocol(MCP)由Anthropic于2024年底发布,旨在标准化LLM与外部工具和数据源的交互方式。其技术架构基于JSON-RPC 2.0协议,定义了三种核心原语:Tools(可调用的函数)、Resources(可读取的数据源)和Prompts(可复用的提示模板)。MCP的设计哲学是「服务器暴露能力,客户端(模型)按需调用」,每次交互都是一个完整的请求-响应回合。
JSON-RPC 2.0的底层意味着每次工具交互都是一个独立的请求-响应对,没有原生的会话状态管理。虽然MCP定义了SSE(Server-Sent Events)传输层以支持流式通信,但其核心交互模型仍然是无状态的RPC调用。这与gRPC的双向流、WebSocket的持久连接等模式形成对比。值得注意的是,MCP的Sampling功能允许服务器反向请求客户端(即模型)进行推理,这在一定程度上打破了单向调用的限制,但仍未改变其回合制的本质特征。
MCP通过JSON-RPC逐个调用类型化工具,本质上是一个回合制的工具选择协议。而代码优先的范式想要的,更接近一个「可导入的模块」——更重要的是,它需要的是数据句柄(data handles)而非数据载荷(payloads),这样中间结果就不会以文本形式实体化到上下文里。数据句柄是一个指向远程对象的引用,允许延迟加载和增量操作;数据载荷则要求每次都将完整数据序列化传输。这反映了分布式系统设计中的经典权衡:传值(pass-by-value)vs 传引用(pass-by-reference)。在传统软件工程中,对于大型数据对象,传引用几乎总是更高效的选择。从这个角度看,MCP在骨子里就是「聊天形状」的——它天然倾向于离散的、回合制的交互模式,而代码优先范式所需要的「在一个执行上下文中持续访问对象、维持状态、进行流式数据处理」在MCP当前的架构中缺乏原生支持。
工具链和评测体系依赖离散调用
下游的一切基础设施——tracing、evals、监控——都是围绕「它调用了哪个工具、传了什么参数」构建的。LangSmith、Braintrust、Arize等主流Agent可观测性平台,其数据模型的核心单元就是「一次工具调用」:包括调用时间、工具名称、输入参数、输出结果、延迟和成本。这种设计选择并非偶然——它直接对应了ReAct框架中Action的离散化特征,使得每一步操作都是可审计、可重放、可计费的。
换成代码优先,这套观测体系需要推倒重来——你需要的不再是「调用了什么工具」,而是「执行了什么代码、在哪一行产生了副作用、运行时状态如何变化」,这是一套完全不同的监控范式,更接近传统软件的APM(Application Performance Monitoring,应用性能监控)而非当前Agent的trace体系。APM工具(如Datadog APM、New Relic)通过字节码注入或运行时hook来追踪函数调用链、内存分配和I/O操作,其粒度和复杂度远超当前Agent监控工具的设计假设。要为代码优先Agent构建等价的可观测性,需要融合代码分析、运行时监控和因果追踪等多种技术,这本身就是一个不小的工程挑战。
安全沙箱是绕不过的挑战
代码优先意味着你必须搭建一个沙箱来运行代码,还要谨慎决定哪些函数被允许调用,以及如何在不直接管理凭证的情况下处理认证问题。目前业界常用的沙箱方案包括:基于容器的隔离(如Docker/gVisor,通过Linux namespace和cgroup实现资源隔离)、基于WebAssembly的轻量级沙箱(如Wasmer/Wasmtime,通过WASM的线性内存模型和能力安全模型实现隔离)、以及基于虚拟机的强隔离方案(如Firecracker microVM,通过硬件虚拟化提供近乎裸金属的隔离强度)。每种方案在安全性、启动延迟和资源开销之间有不同的权衡:容器方案启动快(毫秒级)但隔离较弱;microVM隔离强但启动较慢(百毫秒级);WASM介于两者之间且跨平台性好,但对Python等动态语言的支持仍在成熟中。
作者的赌注是「沙箱 + 出口代理(egress proxy)」的组合。出口代理是一个网络层的安全控制机制——沙箱内的代码不直接持有API密钥或数据库凭证,而是通过一个受控的代理层发起外部请求,代理层负责注入认证信息、执行访问控制策略和审计日志记录。这种模式类似于企业网络中的正向代理,但专门为Agent代码执行场景设计:它可以基于请求的目标地址、HTTP方法、请求体内容等维度实施细粒度的访问控制。这种模式在安全性上优于直接在沙箱内暴露凭证,但增加了架构复杂性和请求延迟。他也指出,其实大多数智能体已经有bash工具了,运行智能体自己编写的实时代码早已成为现实。目前E2B、Modal等平台已提供开箱即用的代码沙箱服务,一定程度上降低了这一门槛。
推理模型暴露旧架构的裂缝
作者分享了一个非常具体的踩坑经历,很能说明问题。他最近尝试切换到一个推理模型(reasoning model),结果一切都崩了。
推理模型(如OpenAI的o1/o3系列、DeepSeek-R1等)与传统聊天模型的核心区别在于其内部包含一个扩展的「思考」阶段——这本质上是一种test-time compute scaling,通过在推理时消耗更多计算资源来提升输出质量。在这一阶段中,模型会生成大量中间推理token(通常对用户不可见),然后才输出最终答案。这种架构对工具调用管线提出了新的挑战:推理过程中模型可能需要多次「假设性」地考虑工具调用,其内部状态管理与传统的单轮生成截然不同。此外,推理模型的输出往往更长、更结构化,对流式传输(streaming)的处理逻辑也有不同要求——传统模型的streaming是token级别的线性输出,而推理模型需要区分「思考中」和「输出中」两种状态,并且思考阶段的token通常不应被流式暴露给框架层的工具调用解析逻辑。
崩的不是推理内容的解析,而是收到了provider返回的400错误——服务端严格校验tool_calls[].function.arguments必须是合法JSON,而一条格式不对的消息,就会「毒化」整个对话历史,导致后续每一个请求都返回400。这一问题的根源在于,推理模型在生成工具调用参数时,其内部推理过程可能产生中间状态的非法JSON片段——例如模型在「思考」阶段生成了一个带有注释或省略号的伪JSON作为规划,而框架层错误地将其捕获并注入了对话历史。由于API的校验是对整个messages数组进行的,一条历史消息中的格式错误会永久性地阻塞后续请求。
有意思的地方在于:这不是某个模型的特定bug,而是一个推理模型这一整类的缺口。它之所以存在,正是因为整条工具调用/流式传输的代码路径,都是在假定「聊天优先、非推理模型」的前提下写出来的。当新一代推理模型出现时,旧的假设开始漏水。这恰恰印证了制度性摩擦的真实存在——不仅是对新范式的阻力,甚至对同一范式内的演进也构成了阻碍。
代码优先智能体的未来:悬而未决的问题
作者坦诚自己一直在实验一个真正意义上的代码优先框架,除了论文里论证的那些好处,他更看重的是:它给了在聊天线程之外探索UI形态的巨大自由。他提到即便是Claude Routines,本质上也只是加了定时触发器的聊天线程而已。
这里涉及一个更深层的问题:当Agent的行动是代码而非工具调用时,其执行过程天然具有「程序」的特征——有明确的控制流、可以被暂停和恢复(类似协程或continuation)、可以有并发分支、可以维护复杂的运行时状态。这意味着Agent的交互界面不必局限于对话式的逐条消息展示,而可以呈现为工作流可视化、实时代码执行面板、甚至是类似Jupyter Notebook的交互式环境。想象一个Agent在处理数据分析任务时,用户可以看到代码的逐步执行、中间变量的实时值、数据的可视化变换——这种交互体验远比「等待模型回复一条消息」要丰富得多。这种UI形态的自由度,是聊天优先架构很难提供的,因为后者将所有交互都压缩进了「消息」这一单一抽象中。
他抛出了两个真诚寻求答案的问题,也值得整个社区思考:
- 有没有人真正在生产环境里跑起来过一个代码优先的系统?收益如何?
- MCP在根本上就是聊天形状的这个判断,是否有误?最近的更新有没有改变什么?
技术优越与生态胜出的鸿沟
这篇讨论的价值,不在于给出结论,而在于清晰地拆解了「技术优越」与「生态胜出」之间的鸿沟。这在技术史上并非孤例——Betamax对VHS(索尼的Betamax在画质和技术指标上优于JVC的VHS,但VHS凭借更长的录制时间、更低的授权费和更开放的生态最终胜出)、LISP对C/C++(LISP在表达力和元编程能力上远超C系语言,但后者凭借硬件亲和性和工业生态主导了系统编程)、Plan 9对Unix(贝尔实验室的Plan 9在概念一致性上远超Unix,但Unix及其后继者凭借庞大的已有代码库和用户群维持了统治地位),都是技术上更优雅的方案输给了生态更成熟的方案的经典案例。
CodeAct的故事提醒我们:在快速演进的AI领域,先发优势、训练投入、协议标准和观测工具链,共同构成了强大的路径锁定。一个范式即便在架构上更优雅,也需要跨越模型训练、通信协议、安全沙箱、开发工具四道门槛,才有可能真正撼动既有格局。
代码优先智能体或许还没赢,但作者用一个「(yet)」保留了悬念——随着推理模型暴露出旧假设的裂缝,这场范式之争远未到盖棺定论的时候。值得注意的是,历史上许多后来居上的技术范式(如容器化取代虚拟机——Docker在2013年发布后仅用3-4年就从边缘工具变为行业标准;REST取代SOAP——RESTful API在2005年后逐步取代了企业级SOAP Web Services),往往是在基础条件成熟到某个临界点后才发生快速翻转。这种翻转通常需要三个条件同时满足:新范式的核心优势在特定场景下产生了数量级的改进、支撑新范式的基础设施足够成熟、以及出现了一个标杆性的成功案例来降低采纳者的认知风险。
对于代码优先智能体而言,这个临界点可能取决于几个变量:沙箱基础设施的标准化程度(E2B、Modal等平台正在推动这一进程)、模型对代码生成的原生优化力度(如果主流模型开始将「生成可执行程序」作为一等输出模式进行优化)、以及是否会出现一个足够有说服力的杀手级应用来证明这种范式在特定场景下的压倒性优势——例如在复杂数据处理、多系统编排或长时间运行的自主任务中,代码优先方案展现出远超工具调用方案的效率和可靠性。
核心要点
相关推荐

EmbeddedSass for .NET:告别Node.js依赖的Sass编译方案
EmbeddedSass for .NET基于官方Embedded Sass协议,让.NET开发者无需Node.js即可原生编译Sass/SCSS。本文解析其技术原理、应用场景及与ASP.NET生态的集成方式。

旧金山到新加坡时差:硅谷科技人的跨太平洋日常
旧金山与新加坡之间存在15-16小时时差,频繁往返两地已成为科技从业者的常态。本文解析SF到SG时差挑战、两大科技中心的连接趋势,以及AI行业全球化布局背后的人才与资本流动。

Anthropic官方Claude Code插件目录发布:精选高质量扩展生态
Anthropic发布官方Claude Code插件目录claude-plugins-official,提供经过审核的高质量插件精选集。了解官方目录的定位、核心价值及对AI编程工具生态的深远影响。