资讯动态

AI Agent范式转移:从工具调用到Code Mode的实战指南

发布时间:2026/10/14 7:18:08 来源:尧图企业网站定制
1. 范式转移不只是多了一个按钮这么简单如果你最近半年一直在关注 AI Agent 相关的开发进展大概会注意到一个明显的变化各家产品都在往同一个方向使劲从让模型调用工具变成让模型直接写代码、跑代码、改代码。这个变化来得很快快到很多人还在把 Agent 当成会调 API 的聊天机器人时新一代的产品已经把代码执行环境直接嵌进了推理流程里。我最早接触工具调用Function Calling / Tool Use是在两年前。那时候的思路很清晰模型不擅长计算就给它一个计算器工具模型不擅长查天气就给它一个天气 API。整体架构像一个大脑配手脚的方案——模型负责理解意图、拆解任务然后通过调用外部工具来补足自身能力的短板。这个思路本身没有错而且确实解决了很多实际问题。但用久了你会发现一个尴尬的现状工具是死的任务是活的。你永远在预先定义工具 → 模型在有限集合里挑选 → 执行并返回结果这个循环里打转。遇到没定义过的场景模型就只能干瞪眼。Code Mode代码模式的出现本质上是在回答一个问题**与其给模型一万个预设工具不如给它一个能自己创造工具的沙盒。**代码本身就是最通用的工具。当模型可以在沙盒环境里自由地写 Python、跑脚本、安装依赖、读取文件、调试报错它其实就不再受限于你预先定义的工具列表了。它可以针对一个从没见过的任务现场写一段代码来生成一个临时工具用完即弃也可以写一个复杂的多步骤脚本把之前需要几十次工具调用的流程压缩成一次执行。这是一个非常深刻的转变**从调用工具到创造工具。**前者是使用者思维后者是工程师思维。过去我们训练模型去理解哪个工具适合当前任务现在我们在训练模型去理解如何用代码解决当前问题。两者的复杂度完全不在一个量级上。这篇文章我想结合自己的实战经历把这次范式转移的核心逻辑、技术架构变化、实际落地效果以及踩过的坑完整地捋一遍。适合正在做 Agent 开发、或者准备把业务接入 Agent 能力的朋友参考。不管你现在用的是哪家的模型或框架这篇文章里的思路应该都能帮你理解为什么代码优先正在成为下一代 Agent 的标配。2. 为什么工具调用模式撑不住了2.1 工具调用的本质是有限选项的排列组合我们先把工具调用模式拆开来看。无论在哪个平台上实现工具调用的核心流程几乎都是这样开发者预先定义一批工具函数每个函数有名称、描述、参数 schema。模型根据用户输入从这批函数中挑一个或多个并生成结构化的参数。外部系统执行这些函数把结果返回给模型。模型基于返回结果继续推理必要时再调用下一轮工具。这套流程最大的问题我总结为三个字不够用。举个例子。假设你做一个数据分析 Agent你定义了读取 CSV、计算均值、绘制图表这三个工具。用户来了一个需求帮我分析一下销售数据看看哪个区域的增长率最异常顺便做一个可视化。模型会怎么处理它先调用读取 CSV再调用计算均值再调用绘图……每个步骤都需要一次模型推理每次都走一遍意图理解 → 工具选择 → 参数生成 → 执行 → 结果解析的完整链路。三次工具调用三次往返延迟而且这还是最简单的场景。如果用户的需求再复杂一点把上个月和这个月的数据做同比按产品线拆分找出下降超过 10% 的品类并生成一份 PDF 报告。你会发现工具列表根本不够用——你需要写一个新的工具来做生成 PDF需要另一个工具来做同比计算可能还需要一个工具来处理数据清洗。每一个新需求都意味着开发者要手动扩展工具列表。长期维护下来工具的数量会爆炸而每个工具的逻辑又很难复用。工具调用模式的另一个隐藏成本是上下文污染。每次工具调用返回的结果都要塞进对话历史里。如果工具返回的是一个巨大的 JSON比如 1 万行数据那么这些内容都会占据上下文窗口而且在下一次推理时还会被模型重新读一遍。我在实际项目中遇到过上下文被工具返回结果撑爆的情况最后只能做截断但截断又会丢失关键信息两头不讨好。2.2 硬编码工具链维护噩梦和天花板工具调用模式的本质是开发者把解决方案写死模型负责搬运。这就带来一个天然的瓶颈Agent 的能力上限不会超过开发者预定义的工具上限。你需要 Agent 能从网页抓数据你得先写一个网页抓取工具。需要它操作 Excel你得先写一个 Excel 处理工具。需要它调用公司内部 API你得先写一个鉴权封装工具。每一个都是工作量而且这些工具往往是一锤子买卖——这个项目里能用换个项目就废了。更头疼的是组合爆炸。真实业务需求几乎很少是单个操作能解决的通常是先 A 再 B 然后如果 C 就 D。在硬编码工具的模式下你只能在代码里写死这些流程分支或者寄希望于模型能聪明地把多个工具串起来。但模型串工具的能力参差不齐一旦中间某一步返回了预期之外的格式整个流程就崩了——模型会开始编造工具返回结果或者反复尝试同一个失败的调用浪费大量 token。我在某个内部项目里统计过在工具调用模式下一个 5 步以内的任务成功率大概是 70% 左右。每次失败几乎都集中在步骤之间数据格式不匹配或者工具返回内容超出预期。后来迁移到 Code Mode同样的任务成功率直接拉到 90% 以上。这不是模型变强了而是代码模式天然具备容错性和灵活性——模型可以读取失败信息、现场修改代码、重新执行这比重新调用一次工具要可靠得多。2.3 一个真实对比工具调用 vs Code Mode为了更直观地说明差异我在本地搭了个实验环境同一个任务分别用两种模式跑了一遍。任务描述是读取当前目录下的 sales.csv 文件统计每个月的总销售额找出环比增长最高的月份并把结果保存成 result.md。工具调用模式下我需要预先定义四个工具读取文件、解析日期、聚合统计、写 Markdown。模型经过四轮工具调用完成了任务耗时约 40 秒Token 消耗约 8000其中数据读取结果占了很大一部分上下文。Code Mode 下模型直接生成了一段 Python 脚本用 pandas 一次性完成读取、聚合、环比计算、写文件全部操作然后我在沙盒里执行。脚本本身约 30 行执行耗时不到 2 秒Token 消耗约 3000其中大部分是模型在写代码时生成的上下文里没有多余的数据污染。两组数据的对比非常明显。更关键的是在 Code Mode 下如果模型生成的脚本报错了它可以读取错误信息、修改代码、重新执行整个过程在沙盒内部闭环完成不需要和外部系统反复交互。这种自我纠正的能力在工具调用模式下很难实现因为你每修一次就得重新走一遍调用外部工具的完整流程。3. Code Mode 的核心架构与设计逻辑3.1 沙盒执行环境Agent 的练功房Code Mode 的落地首先需要一个可靠的代码执行沙盒。这不是简单地给模型一个终端而是要在安全隔离的基础上让模型拥有写代码 → 跑代码 → 看结果 → 改代码的完整循环能力。沙盒的设计有几个关键考量。第一是资源隔离。模型生成的代码可能是恶意的也可能只是无意中写了死循环或者内存爆炸的脚本如果没有资源限制一个 CtrlC 都拦不住的进程可能会拖垮整台机器。常见的做法是用容器或者虚拟机级别的隔离限制 CPU、内存、磁盘和网络访问。第二是依赖管理。模型要跑数据分析就得装 pandas要做爬虫就得装 requests。沙盒需要支持按需安装依赖而且要快——每次重新创建环境显然不现实所以最好是持久化的、可快照恢复的执行环境。第三是文件系统访问范围。模型应该只能读写指定工作目录下的文件不能碰宿主机上的敏感数据。就我自己的实践来说用 Docker 容器做沙盒是目前最省心的方案。每个 Agent 实例配一个专属容器挂载一个临时工作目录限制网络白名单。容器内部预装 Python 环境和常用库其他依赖在运行时通过 pip 按需安装。模型的每次代码执行都通过一个执行接口提交到容器里输出stdout/stderr和返回状态再传回模型形成闭环。3.2 代码生成 → 执行 → 反馈循环Agent 的自我迭代Code Mode 和简单让模型写一段代码给你最大的区别在于模型能看到自己代码的执行结果并根据结果继续修改。这是整个机制的灵魂。我把这个循环称为写→跑→看→改四步循环写模型根据当前任务和上下文生成一段代码通常是 Python 脚本。跑代码在沙盒中执行系统捕获 stdout、stderr、退出码和运行时长。看执行结果反馈给模型。如果成功模型检查输出是否符合预期如果失败模型看到报错信息。改模型基于反馈修改代码、调整逻辑、修复 bug然后重新执行。这个循环看起来简单工程上有很多细节需要打磨。关键是看这一步的反馈质量。如果只是把 stdout 和 stderr 原样丢给模型很多情况下信息是不够的。比如一个脚本运行了 30 秒还没结束模型不知道是死循环还是正常计算——这时候就需要超时机制来打断并把运行超时的提示作为反馈传给模型引导它优化逻辑。再比如脚本运行时安装了额外的依赖系统应该把已安装 xxx 包这类状态变更也通知到模型否则它可能不知道新的库已经可用了。我在实践中发现反馈信息的颗粒度直接决定了模型的自我迭代效率。反馈太粗比如只有执行失败模型只能瞎猜哪里错了反馈太细比如把整个 10 万行的 traceback 都丢过去又会浪费上下文空间还可能让模型被无意义的报错细节带偏方向。比较好的做法是把错误信息做摘要处理提取出错误类型、关键堆栈和出错行号再附上标准输出的末尾几行。3.3 从一次性脚本到Code 智能体多文件项目能力当 Code Mode 只停留在生成一段脚本、执行、结束这个层面时它的威力还没有完全发挥出来。真正的升级是让模型可以持续维护一个代码项目——不仅写代码还能创建多个文件、修改已有文件、组织项目结构像一个真正的工程师一样工作。举个例子如果用户的需求是写一个 Flask 应用提供三个 API 接口每个接口要做参数校验和错误处理单纯的一次性脚本模式只会得到一个散装代码片段需要用户自己去整合。而在项目级的 Code Mode 下模型会先规划目录结构my_app/ ├── app.py ├── routes/ │ ├── __init__.py │ ├── api_v1.py │ └── api_v2.py ├── utils/ │ ├── validators.py │ └── logger.py ├── tests/ │ └── test_api.py └── requirements.txt然后逐个文件生成内容跑测试修 bug最终交付一个可以直接启动的完整项目。这个能力目前在部分框架中被称为Code Agent或Code Interpreter实现逻辑不算复杂——本质上就是给模型提供创建文件写入内容读取文件列出目录这几个原生的代码操作工具然后让模型自由组合。但体验上的差距是巨大的从给你一段代码变成给你一个能跑的工程这中间的跨越比想象中大得多。我在实际项目中用这个能力做过一个内部工具网站需求描述、原型参考、代码生成到部署上线总共不到半天。生成的代码质量肯定比不上专业工程师的反复打磨但作为内部工具已经完全够用。这个体验让我意识到Code Mode 的真正潜力不在于写一段脚本完成任务而在于作为虚拟工程师持续迭代一个项目。4. 用 Code Mode 实战从零搭一个数据自动化 Agent4.1 场景需求与方案设计理论说了不少还是落到一个具体的实战项目上。我最近在帮一个团队做一个自动生成周报的 Agent需求大概是这样每周自动从数据库里拉取业务数据分析关键指标的变化趋势找出异常点生成一份图文并茂的 Markdown 周报重点突出问题和建议把周报推送到内部的文档系统。这个任务用传统工具调用模式来做需要预先定义至少七个工具数据库查询、数据聚合、异常检测、图表生成、Markdown 模板填充、文档上传、定时触发。每一个工具都要写单独的代码维护成本不低。而且异常检测和图表生成这类工具的通用性很差换个业务场景就得重写。用 Code Mode 来做的话整个 Agent 的架构变得异常简洁。我把 Agent 的工作流定义为四个阶段拉取数据模型生成 Python 代码通过数据库连接串查询最近一周的业务数据。分析与可视化模型用 pandas 清洗数据、计算环比和同比指标、用 matplotlib 生成趋势图。生成周报模型把分析结果组织成 Markdown 文档结构嵌入图表路径生成最终报告文件。推送与验证模型调用内部文档 API 上传文件并检查返回状态确认推送成功。整个流程的核心驱动是下面这个执行循环的接口我用简洁的伪代码来展示def execute_and_feedback(code, sandbox): 在沙盒中执行模型生成的代码并将结构化反馈返回给模型。 # 写入代码到沙盒工作目录 sandbox.write_file(agent_task.py, code) # 执行捕获输出、错误、运行时间和退出码 result sandbox.run(python agent_task.py, timeout60) feedback { stdout: result.stdout[-2000:], # 只保留末尾部分防止过长 stderr: result.stderr[-2000:], # 错误信息同样截断 exit_code: result.exit_code, timed_out: result.timed_out, files_created: sandbox.list_workspace(), # 告诉模型它生成了哪些文件 } return feedback模型在这个循环里扮演的角色更像一个远程实习生——你给它一个任务它在工作目录里忙活你只看它的产出和反馈它遇到问题会自己查阅报错、修改代码、重试。这种交互模式的工程实现其实不大但体验上比一次性 API 调用高级很多。4.2 执行流程拆解模型如何一步步完成任务实际跑起来时这个 Agent 的执行流程非常有代表性。我把关键步骤拆开来看。第一步模型规划代码结构。收到生成周报的指令后模型没有直接开写而是先输出了一段思考过程大意是我需要连接数据库获取原始数据然后用 pandas 处理计算周环比和关键指标再用 matplotlib 画两张图最后把结果渲染成 Markdown。这段规划很重要它决定了后续代码生成的方向。我在设计提示词时会特意强调先规划再编码。第二步模型生成数据拉取代码并执行。模型生成的代码大致是这样的import pandas as pd import pymysql conn pymysql.connect( hostdb_host, useragent_user, password***, databasebusiness_db, charsetutf8mb4 ) query SELECT DATE(created_at) AS day, region, amount FROM orders WHERE created_at DATE_SUB(CURDATE(), INTERVAL 7 DAY) df pd.read_sql(query, conn) df.to_csv(weekly_data.csv, indexFalse) print(f数据已保存共 {len(df)} 条记录)第一次执行时模型忘了在数据库连接串里加字符集参数导致中文乱码。但因为它能看到 stdout 里的乱码输出和数据库返回的警告信息它自己就加上了charsetutf8mb4和connect_timeout10第二次执行就成功了。这个修正过程完全不需要我介入这就是 Code Mode 最珍贵的自我纠错能力。第三步数据分析和异常检测。模型加载 CSV按天和地区做透视表计算环比变化率。然后它用了一个比较朴素但有效的方法来定义异常环比超过正负 15% 的地区或者绝对值超过平均值两倍标准差的指标点。代码逻辑不复杂但胜在自定义程度高——这个逻辑如果做成工具服务端很难设计得这么灵活。w pd.read_csv(weekly_data.csv, parse_dates[day]) w[day] w[day].dt.strftime(%Y-%m-%d) pivot w.pivot_table(indexday, columnsregion, valuesamount, aggfuncsum) pct_change pivot.pct_change(fill_methodNone).replace([float(inf), -float(inf)], 0) abnormal pct_change[pct_change.abs() 0.15].stack() print(异常区域和日期) print(abnormal)第四步生成图表和 Markdown 报告。模型用上次生成的weekly_data.csv画了两张图一张按地区分组的 7 天趋势折线图一张全国销售额的周环比柱状图。随后把图表链接和异常分析结果嵌进 Markdown 模板生成了一份相对完整的周报初稿。这里面一个值得注意的细节是模型并没有一次性生成完美的周报而是先生成一个差不多的版本在后续反馈里发现缺了一个汇总表格后又补了一段代码来完善。整个任务从开始到最终交付报告模型一共生成了 6 轮代码前 2 轮是为了完成数据拉取和分析第 3 轮报了错第 4 轮修复第 5 轮生成图表第 6 轮推送文档。总耗时约 4 分钟Token 消耗约 1.5 万。相比工具调用模式需要开发者手动维护工具集这个开发成本基本降到了零。4.3 沙盒细节配置内存、超时与依赖管理Code Mode 跑得顺不顺沙盒配置占了很大的决定因素。我在几轮迭代里把沙盒的参数调成了这样配置项我的取值说明CPU 限制1 核防止模型写出的死循环脚本耗尽资源内存限制2 GB数据分析任务够用也杜绝内存炸弹超时时间60 秒/次超过即杀死进程反馈运行超时磁盘配额1 GB防止模型生成大量临时文件占满磁盘网络访问白名单只允许访问内部 API 和必要的 pip 源依赖预装pandas, matplotlib, requests多数任务不需要现场装减少等待这里尤其要提一下超时机制。模型写的代码偶尔会出现死循环或者某个网络请求一直等不到响应。如果不加超时整个 Agent 会被卡住而且模型拿不到任何反馈只能一直等。设了超时后每次执行最多 60 秒超时信息作为反馈返回给模型它通常会很快意识到问题并重写逻辑。这个机制是 Code Mode 稳定性的兜底保障。依赖管理也是一个容易被忽略的点。沙盒预装不了所有库所以模型常常会生成pip install xxx的命令。我在沙盒里做了一个小优化拦截 pip install 调用在后台安装的同时把安装日志的结尾返回给模型这样它知道依赖正在安装、以及安装完成后可以立即使用。实测下来依赖安装的成功率很高模型很少会因为找不到模块而无脑重试。5. 踩坑实录与性能对比哪些地方容易翻车5.1 我踩过的四个典型坑Code Mode 虽然强大但绝不是放进去就能用的银弹。这几轮实战下来我踩了不少坑挑四个最典型的分享出来。第一个坑是模型的代码风格不稳定。同一个模型有时候生成的是整洁的函数封装型代码有时候是散装的脚本型代码。在短任务里这无所谓但在长任务里如果模型在后续步骤中需要复用前一步的结果散装代码往往会导致变量名拼写不一致、重复计算等低级错误。我的解决办法是在系统提示词里明确要求用函数组织代码把每个步骤封装成独立的函数并在 main 函数中调用。这样即使模型某个函数写错了它可以在后续迭代中只修这一个函数影响范围可控。第二个坑是反馈信息的截断策略太激进。最开始我把 stdout 限制在末尾 500 字符结果模型经常因为看不到完整的报错堆栈而反复猜测。后来调整到 2000 字符并把错误类型和堆栈摘要优先保留体验好了很多。实际上不同任务的反馈长度需求不同我现在的做法是成功时返回 stdout 末尾 1000 字符失败时优先返回 stderr 的前 500 字符和末尾 1500 字符——前面定位错误类型后面看完整堆栈。第三个坑是临时文件管理混乱。模型跑数据任务时会生成各种中间文件清洗后的数据、图片、日志、缓存。如果每次执行都在同一个工作目录里累积很快就会堆满而且模型自己也会被搞混不知道现在目录里哪个文件是最新版本。后来我在每个会话开始时创建一个新工作子目录并把清空工作目录作为每个任务起点的默认操作。模型在上下文中能看到当前目录结构这样一来文件管理变得清晰很多。第四个坑是模型在自我纠错时容易陷入无限循环。有一次模型生成的代码一直报一个第三方库的兼容性错误它连续试了 5 次修改方案全都不行。最后我加了一个最大重试次数的硬限制——每次任务最多 8 轮代码执行超过就强制转向向用户求助而不是继续空转。这个保护机制很重要不然一次复杂任务可能空耗十几轮对话Token 和时间都浪费了。5.2 对比数据Code Mode 的实际提效幅度我在同一个数据集上用工具调用模式和 Code Mode 各跑了一遍前面提到的周报生成任务记录的对比数据很有参考价值指标工具调用模式Code Mode提升幅度开发者预定义代码量约 500 行约 0 行省去全部工具编写任务完成时间约 12 分钟约 4 分钟减少约 67%Token 消耗约 3.5 万约 1.5 万减少约 57%一次成功率约 70%约 88%提升 18 个百分点可处理的需求类型预设场景内几乎无限制能力边界显著扩大当然这个对比只是一个内部项目的参考数据不同任务类型、不同模型配置下的结果会有差异但趋势是很明确的Code Mode 在灵活性和效率上都有数量级的优势。需要说明的是这并不意味着工具调用模式完全没有价值。在需要精确控制行为、强约束输出格式、与企业内部系统深度集成的场景里预先定义工具仍然是更可靠的选择。比如金融交易场景你肯定不希望模型现场写代码去下单而是希望它能调用一个经过严格审核的交易 API。工具调用的确定性和 Code Mode 的灵活性之间没有绝对的好与坏只有适合与不适合。6. 从 Code Mode 到更远的未来Agent 能力边界的扩展方向Code Mode 带来的范式转移目前还只是开始。我观察到的几个有意思的演进方向值得所有做 Agent 的人提前关注。第一个方向是沙盒内自我进化。当前的 Code Mode 还停留在模型为每个任务临时写代码的阶段但下一步很可能是让模型在沙盒内沉淀工具库——它自己写完的一段高质量代码可以被抽象成通用工具存进工具库下次遇到类似任务直接加载。这其实是把即时生成的代码变成了可复用的长期资产。从工程视角来看这就像给 Agent 装了一个成长型工具箱越用越强。第二个方向是多模态执行环境。现在的沙盒大多只能跑 Python 代码但 Agent 的想象空间早就超出文本和数值了。未来的沙盒应该能跑 HTML/JavaScript 渲染出的网页能操作图像处理软件能生成和编辑视频甚至能连接外部仿真环境。模型不只是写 Python 脚本而是操作一个完整的数字工作台。第三个方向是人机协同的代码审查机制。当模型可以自主写代码、改代码时代码质量和安全性就成了必须正面处理的问题。一些团队已经在尝试让模型在完成代码后自己生成测试用例并跑测试再生成代码审查意见。虽然模型自审自测肯定会有盲区但能在一定程度上兜住低级错误。我预期后面会有更多AI 写代码 → AI 测试 → AI 审查 → 专家审核的流水线玩法出现。对我个人来说Code Mode 最打动我的不是它能写代码而是它愿意看着自己写的代码跑起来然后根据结果不断改。这种踏实劲儿比很多只会嘴上计划、手上不动的人要靠谱得多。如果你也在做 Agent 相关的东西我强烈建议你别只在让模型调用工具这个层面打转早点拥抱 Code Mode——让模型亲手写代码、亲手调试你会看到另一个量级的可能性。最后分享一个小技巧在设计你的 Agent 反馈循环时把执行结果摘要做得结构化一些——比如统一用状态: 成功/失败, 关键信息: ..., 建议下一步: ...这样的格式返回给模型。模型对这种结构化反馈的利用率远高于对一段自由散漫的日志的利用率。这个小改动实测能把自我纠错的成功率再拉高 10% 左右。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑