OpenClaw Agent 改配置导致「assistant turn failed」故障排查与修复
问题现象
AI Agent(OpenClaw)在修改自己的配置文件后,突然无法正常响应,会话日志中出现:
[assistant turn failed before producing content]
网关服务间歇性失效,AI 助手「失忆」或「断连」。
故障排查
第一步:查看配置文件
bash
cat ~/.openclaw/openclaw.json
重点关注以下字段:
json
{
"gateway": { "auth": { "token": "***" } },
"models": {
"providers": {
"deepseek": { "apiKey": "***" },
"qwen": { "apiKey": "***" }
}
},
"channels": {
"qqbot": { "clientSecret": "***" }
}
}
如果所有敏感字段都变成了 ***、__OPENCLAW_REDACTED__ 或 ... 占位符,恭喜你,中招了。
第二步:确认配置完整性
bash
python3 -c "
import json
with open('~/.openclaw/openclaw.json') as f:
d = json.load(f)
p = d.get('models',{}).get('providers',{})
for name,prov in p.items():
key = prov.get('apiKey','')
if '***' in key or 'REDACTED' in key or '...' in key:
print(f'❌ {name}.apiKey 已被脱敏覆盖')
else:
print(f'✅ {name}.apiKey 正常')
tok = d.get('gateway',{}).get('auth',{}).get('token','')
if '***' in tok or 'REDACTED' in tok:
print('❌ gateway.auth.token 已被脱敏覆盖')
else:
print('✅ gateway.auth.token 正常')
"
根因分析
问题出在哪里
┌──────────────────────────────────────────────────────────┐
│ Agent 读取配置 │
│ ↓ gateway config.get(API 方式) │
│ 网关安全机制自动脱敏:apiKey → "__OPENCLAW_REDACTED__" │
│ │
│ Agent 拿到脱敏数据,误以为是真实内容 │
│ ↓ 在内存中构造新配置对象 │
│ 带上所有脱敏字段一起写入 │
│ │
│ Agent 写回配置 │
│ ↓ config.apply(全量替换)/ write │
│ 真实密钥被占位符覆盖 ❌ │
│ │
│ 结果:所有 API Key、Token、Secret 全变成 *** │
│ 网关无法认证,AI 助手彻底断连 │
└──────────────────────────────────────────────────────────┘
为什么 Agent 会这么干
OpenClaw 网关的 config.get 接口是一个安全只读视图:
| 返回内容 | 敏感字段显示 |
|---|---|
parsed |
"__OPEN...ED__"(缩略脱敏) |
sourceConfig |
"__OPENCLAW_REDACTED__"(完整脱敏) |
resolved |
"__OPENCLAW_REDACTED__"(完整脱敏) |
这三个层面的返回值结构完整、非敏感字段真实------看起来完全像一份可用配置。只有敏感字段被悄悄替换了。普通阅读很难一眼看出问题。
Agent 如果做了「读配置 → 改配置 → 写回去」的循环操作,就会把脱敏后的占位符当真实数据写回文件。
解决方案
方案一:有备份 --- 直接恢复(推荐)
bash
# 列出备份
ls -la ~/.openclaw/openclaw.json.bak.*
# 恢复最新备份
cp ~/.openclaw/openclaw.json.bak.$(ls -t ~/.openclaw/openclaw.json.bak.* | head -1) ~/.openclaw/openclaw.json
方案二:无备份 --- 手动修复
编辑 ~/.openclaw/openclaw.json,找到所有被 *** 替代的字段,替换为真实值:
| 字段路径 | 说明 |
|---|---|
gateway.auth.token |
网关认证令牌 |
models.providers.deepseek.apiKey |
DeepSeek API Key |
models.providers.qwen.apiKey |
千问 API Key |
channels.qqbot.clientSecret |
QQ 机器人密钥 |
方案三:从历史记录找回
如果 Agent 会话中曾经提到过这些密钥,可以翻看历史会话日志找回原始值。
修复后验证
bash
# 1. JSON 合法性检查
python3 -m json.tool ~/.openclaw/openclaw.json > /dev/null && echo "✅ JSON 格式正确"
# 2. 确认没有漏网的脱敏值
grep -E '__OPENCLAW_REDACTED__|__OPEN...ED__' ~/.openclaw/openclaw.json && echo "⚠️ 仍有脱敏值残留" || echo "✅ 无脱敏值残留"
# 3. 重启网关
systemctl --user restart openclaw-gateway
# 4. 确认服务正常
systemctl --user status openclaw-gateway --no-pager
预防方案:Agent 修改配置的正确姿势
❌ 错误做法(已经踩过坑)
config.get(脱敏数据) → 修改 → config.apply(全量写回)
✅ 正确做法(安全路线)
read 原始文件(绕过网关脱敏) → 只改目标字段 → write 写回
完整的工作流:
┌────────────────────────────────────────────┐
│ 1. 备份 │
│ cp openclaw.json{,.bak.$(date +%Y%m%d)}│
├────────────────────────────────────────────┤
│ 2. read 读取原始文件 │
│ 不走 gateway config.get │
│ 直接读硬盘 → 值是真实的 │
├────────────────────────────────────────────┤
│ 3. 精准修改 │
│ JSON解析 → 只改目标字段 │
│ 其他内容原封不动 │
├────────────────────────────────────────────┤
│ 4. JSON 语法校验 │
│ python3 -m json.tool │
├───────────────────────────────────────────┤
│ 5. write 写回 │
├────────────────────────────────────────────┤
│ 6. 网关验证 │
│ config.get 确认 valid: true, issues: [] │
└────────────────────────────────────────────┘
添加新模型的示例
python
import json
from datetime import datetime, timezone
# 1. 读原始文件
with open("~/.openclaw/openclaw.json") as f:
config = json.load(f)
# 2. 构造新 provider(注意 apiKey 是真实值)
config["models"]["providers"]["new_provider"] = {
"baseUrl": "https://api.example.com/v1",
"apiKey": "sk-xxxxxxxxxxxxx",
"api": "openai-completions",
"models": [
{
"id": "model-v1",
"name": "Model V1",
"reasoning": True,
"contextWindow": 128000,
"maxTokens": 8192,
"compat": {
"supportsTools": True,
"supportsReasoningEffort": True,
"supportedReasoningEfforts": ["low", "medium", "high"],
"reasoningEffortMap": {
"low": "low", "medium": "medium", "high": "high"
},
"thinkingFormat": "deepseek",
"requiresThinkingAsText": True
}
}
]
}
# 3. 写回
with open("~/.openclaw/openclaw.json", "w") as f:
json.dump(config, f, indent=2, ensure_ascii=False)
print("✅ 配置已更新")
总结
| 项目 | 内容 |
|---|---|
| 问题 | Agent 修改配置写入脱敏值,导致 assistant turn failed |
| 根因 | config.get 返回脱敏数据,config.apply 全量覆盖了真实值 |
| 快速修复 | 从备份恢复 or 手动替换 *** 为真实密钥 |
| 长期方案 | 用 read 直读文件 → edit 精准改 → write 回写,不走网关脱敏回路 |
| 教训 | 不要把 config.get 的输出当成可写回的数据,它只是个安全视图 |
文章内容基于 OpenClaw 实际生产环境故障排查经验,配置路径以默认安装 ~/.openclaw/openclaw.json 为准。