Gestión de sesiones
OpenClaw trata una sesión de chat directo por agente como primaria. Los chats directos se colapsan a agent:<agentId>:<mainKey> (por defecto main), mientras que los chats de grupo/canal obtienen sus propias claves. Se respeta session.mainKey.
Usa session.dmScope para controlar cómo se agrupan los mensajes directos:
main(por defecto): todos los DMs comparten la sesión principal para mantener continuidad.per-peer: aislar por id de remitente a través de canales.per-channel-peer: aislar por canal + remitente (recomendado para bandejas de entrada multi-usuario).per-account-channel-peer: aislar por cuenta + canal + remitente (recomendado para bandejas de entrada multi-cuenta). Usasession.identityLinkspara mapear ids de pares con prefijo de proveedor a una identidad canónica para que la misma persona comparta una sesión de DM entre canales cuando usesper-peer,per-channel-peeroper-account-channel-peer.
Modo de DM seguro (recomendado para configuraciones multi-usuario)
Advertencia de seguridad: Si tu agente puede recibir DMs de múltiples personas, deberías considerar seriamente habilitar el modo de DM seguro. Sin él, todos los usuarios comparten el mismo contexto de conversación, lo que puede filtrar información privada entre usuarios.
Ejemplo del problema con la configuración por defecto:
- Alice (
<SENDER_A>) le envía un mensaje a tu agente sobre un tema privado (por ejemplo, una cita médica) - Bob (
<SENDER_B>) le envía un mensaje a tu agente preguntando “¿De qué estábamos hablando?” - Como ambos DMs comparten la misma sesión, el modelo puede responderle a Bob usando el contexto previo de Alice.
La solución: Configura dmScope para aislar sesiones por usuario:
// ~/.openclaw/openclaw.json
{
session: {
// Modo DM seguro: aislar contexto de DM por canal + remitente.
dmScope: "per-channel-peer",
},
}
Cuándo habilitarlo:
- Tienes aprobaciones de emparejamiento para más de un remitente
- Usas una lista de permitidos de DM con múltiples entradas
- Configuras
dmPolicy: "open" - Múltiples números de teléfono o cuentas pueden enviar mensajes a tu agente
Notas:
- El valor por defecto es
dmScope: "main"para continuidad (todos los DMs comparten la sesión principal). Esto está bien para configuraciones de un solo usuario. - El onboarding local del CLI escribe
session.dmScope: "per-channel-peer"por defecto cuando no está configurado (los valores explícitos existentes se preservan). - Para bandejas de entrada multi-cuenta en el mismo canal, prefiere
per-account-channel-peer. - Si la misma persona te contacta en múltiples canales, usa
session.identityLinkspara colapsar sus sesiones de DM en una única identidad canónica. - Puedes verificar tu configuración de DM con
openclaw security audit(ver security).
El gateway es la fuente de verdad
Todo el estado de sesión es propiedad del gateway (el OpenClaw “maestro”). Los clientes de UI (app de macOS, WebChat, etc.) deben consultar al gateway para listas de sesiones y conteos de tokens en lugar de leer archivos locales.
- En modo remoto, el store de sesiones que importa reside en el host del gateway remoto, no en tu Mac.
- Los conteos de tokens mostrados en las UIs provienen de los campos del store del gateway (
inputTokens,outputTokens,totalTokens,contextTokens). Los clientes no parsean transcripciones JSONL para “corregir” totales.
Dónde reside el estado
- En el host del gateway:
- Archivo de store:
~/.openclaw/agents/<agentId>/sessions/sessions.json(por agente).
- Archivo de store:
- Transcripciones:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(las sesiones de temas de Telegram usan.../<SessionId>-topic-<threadId>.jsonl). - El store es un mapa
sessionKey -> { sessionId, updatedAt, ... }. Eliminar entradas es seguro; se recrean bajo demanda. - Las entradas de grupo pueden incluir
displayName,channel,subject,roomyspacepara etiquetar sesiones en las UIs. - Las entradas de sesión incluyen metadatos
origin(etiqueta + hints de enrutamiento) para que las UIs puedan explicar de dónde vino una sesión. - OpenClaw no lee carpetas de sesión legacy de Pi/Tau.
Mantenimiento
OpenClaw aplica mantenimiento al store de sesiones para mantener sessions.json y los artefactos de transcripción acotados a lo largo del tiempo.
Valores por defecto
session.maintenance.mode:warnsession.maintenance.pruneAfter:30dsession.maintenance.maxEntries:500session.maintenance.rotateBytes:10mbsession.maintenance.resetArchiveRetention: por defecto igual apruneAfter(30d)session.maintenance.maxDiskBytes: sin configurar (deshabilitado)session.maintenance.highWaterBytes: por defecto80%demaxDiskBytescuando el presupuesto está habilitado
Cómo funciona
El mantenimiento se ejecuta durante las escrituras del store de sesiones, y puedes activarlo bajo demanda con openclaw sessions cleanup.
mode: "warn": reporta qué se desalojaría pero no muta entradas/transcripciones.mode: "enforce": aplica limpieza en este orden:- podar entradas antiguas más viejas que
pruneAfter - limitar el conteo de entradas a
maxEntries(las más antiguas primero) - archivar archivos de transcripción para entradas eliminadas que ya no están referenciadas
- purgar archivos antiguos
*.deleted.<timestamp>y*.reset.<timestamp>según la política de retención - rotar
sessions.jsoncuando excederotateBytes - si
maxDiskBytesestá configurado, aplicar presupuesto de disco haciahighWaterBytes(artefactos más antiguos primero, luego sesiones más antiguas)
- podar entradas antiguas más viejas que
Advertencia de rendimiento para stores grandes
Los stores de sesiones grandes son comunes en configuraciones de alto volumen. El trabajo de mantenimiento es trabajo en la ruta de escritura, así que stores muy grandes pueden aumentar la latencia de escritura.
Lo que más aumenta el costo:
- valores muy altos de
session.maintenance.maxEntries - ventanas largas de
pruneAfterque mantienen entradas obsoletas - muchos artefactos de transcripción/archivo en
~/.openclaw/agents/<agentId>/sessions/ - habilitar presupuestos de disco (
maxDiskBytes) sin límites razonables de poda/tope
Qué hacer:
- usa
mode: "enforce"en producción para que el crecimiento se acote automáticamente - configura tanto límites de tiempo como de conteo (
pruneAfter+maxEntries), no solo uno - configura
maxDiskBytes+highWaterBytespara límites superiores estrictos en despliegues grandes - mantén
highWaterBytessignificativamente por debajo demaxDiskBytes(el valor por defecto es 80%) - ejecuta
openclaw sessions cleanup --dry-run --jsondespués de cambios de configuración para verificar el impacto proyectado antes de aplicar - para sesiones activas frecuentes, pasa
--active-keyal ejecutar limpieza manual
Ejemplos de personalización
Usar una política de aplicación conservadora:
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "45d",
maxEntries: 800,
rotateBytes: "20mb",
resetArchiveRetention: "14d",
},
},
}
Habilitar un presupuesto de disco estricto para el directorio de sesiones:
{
session: {
maintenance: {
mode: "enforce",
maxDiskBytes: "1gb",
highWaterBytes: "800mb",
},
},
}
Ajustar para instalaciones más grandes (ejemplo):
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "14d",
maxEntries: 2000,
rotateBytes: "25mb",
maxDiskBytes: "2gb",
highWaterBytes: "1.6gb",
},
},
}
Previsualizar o forzar mantenimiento desde CLI:
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce
Poda de sesión
OpenClaw recorta resultados antiguos de herramientas del contexto en memoria justo antes de las llamadas LLM por defecto. Esto no reescribe el historial JSONL. Ver /concepts/session-pruning.
Flush de memoria pre-compactación
Cuando una sesión se acerca a la auto-compactación, OpenClaw puede ejecutar un turno silencioso de flush de memoria que le recuerda al modelo escribir notas durables a disco. Esto solo se ejecuta cuando el workspace es de escritura. Ver Memory y Compaction.
Mapeo de transportes → claves de sesión
- Los chats directos siguen
session.dmScope(por defectomain).main:agent:<agentId>:<mainKey>(continuidad entre dispositivos/canales).- Múltiples números de teléfono y canales pueden mapear a la misma clave principal del agente; actúan como transportes hacia una conversación.
per-peer:agent:<agentId>:direct:<peerId>.per-channel-peer:agent:<agentId>:<channel>:direct:<peerId>.per-account-channel-peer:agent:<agentId>:<channel>:<accountId>:direct:<peerId>(accountId por defecto esdefault).- Si
session.identityLinkscoincide con un id de par con prefijo de proveedor (por ejemplotelegram:123), la clave canónica reemplaza<peerId>para que la misma persona comparta una sesión entre canales.
- Los chats grupales aíslan el estado:
agent:<agentId>:<channel>:group:<id>(las salas/canales usanagent:<agentId>:<channel>:channel:<id>).- Los temas de foro de Telegram agregan
:topic:<threadId>al id del grupo para aislamiento. - Las claves legacy
group:<id>aún se reconocen para migración.
- Los temas de foro de Telegram agregan
- Los contextos entrantes pueden seguir usando
group:<id>; el canal se infiere deProvidery se normaliza a la forma canónicaagent:<agentId>:<channel>:group:<id>. - Otras fuentes:
- Trabajos cron:
cron:<job.id> - Webhooks:
hook:<uuid>(a menos que el hook lo configure explícitamente) - Ejecuciones de nodo:
node-<nodeId>
- Trabajos cron:
Ciclo de vida
- Política de reinicio: las sesiones se reutilizan hasta que expiran, y la expiración se evalúa en el siguiente mensaje entrante.
- Reinicio diario: por defecto a las 4:00 AM hora local del host del gateway. Una sesión está obsoleta cuando su última actualización es anterior al tiempo de reinicio diario más reciente.
- Reinicio por inactividad (opcional):
idleMinutesagrega una ventana deslizante de inactividad. Cuando están configurados tanto el reinicio diario como el de inactividad, el que expire primero fuerza una nueva sesión. - Inactividad legacy: si configuras
session.idleMinutessin ninguna configuración desession.reset/resetByType, OpenClaw permanece en modo solo-inactividad por compatibilidad retroactiva. - Sobreescrituras por tipo (opcional):
resetByTypete permite sobreescribir la política para sesionesdirect,groupythread(thread = hilos de Slack/Discord, temas de Telegram, hilos de Matrix cuando los provee el conector). - Sobreescrituras por canal (opcional):
resetByChannelsobreescribe la política de reinicio para un canal (aplica a todos los tipos de sesión para ese canal y tiene precedencia sobrereset/resetByType). - Disparadores de reinicio:
/newo/resetexacto (más los extras enresetTriggers) inician un nuevo id de sesión y pasan el resto del mensaje./new <model>acepta un alias de modelo,provider/modelo nombre de proveedor (coincidencia difusa) para configurar el modelo de la nueva sesión. Si/newo/resetse envían solos, OpenClaw ejecuta un breve turno de saludo “hello” para confirmar el reinicio. - Reinicio manual: elimina claves específicas del store o borra la transcripción JSONL; el siguiente mensaje las recrea.
- Los trabajos cron aislados siempre crean un
sessionIdnuevo por ejecución (sin reutilización por inactividad).
Política de envío (opcional)
Bloquear entrega para tipos de sesión específicos sin listar ids individuales.
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } },
// Coincide con la clave de sesión cruda (incluyendo el prefijo `agent:<id>:`).
{ action: "deny", match: { rawKeyPrefix: "agent:main:discord:" } },
],
default: "allow",
},
},
}
Sobreescritura en runtime (solo propietario):
/send on→ permitir para esta sesión/send off→ denegar para esta sesión/send inherit→ limpiar sobreescritura y usar reglas de configuración Envía estos como mensajes independientes para que se registren.
Configuración (ejemplo de renombrado opcional)
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // mantener claves de grupo separadas
dmScope: "main", // continuidad de DM (configura per-channel-peer/per-account-channel-peer para bandejas compartidas)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"],
},
reset: {
// Valores por defecto: mode=daily, atHour=4 (hora local del host del gateway).
// Si también configuras idleMinutes, el que expire primero gana.
mode: "daily",
atHour: 4,
idleMinutes: 120,
},
resetByType: {
thread: { mode: "daily", atHour: 4 },
direct: { mode: "idle", idleMinutes: 240 },
group: { mode: "idle", idleMinutes: 120 },
},
resetByChannel: {
discord: { mode: "idle", idleMinutes: 10080 },
},
resetTriggers: ["/new", "/reset"],
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
mainKey: "main",
},
}
Inspección
openclaw status— muestra la ruta del store y sesiones recientes.openclaw sessions --json— vuelca todas las entradas (filtra con--active <minutes>).openclaw gateway call sessions.list --params '{}'— obtiene sesiones del gateway en ejecución (usa--url/--tokenpara acceso remoto al gateway).- Envía
/statuscomo mensaje independiente en el chat para ver si el agente es alcanzable, cuánto contexto de sesión se usa, los toggles actuales de thinking/fast/verbose, y cuándo se refrescaron por última vez tus credenciales de WhatsApp web (ayuda a detectar necesidades de re-enlace). - Envía
/context listo/context detailpara ver qué hay en el system prompt y los archivos de workspace inyectados (y los mayores contribuyentes al contexto). - Envía
/stop(o frases de aborto independientes comostop,stop action,stop run,stop openclaw) para abortar la ejecución actual, limpiar seguimientos encolados para esa sesión y detener cualquier ejecución de sub-agente generada desde ella (la respuesta incluye el conteo de detenidas). - Envía
/compact(instrucciones opcionales) como mensaje independiente para resumir contexto antiguo y liberar espacio en la ventana. Ver /concepts/compaction. - Las transcripciones JSONL se pueden abrir directamente para revisar turnos completos.
Consejos
- Mantén la clave primaria dedicada al tráfico 1:1; deja que los grupos mantengan sus propias claves.
- Al automatizar limpieza, elimina claves individuales en lugar del store completo para preservar contexto en otros lugares.
Metadatos de origen de sesión
Cada entrada de sesión registra de dónde vino (mejor esfuerzo) en origin:
label: etiqueta legible (resuelta desde la etiqueta de conversación + subject/canal del grupo)provider: id de canal normalizado (incluyendo extensiones)from/to: ids de enrutamiento crudos del sobre entranteaccountId: id de cuenta del proveedor (cuando es multi-cuenta)threadId: id de hilo/tema cuando el canal lo soporta Los campos de origen se rellenan para mensajes directos, canales y grupos. Si un conector solo actualiza el enrutamiento de entrega (por ejemplo, para mantener fresca una sesión principal de DM), igual debe proporcionar contexto entrante para que la sesión mantenga sus metadatos explicativos. Las extensiones pueden hacer esto enviandoConversationLabel,GroupSubject,GroupChannel,GroupSpaceySenderNameen el contexto entrante y llamando arecordSessionMetaFromInbound(o pasando el mismo contexto aupdateLastRoute).