AI虚拟团队自动化进化:从“人盯人“到“自愈系统“
💡一句话总结:前三篇讲了架构、踩坑、通信。这篇讲实战进化——系统怎么从"人工调度"一步步变成能自动发现问题、自动修复、自动重试的"自愈系统"。核心是一个字:闭环。
📌 前情回顾
- 第一篇:我用4个AI搭了一个"虚拟开发团队"——架构overview
- 第二篇:AI虚拟团队跑了一个月,我踩了这些坑——Agent撒谎、Gateway崩溃、任务卡死
- 第三篇:AI虚拟团队的"神经系统"——消息总线、心跳检测、自动派发
这一篇讲从第三篇的"能跑"到真正"好用"之间,我做了哪些进化。
🔴 问题一:心跳在跑,但超时任务没人管
现象
心跳每分钟跑一次,检测到任务超时(>5分钟),报告里写着"⏰ 小虾/FIX-xxx 超时11分钟"——然后呢?什么也没发生。
报告发给我看了,但系统不会自动处理。我还是得手动去唤醒小虾、取消旧任务、重新派发。
根因
心跳脚本的超时处理只做了"诊断",没做"修复":
# 旧代码:只ping一下,然后重发消息defdiagnose_and_fix_timeout(agent,task_id,elapsed):result=subprocess.run(['openclaw','agent','--agent',agent_id,'-m','ping','--timeout','15000'])ifresult.returncode==0:# 重新发消息...但没清理旧状态subprocess.run(['openclaw','agent','--agent',agent_id,'-m',content,'--timeout','120000'])returnTrue,"重新派发任务"问题:
- 没取消DB里的旧任务记录(status还是pending)
- 没清理inbox里的旧文件(新消息和旧消息混在一起)
- 没通过正式流程重新派发(直接发消息,不写DB)
- Agent可能根本没收到(消息堆积在inbox里)
修复:4步完整流程
defdiagnose_and_fix_timeout(agent,task_id,elapsed):"""诊断超时原因并自动修复:取消旧任务 → 清理inbox → 重新派发 → 唤醒Agent"""# Step 1: 取消旧DB记录db=sqlite3.connect(TASKS_DB,timeout=5)db.execute("UPDATE tasks SET status='cancelled' WHERE task_id=? AND status='pending'",(task_id,))db.commit()db.close()# Step 2: 清理旧inbox文件(保留.done)inbox_dir=f"{SYNC_DIR}/inbox/{agent_id}"forfinos.listdir(inbox_dir):iftask_idinfandf.endswith('.json')andnotf.endswith('.done'):os.remove(os.path.join(inbox_dir,f))# Step 3: 重新派发(通过send_task.py正式流程)subprocess.run([sys.executable,'send_task.py','小密',agent,task_id,'1',f'超时重派:{task_id}'])# Step 4: 唤醒Agentsubprocess.run(['openclaw','agent','--agent',agent_id,'-m','ping','--timeout','15000'])关键变化:从"诊断+重发消息"变成"取消→清理→正式派发→唤醒"。每一步都有副作用,但每一步都是必要的。
🔴 问题二:Agent完成了,但测试没自动派发
现象
小虾完成开发任务,.done文件有了,但小牛没收到测试任务。我得手动写测试MD、手动派发。
根因
自动派发逻辑auto_dispatch_tests_for_completed_dev()本身没问题——它会扫描小虾inbox的.done文件,检查小牛inbox有没有对应的TEST-{task_id}文件,没有就自动派发。
问题出在触发时机:
- 我直接用
openclaw agent --agent main -m "执行任务"唤醒小虾 - 小虾执行完,创建了
.done文件 - 但心跳没运行(或者在grace period内)
- 自动派发逻辑没机会执行
为什么心跳没运行?
心跳有个"grace period"机制——每次唤醒Agent后180秒内,跳过某些操作避免重复。但这个机制太粗暴,把自动派发也一起跳过了。
而且更根本的问题是:我绕过了心跳流程。直接openclaw agent执行任务,心跳根本不知道发生了什么。
教训
自动化系统的每条路径都必须经过同一个"中枢"。不能有"后门"——即使你是管理员。否则中枢的自动逻辑就形同虚设。
🔴 问题三:报告格式"说一套做一套"
现象
心跳报告显示"✅ 所有任务已完成",但下面还有一堆注意事项。或者报告里有"📋 自动创建测试待办: TEST-xxx"这行字,但不在注意事项区域,而是单独出现在报告上方。
根因
两个独立的bug:
- 逻辑矛盾:当有notes时,报告仍然显示"✅ 所有任务已完成"
- 输出位置错误:
ensure_test_todos_exist()直接print()到stdout,显示在报告上方而非注意事项区域内
修复
# 修复1:有notes时不显示"全部完成"iftotal==doneandnotnotesandnottimeout_tasks:lines.append("✅ 所有任务已完成")# 修复2:把print改成返回notes列表defensure_test_todos_exist(replies):msgs=[]forreplyinreplies:# ... 检查逻辑 ...msgs.append(f"📋 自动创建测试待办: TEST-{task_id}")returnmsgs# 返回列表,由heartbeat收集到notes# heartbeat中:notes.extend(auto_pipeline.ensure_test_todos_exist(replies))notes.extend(auto_pipeline.ensure_fix_todos_exist(replies))关键原则:所有用户可见的信息,必须经过同一个格式化函数。不能有"旁路输出"。
🔄 闭环设计的核心模式
经过这几轮迭代,我总结出一个"自愈闭环"的标准模式:
┌─────────────────────────────────────────────────┐ │ 心跳中枢 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 检测状态 │→│ 自动决策 │→│ 执行动作 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ ↑ ↓ │ │ ┌──────────┐ ┌──────────┐ │ │ │ 收集结果 │←────────────────│ 通知用户 │ │ │ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────┘4个必要环节
| 环节 | 作用 | 缺失后果 |
|---|---|---|
| 检测状态 | 扫描inbox、DB、.done文件 | 不知道发生了什么 |
| 自动决策 | 判断该做什么(重试/派测试/归档) | 检测到了但不处理 |
| 执行动作 | 取消旧任务、派发新任务、唤醒Agent | 决策了但没执行 |
| 通知用户 | 汇报结果和异常 | 执行了但用户不知道 |
每个环节的常见坑
| 环节 | 坑 | 解法 |
|---|---|---|
| 检测 | 检测到但被grace period跳过 | grace只跳过唤醒,不跳过核心逻辑 |
| 决策 | 决策正确但走了旁路(直接print) | 所有输出必须经过统一的format函数 |
| 执行 | 执行了但状态没同步(DB和inbox不一致) | 每个操作都有对应的状态清理 |
| 通知 | 通知了但信息矛盾("已完成"和"有警告"同时出现) | 互斥信息不能同时显示 |
📊 进化前后的对比
| 指标 | v1 手动调度 | v2 基础心跳 | v3 自愈闭环 |
|---|---|---|---|
| 超时处理 | 手动唤醒 | 报告超时 | 自动取消+重派 |
| 测试派发 | 手动写MD+派发 | 手动 | 自动检测+补派 |
| 报告准确性 | N/A | 偶尔矛盾 | 严格一致 |
| 人工干预频率 | 每个任务2-3次 | 偶尔(~30%) | 极少(~5%) |
| 系统"死"的概率 | 高 | 中 | 低 |
💡 给想做类似系统的人的建议
闭环必须完整:检测→决策→执行→通知,缺一不可。缺了"执行"就是空谈,缺了"通知"就是黑盒。
不要有旁路:所有操作必须经过同一个中枢。你手动操作一次,就可能绕过自动逻辑一次。
状态必须一致:DB里的状态、inbox里的文件、.done标记,三者必须同步。任何一个不一致都会导致"幽灵任务"。
报告不能自相矛盾:用户看到的每一行信息都必须是真实状态的反映。"已完成"和"有警告"不能同时出现。
grace period要精细:不能一刀切跳过所有操作。应该只跳过"重复唤醒",不跳过"核心逻辑"。
自动化的代价是复杂度:每加一个自动逻辑,就多一个可能出bug的地方。但不出bug的自动化不叫自动化,叫脚本。
如果这篇文章对你有帮助,欢迎点赞收藏。有问题可以在评论区交流。
