一个人维护一套业务系统的日子我过了快三年。后来我意识到一个很现实的问题不是写代码变快了而是代码质量变得不可控。一个人写接口、一个人改漏洞、一个人上线所有的上下文都在脑子里一旦某个模块三周没碰再打开就跟看陌生人代码一样。刚开始我以为是自己的问题后来试过把任务一股脑丢给单个大模型让它一口气完成一个完整模块结果更糟糕它能写出看起来很像样的代码但一跑全是边界问题没有测试没有校验改一个错又引入两个新错。直到我把这套东西拆成多条流水线让不同角色的智能体分工协作并在每个环节都加上自动验证事情才真正开始变顺。这篇文章就是把我搭建“能自我验证的多智能体软件开发工厂”的过程完整拆给你看思路、架构、落地步骤、踩过的坑。目标读者很明确已经会用大模型写代码但觉得不够可控的开发者想从“一个人包办一切”切换成“一个小型AI团队”的独立开发者以及小团队里负责内部工具链的人。这篇文章不会只给你概念我会直接讲我实际怎么搭、怎么跑、怎么修。1. 先想清楚这个“软件开发工厂”到底是干什么的很多人在聊多智能体的时候第一反应是“多个大模型对话”。这个理解容易跑偏。我搭的东西不是让几个AI在那里聊天吹水而是一套有角色、有工序、有质量检查的软件生产流水线。1.1 从一个人的“单线程”到一群AI角色的“流水线”单枪匹马的开发模式本质是单线程你接到需求自己在脑子里设计、编码、测试、修复最后交付。这个模式在项目小的时候很高效因为没有沟通损耗所有上下文都在你脑子里。但项目一旦变大问题就暴露了上下文会被新需求冲淡旧代码的约束容易被忘掉回归测试只能靠感觉。多智能体工厂的思路完全不同把开发动作拆成可以并行、可以交接、可以验证的独立环节。比如一个负责理解需求的角色把模糊描述拆成明确任务一个负责设计的角色产出技术方案一个负责编码的角色写具体代码一个负责测试的角色写测试用例并执行验证还有一个负责审查的角色检查代码风格和逻辑漏洞。它们之间通过共享的工作区和结构化的任务单据协作而不是通过闲聊式对话。这个转变有一个关键点流水线不追求单个Agent有多聪明而是追求每个Agent只干一件事、干标准。就像工厂里一个工人不需要懂整条产线只需要把自己那个工位做对。多智能体的稳定性来自分工本身而不是来自某个模型的“超能力”。1.2 什么是“能自我验证”的多智能体工厂“自我验证”这四个字是我这套设计的灵魂。单纯让AI写代码不行因为如果没有验证机制AI产出的东西是不是真的能用只能靠人肉去看。而一旦引入验证环节闭环就成立了Agent写完代码自动触发编译、测试、静态检查测试结果再反馈给Agent去修复直到全部通过。这里的“验证”不是简单跑一遍单元测试这么简单。我做的是三层验证第一层格式与编译校验。代码能不能被解释器/编译器正常解析有没有语法错误。第二层逻辑验证。运行测试用例检查功能是否符合预期。第三层变更影响校验。看看这次改动有没有碰坏已有功能也就是回归验证。三层验证列表的目的是把“AI看起来写了代码”和“AI真的交付可用代码”区分开。没有验证回路的多智能体本质还是一堆高级聊天机器人有了验证回路的才配叫工厂。2. 工厂的整体设计角色、任务流和验证回路动手写代码之前我先把整个工厂的运行模型画在纸上。这个阶段最忌讳的是直接打开编辑器开始写Agent因为你会陷入“这个角色到底该干什么”的细节里。我习惯先回答清楚三个问题有哪几个岗位任务怎么流动怎么判断一个环节做完了2.1 角色分工五个必备的AI岗位按照我最终的实践版本一个最小可用的工厂至少需要五个角色需求分析Agent输入是用户一句话输出是结构化任务清单包括功能点、边界条件、验收标准。架构设计Agent根据任务清单输出技术选型建议、模块划分、接口定义以及待实现文件清单。编码实现Agent按照设计文档逐个实现文件代码内要包含必要注释和关键逻辑说明。测试验证Agent为每个功能点编写测试用例然后执行验证输出测试报告并在失败时给出失败原因和修改建议。质量审查Agent对通过测试的代码做最终审查检查是否有明显安全隐患、性能问题和逻辑漏洞给出通过或打回结论。这里要注意五个角色不是必须在一开始就全部同时跑而是沿着任务流依次激活。我的经验是“顺序为主、小范围并行”比如编码Agent写代码的同时测试Agent可以先准备测试框架但同一个文件的读写必须加锁避免两个人同时改一个文件。2.2 任务如何流转状态机是工厂的流水线我不用复杂的任务调度系统而是用一个简单状态机来管理每个开发任务的状态。状态流转是这样的pending任务已创建等待分配。analyzing需求分析Agent在处理。designed设计完成等待编码。coding编码Agent在处理。testing测试验证Agent在处理。reviewing质量审查Agent在处理。passed验证全部通过准备交付。failed某个环节失败等待回退。每个Agent只负责把任务状态从A推到B并且必须附带产物。例如需求分析Agent把状态从pending推进到analyzing完成、状态变成designed同时把任务拆分文档写入共享工作区。下一环节只能消费上一环节的产物不允许跳步。状态机的最大好处是出问题时能快速定位卡点。比如任务一直停在testing多半是测试挂了停在coding多半是编码Agent跑偏或者依赖缺失。日志里只记录状态迁移和产物路径排查起来非常快。2.3 自我验证回路为什么它是整个工厂的心脏整个工厂里最核心的循环不是任务流本身而是“编码-测试-修复-再测试”的闭环。我给这个循环起名叫验证回路。它的基本流程是编码Agent交付代码。测试Agent执行三个动作安装依赖、跑测试用例、输出报告。如果测试失败失败信息被格式化后交给编码Agent。编码Agent结合失败信息修改代码再次提交验证。循环直到测试通过或者达到最大迭代次数。这个回路的参数很关键。我一开始没设上限结果某些任务会死循环模型反复改同一个地方。后来加了两个参数单任务最大修复轮数默认5如果第五轮还没通过自动告警并转给人工。人工介入以后有两条路手动修复后重新提交验证或者调整任务描述后从某个状态重跑。注意验证回路里“失败反馈”要结构化不能直接把几十KB的日志丢给Agent。我后来把失败信息压缩成失败用例名称、期望结果、实际结果、关键错误行、周边代码片段。反馈越精准下一轮修复成功率越高。3. 手把手搭一个最小可用版本下面这部分是实操。假设你要从零开始搭一个最小版本我会按我自己搭建时的顺序走一遍环境准备、目录结构、核心数据模型、Agent执行器、验证模块、调度循环。3.1 环境准备先备好这些工具我不依赖某个特定的Agent框架因为这类框架迭代太快而且容易把我锁在别人设计的抽象里。我选择自己控制核心循环只把大模型调用当作可替换的组件。推荐的基础环境如下一门主流脚本语言我常用Python 3.10以上版本。大模型API接口需要支持传入系统提示词和结构化输出最好支持函数调用。一个虚拟环境管理工具用来隔离每个项目的依赖。一个测试框架能自动发现测试目录下的测试文件并执行断言。一套基础设施比如容器或独立虚拟环境保证每次验证都在干净环境里跑。不推荐新手一上来就追求微服务化把所有Agent拆成独立服务。前期用一个单进程里的多线程/异步调度就够了重点是先把流水线跑通。3.2 工厂目录结构和数据模型我建议按这样一个目录结构组织工厂工作区factory/ workdir/ tasks/ 2025-0601-user-registration/ task.json requirements.md design.md src/ tests/ report.json logs/ agents/ analyzer.py architect.py coder.py tester.py reviewer.py core/ state_machine.py schemas.py runner.py这个结构的意图很清晰每个任务一个独立目录所有中间产物都在里面互不干扰。task.json是任务单据贯穿整个生命周期。task.json我用的最小结构长这样{ task_id: 2025-0601-user-registration, title: 用户注册接口, description: 实现一个带验证码校验的用户注册接口, state: pending, current_step: analyze, max_fix_rounds: 5, artifacts: { requirements: tasks/2025-0601-user-registration/requirements.md, design: tasks/2025-0601-user-registration/design.md, source: tasks/2025-0601-user-registration/src, tests: tasks/2025-0601-user-registration/tests }, last_report: {} }这个数据模型是整个工厂的“单据”每个Agent工作结束时都必须维护这个文件。我后来还加了一个审计字段记录每次状态变更的时间和执行Agent方便回溯。3.3 Agent执行器让每个角色真正干活有了任务单据和目录结构下一步就是写Agent执行器。我这里的Agent执行器不是指一个独立的模型而是一个函数输入是任务上下文输出是更新后的task.json和产物文件。以编码Agent为例核心流程是读取requirements.md、design.md。根据设计文档中的文件清单逐个生成或修改代码文件。把生成结果写入src目录。更新task.json中的state为“testing”并把编码说明追加到last_report。这一步最需要注意的是上下文的窗口控制。设计文档可能很长直接把整份塞进提示词会撑爆上下文。我用的方法是摘要式传递编码Agent只接收“这个文件的职责说明”“对外接口签名”“依赖的其他模块”不接收整份设计文档。具体到每个文件的生成再单独带上下文。给Agent的提示词也要结构化。我不写大段英文散文而是用分节的方式你是一名编码Agent。 任务背景{摘要} 本文件职责{职责} 接口要求{接口} 技术约束{约束} 输出要求只输出代码不要解释过程。这样做的原因是减少自由发挥空间。你越给它发挥空间它越容易“创新”而在软件开发工厂里“创新”往往意味着偏离设计。3.4 验证模块如何判断AI写的代码是否合格验证模块是另一个核心。它的任务不是写测试而是执行测试、产出报告。我让测试Agent写测试用例但真正执行的时候由独立的验证脚本加载测试文件并运行目的是避免“既当运动员又当裁判”——如果让同一个Agent既写代码又写测试它大概率会照着代码逻辑写同义测试等于没测。验证模块的执行逻辑如下def run_validation(task_dir, max_timeout300): setup_environment(task_dir) # 安装依赖、创建虚拟环境 run_static_check(task_dir) # 语法/格式检查 result run_test_suite(task_dir) # 执行测试 report format_result(result) # 结构化报告 save_report(task_dir, report) return report测试报告我会做成类似下面的结构方便喂回给编码Agent{ passed: 8, failed: 2, failures: [ { case: test_register_duplicate_username, expected: 返回400错误码, actual: 返回200并在数据库创建了重复记录, error_line: src/register.py:42, snippet: if user_exists(username): return success_response() } ] }这个结构化报告是整个闭环的粘合剂。没有它编码Agent面对一大段日志根本不知道改哪儿有了它下一轮修复就是小步调优。3.5 调度循环从提交任务到交付产物的完整流程调度器是整个工厂的“主管”它读取任务队列按状态机派发任务给对应Agent执行器。我用一个简单伪代码来表示主循环def factory_loop(task): while task.state not in (passed, failed, needs_human): if task.state pending: run_agent(analyzer_agent, task) elif task.state designed: run_agent(coder_agent, task) elif task.state coding: run_agent(tester_agent, task) elif task.state testing: report run_validation(task) if report[failed] 0: run_agent(reviewer_agent, task) else: if task.fix_round task.max_fix_rounds: task.fix_round 1 task.state coding task.last_report report else: task.state needs_human # 日志、清理、状态持久化我实际操作时会加一个sleep或者并发限制防止多个任务同时跑的时候把API额度瞬间打爆。最小可用版可以先用串行调度一个任务跑完再跑下一个保证可复现。搭建到这里你已经有了一条可以跑通的流水线。虽然还很粗糙但“从任务描述到代码到测试到通过”的闭环已经成立了。下一步就是丢一些真实任务进去压测然后看它在哪里卡住。4. 常见问题与排查技巧实录我真正推荐的实践方式是不要照着我的结构抄完就结束而是拿一个或两个你手头的小需求去跑。我跑了大概不到一个月踩了一堆坑挑几个最典型的分享。4.1 上下文溢出Agent忘记任务目标现象是编码Agent写到最后几个文件时开始偏离设计甚至重新发明接口。排查发现不是模型能力问题而是上下文太长早期的设计约束已经被挤出去了。后来我把设计文档拆成“全局摘要”和“模块详情”每次生成单个文件只加载对应模块详情同时把全局规则压缩成一份只有十行左右的“军规”比如“不准改公共接口”“不准引入新外部依赖”“函数必须带类型注解”。丢给Agent的文件级指令严格限制在一屏以内效果提升肉眼可见。4.2 测试形同虚设断言太少最开始我让测试Agent自动生成测试用例结果测试全过了但是功能依然是错的。原因很简单Agent生成的测试都是“正向用例”只验证输入正常的情况没覆盖边界、重复、权限这些场景。后来我在需求分析阶段就要求列出边界条件清单测试Agent必须针对清单逐条写用例否则打回重写。另一个办法是人工定期随机抽查几条测试用例的质量别迷信“自动生成”。4.3 无限修复循环成本失控这是我早期最痛的一个问题。某次一个支付相关的模块框架每次改完代码测试都从失败变成另一个失败来回了十几轮API账单涨得飞快。后来我加了最大修复轮数第三轮结束后如果还没通过就把问题升级给人工。升级信息包括“前五次的修改内容”“测试反馈摘要”“失败模式分析”这样人工进来一眼就知道大概哪里有问题不用重新跑。4.4 并发写入冲突多个Agent同时改文件当任务流里加入并行处理之后容易遇到两个Agent同时改同一份文件。我的解决办法是引入文件锁凡是准备写入文件先检查是否有锁。更简单一点的方式是把可写区域按角色划分编码Agent只能写src测试Agent只能写tests架构Agent只能写design.md角色之间的交叉写盘要通过调度器转发。4.5 验证环境漂移本地能过工厂却失败这个坑很隐蔽。测试Agent在自己的环境里跑通过但工厂验证模块跑失败。后来发现是依赖版本不一致。解决方法是每建一个任务目录就给它生成一份锁定版本的依赖清单验证前强制按照清单重新安装。别省这一步环境漂移会让你的验证回路形同虚设。5. 进阶扩展与个人实操体会跑通最小版本之后你会开始想加更多能力。这里我给几个我实际用过且有效的扩展方向不说空话。5.1 从单项目到多项目并发当你要同时开发多个模块时单任务流水线就不够用了。我给调度器加了一个按优先级排序的任务队列高优先级任务抢占空闲Agent低优先级任务排队。每个任务目录继续隔离但底层的验证资源虚拟环境、CPU、API额度需要共享。这时候建议做两件事一是给Agent调用加上超时和重试机制二是给每个任务打上预算标签超过预算就直接挂起。5.2 人工审核节点的正确位置很多人以为多智能体工厂可以全自动无人值守我的经验是不行。自动化的优势在于把机械劳动吃掉但最终交付节点的审核必须有人。我目前保留两个人工节点任务启动时人确认需求拆解是否合理任务结束时人抽查代码和测试报告。中间的大规模调试、回归、修改全部交给流水线。这样既不会累死也不至于完全失控。5.3 我给新手的三条建议第一条先用小任务建设信任。别一上来就拿核心金融系统试先拿一个没有任何历史包袱的小工具比如给内部用的文件重命名脚本把它跑通。第二条看日志比看生成的代码更重要。核心调试手段就是看任务状态迁移和测试报告不要盯着Agent生成的“思考过程”看那是干扰信息。第三条保持可回放。每个任务目录保留完整的输入、输出、状态变化记录下次改设计或者排查问题你都能快速重建现场。我在实际操作中最深的体会是多智能体软件开发工厂真正解决的不是“写代码的速度”而是“交付质量的稳定性”。它把不可见的大脑思维过程变成了可见、可测、可修正的流水线。学会把这个闭环搭建起来你就不需要一个人扛所有事情了。你也可以让一个“AI团队”替你扛住大部分重复劳动而你自己去做真正需要判断力的部分。