---
created: "2026-03-21"
type: project
status: active
tags: [trading, multi-agent, openclaw, debugging, optimization]
---

# 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，导致所有有用日志被淹没。

**修复**：
```python
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_send` A2A 协议调用
- invest-analyst 通过 `sessions_send` 明确控制每一轮，手动决定何时停止

### 问题 3：LLM 跳过辩论流程

**现象**：用户发 `/trade-analyze AMZN`，invest-analyst 直接用 `invest-api` skill 做了快速分析，没有调用 trade-analyze skill 触发辩论。

**根本原因**：kimi-coding/k2p5 模型倾向于走捷径——直接回答比调用复杂的多 agent 流程更快。AGENTS.md 中没有足够强的指令区分两种模式。

**修复**：
1. 精简 AGENTS.md，明确触发条件：`/trade-analyze` 或 "要不要买" → **必须使用 trade-analyze skill**
2. 重写 trade-analyze SKILL.md，加入 `CRITICAL` 级别指令和逐步 sessions_send 调用模板
3. 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 关键配置

```json5
{
  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_send` A2A 协议被 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` 都超时。

### 根因分析

1. Gateway 配置 `bind: "lan"`，监听 `0.0.0.0:18789`
2. 但 **`127.0.0.1:18789` 实际连不通**（`curl http://127.0.0.1:18789/` 超时，但 `curl http://192.168.68.108:18789/` 成功）
3. OpenClaw 内部工具默认连 `ws://127.0.0.1:18789`，导致所有 RPC 超时
4. 同时存在 [v2026.3.13 WebSocket handshake bug](https://github.com/openclaw/openclaw/issues/48167)：handshake timeout 只有 3 秒

### 修复

**修复 1：Systemd 环境变量**

在 `~/.config/systemd/user/openclaw-gateway.service` 中添加：
```ini
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](https://github.com/openclaw/openclaw/pull/47388)）**

文件：`~/.nvm/versions/node/v24.13.1/lib/node_modules/openclaw/dist/gateway-cli-CuZs0RlJ.js`（和 `Ol-vpIk7.js`）

```javascript
// 原始（第 7588 行）
const DEFAULT_HANDSHAKE_TIMEOUT_MS = 3e3;
// 修改为
const DEFAULT_HANDSHAKE_TIMEOUT_MS = 10e3;
```

**修复 3：Patch scope grant（来自 [PR #47388](https://github.com/openclaw/openclaw/pull/47388)）**

同一文件，第 22605 行附近：

```javascript
// 原始
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
```

### 注意事项

- 这些 patch 在 `npm update openclaw` 后会被覆盖，需要重新打
- 关注 [PR #47388](https://github.com/openclaw/openclaw/pull/47388) 和 [PR #48950](https://github.com/openclaw/openclaw/pull/48950) 的合并状态
- 合并后升级即可去掉手动 patch

---

## 七、最终验证：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... | ⏳ |

### 关键确认

1. **`sessions_spawn` 成功调用了辩论 agent** ✅
2. **辩论 agent 在后台执行，不在 Discord 输出** ✅（Discord 已禁用）
3. **结果通过 subagent announce 自动返回给 invest-analyst** ✅
4. **流程按顺序执行**：Bull → Bear → Bull Final → (Hawk → Dove) ✅
5. **没有循环** ✅（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` |

查看辩论内容：
```bash
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()
"
```

---

## 七、监控命令速查

```bash
# 实时日志（过滤噪音）
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
```

---

## Related

- [[Trading Agents 混合架构方案]]
- [[Trading Agents 部署记录]]
- [[TradingAgents 原始架构分析]]
- [[OpenClaw 部署配置分析]]
