13 KiB
created, type, status, tags
| created | type | status | tags | |||||
|---|---|---|---|---|---|---|---|---|
| 2026-03-21 | project | active |
|
Trading Agents 调试与优化记录
部署后的调试过程、发现的问题、尝试的方案和最终修复。
一、问题时间线
| 时间 | 事件 | 状态 |
|---|---|---|
| 14:00 | 初次部署,4 个辩论 bot 登录成功 | ✅ |
| 14:05 | 发现 openclaw status --deep 超时 |
⚠️ bind=lan 导致 CLI WebSocket 无法连 localhost |
| 14:09 | 发现 invest-analyst 有 typing 超时 | ⚠️ google-antigravity-auth 插件刷日志 |
| 14:11 | 日志被 Config warning 洪水淹没 | 🔧 删除 plugins.entries.google-antigravity-auth |
| 14:33 | 用户消息被 no-mention 拒绝 |
🔍 辩论 bot requireMention: true 正常拒绝 |
| 14:41 | invest-analyst 回复了快速分析而非触发辩论 | 🔍 LLM 选择了捷径 |
| 14:45 | 测试 @ mention 模式——invest-bear 设 requireMention: false 后响应 |
✅ 确认 bot 能工作 |
| 14:55 | 添加 groupChat.mentionPatterns,切换到 ds-* 风格 @ mention 协调 |
🔧 |
| 15:00 | NVDA 辩论成功触发! Bull/Bear/Hawk/Dove 全部参与 | ✅ 辩论质量很高 |
| 15:00-15:05 | 辩论进入无限循环——agent 通过 @ mention 不断互相回复 | ❌ 核心问题 |
| 15:05 | 强制 gateway restart 停止循环 | 🔧 |
| 15:05 | AMZN 分析——invest-analyst 跳过辩论直接回答 | ❌ LLM 没调用 trade-analyze |
| 15:22 | 最终修复:移除辩论 agent mentionPatterns + 强化 sessions_send 流程 | 🔧 |
二、发现的问题与修复
问题 1:Config Warning 日志洪水
现象:google-antigravity-auth 插件每隔几秒刷一条 warning,导致所有有用日志被淹没。
修复:
del config["plugins"]["entries"]["google-antigravity-auth"]
教训:OpenClaw 中已卸载的插件如果还留在 config 里,会持续刷 warning。应及时清理。
问题 2:@ Mention 模式导致辩论无限循环
现象:invest-analyst 通过 @Bull 在频道中触发 Bull,Bull 回复后 Bear 看到消息并回复,然后 Bull 又回复……无限循环。
根本原因:@ mention 模式下没有内建的轮次限制。每条消息都会触发对方回复。REPLY_SKIP 在 SOUL.md 中写了,但 LLM 没有严格执行。
尝试的方案:
| 方案 | 结果 |
|---|---|
requireMention: true + groupChat.mentionPatterns |
❌ 循环——agent 在频道中互相 @ |
SOUL.md 中写 REPLY_SKIP 规则 |
❌ LLM 不严格执行 |
最终方案:移除辩论 agent 的 groupChat.mentionPatterns |
✅ 辩论 agent 不再响应频道消息 |
最终修复:
- 辩论 agent(bull/bear/hawk/dove)没有
groupChat.mentionPatterns - 辩论 agent 保持
requireMention: true - 只能通过
sessions_sendA2A 协议调用 - invest-analyst 通过
sessions_send明确控制每一轮,手动决定何时停止
问题 3:LLM 跳过辩论流程
现象:用户发 /trade-analyze AMZN,invest-analyst 直接用 invest-api skill 做了快速分析,没有调用 trade-analyze skill 触发辩论。
根本原因:kimi-coding/k2p5 模型倾向于走捷径——直接回答比调用复杂的多 agent 流程更快。AGENTS.md 中没有足够强的指令区分两种模式。
修复:
- 精简 AGENTS.md,明确触发条件:
/trade-analyze或 "要不要买" → 必须使用 trade-analyze skill - 重写 trade-analyze SKILL.md,加入
CRITICAL级别指令和逐步 sessions_send 调用模板 - Skill description 中直接写明 "MUST use sessions_send"
问题 4:Discord bot 频繁断开
现象:health-monitor: restarting (reason: disconnected) 反复出现。
可能原因:10 个 Discord bot 同时从一台机器连接,可能触发 Discord rate limit 或 WebSocket 连接限制。
当前状态:health-monitor 自动重连,功能不受影响,但会导致短暂的消息丢失窗口。
三、@ Mention vs sessions_send 对比
经过实测验证的结论:
| 维度 | @ Mention(ds-* 风格) | sessions_send |
|---|---|---|
| 触发方式 | 在频道中写 @智库 请分析... |
调用 sessions_send 工具 |
| 可见性 | 用户能在频道中看到完整对话 | 后台执行,用户看不到过程 |
| 轮次控制 | ❌ 无内建限制,容易循环 | ✅ maxPingPongTurns: 5 硬限制 |
| 适用场景 | 人类协调(如大统领派任务给智库) | agent 间自动协作 |
| 辩论场景 | ❌ 不适合——agent 间 @ 会死循环 | ✅ 适合——编排者控制每轮 |
结论:ds-* 的 @ mention 模式适合人类在中间协调的场景(大统领手动 @ 智库做任务)。但对于自动化辩论(agent 自动互相辩论),必须用 sessions_send,由编排者手动控制每轮。
四、NVDA 辩论验证结果
虽然出现了循环问题,但辩论本身的质量很高,验证了架构的可行性。
Bull 核心论点
- 分析师共识目标价 $269,较现价 $172.70 有 56% 上行
- RSI 37.8 接近超卖,布林带下轨形成支撑
- AI 需求周期才刚开始,Blackwell 放量
Bear 核心论点
- 85% 分析师看多是情绪极端化危险信号
- MACD 负值且柱状图扩大,下跌动能强化
- PE 35x 对 $4.2T 市值需要持续 30%+ 增长支撑
Hawk 风控评估
- 风险收益比 8:1(止损 $160 vs 目标 $269)
- 建议 15-20% 仓位,现价直接建仓 50%
Dove 风控评估
- 5% 仓位上限
- 减仓 25% 锁定利润
- 更宽止损 $155 避免被正常波动震出
最终方案(辩论共识)
- 减仓 25%(8 股)锁定利润
- 保留 25 股核心仓位
- 止损 $155
- 目标 $220-250
五、最终配置状态
openclaw.json 关键配置
{
agents: {
list: [
// invest-analyst: 有 groupChat.mentionPatterns(响应频道消息)
// invest-bull/bear/hawk/dove: 无 groupChat(只响应 sessions_send)
]
},
tools: {
agentToAgent: {
enabled: true,
allow: ["ds-*系列", "invest-analyst", "invest-bull", "invest-bear", "invest-hawk", "invest-dove"]
}
},
session: {
agentToAgent: { maxPingPongTurns: 5 }
}
}
invest-analyst AGENTS.md 关键逻辑
触发条件判断:
- 简单问题 → 直接用 invest-api skill
- /trade-analyze 或 "要不要买" → 必须用 trade-analyze skill
trade-analyze 流程:
1. curl 收集 4 类数据
2. sessions_send → invest-bull(Round 1)
3. sessions_send → invest-bear(Round 2)
4. sessions_send → invest-bull(Round 3 FINAL)
5. sessions_send → invest-hawk
6. sessions_send → invest-dove
7. 综合裁决 → BUY/SELL/HOLD
辩论 Agent 配置
requireMention: true(不响应频道消息)- 无
groupChat.mentionPatterns(不能被 @ mention 触发) - 只通过
sessions_sendA2A 协议被 invest-analyst 调用 - SOUL.md 中有
REPLY_SKIP规则和字数限制
六、Gateway WebSocket 超时修复(根本问题)
问题
sessions_send 和 sessions_spawn 全部报错:
gateway timeout after 10000ms
Gateway target: ws://127.0.0.1:18789
Source: local loopback
所有 session 工具、openclaw status --deep、openclaw gateway call 都超时。
根因分析
- Gateway 配置
bind: "lan",监听0.0.0.0:18789 - 但
127.0.0.1:18789实际连不通(curl http://127.0.0.1:18789/超时,但curl http://192.168.68.108:18789/成功) - OpenClaw 内部工具默认连
ws://127.0.0.1:18789,导致所有 RPC 超时 - 同时存在 v2026.3.13 WebSocket handshake bug:handshake timeout 只有 3 秒
修复
修复 1:Systemd 环境变量
在 ~/.config/systemd/user/openclaw-gateway.service 中添加:
Environment=OPENCLAW_GATEWAY_URL=ws://192.168.68.108:18789
Environment=OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1
然后 systemctl --user daemon-reload。
这让 gateway 内部工具通过 LAN IP(而非 localhost)连接,绕过了 loopback 不通的问题。
修复 2:Patch handshake timeout(来自 PR #47388)
文件:~/.nvm/versions/node/v24.13.1/lib/node_modules/openclaw/dist/gateway-cli-CuZs0RlJ.js(和 Ol-vpIk7.js)
// 原始(第 7588 行)
const DEFAULT_HANDSHAKE_TIMEOUT_MS = 3e3;
// 修改为
const DEFAULT_HANDSHAKE_TIMEOUT_MS = 10e3;
修复 3:Patch scope grant(来自 PR #47388)
同一文件,第 22605 行附近:
// 原始
if (!device && (!isControlUi || decision.kind !== "allow")) clearUnboundScopes();
// 修改为
if (!device && (!isControlUi || decision.kind !== "allow")) { clearUnboundScopes(); } else if (!device && decision.kind === "allow") { scopes = ["operator.read"]; connectParams.scopes = scopes; }
验证
修复后 openclaw gateway call status 返回正常 JSON,sessions_spawn 成功:
15:49:43 status: "accepted", childSessionKey: "agent:invest-bull:subagent:ad2d265d..."
15:50:06 [subagent task] bull-AMZN: completed successfully
注意事项
七、最终验证:AMZN 辩论流程
完整时间线
| 时间 (UTC) | 事件 | 状态 |
|---|---|---|
| 15:48:20 | 读取 trade-analyze skill | ✅ |
| 15:48:36 | 收集 AMZN 数据(curl API) | ✅ |
| 15:49:13 | metrics + sentiment 数据返回 | ✅ |
| 15:49:27 | technical + macro 返回 503 | ⚠️ K8s API pod 暂时不可用 |
| 15:49:43 | sessions_spawn → invest-bull |
✅ accepted |
| 15:50:06 | Bull 完成,结果返回 | ✅ |
| 15:50:25 | sessions_spawn → invest-bear |
✅ accepted |
| 15:50:53 | Bear 完成,结果返回 | ✅ |
| 15:51:04 | sessions_spawn → invest-bull (final rebuttal) |
✅ accepted |
| 15:51:08 | 等待 Bull Final + Hawk + Dove... | ⏳ |
关键确认
sessions_spawn成功调用了辩论 agent ✅- 辩论 agent 在后台执行,不在 Discord 输出 ✅(Discord 已禁用)
- 结果通过 subagent announce 自动返回给 invest-analyst ✅
- 流程按顺序执行:Bull → Bear → Bull Final → (Hawk → Dove) ✅
- 没有循环 ✅(sessions_spawn 是一次性的,不会互相触发)
八、sessions_send vs sessions_spawn 最终结论
| 工具 | 能否工作 | 原因 |
|---|---|---|
| @ mention | ❌ | 导致无限循环 |
| sessions_send | ❌ | Gateway 内部 WebSocket 死锁(同进程内自连) |
| sessions_spawn | ✅ | 非阻塞,独立 lane 执行,announce 回传结果 |
最终方案:sessions_spawn + announce 回传。
九、Session 文件位置
| Agent | Session 路径 |
|---|---|
| invest-analyst | ~/.openclaw/agents/invest-analyst/sessions/*.jsonl |
| invest-bull | ~/.openclaw/agents/invest-bull/sessions/*.jsonl |
| invest-bear | ~/.openclaw/agents/invest-bear/sessions/*.jsonl |
| invest-hawk | ~/.openclaw/agents/invest-hawk/sessions/*.jsonl |
| invest-dove | ~/.openclaw/agents/invest-dove/sessions/*.jsonl |
查看辩论内容:
python3 -c "
import json
with open('SESSION_FILE.jsonl') as f:
for line in f:
d = json.loads(line)
msg = d.get('message', d)
role = msg.get('role', '')
content = msg.get('content', '')
if isinstance(content, list):
for c in content:
if isinstance(c, dict) and c.get('type') == 'text':
content = c.get('text', '')
break
if role == 'assistant' and len(str(content)) > 50:
print(f'[{role}] {str(content)[:300]}')
print()
"
七、监控命令速查
# 实时日志(过滤噪音)
journalctl --user -u openclaw-gateway.service -f --output=cat | grep -v "Config warn"
# 检查辩论 agent 是否有新 session
for a in invest-bull invest-bear invest-hawk invest-dove; do
echo "$a: $(ls ~/.openclaw/agents/$a/sessions/*.jsonl 2>/dev/null | wc -l) sessions"
done
# 检查 bot 登录状态
journalctl --user -u openclaw-gateway.service --no-pager -n 100 | grep "logged in"
# 检查是否有循环(大量 lane wait)
journalctl --user -u openclaw-gateway.service --no-pager --since "5 min ago" | grep -c "lane wait"
# Gateway 重启(需要 nvm)
export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; openclaw gateway restart