背景 链接到标题
在本地 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.
三个关键特征:
- Abort 极快:deepseek 仅 46ms,Kimi 也仅 4.1s,远低于 15s 超时
- 无有效错误原因:
reason=none,说明 Gateway 内部主动中断 - 主线对话正常:同一 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 胜出)时才会计数。非超时的返回值(包括 unavailable、failed、no_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),记忆系统本身正常工作
- 实时记忆召回功能暂不可用,主线对话不受影响
后续上游修复合入后更新本文。