最近我在折腾一个挺有意思的小项目让 AI Agent 自己完成“写代码→跑测试→看报错→改代码→再跑测试”这条循环。一开始我以为这只是个“自动化测试玩具”但实际搭完才发现它在做的是把传统开发里最耗人的“反复编译、反复排查、反复修改”阶段从人肉流程里摘出来变成一个可以自主运转的闭环。今天就把这个项目的设计思路、实现细节、踩坑记录和可复现的配置方式完整写出来希望能给正在琢磨 AI Agent 开发、或者想做自动化开发闭环的朋友一些参考。先解释一下这个项目解决的真实痛点。我们平时写业务代码真正花在“写”上的时间其实不多更多时间消耗在构建失败、测试不过、定位 bug、修完又引入新问题的来回拉扯里。这套闭环做的事情就是把“构建、测试、修复”这三个环节交给 Agent 自主迭代Agent 修改代码后主动触发构建构建失败时读取错误日志并修正再触发测试测试失败时继续分析并调整直到全部通过或者达到设定上限才停手。它非常适合三类人一类是刚接触 AI Agent 开发、想知道 Agent 如何与本地环境真实交互的新手一类是被重复性构建修复折磨、想尝试让机器自动处理低级错误的工程师还有一类是做 Agent 应用产品、需要把“代码自动修复”能力集成进产品的开发者。1. 这个项目到底在做什么开发闭环的四个环节1.1 构建让 Agent 拥有“动手能力”很多人理解的 AI 编程还停留在“让模型生成一段代码、然后复制粘贴到项目里”的阶段。但这套闭环里的构建是让 Agent 自己掌握工程项目的完整“动手流程”。我说的构建不是单指编译而是要能覆盖日常开发中的三类动作打包编译、依赖安装、静态检查。比如 Java 项目里执行mvn compilePython 项目里执行pip install -r requirements.txt或者python -m build前端项目里执行npm run build。这些动作在传统开发里是工程师敲命令完成的在闭环里则变成 Agent 可调用的“工具”Agent 决定何时构建、怎么构建、构建失败后如何处置。这里有一个容易被忽略的设计点构建动作必须标准化。Agent 不可能像人一样在终端里摸索命令它只适合调用固定的、封装好的构建脚本。所以我在项目里写了一个build.sh作为统一入口无论什么语言项目Agent 只执行一条命令拿到退出码和输出日志。这样做的好处是Agent 不需要理解每个项目的构建差异只需要理解“退出码 0 代表成功、非 0 代表失败”把复杂性收敛到脚本层。1.2 测试机器生成的代码必须由机器验收代码改完了谁说了算在传统开发里是测试、评审、上线。在闭环里测试是唯一的验收标准也是 Agent 行为的“安全网”。我在这套系统里用的测试策略是“分层验收”第一层是静态检查像 lint、类型检查、格式检查这层能拦截大量低级错误第二层是单元测试针对改动的函数和方法做逻辑验证第三层是集成测试或端到端测试确认改动没有破坏整体流程。测试环节的关键不是“跑一下测试命令”而是要把测试结果“翻译”成 Agent 能理解的信息。测试输出千奇百怪有 pytest 的短格式、有 JUnit 的 XML 报告、有npm test的一长串 console 输出Agent 直接看原始日志很容易被噪声干扰。我的做法是写一个parse_test_result.py把测试结果解析成结构化 JSON里面包含三个字段总用例数、失败用例数、失败原因摘要。Agent 看到这份 JSON就知道下一步该干什么不需要在高密度日志里自己找线索。1.3 修复把报错变成 Agent 能理解的决策依据以前用 AI 修 bug大家的做法通常是“把整个报错堆栈粘进对话窗口让模型分析”。但我在这个项目里发现即便模型非常擅长看堆栈它依然缺三样东西完整上下文、修改工具、快速验证能力。闭环里的修复模块就是要同时解决这三样。修复模块的运行逻辑是这样的测试结果解析模块发现失败用例后会把“失败信息 相关代码片段 最近一次构建日志”打包成一份修复上下文物件传给 Agent。Agent 先基于源码分析错误原因然后在代码库中定位可能的修改点生成 diff 形式的修改建议。这里我没有让 Agent 直接重写整个文件而是用补丁工具把修改精准应用到目标行附近这样能避免模型“越改越飘”、“越写越远”的问题。修改完成后闭环不会停下来等人检查而是立刻重新进入构建和测试阶段用结果验证这次修复是否有效。1.4 循环闭环的真正价值在于沉淀反馈很多人问循环不就是 while 循环吗有什么技术含量但真正有含量的是循环里的“反馈沉淀”机制。每次修复失败我会把“错误类型 错误信息 Agent 做了什么修改 修改后结果”记录到一个历史记录表里。当下一次遇到类似错误时Agent 可以先去查这个表看历史失败案例避免重复踩同一个坑。这个设计让闭环从“无状态的一次次尝试”变成了“有积累的持续优化”。我甚至加了一个简单的相似度匹配当新的报错信息和历史记录里某条记录的相似度超过阈值就把历史修复方案作为参考上下文提供给 Agent。实际跑起来以后第二三轮遇到的不少错误Agent 都能从历史记录里找到相近的解法修复效率提升非常明显。2. 工具选型与架构设计LLM、Agent框架与执行环境怎么搭2.1 Agent、LLM、AI模型究竟有什么区别做这个项目之前我花了不少时间厘清一个基本概念体系因为网上讨论 AI Agent 时经常把几个词混用。LLM大语言模型是一个“会思考的引擎”它擅长理解文本、生成代码片段、推理分析典型的例子就是 DeepSeek、GPT 这类模型本身。AI 模型是一个更大的伞涵盖 LLM、图像分类、语音识别、向量嵌入等各种模型。而 AI Agent 是构建在 LLM 或多种 AI 模型之上的“行动体”它不只会“想”还会“做”——调用工具、操作文件、运行命令、根据反馈做决策。所以如果你问“DeepSeek 是 AI Agent 吗”答案是它本质上是 LLM不是 Agent。但你可以用 DeepSeek 作为 Agent 的“大脑”让一个 Agent 系统去调用 DeepSeek 的 API 来完成代码修复决策。这是很多入门者容易混淆的第一关。2.2 闭环里最核心的选型考量在工具选型上我纠结最多的是三件事模型选型、Agent 框架选型、执行环境选型。模型方面我最终选择了“可以本地部署的代码模型 云端通用模型”双通道方案。本地部署的模型用于高频的代码生成和简单修复速度快、不消耗接口费用云端模型用于错误语义分析和复杂排错理解能力强。如果你只是做学习验证不必搞这么复杂用一个 DeepSeek 或者开源代码模型的 API 就足够跑通闭环。关键指标是“上下文窗口”和“代码理解能力”因为 Agent 每次处理要同时容纳代码片段、测试日志、历史记录窗口太小很容易截断关键信息。Agent 框架方面我发现圈子里的讨论极多但从闭环项目的实际诉求出发真正重要的只有三层任务规划层、工具调用层、控制循环层。你可以选择成熟框架如 LangGraph、AutoGen、CrewAI也可以自己写一个轻量版。我自己选择了自己写轻量调度器因为闭环逻辑其实很固定不需要太复杂的编排反而自己写更能清楚地控制每一步。执行环境方面我建议在容器或者虚拟机里跑不要让 Agent 直接在开发主机上随意执行构建命令。原因很简单Agent 自动修改代码后可能引入任何未知状态容器可以随时销毁重建。给 Agent 一个“可以随便摔打”的环境比给它一个小心翼翼地保护的正式环境更安全。我实际用的是 Docker镜像构建好的项目环境可以反复起停训练和调试成本都低。2.3 一个最小可行的架构把上面这些选型落地后我得到的最小架构如下供你参考。整体可以分为 5 个模块LLM 内核、任务规划器、工具调用层、记忆与上下文、循环控制器。LLM 内核就是负责实际推理和代码生成的模型它本身不做决策只是提供“智能响应”。任务规划器接收“构建失败”或“测试失败”这类事件拆解成“诊断问题→定位代码→生成补丁→执行构建→验证测试”这样的步骤序列。工具调用层是 Agent 的“手”封装了run_build、run_test、apply_patch、read_file、write_file、search_code等工具每个工具都是可直接执行的命令或者 API 调用。记忆与上下文模块负责管理历史错误库、会话上下文和当前任务状态。循环控制器是闭环的“节拍器”决定什么时候继续循环、什么时候停止、什么时候主动请求人类介入。这个架构的好处是职责单一、模块边界清晰任何一个模型框架的更新都不会影响其他模块。如果你用成熟框架也建议按这个分层来组织代码不要让 Agent 直接裸调工具否则流程会乱成一团。3. 核心模块拆解与实现细节3.1 任务规划与上下文管理如果不做任何规划直接把报错日志丢给模型让它“看着办”效果会非常不稳定。我在跑的过程中发现Agent 往往会因为上下文过长而把注意力分散到无关代码上。所以任务规划器很重要它的职责是把一次修复任务压缩到最小信息集内。具体实现方式是给 Agent 设定一套固定的“任务模板”。模板包含四个部分第一当前构建或测试状态一句话概括第二错误摘要从日志中提取的前几条关键信息第三相关代码位置指向最近修改或报错涉及的文件和行号第四可操作选项比如“重新构建”“查看最近改动”“修改指定函数”“跳过本次循环”。Agent 基于模板做决策时思路会清晰很多因为它不需要自己在海量信息里翻找。上下文管理上我采用了一个滑动窗口策略每次循环结束时只保留最近三次循环的有效信息其余历史信息要么归档到长期记忆库要么直接丢弃。这样做能避免上下文无限膨胀。实测中上下文从 8k 膨胀到 30k 之后Agent 的修改准确率会明显下降所以控制上下文长度比任何提示词技巧都重要。3.2 构建阶段的实现要点我实现构建阶段时遇到的最大问题是不同项目的构建差异太大Agent 的“通用能力”在具体项目里不好使。比如有的项目需要先拉取内网依赖有的需要设置特殊环境变量有的需要特定版本的 JDK 或 Node。如果这些都靠 Agent 自行摸索效率会低到无法接受。解决方案是把环境差异“前置”。我在项目的agent_config.yaml里定义好构建命令、环境变量、依赖管理方式、测试命令。Agent 在执行构建工具时其实只是执行了一段预先配置好的脚本而不是自由地在终端里发挥。这样做的直接好处是Agent 遇到构建失败时原因通常集中在代码逻辑或依赖版本而不是“不知道要在哪个目录下执行命令”这种环境问题。本质上我们是在用“有限动作空间”换“更高的成功率”这是一个值得记住的设计哲学。另一个要点是构建日志的截取策略。构建日志动不动就几百行不能全量传给模型。我用了一个log_filter工具先识别日志中的 ERROR、FAILED、Exception 等关键字再把匹配行单独提取出来并附上前后的少量上下文行。经过这套处理后传给 Agent 的错误信息往往只有原来日志的十分之一但问题描述反而更清晰。3.3 测试执行与结果归一化测试执行本身不难难的是“归一化”。我一开始直接用 pytest 的输出作为 Agent 输入结果发现一堆assert 1 2这种信息Agent 并不能直观看懂失败的业务含义。后来我调整了策略先跑测试然后解析测试结果文件再用模板生成一段“失败说明”这段说明里包含失败用例名、失败类型、断言内容、涉及的函数名和当前实现代码。这样 Agent 看到的就是结构化的“问题描述”而不是原始日志。测试命令的设计也有一些讲究。为了尽量节省循环时间我把测试分为“快速回归”和“全量测试”两档。快速回归只运行与最近改动文件相关的用例适用于 Agent 在循环内部的快速验证全量测试则用于最终验收确保整体功能没有回归。这个设计让单轮循环时间从几分钟缩短到几十秒整个闭环的迭代速度大幅提升。如果你做的项目用 JUnit 这类 Java 测试框架需要写一个兼容的解析脚本把 XML 报告转成同样的 JSON 格式。我在项目里保留了pytest、JUnit、npm test三种解析器接口统一后面接入新框架只需新增一个解析函数。3.4 修复引擎与错误分类修复引擎是闭环里最聪明也最难做的部分。我的做法是先把错误分类不同错误用不同的修复策略。第一类是“语法类错误”比如括号不匹配、导入错误、类型错误这类错误直接定位到报错行让 Agent 做局部修复成功率极高。第二类是“逻辑类错误”比如断言失败、接口参数不对这类错误需要 Agent 阅读相关函数上下文做小范围逻辑修改。第三类是“架构类错误”比如模块依赖问题、并发问题这类错误靠 Agent 单点修改很难解决我会立即触发“积累三次修复失败后请求人工介入”的熔断机制。修复动作本身我坚持用“补丁”而不是“全量重写”。因为全量重写会让 Agent 有概率引入无关改动而补丁只针对目标位置做最小修改。补丁由模型生成后统一由apply_patch工具解析并应用如果有语法错误Agent 会在下一轮看到新的构建错误继续修正补丁。这种“小步快跑、持续纠偏”的策略非常稳。错误分类还有一个隐藏用途构建一个“修复策略推荐表”。比如错误类型是“ImportError”推荐策略就是“检查模块路径、补充依赖、替换为已有模块”错误类型是“TypeError”推荐策略就是“检查参数类型、转换类型、调整函数签名”。我用 JSON 配置维护了一个包含 20 多种常见错误类型的策略表Agent 拿到错误摘要后先查表查不到才让大模型自由分析。这个表极大降低了 Agent 的无效思考时间。3.5 循环控制与终态判定循环控制是我认为整个系统里最需要“工程感”的部分。如果循环没有良好的终止条件Agent 可能会在一个错误上反复横跳消耗大量时间。我的终止条件有三层第一层是“测试全部通过”自然终止第二层是“达到最大循环轮次比如 8 轮”强制终止第三层是“连续两轮修改完全相同但结果未变”说明 Agent 卡住了提前熔断终止。除了终止条件还有“进度记录”。每一轮循环结束时我会把当前状态写入一个loop_state.json包含当前轮次、已尝试的修改方案、测试结果、剩余待处理错误。这样即使系统中途崩溃也可以从断点恢复。调试时这个文件极其有用你能清楚地看到 Agent 每一步做了什么决策而不是只有最终结果。关于“让 Agent 自己跑”这件事我的建议是给 Agent 足够多的自由度但在关键节点设置检查点。比如当 Agent 修改了超过 5 个文件时强制停顿一下当 Agent 删除了某段代码时要求它在日志中说明原因。这些检查点不会让 Agent 变慢太多但能避免它做出不可控的“大刀阔斧式重构”。4. 从零跑通一个最小闭环4.1 准备一个“足够简单又足够真实”的项目想要验证这套闭环不建议一上来就拿大型系统试水但也不建议用 Hello World 这种没有营养的项目。我建议准备一个“有真实业务逻辑但代码量不大”的项目例如一个用 FastAPI 写的 HTTP 接口服务配合 SQLAlchemy 做数据访问外加几个接口和简单的业务校验。这种项目既有构建动作安装依赖、启动服务又有测试逻辑接口测试、数据校验还能暴露真实的代码 bug非常适合端到端验证。我的实际做法是准备一个包含 5~10 个函数的小型 Python 项目配套 20 个左右的 pytest 用例故意在代码里埋入三个 bug包括一个函数命名错误、一个参数类型不匹配、一个业务逻辑边界条件错误然后让 Agent 自主修复。这个场景能覆盖绝大多数闭环行为又不会让任务复杂到难以复现。4.2 关键参数配置清单跑通闭环最重要的一步是配置参数我在这里把关键参数整理成一张表你可以直接参考。最大循环轮次建议设置为 6~10 轮太少了不够用太多了成本高上下文窗口控制在 8k~16k 之间太大会分散模型注意力测试超时时间设置为 120 秒避免测试命令卡死构建超时时间设置为 300 秒因为第一次安装依赖通常较慢历史错误库匹配阈值设置为 0.75太低容易误匹配太高几乎找不到历史案例单文件最大修改行数设置为 50 行防止模型大范围重写文件。参数名称推荐值设置原因最大循环轮次8 轮足够完成常规修复防止无限消耗上下文窗口8k~16k平衡信息完整度与模型注意力构建超时300 秒覆盖首次依赖安装耗时测试超时120 秒防止单条用例卡死拖累循环历史错误匹配阈值0.75避免误匹配保证参考方案有效单文件最大修改行数50 行强制最小化修改降低副作用4.3 观察一次真实循环的日志我实际跑过一次修复过程日志记录的过程很有意思。第一轮Agent 执行构建命令构建失败错误是ModuleNotFoundError: No module named pydantic_settings。Agent 检查历史记录发现没有类似案例于是分析源代码判断是依赖缺失向工具调用层发起pip install pydantic-settings重新构建构建通过。第二轮进入测试阶段测试失败一个用例报AssertionError: expected status code 200, got 422。Agent 定位到接口函数发现参数校验逻辑把page参数误当成字符串处理于是加了一个类型转换重新测试通过。第三轮全量测试通过闭环自动终止。这个过程表面看起来很简单但如果没有闭环系统一个工程师要手动完成同样的排查至少需要 10 分钟的来回操作而 Agent 在 3 分钟内完成了三轮回合。更关键的是一旦这个闭环跑通它可以同时处理多个独立项目每项目一个容器、一个 Agent 实例互不干扰这是人肉流程完全做不到的横向扩展能力。5. 常见问题与排查技巧实录5.1 典型问题速查表在实现和调试过程中我遇到了不少典型问题这里整理成表格方便大家遇到类似情况时快速定位。Agent 进入死循环式修改表现为连续多轮修改但测试结果毫无变化解决办法是检查终止条件把“连续两轮无变化”熔断机制打开。Agent 找不到报错文件位置原因是上下文里没有包含足够清晰的代码定位信息应该在任务模板中加入文件路径和行号。Agent 修改一次就引入新错误原因是单次修改范围过大应该限制单文件修改行数并强制使用补丁方式。测试环境不稳定导致误判表现为同一段代码有时通过有时失败解决办法是把测试放入 Docker 容器用固定镜像重建环境。常见问题可能原因解决方案Agent 连续修改但测试结果无变化缺少熔断机制开启“连续两轮无变化”终止条件Agent 找不到错误位置上下文缺少代码定位信息在任务模板中注入文件路径与行号修改一次引入多个新错误单次修改范围过大限制单文件修改行数优先生成补丁测试结果不稳定环境依赖不一致使用 Docker 固定环境删除缓存后重建Agent 修改了无关代码指令约束不明确在修复策略中强调“最小化修改”原则5.2 三个容易被忽略的设计细节第一个细节是日志冗余问题。构建日志里两行相似的错误往往只是噪声比如同一错误在编译多个文件时重复出现如果原封不动传给模型模型容易误判为多个独立错误。我的办法是在 parse_result 阶段做一次“去重归一化”把高度相似的错误信息合并成一条附上出现次数。这个优化实施后Agent 的决策准确率提高了不少。第二个细节是修改撤销能力。很多实现没有考虑 Agent 修改错了怎么办。我给代码仓库做了一个镜像分支每次应用 Agent 的补丁前先记录当前 Git commit hash。如果某轮修改后测试结果比上一轮更差可以一键回滚到上一版本再让 Agent 换一个方向修复。没有这个撤销能力Agent 一旦在错误方向上越走越远整个循环就废了。第三个细节是模型提示词的稳定性和复用性。不要每次都在循环里动态拼接复杂的提示词而是把“构建失败分析”“测试失败分析”“补丁生成”“代码审查”等固定场景的提示词写成模板文件循环里只做模板填充。这样不仅大幅减少 token 消耗还能固定 Agent 的行为模式排查问题时也能直接审查模板上下文不必每次从日志里反推 Agent 是怎么被引导的。6. 我的实操经验与下一步扩展方向这套闭环系统我从 0 到 1 搭完大概用了两周实际调试占了一半以上的时间。我个人体会最深的是要对 Agent 的“行为习惯”有耐心它会经常给出意料之外的解法但你要把意外当成信息而不是当成 bug。比如有一次 Agent 没有直接修复一个类型错误而是把一个函数替换成了功能等价但风格不同的写法测试通过了但代码可读性下降。后来我加了“代码风格检查”到测试阶段的静态检查层才把这类问题拦住。下一步我会在两个方向继续扩展。第一是把知识库引入闭环。现在 Agent 处理错误时基本靠模型自身知识但如果在系统中接入一个内置故障知识库或 RAG 检索库再叠加外部知识图谱Agent 在修复之前就能参考历史故障案例和业务文档修复意图会更贴近真实业务。第二是把 MCP 这类标准化工具接入协议用起来让 Agent 能更规范地挂载测试工具、构建工具和数据查询工具而不只是封装 shell 命令。第三是从单 Agent 向多 Agent 演进比如让“构建 Agent”“测试 Agent”“修复 Agent”各司其职由调度中心统一协调这对大型项目的闭环效率会有明显提升。最后分享一个小技巧无论你用哪套框架哪类模型都建议在闭环系统里保留完整的“循环过程审计日志”。不要只看最终是否通过更重要的是观察 Agent 每轮做了什么决策、在哪里犹豫、在哪里犯错。开发闭环这件事本质上是一个不断把“自动修复”变得更可靠、更安全的过程而审计日志就是你迭代改进闭环本身的最重要依据。