我们把AI员工"小虾"改成了"小武"。 然后,所有超时重试的任务,都送到了一个叫"开发"的人手里。 系统里根本没有这个人。
背景
我们的AI团队有四个角色:统筹、开发、测试、体验。员工可以改名------用户觉得"小虾"不够正式,改成了"小武"。
改名很顺利。配置中心保存,前端显示"小武",任务派发到 inbox/main/------一切都对。
直到第二天凌晨,统筹报告突然刷屏:
arduino
❌ 未知Agent: 开发(×4)
⚠️ 重试文件接收人: "开发"(仍然不是小武)
📊 DEV-20260822-005: pending(等待处理------31分钟)
问题:任务送给了"开发"
任务超时后,系统会自动生成重试文件,重新唤醒agent处理。但重试文件的接收人变成了"开发"------一个【不存在的角色】。
openclaw的agent列表里只有 main(小武)和 xnew(小杰)。"开发"是谁?
打开重试文件看:
json
{
"from": "小文",
"to": "开发", // ← 谁??
"content": "任务超时请重试"
}
排查:名字从哪来的?
顺着代码找。重试文件是 task_monitor_retry.py 生成的。它的角色映射:
python
# 理想情况:读取config.json的员工名(小武/小杰/小文)
def _agent_names():
nm = {'xiaomi': '统筹', 'main': '开发', 'xnew': '测试', 'xbai': '体验'}
# 读config.json覆盖...
看到没------默认值里,main 的中文名是"开发"!
如果 config.json 读不到,函数就返回默认值------main → "开发"。
那为什么读不到config.json?
python
# 路径候选
for _cfgp in [os.path.join(WS_DIR, 'config', 'config.json'), # D:\workspace\config\config.json
os.path.join(SCRIPTS_DIR, '..', '..', 'config', 'config.json')]: # D:\workspace\scripts\send_Check\..\..\config
Windows上:
WS_DIR\config\config.json→D:\workspace\config\config.json------ 不存在(配置在安装目录)SCRIPTS_DIR\..\..\config→ 而SCRIPTS_DIR来自task_monitor_common.py:
python
SCRIPT_DIR = os.path.join(WS_DIR, "scripts", "send_Check")
# = D:\workspace\scripts\send_Check ------ 这个目录根本不存在!
两个候选路径全是错的------config.json一个都没读到------函数回退到默认名------main → "开发"。
类比:改名后,通讯录还是旧的
就像公司里张三改名叫李四,但系统里的工单系统还写着"张三转交"。人事系统更新了,工单系统没更新------所有新工单都发给了一个已经不存在的"张三"。
我们的问题一模一样:
- ✅ 配置中心(人事系统):员工叫小武
- ❌ task_monitor_retry(工单系统):还写着"开发"(角色默认名)
修复:一条路读不到,就多给几条路
python
# 修复:加安装目录\config路径(__file__定位------Windows/容器通用)
_here = os.path.dirname(os.path.abspath(__file__))
for _cfgp in [os.path.join(_here, '..', '..', 'config', 'config.json'), # 安装目录\config ← 新增!
os.path.join(WS_DIR, 'config', 'config.json'),
os.path.join(SCRIPTS_DIR, '..', '..', 'config', 'config.json')]:
同时把 task_monitor_common.py 的 SCRIPT_DIR 也修了------优先用脚本自身目录:
python
_HERE_DIR = os.path.dirname(os.path.abspath(__file__))
if os.path.exists(os.path.join(_HERE_DIR, 'task_monitor.py')):
SCRIPT_DIR = _HERE_DIR # 脚本在app/scripts------产品化后正确位置
else:
SCRIPT_DIR = os.path.join(WS_DIR, 'scripts', 'send_Check') # 旧开发环境兼容
还有 AGENT_IDS / ROLE_MAP 全部动态化------从config.json读员工名,改名后自动跟随。
经验总结
- 改名是个全局操作------不是改一个配置文件就完事。所有用到旧名的地方(角色映射/目录判断/通知文案)都要跟着变
- 默认值会咬人 ------
{'main': '开发'}这种回退默认名,平时看不见,一旦配置读取失败,就把任务送给一个不存在的人 - 路径候选要多给几条------Windows/容器/Linux的目录结构不同,一条路径读不到就回退,回退就出错
- "回退"本身要可观测------如果默认值被用了,应该打日志("⚠️ 使用默认角色名------config.json未读取"),而不是静默回退