背景 链接到标题

在本地 Mac Mini 上部署了 OpenClaw 作为个人 AI 助手,使用飞书通道直连。开启了完整的记忆系统:

  • Active Memory — 对话中实时检索记忆并注入上下文
  • Memory Core + Dreaming — 凌晨自动整理短期记忆,promote 到长期记忆
  • Memory Wiki — 将 MEMORY.md 编译为结构化知识库

Embedding 后端使用 Ollama(bge-m3)部署在同一内网的 GPU 服务器上,memory 索引完全正常:93 个文件,1208 个 chunk,向量检索已就绪。

Active Memory 始终无法工作

现象 链接到标题

主线对话一切正常,AI 助手能正常回复飞书消息。但每次对话时 Active Memory 返回 status=unavailable

active-memory agent=main ... activeProvider=deepseek activeModel=deepseek-v4-flash
  start timeoutMs=15000 queryChars=106 searchQueryChars=106
  done status=unavailable elapsedMs=2345 summaryChars=0

下游模型调用在几十毫秒内被中断:

provider-transport-fetch error provider=deepseek ... elapsedMs=46
  AbortError: This operation was aborted

排障过程 链接到标题

尝试 1:修复 Embedding Provider 链接到标题

早期 memory_search 默认使用 OpenAI embedding,但 OpenAI API key 未配置,报错:

memory sync failed (search): Error: No API key found for provider "openai"

将 embedding provider 改为内网 Ollama(bge-m3),重建索引后 memory status --deep 确认一切正常:

Provider: ollama (bge-m3)
Indexed: 93/93 files · 1208 chunks
Embeddings: ready
Vector store: ready

但 Active Memory 仍返回 unavailable

尝试 2:更换不同模型 链接到标题

怀疑是 deepseek API 稳定性问题,逐一尝试了所有可用的模型:

模型 Provider 耗时 结果
qwen3.5:9b Ollama(内网) 15s 超时(实际模型响应 >38s)
qwen3.5:2b Ollama(内网) 8-13s 超时 / unavailable
deepseek-v4-flash DeepSeek API 46ms AbortError
kimi-k2.5 Moonshot API 4.1s AbortError

不同 Provider 的 API 都返回同样的 AbortError,说明不是模型本身的问题

尝试 3:放宽断路器参数 链接到标题

查阅官方文档发现 Active Memory 内置断路器,默认 circuitBreakerMaxTimeouts: 3。尝试将阈值放大到 20:

"circuitBreakerMaxTimeouts": 20,
"circuitBreakerCooldownMs": 30000,
"setupGraceTimeoutMs": 5000

无效,因为 unavailable 不计入断路器计数器(仅 timeout 会计入),断路器根本不是原因。

尝试 4:不设显式 Model,继承 Session Model 链接到标题

去掉 config.model,让 Active Memory 继承 Session 的 Model(deepseek-v4-flash),结果相同。

关键日志 链接到标题

[plugins] active-memory: agent=main session=agent:main:main
  activeProvider=deepseek activeModel=deepseek-v4-flash
  done status=unavailable elapsedMs=2345 summaryChars=0

[provider-transport-fetch] [model-fetch] error
  provider=deepseek api=openai-completions model=deepseek-v4-flash
  elapsedMs=46 name=AbortError
  message=This operation was aborted

[agent/embedded] embedded run failover decision
  runId=active-memory-xxx... stage=assistant
  decision=surface_error reason=none
  from=deepseek/deepseek-v4-flash
  rawError=Request was aborted.

三个关键特征:

  1. Abort 极快:deepseek 仅 46ms,Kimi 也仅 4.1s,远低于 15s 超时
  2. 无有效错误原因reason=none,说明 Gateway 内部主动中断
  3. 主线对话正常:同一 Session、同一 Model 的 Main Agent 请求完全正常

源码分析与 Issue 关联 链接到标题

查看 OpenClaw GitHub 仓库 extensions/active-memory/index.ts 源码,定位到关键机制:

断路器实现(L56-367) 链接到标题

const DEFAULT_CIRCUIT_BREAKER_MAX_TIMEOUTS = 3;
const DEFAULT_CIRCUIT_BREAKER_COOLDOWN_MS = 60_000;

status=unavailable 不会触发断路器,只有在子 Agent 超时TIMEOUT_SENTINEL 胜出)时才会计数。非超时的返回值(包括 unavailablefailedno_relevant_memory)反而会重置断路器。因此断路器不是根因。

Session 锁竞争(已知 Bug) 链接到标题

核心问题在 Active Memory 子 Agent 和 Main Agent 之间的 Session 锁竞争。流程如下:

用户消息 → Gateway
  ├─ 创建 blocking sub-agent(获取 Session 锁)
  ├─ sub-agent 尝试调用模型
  ├─ main agent 也要获取同一 Session 锁
  ├─ 锁冲突 → main agent 抢到
  └─ sub-agent 被 abort → 返回 status=unavailable

这就是为什么不同 Provider/Model 的结果高度一致:Abort 发生在 Gateway 内部,与远端模型 API 无关。

相关 Issue 链接到标题

Issue 状态 描述
#90082 Open / P1 Active Memory 断路器太激进;失败时 fallback prompt 注入主 Session,与本文描述的锁竞争直接相关
#88077 Open / P2 queryMode: "message" 模式下子 Agent 仍收到完整 prompt 包(含 system prompt + tools),导致上下文巨量膨胀
#85644 Closed / P0 Active Memory 子 Agent 泄漏 → OOM,含 embedded abort settle timeout。已修复但残留锁竞争问题
#86996 Open / P1 Active Memory + Codex 高延迟,启动 abort 和 Gateway 事件循环卡死

根因总结 链接到标题

OpenClaw 2026.6.5 中 Active Memory 插件的 blocking sub-agent 实现存在 session 锁竞争(#85644 修复后仍有残留)。Gateway 在同一 Session 上试图同时调度子 Agent 和 Main Agent 时,Main Agent 优先获取锁,子 Agent 被强制 Abort,导致 Active Memory 始终 unavailable

这与模型配置(deepseek / kimi / ollama)、embedding provider、断路器参数无关。任何 Provider 都会被同一机制中断。

当前配置 链接到标题

采用上游推荐的无显式 Model 方案,继承 Session Model,配合放大后的断路器参数,等上游修复后自动生效:

{
  "plugins": {
    "entries": {
      "active-memory": {
        "enabled": true,
        "config": {
          "agents": ["main"],
          "queryMode": "message",
          "timeoutMs": 15000,
          "circuitBreakerMaxTimeouts": 20,
          "circuitBreakerCooldownMs": 30000,
          "setupGraceTimeoutMs": 5000
        }
      }
    }
  }
}

临时方案 链接到标题

  • 保持开启 Active Memory,等待上游修复(#90082 未合入,仍 Open)
  • 禁用 Active Memory 不影响 Memory Core 的 Dreaming(凌晨 3:00)和 Wiki Compile(凌晨 5:00),记忆系统本身正常工作
  • 实时记忆召回功能暂不可用,主线对话不受影响

后续上游修复合入后更新本文。