主动内存超时:阻塞召回传递超出配置的超时时间
主动内存在返回跨多个模型和提供商的召回摘要之前持续超时,尽管配置的超时时间为8000ms,但超时触发在大约8084ms。
🔍 症状
Active Memory 在配置的超时窗口内无法完成其阻塞召回传递。以下诊断输出持续出现:
🧩 Active Memory: timeout 8084ms message 0 chars
🔎 Active Memory Debug: none retrieved
网关日志确认了超时行为:
active-memory ... done status=timeout elapsedMs=8092 summaryChars=0
embedded_run_failover_decision ... failoverReason=timeout profileFailureReason=timeout
诊断表现
- 超时阈值:超时在约 8084-8092ms 处触发(对比配置的 8000ms),表明超时检查在阻塞调用开始后执行
- 零字节响应:
summaryChars=0确认在超时前未生成摘要 - 模型无关:该问题在所有测试的模型中均可复现:
openai-codex/gpt-5.4ollama/glm-5.1:cloudollama/llama3.1:8bollama/gemma4:e4b
- 后端无关:空闲和排队/繁忙的运行环境表现出相同的行为
- 提供商链:影响
openclaw → ollama路由配置
环境上下文
| 组件 | 值 |
|---|---|
| OpenClaw 版本 | 2026.4.12 / 26.4.14 |
| 操作系统 | macOS |
| 安装方式 | npm global |
| 记忆后端 | builtin/default (memory-core) |
| 嵌入模型 | qwen3-embedding (Ollama) |
| 聊天上下文 | Discord DM (direct) |
🧠 根因分析
主要根因:同步嵌入检索阻塞
超时的发生是因为 Active Memory 的阻塞召回传递在调用 LLM 进行摘要之前,对记忆后端执行同步嵌入查找。当嵌入检索阶段超过配置的超时时,LLM 调用永远不会执行。
故障序列分析
┌─────────────────────────────────────────────────────────────┐
│ Active Memory Blocking Recall Pass │
├─────────────────────────────────────────────────────────────┤
│ 1. Memory Query (synchronous) │
│ └─→ Embedding retrieval via qwen3-embedding │
│ └─→ Memory backend search │
│ └─→ BLOCKS HERE (timeout: 8084ms) │
│ │
│ 2. LLM Summarization (never reached) │
│ └─→ Summary generation │
└─────────────────────────────────────────────────────────────┘
促成因素
嵌入式运行超时传播:
embedded_run_failover_decision日志条目表明 Active Memory 超时会传播到嵌入式运行上下文,导致故障转移决策日志记录。这表明内存召回和响应生成阶段之间存在紧密耦合。同步记忆后端查询:内存搜索使用同步嵌入检索。当
qwen3-embedding遇到延迟(到 Ollama 的网络往返、模型加载或向量搜索开销)时,累积延迟会在生成第一个 token 之前超过 8000ms 超时。超时检查时机:超出 84-92ms(实际 8084ms vs. 配置 8000ms)表明:
- 超时在每个阻塞操作完成后检查
- 嵌入检索本身需要约 8084ms
- 不存在亚毫秒超时检查的提前退出机制
查询模式配置:
queryMode: “message”设置可能触发完整消息嵌入而不是轻量级语义搜索,增加检索延迟。
架构不一致
memory-core 后端的嵌入式内存检索未实现:
- 异步/非阻塞嵌入检索
- 每阶段超时预算(检索与生成的单独预算)
- 获得首个实质性结果时的提前终止
🛠️ 逐步修复
修复 1:增加 Active Memory 超时(立即缓解)
增加超时以适应嵌入检索延迟:
修复前:
"active-memory": {
"enabled": true,
"config": {
"timeoutMs": 8000,
...
}
}修复后:
"active-memory": {
"enabled": true,
"config": {
"timeoutMs": 30000,
...
}
}修复 2:分离检索和生成超时
为嵌入检索和 LLM 生成配置单独的超时预算:
"active-memory": {
"enabled": true,
"config": {
"timeoutMs": 30000,
"retrievalTimeoutMs": 10000,
"generationTimeoutMs": 20000,
...
}
}修复 3:切换到异步/轻量级查询模式
将 queryMode 从 “message” 更改为 “semantic” 或 “hybrid”:
修复前:
"queryMode": "message"修复后:
"queryMode": "semantic"修复 4:使用更快的嵌入模型
将 qwen3-embedding 替换为更快的本地嵌入模型:
"active-memory": {
"config": {
"embeddingModel": "ollama/nomic-embed-text"
}
}然后重启 Ollama 以确保模型被缓存:
ollama pull nomic-embed-text
systemctl restart ollama修复 5:临时禁用 Active Memory(用于生产环境)
如果超时阻止了生产环境,禁用阻塞召回:
"active-memory": {
"enabled": false
}或限制为非阻塞模式:
"active-memory": {
"config": {
"blockingMode": false,
"asyncRecall": true
}
}修复 6:记忆后端健康检查
验证记忆后端连接和索引状态:
# Check memory backend status
openclaw memory status
# Verify embedding model availability
ollama list | grep qwen3-embedding
# Test memory search latency manually
openclaw memory search "test query" --verbose🧪 验证
应用修复后的验证步骤
步骤 1:启用详细和跟踪日志
/verbose on
/trace on步骤 2:触发 Active Memory 召回
发送应触发内存召回的消息:
what was my last message to you步骤 3:验证非超时行为
预期输出(成功):
🧩 Active Memory: completed 2341ms message 87 chars
🔎 Active Memory Debug: retrieved summary "User asked about..."
预期网关日志:
active-memory ... done status=success elapsedMs=2345 summaryChars=87
步骤 4:确认未触发故障转移
验证以下内容不存在:
embedded_run_failover_decision ... failoverReason=timeout
步骤 5:运行诊断命令
openclaw memory test --mode recall --verbose预期输出:
Memory recall test: PASS
Retrieval latency: 1243ms
Generation latency: 892ms
Total: 2135ms (within timeout budget)
步骤 6:验证记忆后端健康状态
openclaw memory status预期输出应显示:
backend: memory-coreindexed: trueembedding: qwen3-embedding (or configured model)status: healthy
⚠️ 常见陷阱
超时过于接近嵌入延迟:将
timeoutMs设置为仅略高于典型嵌入检索时间会不给 LLM 生成留下预算。确保总超时容纳两个阶段加上 20% 的余量。Ollama 模型未预加载:在首次请求时,Ollama 下载并加载嵌入模型,导致显著延迟。始终预加载模型:
ollama pull ollama/gemma4:e4b ollama pull qwen3-embedding远程 Ollama 的网络延迟:如果 Ollama 运行在远程主机或 Docker 容器上,网络延迟会叠加嵌入检索时间。使用本地 Ollama 或将超时增加 2-3 倍。
内存索引未构建:如果记忆后端没有索引内容,召回传递可能仍会对空结果执行嵌入查询,导致意外延迟。在排除超时故障之前验证索引状态。
阻塞模式覆盖:某些配置或插件可能强制将
blockingMode: true覆盖用户设置。检查:openclaw config get active-memory.blockingModeDiscord DM 特定问题:该问题在 Discord DM 上下文中观察到。其他平台(Slack、Teams、终端)可能由于网关实现差异而具有不同的超时行为。
版本不匹配:该问题在
2026.4.12上报告但提及26.4.14。确保客户端和网关使用相同版本,因为超时处理可能在版本之间发生了变化。并发内存操作:如果多个内存操作同时运行(索引、搜索、召回),它们可能争夺嵌入模型资源。排队内存操作或使用专用嵌入实例。
🔗 相关错误
embedded_run_failover_decision:由 Active Memory 阻塞召回到嵌入式运行上下文的超时传播触发的故障转移决策。memory.search.timeout:内存后端搜索操作超过其超时阈值(可能独立发生或作为 Active Memory 失败的一部分)。embedding.model.not_found:配置的嵌入模型(qwen3-embedding)在 Ollama 中不可用,导致超时前的同步回退延迟。active-memory.summary_chars=0:Active Memory 完成但生成零字符,表明摘要阶段被跳过或静默失败。gateway.active_memory.done.status=timeout:网关级别状态,表示 Active Memory 操作以超时状态完成,区别于status=success或status=error。llm.context.window.exceeded:如果内存召回摘要包含在后续请求中并超过上下文限制,可能发生,与maxSummaryChars配置错误相关。历史记录:v2026.3.x 内存后端回归:先前版本存在已知的内存召回延迟问题,原因是后端初始化。升级后确保重新构建索引。