AI多Agent协作系统实战(六):心跳自动暂停、计数Bug与Config连锁故障
前言自动化流程基本跑通了。但今天早上一看心跳报告发现不对劲——明明所有任务都完成了报告还显示活跃任务2表格却是空的。更离谱的是心跳每分钟还在跑完全没自动暂停。这一查不要紧一口气发现了三个关联bug计数逻辑错误、自动暂停失效、config.yaml解析失败。记录一下排查和修复过程。一、计数Bugcompleted被算成活跃现象心跳报告显示【小密统筹报告 07-05 20:16】 活跃任务2 | # | 任务ID | 完善内容 | 开发 | 测试 | 复核 | |---|--------|----------|------|------|------| 空标题说2个活跃任务但表格是空的。原因calc_progress()函数的计数逻辑有问题# 原来的逻辑iftid.startswith((DEV-,FIX-,REDEV-)):test_idfTEST-{tid}has_testany(t[0]test_idfortinall_tasks)# 只计算未完成或测试失败/待处理的ifst!completedornothas_test:total1# ← BUG在这里问题一个DEV任务completed了但没有对应TEST任务时st ! completed是Falsenot has_test是True结果total 1——completed被算成了活跃。修复简化逻辑只计pending为活跃# 修复后fortid,stinall_tasks:if_*intidornottid.startswith((DEV-,FIX-,REDEV-,TEST-)):continueifstpending:# 只有pending才算活跃total1task_rows.append((tid,st))completed、verified、archived、cancelled、failed——统统不算活跃。二、自动暂停失效3个孤儿任务现象计数修好了0个pending任务但心跳还在每分钟跑没有自动暂停。原因auto_pause_if_idle()函数检查是否有未完成任务activedb.execute( SELECT COUNT(*) FROM tasks WHERE msg_typenew_task AND to_agent IN (小虾,小牛,小白) AND status NOT IN (completed,verified,archived) ).fetchone()[0]问题SQL没排除cancelled和failed。DB里有3个孤儿记录TEST-FIX-0705-ADMIN-CHECKIN-BLOCK_*— cancelledTEST-FIX-0705-ATTENDANCE-3-BUGS_*— failed ×2这3个死人被算成了活跃任务阻止了自动暂停。修复两步1. 清理孤儿数据db.execute(DELETE FROM tasks WHERE status IN (cancelled,failed) AND task_id LIKE TEST-% AND (task_id LIKE %_* OR task_id LIKE %_20260705))2. SQL排除cancelled/failedAND status NOT IN(completed,verified,archived,cancelled,failed)现在0个活跃任务时心跳自动调用hermes cron pause fd1356414b27暂停自己。三、Config.yaml连锁故障现象hermes cron pause命令报错⚠️ hermes config: Failed to parse /home/chaw/.hermes/config.yaml: mapping values are not allowed here, line 150, column 10命令本身执行成功了paused但每次都要报这个警告。原因config.yaml里auxiliary部分有17处缩进错误# 错误写法auxiliary:web_extract:provider:custom# ← 缩进不对应该在web_extract下面model:provider: custom跟web_extract:同级YAML解析器认为这是语法错误。修复批量修复17处缩进# 修复逻辑lines[i] line.strip()# 加2个空格缩进加上delegation和x_search部分的2处单独修复共19处。验证importyamlwithopen(config.yaml)asf:yaml.safe_load(f)# ✅ 解析成功四、表格过滤cancelled/failed现象即使计数对了表格还是会显示cancelled的任务| 1 | FIX-0705-ATTENDANCE-BANNER-UI | 考勤横幅UI修复 | ⏳ | - | - | | 2 | FIX-0705-ATTENDANCE-LEAVE-AVATAR | 考勤LEAVEAVATAR修复 | ⏳ | - | - |第一个任务其实已经被cancelled了不该显示。原因format_report.py的_build_task_table()没有过滤cancelled/failed状态# 只过滤了_*后缀和非标准任务IDif_*intidornottid.startswith((DEV-,FIX-,REDEV-,TEST-)):continue# 没有过滤cancelled/failed ← BUG修复加一行过滤# 过滤终态任务cancelled/failed不显示在表格中ifstin(cancelled,failed):continue五、自动暂停/恢复的完整流程修复后的完整闭环派发任务 ↓ send_task.py 自动 resume 心跳hermes cron resume fd1356414b27 ↓ 设置宽限期resumed_at now5分钟内不暂停 ↓ 心跳每分钟运行监控任务进度 ↓ 所有任务完成0个pending ↓ auto_pause_if_idle() 检测到空闲 ↓ hermes cron pause fd1356414b27自动暂停 ↓ 下次派发任务时再自动resume关键代码# 心跳脚本末尾defmain():# ... 处理任务 ...auto_pause_if_idle()# 空闲时自动暂停# 派发脚本开头defsend_task(from_agent,to_agent,task_id,...):ifmsg_typenew_task:# 派发新任务时自动恢复心跳subprocess.run([hermes,cron,resume,HEARTBEAT_JOB_ID])# 设置宽限期db.execute(INSERT OR REPLACE INTO system_config ...)六、经验总结1. DB查询要排除所有终态pending才是真正的活跃。cancelled、failed虽然不是completed但也不是活跃任务# ❌ 错误只排除了部分终态AND status NOT IN(completed,verified,archived)# ✅ 正确排除所有终态AND status NOT IN(completed,verified,archived,cancelled,failed)2. 孤儿数据要定期清理任务流程中可能产生没有对应主任务的TEST记录比如主任务被取消但TEST任务还留着。要么在流程中清理要么在查询时过滤。3. Config要验证YAML配置文件的缩进错误不会阻止程序运行hermes会fallback到默认配置但会导致自定义配置失效。批量修改配置后应该验证YAML语法python3-cimport yaml; yaml.safe_load(open(config.yaml))4. 自动暂停/恢复是必要的心跳每分钟跑一次空闲时浪费资源。自动暂停派发时恢复既不丢监控又省资源。系列文章AI多Agent协作系统实战一架构设计AI多Agent协作系统实战二任务调度AI多Agent协作系统实战三心跳监控AI多Agent协作系统实战四自动部署AI多Agent协作系统实战五铁律、超时与心跳监控的踩坑实录AI多Agent协作系统实战六心跳自动暂停、计数Bug与Config连锁故障