OpenClaw Session 卡死与死锁深度分析:从状态机到排查手册

OpenClaw Session 卡死与死锁深度分析:从状态机到排查手册
研究员:黄山(wairesearch) 日期:2026-04-23 版本:1.0

基于 OpenClaw v2026.4.12 源码 + 官方文档 + GitHub Issues


执行摘要

如果你用过 OpenClaw 一段时间,大概率遇到过这个场景:Bot 显示”输入中”,然后……就没有然后了。

这篇文章系统分析了 OpenClaw Session 的状态管理机制,梳理了 7 种已确认的 Stuck 模式3 种死锁场景,并提供了一份实用的排查手册。无论你是 OpenClaw 的日常用户还是深度定制者,这篇都能帮你理解”为什么 Bot 会卡住”以及”怎么快速恢复”。


Session 状态管理机制

完整生命周期

一条消息从发出到得到回复,经过以下流程:

消息到达  路由(sessionKey)  入队(Command Queue)  获取 Session 
     加载 SessionManager  构建 System Prompt  LLM 推理
     工具执行  流式回复  Compaction 检查  释放锁  排队下一个

状态机模型如下:

                    ┌──────────┐
    新消息到达 ──→    queued       Command Queue 等待
                    └────┬─────┘
                          lane 空闲获取 session 写锁
                         
                    ┌──────────┐
                     running      LLM 推理 + 工具执行
                    └────┬─────┘
                         
              ┌──────────┼──────────┐
                                  
                                  
         ┌────────┐ ┌────────┐ ┌────────┐
         complete aborted   error  
         └────────┘ └────────┘ └────────┘
                                  
              └──────────┴──────────┘
                         
                    Compaction可选)→ 释放锁
状态 含义
queued 消息入队,等待 lane 空闲
running Agent 正在执行(LLM 推理 + 工具调用)
aborted 被用户或超时中止
complete 成功完成
error 执行出错
compacting 自动压缩进行中

两层持久化架构

文件 用途
Session Store sessions.json sessionKey → SessionEntry 映射
Transcript <sessionId>.jsonl 追加写入的对话树(JSONL 格式)

三层并发控制

OpenClaw 使用三层机制防止并发冲突:

  1. Command Queue(Lane 系统)main(入站消息,并发上限 4)、subagent(子 Agent,上限 8)、cron(定时任务)、nested(嵌套调用),每个 session 同一时间只有一个 active run。

  2. Session 文件锁.jsonl.lock 锁文件,超时 10 秒。

  3. Gateway 进程级隔离:单进程模型,restart 时有 30 秒 drain 机制。


7 种 Stuck 模式

通过分析 GitHub Issues 和源码,我们确认了以下 7 种 Session 卡死模式:

模式 1:LLM API 流式挂起 — 最高频 🔴

Issue: #17258

上游 LLM API 接受了流式请求但不产生任何 token。HTTP 连接保持打开,系统一直等到绝对超时(默认 600s)。

T+0s    流式请求开始API 返回 HTTP 200
T+2s    ...静默 token 到达...
T+120s  Typing indicator 过期用户看到 Bot "离线"
T+300s  超时触发session abort

解决方案:v2026.2.x 引入了 llm.idleTimeoutSeconds,建议设为 90 秒。

模式 2:Compaction 死循环 + 锁文件残留 🔴

Issue: #21621

Browser Tool 执行后触发 compaction,compaction 进入 retry 循环永不完成。关键特征:日志中有 compaction retry 但没有 embedded run done

模式 3:Gateway 自请求死锁 🔴

Issue: #18470

Agent 在 active turn 中调用 openclaw sessions --json → CLI 需要查询 Gateway → Gateway 在等 agent turn 完成 → 经典死锁

模式 4:Session 文件锁超时 🟡

Issue: #31489

.jsonl.lock 文件因崩溃残留,10 秒后锁获取失败,agent 无法回复。

模式 5:Gateway Restart 时 Compaction 中断 🟡

Issue: #17635

config.apply 触发 SIGUSR1 restart,但 30 秒 drain timeout 不够 compaction 完成。

模式 6:Context 超限导致 Compaction 死循环 🔴

Issue: #25620

Context 超过模型 token 限制 → /compact 的 summarization 请求本身也超限 → 无法压缩 → 死循环。

模式 7:工具调用失败无恢复 🔴

Issue: #8288

工具调用挂起后无超时、无恢复、无 fallback。唯一恢复方式是 /new/reset,但会丢失全部上下文。

Stuck 原因分类汇总

类别 根因 频率 严重度
LLM 挂起 API 流式不活跃 极高 🔴
Compaction 死锁 Lock 残留 + retry 循环 🔴
自请求死锁 Gateway 循环依赖 🔴
文件锁超时 .lock 残留 🟡
Restart 中断 Drain timeout 不够 🟡
工具无超时 无 timeout/fallback 🔴
Sub-agent 未返回 子 agent 卡住 🟡

3 种死锁场景

死锁经典四条件

条件 OpenClaw 中的表现 是否成立
互斥 Session 写锁、文件锁、per-session lane 串行
占有且等待 Agent turn 占 session lane,同时等 LLM/工具
不可剥夺 锁只在 turn 完成后释放
循环等待 Gateway 自请求:turn 等命令 → 命令等 turn

死锁 1:Gateway 自请求死锁

┌──────────────┐          ┌──────────────┐
 Agent Turn    ──等待─→  内部命令     
 (lane 被占)             (需查 Gateway)
               ←─阻塞──               
└──────────────┘          └──────────────┘

Agent 通过 exec 调用 openclaw CLI,CLI 需通过 WebSocket 查询 Gateway,但 Gateway 被 active session lane 阻塞。

死锁 2:Compaction Lock 死锁

Compaction 过程中 Gateway crash → lock 文件残留 → 所有后续操作 10 秒超时失败。

死锁 3:Compaction 超限悖论

Context 过大  触发 Compaction  summarization 也超限  失败  仍然过大  循环

排查手册

症状速查表

症状 可能原因 解决方案
Bot 显示”输入中”然后消失 LLM API 挂起 设置 llm.idleTimeoutSeconds: 90
Bot 完全无响应 Session lock 残留 删除 lock 文件 + 重启 Gateway
Compaction 后卡住 Compaction retry 循环 重启 Gateway + 删 lock
内部命令 10 分钟超时 Gateway 自请求死锁 改用 session tools API
费用异常高 Stuck → timeout → retry 风暴 缩短 timeout + 设 spend limit
/compact 失败 Context 超限悖论 /new 重建 session
Sub-agent 不返回 子 agent 卡在工具调用 subagents kill all

手动恢复命令

# 1. 检查 session 状态
openclaw sessions --json
openclaw sessions --active 120

# 2. 在 chat 中重置
/stop             # 停止当前 agent run
/new              # 新建 session
/reset            # 重置当前 session

# 3. 清除锁文件(确保无活跃 run)
ls ~/.openclaw/agents/*/sessions/*.lock
rm -f ~/.openclaw/agents/*/sessions/*.lock

# 4. 重启 Gateway
openclaw gateway restart

# 5. Session 清理
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce

# 6. 核弹选项(完整重置)
openclaw reset --scope config+creds+sessions --yes

日志关键词速查

grep -i "stuck\|timeout\|abort\|compaction retry\|lock\|deadlock\|drain" \
  ~/.openclaw/logs/*.log

推荐配置调优

以下配置可显著降低 Stuck 发生概率:

{
  agents: {
    defaults: {
      // 从默认 48h 缩短到 30min
      timeoutSeconds: 1800,
      llm: {
        // API 90s 无响应则中止
        idleTimeoutSeconds: 90,
      },
      compaction: {
        enabled: true,
        reserveTokens: 20000,
        reserveTokensFloor: 20000,
        memoryFlush: { enabled: true, softThresholdTokens: 4000 },
      },
    },
  },
  session: {
    maintenance: {
      mode: "enforce",
      pruneAfter: "30d",
      maxEntries: 500,
    },
    reset: {
      idleMinutes: 120,  // 2h 无活动自动重置
    },
  },
  messages: {
    queue: {
      mode: "collect",
      debounceMs: 1000,
      cap: 20,
      drop: "summarize",
    },
  },
}

预防最佳实践

  1. 避免 Agent Turn 中调用内部 CLI 命令 — 改用 session_status 等内部 RPC 工具
  2. 设置合理超时timeoutSeconds: 1800idleTimeoutSeconds: 90
  3. 监控 lock 文件 — 定期检查并清除超过 5 分钟的 .lock 文件
  4. 用 systemd/launchd 监管 Gateway — 异常退出自动重启
  5. 开启 memoryFlush — 压缩前保存关键上下文
  6. Sub-agent 用 sessions_yield — 不要 poll 循环等待

架构洞察

通过这次分析,我们发现几个值得关注的架构层面问题:

  1. 默认 48h 超时是 Stuck 的放大器 — 即使出了问题,系统也要等很久才超时。缩短到 30 分钟可以显著改善用户体验。

  2. 自请求死锁是设计缺陷 — Agent 能通过 exec 调用 openclaw CLI 并触发 Gateway 自查询,形成循环依赖。应在架构层面让内部命令走独立通道。

  3. 文件锁机制脆弱 — 基于文件锁的并发控制在进程崩溃时必然残留。建议改为带 PID + 时间戳的锁,或在单进程架构下使用进程内锁。

  4. Compaction 是高频触发器 — 多个 Issue 都与 compaction 相关,它涉及 LLM 调用 + 文件锁 + retry,任一环节卡住都导致 session 不可用。

  5. 缺少主动死锁检测 — 建议添加 session 活跃时间 watchdog、lock 文件 TTL、自请求检测等机制。


相关 GitHub Issues

Issue 标题 状态
#17258 Streaming inactivity timeout ✅ 已修复
#21621 Browser Tool Triggers Compaction Deadlock 报告中
#18470 Gateway Deadlock: Internal Commands Hang 报告中
#31489 Session file locked (timeout 10000ms) 报告中
#17635 Gateway restart during compaction 报告中
#25620 Compaction fails on context overflow 报告中
#8288 Agent hangs on failed tool calls 报告中

总结

Session Stuck 和死锁是 OpenClaw 用户最常遇到的痛点之一。理解其背后的状态机模型、并发控制机制和已知的 7 种 Stuck 模式,能帮助你在问题发生时快速定位和恢复。更重要的是,通过合理的配置调优和最佳实践,大部分 Stuck 问题可以被预防。

记住这个优先级:/stop,再看 lock 文件,最后 restart Gateway。大多数情况下,前两步就能解决问题。

📖 相似文章推荐

上一篇
Hermes Agent 记忆系统深度研究:三层架构如何让 AI 不再失忆
下一篇
Tool Call Stuck 解决方案 v2:先看源码再提方案