最近我把整个工作流改成了“零干预”模式,折腾出了一套能让AI真正越用越聪明的自动进化方案。核心是围绕某开源自动化框架展开的,也就是标题里那套OpenClaw/Moltbot的思路,让代理自动操控编码模型CLI,以规格文件为唯一准绳,全程不需要人工盯着终端,从需求分解、代码生成、自动验证到失败修复全部由系统自己闭环完成。最关键的是,这套系统不是每次从头开始,而是会把失败案例沉淀成教训库,下一次遇到同类问题直接绕坑走。这篇文章不聊概念,直接讲架构、配置、坑点和我实测跑通一个完整任务的过程。
1. 为什么需要“自动进化”型助手:固定脚本和自学习代理是两码事
1.1 传统自动化脚本的根本局限
过去我们聊AI自动化,基本是“写好流程脚本,然后靠着规则触发”。比如监听某个目录,文件一变化就执行一段命令;或者解析一个任务列表,逐条调用API。这种方式的优点是稳定,缺点是根本不具备适应性。只要输入格式稍微变化、环境变量名改一下、第三方服务返回了一个预期外的异常,整个流程立刻崩掉,而且崩得毫无预兆。
我之前的做法是给脚本不断增加异常分支,try-except套了一层又一层,最后代码看起来像一个膨胀到失控的怪物。每一个新分支只解决一个特定的历史故障,本质上是在给系统打补丁,而不是让系统学会举一反三。这种“打补丁式自动化”维护成本非常高,因为每次环境或依赖变化都要人工介入去修改规则。
1.2 规格驱动开发解决了什么痛点
规格驱动开发(Spec-Driven Development)的核心思路是:人只负责写清楚“要什么、边界是什么、怎么算完成”,机器负责把规格翻译成代码。以前的开发流程里,需求文档和代码之间存在巨大的鸿沟,产品经理写的需求和技术实现之间总有理解偏差,而规格驱动开发试图把“验收标准”变成第一等公民。
在我的实践中,规格文件承担了三个角色:给执行代理提供任务目标的说明书、给验证模块提供是否完成的判断依据、给人类提供唯一需要审查的产物。规格文件写得好,代理就不需要反复向人确认;规格文件写得不清楚,代理可能在一个错误的方向上越走越远。所以这个方案里,真正考验人的能力从“写代码”变成了“写规格”。
1.3 自动进化带来的实际体验差异
用上自动进化之后,最直观的感受是整个开发周期里,“等待”的时间变长了,但“盯屏幕”的时间变成了零。以前我开着终端跑自动化,每隔几分钟就要看一眼输出,确保它没有跑偏。现在我把任务规格丢进系统,直接去做别的事情,过一段时间回来看结果。系统会自己在工作目录里生成代码、运行测试、分析报错、调整方案,甚至会在修复完成后给我发一份简短的变更摘要。
比“不用盯屏幕”更有价值的是,系统在连续执行多个任务之后,对项目代码风格、依赖关系、常见坑点形成了自己的记忆。比如第一次犯过的错误,第二次基本不会再犯;在新任务里遇到和教训库中相似度极高的错误签名时,它会直接引用历史解决方案。这就是“越用越聪明”的真正含义。
2. 自动操控编码模型CLI的架构:指挥、执行、验证、记忆四件套
2.1 整套系统由四个模块构成
这套方案的架构不算复杂,核心是四个模块:规划器(Planner)、执行器(Executor)、验证器(Verifier)、记忆管理器(Memory Manager)。它们各司其职,形成了一条完整的闭环链路。
规划器负责读取规格文件,把它拆解成一个有序的任务步骤。执行器负责把每一步任务指令转换为具体的命令,通过命令行方式发送给编码模型CLI,并采集它的输出。验证器负责判断执行结果是否满足验收标准,比如运行编译、执行测试、检查文件是否生成。记忆管理器是自动进化的核心,它记录每次失败发生时的错误特征、上下文、修复方案,并在后续任务中提供相似度匹配。
这四个模块的关系是流水线式的:规划器先生成任务清单,执行器逐条执行,验证器检验成果,失败则查询记忆管理器,拿到历史经验后修正指令再次执行。整个循环由一套任务状态机控制,直到所有步骤通过验证或达到最大迭代次数。
2.2 会话管理:让编码模型保持上下文连贯
自动操控编码模型CLI时,一个容易翻车的地方是会话上下文。如果每执行一条指令就新建一个会话,模型会完全失去对项目背景、此前代码结构的记忆,生成的内容会非常碎片化。但如果持续保持同一个会话,又会遇到上下文窗口被填满、系统开始遗忘早期关键信息的问题。
我的做法是设置一个会话池,按任务维度隔离上下文。同一个任务的所有指令和反馈在同一个会话里流转,任务完成之后把会话关闭,重要结论转存到记忆库。每次执行器发送指令之前,会先计算当前会话的Token占用,如果接近上限,就执行一次“摘要折叠”,把前面几轮的关键信息(当前目标、已验收部分、遗留问题)压缩成摘要,然后开启新的会话上下文。这一步直接决定了长时间任务的稳定率。
2.3 输出解析与任务状态机
编码模型CLI会输出大量文本,包括思考过程、代码块、命令输出、错误信息。执行器不能把这些内容全部原样交给验证器,需要先做一轮解析,提取出真正关键的部分。我解析的目标是三类信息:动作意图(模型准备执行什么操作)、代码变更(新增或修改了哪些文件)、报错片段(测试或编译输出里的Exception、Error信息)。
解析完成之后,任务状态机把当前状态标记为以下几种之一:待执行、执行中、待验证、验证通过、验证失败、已修复、已完成。状态机的迁移规则很重要,比如验证失败之后不能直接跳回已完成,必须先经过记忆查询和指令修正的环节。这个严谨的状态流转,保证了整个自动进化过程是可追踪、可回放的,不会出现“看似完成但实际缺步骤”的情况。
3. 从零搭建自动进化系统:规格文件、记忆库与调度配置
3.1 项目目录与最小骨架
搭建这套系统不需要很复杂的工程,按我的经验,一个项目目录就能装下全部核心模块:
auto-agent/ ├── specs/ # 规格文件放这里 │ └── task_login.md ├── workspace/ # 编码模型CLI的工作目录 │ ├── src/ │ └── tests/ ├── memory/ │ └── lessons.db # 教训库,SQLite文件 ├── modules/ │ ├── planner.py │ ├── executor.py │ ├── verifier.py │ └── memory_manager.py ├── config.yaml # 核心配置 └── main.py # 主调度入口这个结构的重点是:规格、代码、记忆三块物理隔离。规格目录只放人类撰写的需求描述;工作目录是编码模型CLI实际生成和修改代码的地方;记忆库是系统级资产,不随某个任务销毁。目录隔离做不好,后面教训库的积累就会变得混乱。
3.2 核心配置文件解析
下面这份配置是跑通整套流程的关键参数,每一行背后都有讲究:
agent: max_iterations: 12 # 单个任务允许的最大验证-修复轮数 session_timeout_seconds: 600 # 会话空闲超时 planner_model: primary-llm # 规划模型,负责拆分任务 executor_cli: code-cli # 编码模型CLI命令 spec: dir: ./specs auto_archive_done: true # 已完成任务规格自动归档 executor: max_output_chars: 16000 # 单次输出截断阈值 retry_on_timeout: 3 context_fold_threshold: 0.72 # 会话上下文占用72%时触发摘要折叠 verifier: test_cmd: "cd ./workspace && python -m pytest tests/" build_cmd: "cd ./workspace && python -m compileall src/" required_files: ["src", "tests"] memory: store: ./memory/lessons.db similarity_threshold: 0.78 # 相似度低于阈值就不回灌 max_lessons_per_task: 20 # 每个任务最多新增教训条目数 auto_prune: true # 自动清理长期未命中的旧教训其中的similarity_threshold值得专门说一下。如果阈值设置太低,比如0.55,那么很多表面相似但根因不同的错误都会被匹配上,系统会把错误的修复方案回灌给当前任务,反而导致偏离。我试过0.70、0.75、0.78几档,0.78在这套方案里的命中率和精确度最均衡。阈值太高也不行,会漏掉大量本可复用的经验。
3.3 规格文件的撰写要点
规格文件是整个自动进化体系的上游,质量决定了系统上限。我通常用Markdown格式写规格,结构固定为四段:功能需求、验收标准、约束条件、交付物清单。
# 任务规格:用户登录接口开发 ## 功能需求 - 提供 POST /api/login 接口 - 接收用户名和密码,校验通过后返回访问令牌 - 令牌有效期为 24 小时 ## 验收标准 - 正确凭据返回 200 状态码且响应体包含 token 字段 - 错误密码返回 401 状态码 - 请求体缺少字段时返回 400,并附带精确的错误描述 - 连续失败 5 次后锁定账户 15 分钟 ## 约束条件 - 必须复用项目已有的数据库连接池,禁止新增连接 - 密码必须使用加密哈希存储,禁止明文传输 - 日志必须包含登录事件的时间、IP、账号、结果 ## 交付物清单 - src/auth/login.py - tests/test_login.py - 更新 API 路由注册文件验收标准必须写成机器可验证的语句,避免“用户体验良好”“性能优异”之类的模糊描述。约束条件是防止AI自由发挥时引入不合理依赖的关键,比如上面“禁止新增连接”这一条,就能避开AI自作主张创建一套新数据库链接逻辑的坑。
3.4 第一次启动后的预期结果
配置好环境和规格文件之后,运行主调度入口,系统会按顺序执行:规划器读取规格,生成任务步骤列表;执行器调用编码模型CLI逐个步骤生成代码;验证器运行编译和测试;失败则进入记忆查询与修复循环。第一次运行通常在几分钟到十几分钟之间,取决于任务复杂度和CLI生成速度。
此时不要期待一次成功。实测下来,第一次任务的失败率会明显高于之后的同类任务,这不是坏事,恰恰是自动进化系统积累初始教训库的过程。系统会在第一次“笨拙地踩坑”之后,逐渐表现出越来越熟练的行为模式。
4. 让系统自动记住坑:教训库的捕获、匹配与回灌机制
4.1 失败信息的结构化捕获
自动避坑的第一步是把失败变成结构化数据。验证器在检测到测试失败或编译错误时,不会只丢给执行器一段日志,而是调用记忆管理器做一次“失败快照”。快照里至少包含完整报错信息、关键错误类型、导致失败的最相近代码片段、当时正在执行的任务目标、验证器的判断依据。
这里有个很容易忽略的细节:报错文本的去重与归一化。同一类错误在不同任务里可能表现为完全不同的字面量,比如失败的文件名、变量名不同,但错误本质都是“空指针访问数组元素”。所以在存入教训库之前,我会用一套规则做归一化:把数字、字符串、变量名替换为占位符,然后提取错误类型的核心签名。这样后续相似度匹配才有意义。
4.2 教训条目的数据结构设计
教训库用SQLite存储,单条记录包含以下核心字段:
{ "id": "lesson_0007", "category": "web_auth", "error_signature": { "error_type": "AttributeError", "keyword": "'NoneType' object has no attribute 'get'" }, "trigger_context": "解码访问令牌后立即读取user_id字段", "solution": "在读取user_id之前先检查payload是否为None,并增加缺失字段的默认值处理", "source_spec": "用户登录接口开发", "created_at": "2025-03-21T10:24:00Z", "hit_count": 3, "last_hit_at": "2025-03-22T16:40:00Z" }hit_count字段记录了这条教训被成功复用且验证通过的次数,这个数字在后续自动清理时会参与权重计算。如果某条教训长期未被命中,会被降权甚至删除,避免教训库无限膨胀。category字段用于粗粒度过滤,比如web认证相关的错误不需要在数据处理任务中检索,减少无意义的相似度计算。
4.3 相似度匹配与指令回灌策略
当验证器报告一次新的失败时,记忆管理器会在教训库中执行两步检索。第一步按category做粗筛,第二步在结果集中计算错误签名和触发上下文的文本相似度。超过阈值的条目会被视为匹配成功,其中相似度最高的那条会被选中。
选中历史教训之后,执行器不是简单地把“上次的解决方案”复制给编码模型CLI,而是把它作为一个“专家建议片段”注入到当前提示中。提示里会说明:“以下是你之前遇到过的类似问题的修复建议,请参考该建议分析当前报错是否属于同一根因。”这个措辞看起来无关紧要,但实际效果差别很大。如果直接把历史方案混进普通指令里,模型有时候会无脑套用,而加上“是否属于同一根因”的语态后,模型会先做判断再决定是否采纳。
4.4 防止教训库“越学越乱”
记忆库如果设计不好,会出现一个很尴尬的局面:系统记住了大量错误经验,但每条经验之间互相矛盾,甚至把正确的做法给覆盖了。我在实际测试中就遇到过,系统因为回灌了一条错误的历史教训,把一个原本正确的实现改坏了。
控制这种混乱需要三个机制。一是单任务教训数量上限,每个任务最多新增20条教训,超出之后再遇到失败就不再写入,而是强制触发人工审查标记。二是验证门槛,新增的教训必须以“修复后测试通过”作为前提,没有经过验证的失败经验不允许入库。三是定期清理,历史教训的权重会随时间和命中情况衰减,长期未命中的冷门条目自动进入候选删除列表。
5. 零干预规格驱动开发的完整实录:从任务创建到验证通过
5.1 我选定的测试任务:商品库存扣减接口
为了验证这套自动进化系统在真实场景中的表现,我给系统下达了一个带有一定业务复杂度的任务:开发一个商品库存扣减接口,要求支持超卖拦截、缓存更新、操作日志记录。难度在于验收标准里有几条边界条件需要同时满足,比如“并发扣减超过剩余库存时必须拒绝请求且返回明确错误码”。
我把规格文件写到配置的specs目录,启动主调度入口,然后关闭了终端窗口。本次任务的记录来自系统自身输出的日志,全程没有人工干预。
5.2 首次执行:生成代码、跑测试、第一次失败
系统先由规划器把规格拆成五步:设计路由、实现扣减逻辑、添加超卖判断、接入缓存、补充测试用例。编码模型CLI在约三分钟内完成了第一版代码。验证器随即运行构建与测试,结果只有一条用例失败:并发场景下库存被扣减到了负数。
从日志看,验证器捕获到失败断言信息,经过归一化后,错误签名被识别为“并发场景下共享计数器未加锁”。记忆管理器的粗筛命中了category为“inventory”的教训,但相似度只有0.62,低于0.78的阈值,所以没有被回灌。系统进入自主分析模式,执行器重新编码了“在扣减前对库存行加锁”的逻辑,并添加了原子更新条件。
5.3 自动修复与回归验证:第一次展现“聪明”
修复后的代码通过了全部测试用例,验证器还对原规格里的约束条件做了逐项复核,包括缓存更新策略和日志字段完整性。整个任务从开始到确认完成耗时约十四分钟,其中超过一半时间花在自主修复轮次上。
更值得记录的细节是,这个修复过程被记忆管理器写入了一条新教训,错误签名是“并发扣减未加锁”,解决方案是“使用条件更新语句确保原子性”。这意味着如果以后其他任务涉及库存或类似的并发写操作,系统会直接拿到这次的修复经验,不用再次从头排查。这就是“越用越聪明”从口号变成现实的过程。
5.4 系统在什么情况下会主动请求人工介入
整个流程虽然零干预,但不意味着绝对不接触人。系统设置了三个自动请求人工介入的触发条件:达到最大迭代次数仍未能通过验证、所有候选教训的相似度低于0.5且失败模式从未见过、业务语义涉及“删除类”或“批量覆盖类”的高风险操作。当遇到这三种情况时,系统会把当前状态、失败原因、候选方案打包成一份简报,暂停任务,等待人类决定。
这种“知进退”的设计我觉得比一味追求全自动更重要。全自动的前提是系统有足够的能力边界认知,知道自己什么时候该停下来。一个不会停下来的自动化系统,在某些场景下是灾难。
6. 实测中的典型翻车现场与我的几条收敛建议
6.1 上下文爆炸导致偏题
最早测试时我把会话摘要折叠阈值设到了0.92,想着让模型尽量保留更多上下文。结果跑了几个任务之后,系统开始出现“答非所问”的情况,指令让它优化登录接口,它却在重构日志模块。原因是上下文窗口在接近上限时,模型早期的重要约束信息被挤掉了,后续指令的解读完全走样。
把阈值降到0.72并增加摘要折叠机制之后,这个现象基本消失。摘要折叠并不是简单地裁剪前文,而是把当前任务目标、已验证部分、待办事项重新整理成一段结构化的任务摘要。它改变了提示的形态,但不改变任务的实质目标。
6.2 学到了错误的教训并反向传播
最让人头疼的一类问题,是系统在一次偶然失败中学到了一个不正确的恢复方案,然后在后续任务中不断复用。我遇到过这样的情况:一次测试失败实际上是由于第三方服务短暂不可用导致的,但系统把失败归因为代码逻辑错误,写入了一条“修复方案”。后续任务触发了这条错误教训的相似匹配,导致大量本无问题的代码被修改。
止损的关键是给新教训设置一个“试用期”。我调整了记忆管理器的逻辑:新增教训在第一次被命中时,不会直接进入回灌流程,而是先标记为“待验证”,系统会记录这条修复是否真的帮助任务通过了验证。连续验证通过两次以上的教训,才会进入正式回灌库。这个机制基本杜绝了错误教训的扩散。
6.3 规格文件措辞歧义的代价
规格驱动开发里,模型生成的内容再聪明,也扛不住规格本身有歧义。我写过一条验收标准:“缓存必须实时更新”,结果系统理解为每次扣减都需要同步执行缓存写操作,完全没考虑异步更新和失败重试的场景。
现在写规格文件我会刻意规避两类措辞:一是“必须/确保”这类没有程度量词的要求,必须量化成“更新延时不得超过5秒”或“失败重试至少3次”;二是涉及时间、状态、边界条件的描述,必须把前置条件和异常分支都写出来。规格文件多花半小时,系统可能就少跑一个小时的错误修复轮次。
6.4 收敛建议:给自动进化立几条边界
根据这段时间的实操经验,想用这套方案真正提升效率,有几个边界提前定好会更省心。第一,给大任务设置时间上限,不要让系统无限重试,重试成本有时候高于人工写一遍的成本。第二,定期关注教训库的命中率报表,如果连续多个任务都没有命中任何历史教训,说明规格多样性和任务相似度之间存在断层,需要补充更多样本。第三,把规格文件视为代码来管理,纳入版本控制、有评审流程、有变更记录,规格本身变了,系统行为才会跟着正确调整。
我的经验是,自动进化系统最适合的工作是那些“模式明确、验收可量化、历史经验可复用”的开发子任务,比如接口增改、校验逻辑补充、测试用例编写、常见bug修复。它暂时不适合做架构级重构或产品方向创新,那种任务需要的判断力已经超出了当前这套“记忆+匹配+回灌”机制的能力边界。
最后分享一个新发现:在多个任务跑完之后,我注意到配备记忆库的系统相比没有记忆库的版本,在新任务第一次验证通过率上提升了明显层次,而且越到后面,差距越大。这让我更确信,未来自动化开发的方向不是做出更聪明的单次生成模型,而是构建能持续积累经验的系统生态。你如果也准备上手,建议从一个小而真实的接口任务开始,规格写细一点,记忆阈值的参数不需要迷信默认值,实际跑两轮再调。