派发日志:
✅ 已即时唤醒小天处理任务小天:zzz... 任务在inbox里躺了一整夜。
背景
任务派发成功后,系统会【立即唤醒】agent处理------这是三层唤醒架构的第一层:"即时唤醒"。设计很完美:
scss
派发 → 写inbox → wake_agent() → openclaw agent --message "有新任务" → agent醒来读文件
日志也显示唤醒成功。但任务就是不动。
问题:唤醒"成功"了,任务没人处理
凌晨的统筹报告:
yaml
📊 DEV-20260822-001: pending(已过248分钟------严重超时)
📊 小天(main): ❌ 无活跃session
📊 任务已投递到inbox------等待小天启动后处理
派发日志明明写着"已即时唤醒",agent却毫无反应。session一个都没有------agent压根没被叫起来过。
排查1:唤醒命令真的执行了吗?
wake_agent.py 的核心:
python
subprocess.Popen(
['openclaw', 'agent', '--agent', openclaw_id, '--message', message],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
start_new_session=True
)
print(f"✅ 已即时唤醒{agent_name}处理任务", file=sys.stderr)
注意看------stdout和stderr全部 DEVNULL!
Popen 只要成功【启动进程】就返回,进程内部的失败------比如openclaw读到错误配置、认证失败、模型报错------全部静默吞掉。然后打印"✅ 已即时唤醒"。
唤醒的"成功",是打印出来的。agent的醒来,才是真的。
排查2:openclaw读了什么配置?
容器里跑 openclaw agent 命令------它读 OPENCLAW_HOME 指定的配置。但 wake_agent 的子进程继承了运行它的进程的环境------那个进程(send_task.py)的环境里【没有 OPENCLAW_HOME】!
于是 openclaw 去读默认的 ~/.openclaw/------容器里根本没有这个目录(配置在 /vol1/1000/ai-team-collab/openclaw/)。读不到配置 → agent起不来 → 静默失败 → 打印"唤醒成功"。
排查3:还有个更隐蔽的------旧名判断
send_task.py 的唤醒段:
python
if msg_type == "new_task" and to_agent in ["小虾", "小牛", "小白"]:
...
wake_agent(to_agent, ...)
看到没------硬编码旧名! 员工改名后,to_agent 是"小天"------不在 ["小虾", "小牛", "小白"] 里------整个唤醒段根本不执行!
而且唤醒段里还引用了一个不存在的变量 _fname:
python
_wake_f = os.path.join(WS_DIR, 'claw-sync', 'inbox', _role, _fname) # _role/_fname未定义!
NameError 被 try/except 捕获------打印一句"⚠️ 即时唤醒失败"------继续跑。唤醒悄悄死掉。
类比:闹钟响了,但响的是别人的闹钟
设了6点的闹钟叫醒自己去赶飞机。结果:闹钟响了(打印"已唤醒"),但响的是隔壁房间的闹钟(读错了配置),而且自己根本没设6点的闹钟(旧名判断没触发)------人没醒,飞机飞了。
三个独立的小故障,任何一个都足以让agent睡过站,三个叠加------必挂。
修复:让"唤醒"变成可验证的事实
python
# ① 环境:OPENCLAW_HOME显式传入(容器/Windows探测)
_envw = os.environ.copy()
if os.path.isdir('/vol1/1000/ai-team-collab'):
_envw['OPENCLAW_HOME'] = '/vol1/1000/ai-team-collab/openclaw'
# ② 角色判断动态化(改名不失效)
if msg_type == "new_task" and ROLE_MAP.get(to_agent) in ('main', 'xnew', 'xbai'):
# ③ 唤醒消息带inbox文件绝对路径(规范:wake消息必须指定具体文件)
wake_agent(to_agent, f'请读取文件 {inbox_path},按content中的步骤执行')
关键一条经验:唤醒的验证标准不是"命令发出去了",而是"agent的session开始活动了"。后来我们在task_monitor里加了session活跃度检测------唤醒后15分钟session没动静,就判定唤醒失败,走恢复流程。
经验总结
DEVNULL会吞掉所有真相------后台命令的stdout/stderr全丢弃,等于闭着眼开枪- 子进程环境不是继承的"完整环境"------OPENCLAW_HOME这种关键变量,必须在调用处显式传入
try/except包裹唤醒段,等于给失败发了免死金牌------异常要打日志,不能静默- 旧名硬编码是定时炸弹------改名需求一出现就炸
- "唤醒成功"要定义成可观测的:session mtime更新了,才算真的醒了