
第五章Coding Agent 与通用 Agent 学习笔记学习来源https://bojieli.github.io/ai-agent-book/book/chapter5/本章的核心是说明如何把模型、上下文、工具、约束、验证、纠错与文件系统组合成一个可靠的 Coding Agent并进一步说明为什么代码生成可以成为通用 Agent 的元能力。一个成熟的 Coding Agent 不只是生成代码而是能够理解项目、制定方案、修改文件、执行命令、运行测试、处理错误、回滚恢复并最终交付可验证的结果。一、Coding Agent 的整体架构与工作流程1.1 Coding Agent 的基础能力Coding Agent 的核心工作可以概括为对代码仓库进行“搜索、读取、修改、执行和验证”。基础工具通常包括 Code Interpreter、Bash Shell、文件读取、文件写入、文件编辑、Glob 文件名搜索和 Grep 内容搜索。这些工具看起来简单但组合起来已经能够覆盖绝大多数编程任务。相比为每一种需求都提前开发专用工具Coding Agent 可以直接通过代码和 Shell 动态解决问题因此代码生成本身具有较强的通用性。对于开放任务型通用 Agent文件系统不仅用于保存文件还承担了工作空间、长期记忆和中间状态存储的作用。Agent 可以从项目文件中读取上下文把代码、数据、日志和生成结果写回文件并将稳定经验沉淀为项目指令或长期记忆。也就是说Coding Agent 文件系统可以构成通用 Agent 的基础执行框架。1.2 Harness 在 Coding Agent 中的作用Coding Agent 的稳定性不能只依赖模型能力更依赖 Harness。Harness 一方面提供上下文和工具让 Agent 有能力完成任务另一方面通过约束、验证和纠错机制限制错误行为。软件工程本身已经具备完善的测试、Lint、类型检查、Git、CI 和沙盒环境这些机制天然适合作为 Agent 的自动反馈系统。因此Coding Agent 成熟度较高的重要原因不只是模型会写代码而是代码任务本身具有较强的可验证性。Harness 的核心原则可以概括为能用程序强制执行的规则不要只写成自然语言提示能自动验证的结果不要完全依赖人工审查错误反馈应尽量快速、结构化任何高风险修改都应具有可靠的回退机制。对 Agent 来说“代码写完”不是任务结束只有测试、检查和最终验证通过才可以认为任务完成。1.3 Coding Agent 的整体流程按 Prompt 约束理解这一部分可以直接理解成 Coding Agent 在执行任务时需要遵守的一组工程约束。复杂任务并不是“收到需求后直接开始写代码”而是依次完成项目理解、需求澄清、方案设计、实现、测试、自审查和文档同步。项目理解约束在修改代码之前先阅读README、CLAUDE.md、AGENTS.md、.cursorrules等项目说明理解目录结构、主要模块、构建方式、测试命令和禁止修改的区域。如果缺少关键文档应先通过阅读代码建立项目结构认知而不是直接开始修改。需求澄清约束对简单且边界明确的任务可以直接实现对“优化性能”“重构系统”等范围模糊的任务应先明确目标、影响范围、允许的权衡和验收标准。在需求仍然存在关键歧义时不应盲目编码。设计约束对影响多个模块或涉及重要架构变化的任务在编码前先形成简洁设计方案说明需要修改哪些模块、采用什么方案、是否增加依赖、可能影响哪些已有功能。复杂任务应先验证方案再进入大规模代码修改。实现约束实现时优先复用项目已有抽象、工具和代码风格避免无必要地重复造轮子。修改应尽量局部、可回滚并避免为了让测试通过而采用破坏性捷径例如删除已有逻辑、绕过权限或修改测试本身。测试约束修改完成后必须运行测试而不是只检查代码是否生成成功。新增或修改功能应覆盖正常路径、边界情况和异常情况。如果测试失败应分析错误、修复代码并重新测试形成“测试—修复—再测试”的闭环。代码审查约束测试通过后还要检查代码可读性、重复逻辑、性能、安全问题、类型错误和代码规范。必要时运行 Linter、类型检查器或代码审查 Sub-Agent。测试通过并不意味着代码一定适合交付。文档同步约束如果修改影响架构、模块依赖、接口或核心行为应同步更新项目文档。文档与代码必须共同演化避免未来的 Agent 或开发者读取过时信息。因此这套流程可以压缩成一句话先理解再规划修改后立即验证验证失败继续修复重要变更同步文档只有验证通过才结束任务。二、故障错误与恢复核心问题生产级 Harness 会遇到哪些故障如何检测和恢复什么时候必须终止2.1 常见故障分为四层API 层故障包括 HTTP 429 限流、服务过载、请求超时、连接中断、流式输出被截断等。这类问题通常不是任务逻辑本身导致而是模型服务或网络基础设施的问题。工具层故障包括调用不存在的工具、参数格式不符合 Schema、工具执行抛出异常以及模型面对同一个工具错误不断原样重试。其中“相同调用反复失败”尤其危险因为它容易把 Agent 带入无限循环。上下文层故障包括上下文窗口溢出、压缩失败以及消息轨迹结构损坏。例如已经出现tool_call却缺少对应的tool_result会导致后续模型无法正确理解历史状态。控制流层故障主要是死循环和死亡螺旋。死循环指 Agent 不断重复相同操作但没有产生新进展死亡螺旋则是错误处理逻辑自身再次调用模型并继续报错导致恢复机制不断触发自己。2.2 如何检测故障故障检测的第一原则不是“失败就重试”而是先判断错误类型是否值得重试。限流、网络抖动和短时过载通常可以重试参数错误、权限不足、工具不存在则不能原样重试必须修改调用参数、切换策略或停止当前路径。因此生产级 Harness 应维护“错误类型 → 恢复策略”的明确映射而不是统一使用重试。除了单次错误还必须检测重复模式。系统可以对“工具名 参数”生成调用指纹如果完全相同的调用连续出现且结果没有变化就说明 Agent 可能已经进入无进展循环。同时应维护连续失败计数器为后续熔断提供依据。每个长连接都需要独立的活性信号不能只依赖连接超时。流式连接可能没有主动断开但已经停止输出。此时 SDK 可能仍认为连接有效所以 Harness 需要设置 watchdog timer。如果在指定时间内没有收到新 token 或事件应主动终止当前流并触发恢复流程。对于消息轨迹也需要完整性检查发现工具调用缺少结果消息时应在进入下一轮模型推理前修复结构。2.3 如何恢复故障故障恢复应遵循“从低成本、对用户透明的方法开始逐步升级”的原则。静默重试。对限流、短时过载和网络抖动使用指数退避与随机抖动进行重试并尊重服务端给出的等待时间。主任务链路值得重试而标题生成、输入建议等辅助功能失败时通常可以直接放弃避免后台任务大量重试挤占配额。降级与接续。如果单纯重试仍然失败就改变请求方式。例如输出长度达到上限时可以增加输出预算或者让模型从已有内容继续生成主模型持续不可用时可以切换备用模型高成本模式被限流时可以降级到标准模式。工具错误反馈给模型。对“工具不存在”“参数不合法”“执行异常”等问题不应直接终止会话而应把错误包装成结构化 Tool Result 返回模型让模型在下一轮根据明确的错误信息自行修正。错误反馈越具体模型越容易纠正。最终暴露给用户。在自动重试、参数修复、降级、备用模型等方案都失败后再把错误呈现给用户并说明系统已经尝试过哪些恢复动作。中间恢复过程不应反复向用户暴露临时错误。2.4 跨模型接管当主模型持续不可用时可以由另一个模型继续未完成的轨迹但前提是轨迹不能完全绑定某一家模型厂商的私有消息格式。工具调用的语义通常可以转换而模型的 reasoning、签名或厂商私有凭证可能无法跨模型复用。因此更合理的做法是把 Agent 轨迹保存成中立格式将可迁移的文字内容、工具名称和参数保留下来将厂商私有凭证单独存储或在切换时丢弃。这说明 Agent 的运行轨迹本身也是重要基础设施。中立轨迹不仅可以用于模型故障接管还可以用于后续的轨迹重放、Agent 评估、训练样本构造和经验提取。2.5 什么时候必须终止恢复机制不能无限执行。以下情况应触发熔断或人工接管同一工具调用反复出现且无进展同一恢复路径连续失败超过阈值达到最大迭代轮数会话 token、时间或调用预算耗尽恢复逻辑自身开始递归触发继续执行可能产生不可逆的危险操作。特别需要防止“死亡螺旋”。错误处理路径中应尽量禁止再次触发不必要的 LLM 调用例如任务因上下文溢出结束时不应再调用 LLM 自动生成 commit message 或记忆摘要。对于无法完全避免的递归恢复应设置恢复深度计数器并强制终止。最终原则是可恢复错误自动恢复无进展错误及时熔断高风险错误交给人工。三、Coding Agent 的实现技巧3.1 并行工具调用、流式执行与级联中止传统 Agent 经常采用“生成工具调用 → 等待工具执行 → 再生成下一步”的串行方式因此会浪费大量等待时间。更高效的实现会结合流式模型输出当第一个工具调用的参数已经完整生成并通过校验时就立即开始执行不必等待模型把后续所有工具调用都生成完。对于互不依赖的多个工具调用还可以同时并行执行从而让模型生成与工具执行发生重叠显著降低整体延迟。但并行执行必须明确故障边界。工具应声明是否允许并发默认可以采用更保守的“禁止并发”策略。一个调用失败后只应中止同一批中依赖该结果的后续调用不能把无关调用一起取消更不能因为一个文件读取失败就终止整个 Agent。这里的关键思想是故障应该局部传播而不是无限向上扩散。3.2 上下文精细化管理代码仓库通常远大于模型上下文因此不能把整个项目一次性塞给模型。文件读取工具应支持按行号范围读取并在返回结果中保留真实行号便于 Agent 精确定位代码。对于编译、测试等产生的大量终端输出也不能原样全部放入上下文应保留关键的开头和结尾将完整日志保存为文件在需要时再按需读取。这类设计的重点不是简单“压缩上下文”而是让 Agent 随时能够重新获取需要的信息。也就是说文件系统负责保存完整状态上下文只保留当前决策所需的最小信息。3.3 环境信息动态注入Coding Agent 的决策高度依赖当前运行环境例如当前工作目录、Git 分支、最近提交、已暂存和未暂存修改。因此这些信息应在每轮推理前以动态状态栏的方式追加到上下文而不是长期写死在 System Prompt 中。这样既可以保持 Agent 对实时环境的准确感知也可以避免频繁变化的状态破坏稳定前缀和 KV Cache。3.4 命令执行状态持久化很多开发操作依赖终端状态例如cd切换目录、激活虚拟环境、设置环境变量和启动后台服务。如果每条命令都创建新的 Shell会导致这些状态不断丢失。因此Coding Agent 通常应维护一个长期存在的终端会话在整个任务执行期间复用该 Shell。需要并行或隔离时再额外创建独立终端。3.5 即时语法反馈文件修改完成后不应等到整个任务结束才发现基础语法错误。更合理的方式是在编辑工具完成写入后自动运行语法检查、Linter 或类型检查并把结果直接附加到工具返回值中。这样 Agent 可以在错误刚产生时立即修复减少后期定位成本。这与 IDE 的即时错误提示类似也是 Harness“快速反馈”原则的具体体现。四、搜索、文件编辑与安全机制4.1 Coding Agent 的搜索方式代码搜索并不是只有一种方法。glob适合快速理解文件结构和定位某类文件grep/ripgrep适合已经知道函数名、变量名、错误信息等具体文本时进行精确搜索语义搜索适合“不知道代码具体叫什么但知道它是做什么的”的探索任务符号级搜索则用于追踪定义和引用关系。实际使用时更重要的是组合而不是追求单一搜索方案。常见策略是先快速扫目录再通过关键词定位具体实现必要时再追踪引用关系。近年来部分 Coding Agent 更倾向通过 Agent 自主组合glob grep现场搜索而不是长期维护代码向量索引因为代码变化快索引维护本身也有成本。4.2 文件编辑工具文件编辑工具的难点是如何让模型准确表达“修改哪一段、改成什么”。常见方案包括完整字符串替换、行号定位、首尾字符串匹配以及 Patch/Diff 等。当前实用性较高的方案通常强调可验证和可失败例如 Old String → New String 要求旧文本在文件中真实存在且最好唯一匹配失败时直接返回错误而不是让系统猜测应该修改哪里。对于 Agent 来说编辑工具越确定越好。相比让模型输出模糊的自然语言修改建议更可靠的方法是提供结构化编辑接口让系统能够在真正落盘之前验证定位是否准确。大量编辑还应配合 Git diff、测试和回滚机制避免一次错误修改污染整个代码库。4.3 Coding Agent 的安全Coding Agent 通常拥有文件读取、写入、Shell 和网络能力因此其风险远高于普通聊天模型。真正有效的安全策略不是只过滤输入中的恶意关键词而是限制 Agent 即使受到提示注入后也无法完成危险动作。重点包括网络出口控制、文件系统隔离、资源限制、危险命令语义分析和持久记忆安全。代码执行环境应优先放在沙盒中默认限制网络访问仅放行明确需要的域名源码、凭证和生成物应使用不同的挂载权限SSH Key、Token 等敏感文件不应直接暴露给沙盒CPU、内存、磁盘和运行时间都应设置上限。Shell 安全也不能只依赖rm、curl等关键字黑名单因为危险操作可以隐藏在管道、子命令或参数组合中应尽量根据命令真实语义进行判断。此外长期记忆也是安全边界。来自网页、邮件等不可信来源的内容不能未经检查直接写入MEMORY.md等长期记忆否则一次提示注入可能跨会话持续影响 Agent。五、代码是通用 Agent 的元能力5.1 什么是“元能力”普通工具解决的是预先定义好的任务而代码生成能够在运行时创造新工具、新规则和新表达形式因此可以被视为一种元能力。当 Agent 遇到工具箱中没有的能力时可以临时生成脚本、API 适配器、校验器或界面而不需要开发者提前枚举所有情况。这也是 Coding Agent 能成为开放任务型通用 Agent 核心的重要原因。5.2 代码作为思考工具LLM 擅长理解自然语言但在精确计算、符号推导和复杂逻辑约束中仍可能出错。更合理的分工是让 LLM 负责理解问题和构造形式化表达让 Python、SymPy、NumPy、SciPy 或约束求解器负责确定性计算。代码执行结果还可以直接作为验证信号从而减少自然语言推理中的计算错误。5.3 代码作为业务规则约束自然语言规则容易存在歧义而代码规则具有确定性。因此对于退款、支付、删除数据等不可逆操作不能只依赖 System Prompt 告诉模型“请遵守政策”还应该在执行工具内部加入程序化校验。自然语言规则适合帮助模型理解和解释代码校验则负责最终的强制执行两者应同时存在。这再次体现 Harness 的核心思想重要规则应该编码化而不是只文档化。对高风险操作应以服务端真实数据作为判断依据而不是相信模型自己传入的“我已经检查过”。5.4 代码驱动的多媒体生成PPT、PDF、网页、视频等内容都可以通过代码描述因此 Agent 可以把多媒体生成转化为代码生成问题。真正困难的地方不是生成代码而是验证最终渲染效果。因此本章反复采用 Proposer–Reviewer 机制一个 Agent 负责生成代码另一个 Agent 或 Vision 模型负责查看渲染结果并提出结构化修改意见直到结果满足要求。代码生成和生成模型并不是互相替代。具有明确尺寸、规则和强验证要求的对象更适合代码生成复杂度极高、难以用少量参数精确描述的视觉对象更适合生成模型。选择哪一种路线应取决于产物是否容易形式化以及是否需要精确验证和后续可编辑性。5.5 代码作为系统适配器真实系统中的 API、日志格式和数据结构会不断变化Agent 可以读取接口文档或观察真实样本然后临时生成解析和转换代码。这使代码成为连接不同系统的适配层。对于没有 API 的系统也可以先通过 Computer Use 完成操作再把成功的操作过程固化成 RPA 脚本提高后续执行速度和稳定性。在 Agent 运维中这种能力还可以用于日志解析和问题诊断读取轨迹日志自动定位异常模块生成问题报告、回归测试甚至通过 MCP 创建 GitHub Issue。代码生成因此不只是“完成用户任务”也可以成为 Agent 系统自身的维护工具。5.6 代码作为生成式 UI纯文本对话在复杂信息收集和数据展示场景中效率较低。Agent 可以动态生成表单、图表和交互页面让用户一次性填写多个相关字段或者把查询结果直接交给前端渲染。对于 SQL 等场景更好的模式通常是让 LLM 只负责生成查询 Artifact而不是让大量数据库结果经过 LLM 再转述这样可以减少 token 消耗和抄写错误。但动态代码不能直接获得无限权限。数据库应采用只读账号限制 SQL 类型、可访问表和返回规模前端生成代码也应运行在隔离环境中。生成式 UI 提升了交互能力但仍然需要 Harness 在执行层完成权限和安全约束。5.7 Agent 自举用代码创造 Agent代码生成的进一步应用是让 Agent 创建或修复另一个 Agent。例如 Doctor 类工具可以先用确定性规则检测 Token 过期、端口冲突、依赖缺失等常见问题再让 LLM 处理规则无法覆盖的长尾故障。这里最合理的架构不是“全部交给 LLM”而是确定性检查负责高频问题LLM 负责复杂语义分析。让 Agent 创建新 Agent 时也不应该完全从零开始生成。更可靠的做法是提供高质量 Agent 范例让模型复制成熟框架后进行适应性修改包括调整 Prompt、增删工具和业务逻辑而保留已经验证过的上下文管理、工具调用和错误恢复机制。换句话说好的代码范例本身就是一种比长 Prompt 更强的工程约束。六、实验实验 5-1 ★★★跨厂商的轨迹接管实验目标验证一份中立的轨迹格式能否让跑到一半的 Agent 轨迹换一家模型接着跑完并量化“原样直传”与“一刀切剥光”两种做法的代价。技术方案任务需要多轮工具调用跑到中途对当前厂商注入连续的限流与过载响应熔断后切换到另一家继续。轨迹按中立格式保存思考分为可移植的文字与不可移植的凭证两部分工具调用只记录名称与参数。三种做法对照直传把原厂商返回的消息原样搬进新厂商的结构剥离删掉全部思考与凭证中立丢弃凭证把文字或厂商给出的思考摘要以普通内容的身份带入标识符按目标厂商重新生成遇到强制要求凭证的接收端则把历史调用改写为文字叙述。选三家线上格式互不相同的厂商两两切换。验收标准切换后的首个请求都要留下原始响应直传的失败必须是厂商真实返回的错误不得以模拟错误代替。要求中立做法在全部厂商组合上都不出现接口错误另外两种在哪些组合上失败、报什么错如实记录。三者对比任务完成率、切换后重复调用同一工具的次数按“工具名 参数”指纹计以及切换后到完成所需的额外轮数与 token。若中立做法在重复调用上并未优于剥离同样如实记录。方案接管成功数据及总额正确原样直传3/63/6删除思考4/64/6中立格式6/66/6实验 5-2 ★★输出到一半断掉之后的接续实验目标比较“整轮重发”与“以半截输出为前缀续写”两种恢复方式在成本、正确性与副作用上的差异。技术方案在流式响应上取三个断点——思考中途、正文中途、工具调用参数中途——切断连接。三种恢复方式丢弃半截整轮重发把半截内容作为末尾的 assistant 消息要求模型接着写有的厂商原生支持有的要求显式标注这是一条待续写的消息没有这条接口的则退回下一种追加一条元指令说明从断点继续。半截的工具调用无法以原生结构回传需先转成文字再让模型补完拼接后重新解析校验。若半截输出里已有工具因流式提前执行续写前按调用指纹去重避免重复副作用。验收标准三类断点各重复若干次报告每种方式的恢复成功率、相对整轮重发节省的输出 token、补完后参数的合法率与语义正确率拼接处容易多出空白或重复字符合法不等于正确以及重复副作用次数。同时记录哪些断点在某些厂商上无法复现以及降级路径是否可用。七、本章总结第五章真正想说明的是Coding Agent 的能力来源于模型但可靠性来源于 Harness。模型负责理解需求、生成方案和代码Harness 通过项目指令、工具边界、测试、Lint、CI、Git、沙盒和错误恢复机制把模型的开放生成能力限制在一个可验证、可恢复的工程闭环中。从通用 Agent 的角度看代码生成之所以重要是因为它不仅能写程序还能用于精确计算、业务规则校验、多媒体生成、系统适配、生成式 UI以及创建和修复 Agent 自身。代码因此不是普通工具而是一种可以继续创造工具、规则和系统的“元能力”。本章最值得记住的是计划先于行动验证决定完成错误处理要覆盖检测、恢复、接管和终止整个循环能编码化的约束不要只写在 Prompt 里。