Active Memory Timeout: Blocking Recall Pass Excede el Tiempo de Espera Configurado
Active Memory consistentemente excede el tiempo de espera antes de devolver summaries recuperadas a través de múltiples models y providers, con el timeout disparándose en ~8084ms a pesar de una configuración de 8000ms.
🔍 Síntomas
Active Memory no logra completar su paso de recuperación bloqueante dentro del ventana de tiempo de espera configurada. La siguiente salida de diagnóstico aparece consistentemente:
🧩 Active Memory: timeout 8084ms message 0 chars
🔎 Active Memory Debug: none retrieved
Los logs del gateway confirman el comportamiento de timeout:
active-memory ... done status=timeout elapsedMs=8092 summaryChars=0
embedded_run_failover_decision ... failoverReason=timeout profileFailureReason=timeout
Manifestaciones Diagnósticas
- Umbral de timeout: El timeout se activa en ~8084-8092ms (vs. los 8000ms configurados), lo que indica que la verificación del timeout ocurre después de que comienza la llamada bloqueante
- Respuesta de cero bytes:
summaryChars=0confirma que no se generó ningún resumen antes del timeout - Agnóstico al modelo: El problema se reproduce en todos los modelos probados:
openai-codex/gpt-5.4ollama/glm-5.1:cloudollama/llama3.1:8bollama/gemma4:e4b
- Agnóstico al backend: Tanto los entornos de ejecución inactivos como los ocupados/en cola presentan comportamiento idéntico
- Cadena de proveedores: Afecta la configuración de enrutamiento
openclaw → ollama
Contexto del Entorno
| Componente | Valor |
|---|---|
| Versión de OpenClaw | 2026.4.12 / 26.4.14 |
| Sistema Operativo | macOS |
| Método de Instalación | npm global |
| Backend de Memoria | builtin/default (memory-core) |
| Modelo de Embedding | qwen3-embedding (Ollama) |
| Contexto de Chat | Discord DM (directo) |
🧠 Causa raíz
Causa Raíz Principal: Recuperación Síncrona de Embeddings Bloqueante
El timeout ocurre porque el paso de recuperación bloqueante de Active Memory realiza búsquedas de embeddings síncronas contra el backend de memoria antes de invocar el LLM para la resumación. Cuando la fase de recuperación de embeddings excede el timeout configurado, la llamada al LLM nunca se ejecuta.
Análisis de la Secuencia de Fallas
┌─────────────────────────────────────────────────────────────┐
│ Active Memory Blocking Recall Pass │
├─────────────────────────────────────────────────────────────┤
│ 1. Memory Query (synchronous) │
│ └─→ Embedding retrieval via qwen3-embedding │
│ └─→ Memory backend search │
│ └─→ BLOQUEADO AQUÍ (timeout: 8084ms) │
│ │
│ 2. LLM Summarization (never reached) │
│ └─→ Summary generation │
└─────────────────────────────────────────────────────────────┘
Factores Contribuyentes
Propagación del Timeout en Ejecución Embebida: La entrada de log
embedded_run_failover_decisionindica que el timeout de Active Memory se propaga al contexto de ejecución embebida, causando el log de decisión de failover. Esto sugiere un acoplamiento estrecho entre las fases de recuperación de memoria y generación de respuesta.Consulta Síncrona al Backend de Memoria: La búsqueda de memoria utiliza recuperación de embeddings síncrona. Cuando
qwen3-embeddingexperimenta latencia (viaje de red a Ollama, carga del modelo, u overhead de búsqueda vectorial), el retraso acumulativo excede el timeout de 8000ms antes de que se genere el primer token.Timing de Verificación del Timeout: El exceso de 84-92ms (
8084ms real vs. 8000ms configurado) indica que:- El timeout se verifica después de que cada operación bloqueante se completa
- La recuperación de embeddings en sí toma ~8084ms
- No existe mecanismo de salida anticipada para verificaciones de timeout sub-milisegundo
Configuración del Modo de Consulta: La configuración
queryMode: “message”puede activar el embedding completo del mensaje en lugar de una búsqueda semántica ligera, aumentando la latencia de recuperación.
Inconsistencia Arquitectónica
El backend memory-core no implementa:
- Recuperación de embeddings asíncrona/no bloqueante
- Presupuestos de timeout por fase (presupuestos separados para recuperación vs. generación)
- Terminación anticipada ante el primer resultado sustancial
🛠️ Solución paso a paso
Solución 1: Aumentar el Timeout de Active Memory (Mitigación Inmediata)
Aumenta el timeout para acomodar la latencia de recuperación de embeddings:
Antes:
"active-memory": {
"enabled": true,
"config": {
"timeoutMs": 8000,
...
}
}Después:
"active-memory": {
"enabled": true,
"config": {
"timeoutMs": 30000,
...
}
}Solución 2: Separar los Timeout de Recuperación y Generación
Configura presupuestos de timeout separados para la recuperación de embeddings vs. la generación del LLM:
"active-memory": {
"enabled": true,
"config": {
"timeoutMs": 30000,
"retrievalTimeoutMs": 10000,
"generationTimeoutMs": 20000,
...
}
}Solución 3: Cambiar a Modo de Consulta Asíncrono/Ligero
Cambia queryMode de “message” a “semantic” o “hybrid”:
Antes:
"queryMode": "message"Después:
"queryMode": "semantic"Solución 4: Usar un Modelo de Embedding Más Rápido
Reemplaza qwen3-embedding con un modelo de embedding local más rápido:
"active-memory": {
"config": {
"embeddingModel": "ollama/nomic-embed-text"
}
}Luego reinicia Ollama para asegurar que el modelo esté en caché:
ollama pull nomic-embed-text
systemctl restart ollamaSolución 5: Deshabilitar Active Memory Temporalmente (Para Producción)
Si el timeout está bloqueando producción, deshabilita la recuperación bloqueante:
"active-memory": {
"enabled": false
}O restringe al modo no bloqueante:
"active-memory": {
"config": {
"blockingMode": false,
"asyncRecall": true
}
}Solución 6: Verificación de Salud del Backend de Memoria
Verifica la conectividad del backend de memoria y el estado de indexación:
# 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🧪 Verificación
Pasos de Verificación Después de Aplicar las Soluciones
Paso 1: Habilitar Logging Verboso y de Trazas
/verbose on
/trace onPaso 2: Activar la Recuperación de Active Memory
Envía un mensaje que deba activar la recuperación de memoria:
what was my last message to youPaso 3: Verificar Comportamiento Sin Timeout
Salida esperada (éxito):
🧩 Active Memory: completed 2341ms message 87 chars
🔎 Active Memory Debug: retrieved summary "User asked about..."
Log esperado del gateway:
active-memory ... done status=success elapsedMs=2345 summaryChars=87
Paso 4: Confirmar Que No Se Activó Failover
Verificar ausencia de:
embedded_run_failover_decision ... failoverReason=timeout
Paso 5: Ejecutar Comando de Diagnóstico
openclaw memory test --mode recall --verboseSalida esperada:
Memory recall test: PASS
Retrieval latency: 1243ms
Generation latency: 892ms
Total: 2135ms (within timeout budget)
Paso 6: Verificar la Salud del Backend de Memoria
openclaw memory statusLa salida esperada debe mostrar:
backend: memory-coreindexed: trueembedding: qwen3-embedding (o modelo configurado)status: healthy
⚠️ Errores comunes
Timeout Demasiado Cerca de la Latencia de Embedding: Configurar
timeoutMssolo ligeramente más alto que el tiempo típico de recuperación de embeddings no deja presupuesto para la generación del LLM. Asegúrate de que el timeout total acomode ambas fases más un margen de seguridad del 20%.Modelo de Ollama No Precargado: En la primera solicitud, Ollama descarga y carga el modelo de embedding, causando latencia significativa. Siempre precarga los modelos:
ollama pull ollama/gemma4:e4b ollama pull qwen3-embeddingLatencia de Red con Ollama Remoto: Si Ollama se ejecuta en un host remoto o contenedor Docker, la latencia de red se suma al tiempo de recuperación de embeddings. Usa Ollama local o aumenta el timeout en 2-3x.
Índice de Memoria No Construido: Si el backend de memoria no tiene contenido indexado, el paso de recuperación puede ejecutar consultas de embedding contra resultados vacíos, causando latencia inesperada. Verifica el estado del índice antes de solucionar el timeout.
Override del Modo Bloqueante: Algunas configuraciones o plugins pueden forzar
blockingMode: trueindependientemente de la configuración del usuario. Verifica:openclaw config get active-memory.blockingModeEspecificidades de Discord DM: El problema se observó en contexto de Discord DM. Otras plataformas (Slack, Teams, terminal) pueden tener diferentes comportamientos de timeout debido a diferencias en la implementación del gateway.
Desajuste de Versión: El problema se reportó en
2026.4.12pero menciona26.4.14. Asegúrate de que tanto el cliente como el gateway estén en la misma versión, ya que el manejo de timeout puede haber cambiado entre versiones.Operaciones de Memoria Concurrentes: Si múltiples operaciones de memoria se ejecutan concurrentemente (indexación, búsqueda, recuperación), pueden competir por los recursos del modelo de embedding. Cola las operaciones de memoria o usa instancias de embedding dedicadas.
🔗 Errores relacionados
embedded_run_failover_decision: Decisión de failover activada por la propagación del timeout desde la recuperación bloqueante de Active Memory al contexto de ejecución embebida.memory.search.timeout: La operación de búsqueda del backend de memoria excedió su umbral de timeout (puede ocurrir independientemente o como parte del fallo de Active Memory).embedding.model.not_found: El modelo de embedding configurado (qwen3-embedding) no está disponible en Ollama, causando retrasos de fallback síncrono antes del timeout.active-memory.summary_chars=0: Active Memory completó pero generó cero caracteres, indicando que la fase de resumación fue omitida o falló silenciosamente.gateway.active_memory.done.status=timeout: Estado a nivel de gateway indicando que la operación de Active Memory completó con estado timeout, distinto destatus=successostatus=error.llm.context.window.exceeded: Puede ocurrir si el resumen de recuperación de memoria se incluye en solicitudes posteriores y excede los límites de contexto, relacionado con la configuración incorrecta demaxSummaryChars.Histórico: Regresiones del Backend de Memoria en v2026.3.x: Versiones anteriores tenían problemas conocidos con la latencia de recuperación de memoria debido a la inicialización del backend. Asegura una reconstrucción fresca del índice después de actualizar.