从工具调用到代码执行:Agent的Code Mode范式转移与工程实践

发布时间:2026/10/22 4:44:08
从工具调用到代码执行:Agent的Code Mode范式转移与工程实践 过去三个月我在好几个 Agent 项目里都把「工具调用」换成了「代码执行」作为默认动作。不是工具调用不好用而是当你认真做了一两个长任务之后会明显踩到一个临界点预定义工具越来越多Agent 的动作空间反而越来越僵遇到没见过的边界情况就只能「原地打转」。这个临界点出现的时候就是 Code Mode 该上场的时候。所谓 Code Mode我给它下一个朴素定义Agent 不再依赖提前注册好的有限工具集而是在一个受控、可回滚的运行时环境里动态生成代码、执行代码、读取反馈、反复修正直到把任务做完。这跟传统的 Function Calling / Tool Call 路线不是同一个壳子套新皮而是整套动作空间、容错方式、状态管理逻辑都在变。这篇文章我把这几年在实际项目里的观察、拆解和踩坑记录整理出来给正在做 Agent 的朋友们一个参考。1. 从「配工具」到「给环境」这场转移是怎么发生的1.1 工具调用的黄金时代可控但也把自己框死了早期做 Agent 应用最主流的路子是「函数调用 / 工具调用」。流程很简单开发者把能力封装成一个个函数给每个函数写清楚名字、描述、参数格式塞进模型上下文里模型在推理时根据任务挑一个函数填好参数返回运行时解析并执行。这套方案的价值在于「可控」。每个工具能做什么、不能做什么都是提前约定的动作空间封闭审计线清晰单次调用延迟也很低。一个查天气的 Agent只需要暴露query_weather(city)一个工具模型永远不可能去读文件、跑脚本、改系统配置。对于业务场景固定、边界明确的任务工具调用至今仍然是性价比最高的方案。但金色光环下有个结构性的天花板工具集是人类手工定义的而真实任务的长尾分布是无限的。第一周六个工具够用第二周发现用户要处理 PDF 里的表格你写个parse_pdf第三周又要处理 Excel 里的脏数据你写个clean_excel第四周来了个「帮我汇总这几个文件里所有大于阈值的异常记录」你会发现前面所有工具的单点能力都覆盖不了这种组合型任务。最后工具越堆越多模型在上下文里选工具的行为越来越像「在一万条目录里翻找」。我见过某个模拟项目为了做一个「跨平台数据比对」的 Agent团队注册了 68 个工具光系统提示词就塞了快两万 token。结果模型经常在相近语义的工具之间选错或者参数填得格式正确但语义完全不对。问题不在模型笨而是这个模式逼着模型去理解「人类为每种情况预设的窄接口」而不是理解「任务本身」——任务一旦复杂工具调用必然难以为继。1.2 Code Mode 的崛起模型能写代码这一步棋就活了Code Mode 的底层逻辑完全相反不给 Agent 预设「做什么」的接口而是给一个「怎么做」的环境。你不用告诉它这个世界有哪些函数你只需要说「环境里有 Python、文件系统、依赖安装器你看着办」。为什么这件事现在才火起来而不是三年前核心原因是推理模型代码能力的跃迁以及沙盒运行环境的逐渐成熟。今天的模型在生成可执行代码、读懂报错、自主 debug 这件事上水平已经接近一个「有点经验的初级开发」。当这套能力叠加到一个能真实执行代码的环境里Agent 就从一个「只会按遥控器按钮的机械臂」变成了「能在厨房里自由发挥的厨师」。举个实际例子。任务是「读取某个 CSV剔除掉重复行统计各城市销量输出一张排行图」。在工具调用方案里你需要准备文件读取工具、CSV 解析工具、数据清洗工具、聚合统计工具、图表绘制工具还得祈祷模型能按正确的顺序把它们串起来。在 Code Mode 方案里Agent 只需要pandas一顿操作从读文件到画图一根流水线走完中间遇到报错自己改代码最后还能把图表保存成文件扔给你。这一步棋的关键不在于「少写几个工具定义」而在于动作空间的质变。工具调用模式下的动作空间是离散的、有限的必须枚举Code Mode 下的动作空间是连续的、近似无限的靠代码生成来覆盖。枚举总有漏网之鱼而生成能覆盖长尾。1.3 为什么说是「范式转移」而不是「升级」很多人会觉得 Code Mode 只是「工具调用的一种特殊形态」把 Python 解释器本身当成了一个超级工具。真正用过一段时间后你就会明白这两者在多个维度上是不同物种我用一张表直接对比对比维度工具调用Tool UseCode Mode动作空间有限、离散只能调用已注册工具无限、连续由代码动态生成抽象层级API 语义人类给接口写说明编程语言直接操作数据和逻辑错误恢复预先定义错误码模型猜读运行时报错改代码再跑上下文消耗大量工具描述占用输入随工具数膨胀代码即指令紧凑且自解释状态管理函数执行完毕状态即失中间数据靠外部存储文件系统就是记忆中间产物落盘可续跑长尾覆盖靠堆工具数量指数级维护成本靠模型代码能力复杂度相对平稳从这个表能看出来「升级」只是换了更先进的动作执行器而「范式转移」是改变了整个 Agent 运行的三层基础怎么做决策、怎么从错误里恢复、怎么记忆中间状态。这三点恰恰决定了一个 Agent 在真实粗粝环境里能走多远。2. 核心机制Code Mode 到底在解什么问题2.1 静态工具定义的「天花板」一个 JSON Schema 的困局要理解 Code Mode 解的是什么问题先得正视工具定义在天花板下的憋屈。传统工具调用的核心资产是「工具描述」通常长这样{ name: query_daily_sales, description: 查询指定日期范围的销售数据返回按渠道聚合的金额列表, parameters: { type: object, properties: { start_date: { type: string, format: date }, end_date: { type: string, format: date }, channel: { type: string, enum: [online, offline, all] } }, required: [start_date, end_date] } }这段描述写得好不好直接决定模型能不能正确调用。但两个结构性矛盾永远绕不开第一参数语义是压缩过的。channel: online到底代表哪些具体渠道模型只能根据名字猜。如果业务定义里 online 包括小程序、App、H5 三个来源模型并不知道这三个来源的边界。一旦用户问「App 和小程序加起来的销量」这个静态接口就卡死了因为参数枚举里没有这个组合。第二工具描述的数量会反噬上下文。工具越多系统提示词越长模型注意力被稀释选错工具的概率不降反升。实际项目里工具超过三四十个以后正确率会明显下滑而 Code Mode 模式下这些「组合查询」就是两行 pandas 代码的事不需要任何人提前穷举。用一句话概括这个困局静态工具是「设计时封装的答案」Code Mode 是「运行时推导的解法」。前者的维护成本按工具数线性甚至指数增长后者只需要模型会写逻辑。2.2 代码生成把「枚举接口」变成「推演过程」Code Mode 解问题的动作不再是「选一个函数」而是「写一段程序」。说起来只是动作形式的差别实际推演能力差了很远。举例任务给一个包含多层子目录的项目代码库做「函数依赖分析」找出哪些函数从未被其他函数引用。工具调用模式下你得预先定义目录遍历、文件解析、符号提取、引用统计、结果格式化五类工具并对每种语言写不同解析逻辑工作量巨大——这就是为什么传统静态分析的 Agent 产品很难做。Code Mode 模式下Agent 自己就能写出类似下面的逻辑在环境里跑完给你结论import os, ast from collections import defaultdict defined set() referenced defaultdict(int) for root, dirs, files in os.walk(src): for f in files: if f.endswith(.py): path os.path.join(root, f) tree ast.parse(open(path).read()) for node in ast.walk(tree): if isinstance(node, ast.FunctionDef): defined.add(node.name) elif isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load): referenced[node.id] 1 unused [fn for fn in defined if referenced[fn] 0] print(未引用函数, unused)这段代码严格来说并不算完美比如它会把函数定义所在文件自己的引用也算进去但没关系——Code Mode 的美妙之处在于它是一个闭环代码跑完输出结果Agent 自己看到结果里有误报可以立刻改代码、加排除逻辑、重跑。它不是在调用别人准备好的「正确答案」而是自己在推演问题的解。这就是「从工具到代码」的实质Agent 第一次可以自由地修改自己解决问题的能力来源而不是被开发者预设的能力边界所框定。2.3 状态与记忆文件系统是新的上下文工具调用模式下有一个很隐蔽但致命的短板函数执行是有状态边界的。假设你让 Agent 先下载一份数据、清洗、建模、出报告每一步都靠独立工具执行。上一个工具处理完得到的结果如果要传给下一个要么写在系统外的临时库里要么强行塞回对话上下文。可一旦中间结果很大比如一版清洗后的 DataFrame你不可能把它整个塞进模型上下文里。于是这个任务经常链断在中间。Code Mode 天然绕过了这个问题。Agent 可以把每一步的中间产物写成文件raw.csv、cleaned.csv、model.pkl、report.xlsx下次执行直接pd.read_csv(cleaned.csv)接着干。文件系统在这里扮演了「外部记忆」的角色比大模型上下文便宜、持久、可回放而且还偷不走。这也是我理解为什么很多 Agent 产品要把「工作目录」这个概念做得那么重。一个带持久化工作目录的 Agent本质上是在结构上给自己装了一个「可跨对话续用的记忆体」。上下文窗口终归是「短时记忆」而文件系统是「硬盘」两者一配合Agent 能跑通的任务复杂度直接上一个台阶。3. 实操给 Agent 接上 Code Mode 的正确姿势3.1 先搭一个安全的执行沙盒这是所有前提的前提如果说 Code Mode 最大的优点是「自由」那它最大的风险也是「自由」。让一个 Agent 能跑任意代码就等于把一个陌生开发者的脚本放进了你的磁盘和网络里。所以真正动手接 Code Mode 之前第一件事不是调模型而是搭隔离环境。我的建议基线是这么一套组合用容器或轻量虚拟机隔离执行环境主系统目录只读挂载默认断网如果业务确实需要拉数据用白名单代理只放行特定域名限制 CPU、内存、磁盘配额防止 Agent 写出一个while True把资源吃爆设置单次任务执行超时比如 120 秒强制终止工作目录落到宿主的临时挂载点任务结束直接销毁防止残留文件污染下一次任务。实操时我常用的沙盒启动逻辑大概长这样不同容器引擎的写法略有差异思路一致# 伪代码沙盒启动实际命令取决于容器引擎实现 sandbox run \ --image python:3.11 \ --no-network \ --memory 512m \ --cpus 1 \ --timeout 120 \ --read-only-fs \ --workdir /tmp/agent-job-001 \ python /tmp/agent-job-001/main.py这里每个限制都是有理由的--no-network挡住了恶意下载和回传--memory 512m和一核 CPU 保证一个失控脚本不至于拖垮宿主机--timeout是「断头铡」Agent 陷入死循环的时候至少能被终止--read-only-fs是防止它通过漏洞改系统目录。别嫌这些限制麻烦——我见过太多人图省事结果 Agent 在测试环境里把临时目录塞满或者无限拉取依赖包最后整个服务被拖挂。安全基线这东西宁可过度设计。3.2 任务分诊不是所有任务都该进 Code Mode有了安全环境下一步是学会「分诊」。Code Mode 不是银弹有些任务直接上工具调用反而更快更稳。我做项目时通常会按这张表来决定走哪条路任务类型推荐模式理由单点状态查询查天气、查库存、查订单工具调用延迟低、成本低、结果可预期固定流程业务发邮件、创建工单、推送消息工具调用动作边界明确且需要操作外部系统工具更安全数据处理、文件整理、格式转换Code Mode长尾格式多代码能覆盖任意情况信息爬取、网页解析、内容聚合Code Mode每个网站结构都不一样工具预置不现实代码库分析、测试脚本编写Code Mode本身就是代码任务用代码处理最直接纯知识问答、头脑风暴两者都不用直接对话别让 Agent 瞎折腾为什么「固定流程业务」不要乱上 Code Mode因为发邮件这种操作写死成工具能保证参数校验、权限审批、审计日志一条链是完整的而让 Agent 自己写个 SMTP 脚本去发虽然也能跑但安全性和合规性都是裸奔。我见过最离谱的一次是 Agent 在 Code Mode 下为了完成「清理临时文件」的任务试图rm -rf一个挂载点目录下的东西——代码世界里没有「工具边界」概念它只会按自己理解的目标干活。这个经验反过来也重要判断一个任务适不适合 Code Mode不是看它复不复杂而是看它「结果的正确性」能不能通过执行反馈来验证。能验证的报表对不对、结果文件生成没生成适合代码执行不好验证或者涉及外部副作用不可逆的删除、发送、下单老老实实用工具。3.3 实测记录同一份数据两条路线谁更顺我在一个模拟项目里做过很有意思的对比测试任务是「处理一份含大量脏数据的销售 CSV剔除无效记录、按城市汇总、输出一份排名前五的图表」。两条路线跑了同一个任务过程差异非常典型。先看工具调用路线。为了让这套方案能跑我预先定义了五个工具read_csv、validate_row、aggregate_by_city、generate_chart、write_report。听上去覆盖面已经够全了但一跑就露馅。模型在思考「什么叫有效记录」时完全依赖我写进validate_row描述里的规则然而那批脏数据的「脏法」五花八门——有的日期字段是2024/13/99有的数字列混着单位「1.2万」有的城市名大小写写了一半。规则写少了它判不掉规则写多了描述本身就把上下文塞满了。最后模型在四个工具之间来回倒腾参数的语义在老考验它改了两轮也没把图出干净。再看 Code Mode 路线。给 Agent 一个空环境 原始 CSV 路径它自己先print(df.head())看结构然后写一段逻辑把异常日期、非法数字和城市名规范化全处理掉接着groupby汇总、matplotlib画图、to_png存储。全程它自己看着输出报错改了两处一次是读取时编码格式报错它换成encodinggbk重跑一次是图里中文标签显示乱码它添了字体配置。整个过程二十多次迭代全部自动完成最后交付的是一张干净规范的排行图和一份输出统计的文本文件。两条路线的差别不在「模型聪明程度」而在错误恢复半径。工具调用下模型想调参只能反复猜不同参数重调接口Code Mode 下它手里有完整的调试器、报错流和控制流它就是一个小开发者在干活自然是后者的灵活度高得多。所以我现在遇到「探索型」「脏活型」任务毫无悬念直接上 Code Mode。4. 踩坑记录Code Mode 里那些坑我替你们踩过4.1 「代码写得出跑不通」的回环问题第一个也是最常见的坑Agent 给出了一大段代码看起来逻辑完整、注释工整但一执行就炸。更气人的是有些 Agent 在拿到报错后压根不理会报错内容继续按原思路输出一段几乎一样的代码来回死循环。这个问题的根子通常不在模型在于你的架构里没把执行反馈接回模型上下文。Code Mode 是个闭环模型必须能看到代码执行后的 stdout、stderr、退出码它才有办法在下一轮针对报错做修改。我在早期接入时犯过一个大错只把「是否执行成功」作为布尔值返回模型看不到具体报错信息于是它只能瞎猜越猜越偏。后来我把标准输出和错误输出完整塞回上下文效果立刻改善。在这个循环里还有一个工程细节值得注意模型迭代修 bug 的次数要设上限比如最多 10 次防止它在一段错误代码上无限纠缠。同时每次返回给模型的报错信息要截断比如只保留最后 2000 字符否则一个巨大堆栈能把上下文全灌满反而干扰模型注意力。4.2 透明性回退与审计难题Code Mode 的第二个大坑是「黑盒效应」。工具调用模式下Agent 每一步干了什么都清晰记录在案调用了哪个工具、传了什么参数。而 Code Mode 下它可能写了一段脚本把一堆文件全改了你在界面上只看到一串执行日志——如果不主动设计事后根本无从追踪它到底动了什么。我这边的对策分成三层。第一层强制读回显存要求 Agent 在关键步骤后打印中间结果的摘要写入日志文件比如处理后 DataFrame 的行数、每个文件的生成路径这些会沉淀成审计轨迹。第二层只读与写分离把「任务运行目录」和「被操作的业务目录」分开Agent 的代码只能读写自己的临时工作区要动业务数据必须走受控的写接口这样就算它乱来破坏半径也不大。第三层中间产物保留被覆盖的文件生成版本快照至少保留最近几轮方便人工回溯时对比差异。我一直跟团队强调一个原则可观测的 90%比不可观测的 99% 有价值得多。一个完全自主但没人看得懂的 Agent上线之后一旦出错恢复成本远高于一个动作稍慢但轨迹清楚的可控 Agent。Code Mode 的自由度越高配套的可观测性设计就越不能省。4.3 资源爆炸与安全风险实录最后一块实操硬骨头是安全与资源治理。我把实际遇到过的风险场景和对应的止血手段整理成一张速查表各位可以直接抄作业风险场景典型现象止血对策死循环或失控递归脚本无限空转CPU 打满强制超时终止 CPU 配额 作业重试次数上限大文件生成磁盘被日志或下载文件塞满磁盘配额 单文件大小上限 任务结束清空工作目录拉取恶意依赖pip install安装了来路不明的包默认断网 私有镜像源白名单 禁止直连公网读取敏感文件代码尝试访问用户目录或密钥文件只读挂载业务路径 工作目录独立 路径遍历检测执行破坏性命令rm -rf、格式化脚本工作目录限制在沙箱内 危险命令拦截 审批机制这个表里前四条我都真实踩过不是纸上谈兵。最典型的一次是某个 Agent 在处理压缩包时写了一个解压逻辑没考虑到「压缩包里有同名文件会覆盖」的情况差点把上一次运行的中间大写文件全覆盖掉。那次之后我在沙盒设计里强制加了「工作目录每次任务全新创建、不保留上次文件」的规则从根上断掉了残留状态互相污染的可能。要我说Code Mode 的安全不是「一个配置项」能解决的而是一整套围绕沙箱运行时的约束组合。自由度给得越足约束就要做得越细两者永远是一对平衡木。4.4 别忘了成本代码执行比工具调用贵很多人容易忽略的是成本账。工具调用一次通常几百毫秒内结束token 消耗主要是参数往返Code Mode 一次任务可能要跑几十次「生成代码—执行—读反馈」循环算上环境启动、依赖安装、代码执行时间成本和 token 成本都可能高出数倍。我在某个批量处理任务里测过一次同样一批 20 个文件工具调用路线跑完大约 3 分钟、消耗约 2 万 tokenCode Mode 路线因为要反复看报错和修改逻辑跑了大概 15 分钟、消耗了近 8 万 token。所以分诊那一步不是多余的。能确定性的活别交给代码解释器只有探索型的活才值得付出这个成本。实际系统里可以把两条路结合先用工具调用做确定性动作只在遇到长尾异常时降级到 Code Mode 去「动态扩展能力」把两种模式的性价比都吃上。我最近做的几个工程都是这么设计的效果比单走一条路稳定很多。5. 接下来会往哪走环境、闭环与治理我个人的判断是Code Mode 不会停留在「一个代码沙盒」这么简单的形态上。接下来这个范式会沿着三个方向继续演化第一执行环境会从「代码沙盒」扩展成「环境连续体」。以前我们给 Agent 的是 Python 解释器那只是能力孤岛下一步会是浏览器、终端模拟器、桌面应用操作这一整套环境。Agent 不再只是「写代码跑逻辑」而是能在一个虚拟电脑里开浏览器、抓页面、操作表单、移动文件。工具调用模式下那些必须写死的外部系统接口在环境连续体里可以被「看屏幕、点按钮、输入文本」这种更通用的能力替代这个方向一旦跑通Agent 的泛化能力又会涨一大截。第二「可执行」会成为产品设计的默认原则。以后做 Agent 产品问题不再该是「要不要给它代码执行能力」而是「什么样的任务可以自动进执行环境」。对话式交互更像「想法层」真正要落地干活、要产出可验证结果的任务都应该有对应的执行业务层。换句话说一个 Agent 只有在能对现实产生确定性影响时才算是真正工作起来。你不能让 Agent 嘴上说「我已经帮你处理好了」得让它真的在沙盒里把文件处理完再把报告拿给你。第三治理体系会反过来牵引模型层能力。随着 Code Mode 普及安全、审计、权限这些治理需求会倒逼模型学会「在约束下行动」比如知道哪些路径不能碰、哪些命令不能执行、哪些操作需要二次确认。现在的大模型在「避免做坏事」上的能力还很初级主要靠沙箱硬隔离兜底未来模型如果能原生理解权限边界和任务伦理边界才能真正走向高自主度的无人值守运行。从工具调用走到 Code Mode表面看是 Agent 的动作方式变了本质上是我们把「设计时确定行为」的旧范式切换成了「运行时靠执行反馈自愈」的新范式。这条路还远没到终局但方向已经很清楚了。如果你现在刚开始做 Agent我的建议是别急着把大把时间花在堆工具定义上先搭一个安全沙盒环境让 Agent 在里面多跑几轮真实脏任务感受一下「代码执行闭环」带来的推演能力和意想不到的问题你会很快理解为什么这么多人把这次变化称为范式转移。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询