SpyBara
Go Premium

agent-sdk/session-storage.md 2026-06-16 21:57 UTC to 2026-06-17 17:02 UTC

5 added, 3 removed.

2026
Mon 29 21:00 Sat 27 01:01 Fri 26 23:00 Thu 25 23:58 Wed 24 22:02 Tue 23 22:00 Mon 22 23:59 Fri 19 22:58 Thu 18 22:00 Wed 17 17:02 Tue 16 21:57 Mon 15 23:02 Sat 13 21:59 Fri 12 22:00 Thu 11 23:01 Wed 10 23:57 Tue 9 06:34 Mon 8 06:52 Sat 6 06:24 Fri 5 06:45 Thu 4 06:52 Wed 3 06:53 Tue 2 06:51

Persistir sesiones en almacenamiento externo

Refleja transcripciones de sesiones en S3, Redis o tu propio backend para que cualquier host pueda reanudarlas.

De forma predeterminada, el SDK escribe transcripciones de sesiones en archivos JSONL bajo ~/.claude/projects/ en el sistema de archivos local. Un adaptador SessionStore te permite reflejar esas transcripciones en tu propio backend, como S3, Redis o una base de datos, para que una sesión creada en un host pueda reanudarse en otro.

Razones comunes para usar un almacén de sesiones:

  • Implementaciones multi-host. Las funciones sin servidor, los trabajadores con escalado automático y los ejecutores de CI no comparten un sistema de archivos. Un almacén compartido permite que cualquier réplica reanude cualquier sesión.
  • Durabilidad. Los contenedores locales son efímeros. Un almacén respaldado por S3 o una base de datos sobrevive a reinicios y redeploys.
  • Cumplimiento y auditoría. Mantén transcripciones en almacenamiento que ya gobiernas, con tus propias reglas de retención, cifrado y controles de acceso.

La interfaz `SessionStore`

Un SessionStore es un objeto con dos métodos requeridos, append y load, y tres métodos opcionales. El SDK llama a append para escribir entradas de transcripción durante una consulta y a load para leerlas de nuevo para reanudar.

// Exported from @anthropic-ai/claude-agent-sdk as
// SessionStore, SessionKey, SessionStoreEntry.

type SessionKey = {
projectKey: string;
sessionId: string;
subpath?: string;
};

type SessionStore = {
// Required
append(key: SessionKey, entries: SessionStoreEntry[]): Promise<void>;
load(key: SessionKey): Promise<SessionStoreEntry[] | null>;

// Optional
listSessions?(
projectKey: string,
): Promise<Array<{ sessionId: string; mtime: number }>>;
delete?(key: SessionKey): Promise<void>;
listSubkeys?(key: {
projectKey: string;
sessionId: string;
}): Promise<string[]>;
};

SessionKey direcciona una transcripción. projectKey es una codificación estable y segura para el sistema de archivos del directorio de trabajo, sessionId es el UUID de la sesión, y subpath se establece cuando la entrada pertenece a una transcripción de subagenteor archivo sidecar en lugar de la conversación principal. Trata subpath como una clave de sufijo opaca; sigue el diseño en disco, por ejemplo subagents/agent-<id>. Cuando subpath no está definido, la clave se refiere a la transcripción principal.

Método Requerido Se llama cuando
append Después de que cada lote de entradas de transcripción se escriba localmente. Las entradas son objetos seguros para JSON, uno por línea en el JSONL local.
load Una vez antes de que se genere el subproceso, cuando resume está establecido. Devuelve null si la sesión es desconocida.
listSessions No Por listSessions({ sessionStore }) y por query()/startup() con continue: true. Si no está definido, esas llamadas lanzan una excepción.
delete No Por deleteSession({ sessionStore }). Eliminar la clave principal (sin subpath) debe cascada a todas las subclaves para esa sesión. Si no está definido, la eliminación es una no-op, que se adapta a backends de solo anexión.
listSubkeys No Durante la reanudación, para descubrir transcripciones de subagenteor. Si no está definido, solo se restaura la transcripción principal.

Inicio rápido

El SDK incluye un InMemorySessionStore para desarrollo y pruebas. El ejemplo a continuación ejecuta una consulta con el almacén adjunto, captura el ID de sesión del mensaje de resultado, luego reanuda desde el almacén en una segunda llamada query(). La segunda llamada pasa la misma instancia de almacén más resume, por lo que el SDK carga la transcripción del almacén en lugar del sistema de archivos local:

import { query, InMemorySessionStore } from "@anthropic-ai/claude-agent-sdk";

const store = new InMemorySessionStore();

let sessionId: string | undefined;
for await (const message of query({
prompt: "List the TypeScript files under src/",
options: { sessionStore: store },
})) {
if (message.type === "result") {
sessionId = message.session_id;
}
}

// Resume from the store. The agent has full context from the first call.
for await (const message of query({
prompt: "Summarize what those files do",
options: { sessionStore: store, resume: sessionId },
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}

La segunda consulta imprime un resumen de los archivos de la primera consulta, lo que muestra que el agente reanudó con contexto completo desde el almacén.

Escribe tu propio adaptador

Implementa append y load contra tu backend. Añade listSessions, delete y listSubkeys si deseas que listSessions(), deleteSession() y la reanudación de subagenteor funcionen contra el almacén.

Las entradas pasadas a append se escriben como SessionStoreEntry (un objeto { type: string; ... }). Trátalas como valores opacos seguros para JSON: persístalas en orden y devuélvelas desde load en el mismo orden. load debe devolver entradas que sean profundamente iguales a lo que se anexó; la serialización byte-igual no es requerida, por lo que backends como Postgres jsonb que reordenan claves de objeto están bien.

Implementaciones de referencia

El repositorio del SDK de TypeScript incluye adaptadores de referencia ejecutables para S3, Redis y Postgres bajo examples/session-stores/. No se publican en npm; copia el archivo src/ que necesites en tu proyecto e instala el cliente backend correspondiente.

Adaptador Cliente backend Modelo de almacenamiento
S3SessionStore @aws-sdk/client-s3 Un archivo de parte JSONL por append(); load() lista, ordena y concatena.
RedisSessionStore ioredis Lista RPUSH/LRANGE por transcripción, más un índice de conjunto ordenado de sesión.
PostgresSessionStore pg Una fila por entrada en una tabla jsonb, ordenada por BIGSERIAL.

Cada adaptador toma una instancia de cliente preconfigurada, por lo que controlas credenciales, TLS, región y agrupación. Por ejemplo, con S3:

import { query } from "@anthropic-ai/claude-agent-sdk";
import { S3Client } from "@aws-sdk/client-s3";
import { S3SessionStore } from "./S3SessionStore"; // copied from examples/session-stores/s3

const store = new S3SessionStore({
  bucket: "my-claude-sessions",
  prefix: "transcripts",
  client: new S3Client({ region: "us-east-1" }),
});

for await (const message of query({
  prompt: "Hello!",
  options: { sessionStore: store },
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

// Later, possibly on a different host:
for await (const message of query({
  prompt: "Continue where we left off",
  options: { sessionStore: store, resume: "previous-session-id" },
})) {
  // ...
}

Valida tu adaptador

Ambos SDKs incluyen un conjunto de conformidad que afirma el contrato de comportamiento que append, load y los métodos opcionales deben satisfacer. Las pruebas para métodos opcionales se omiten automáticamente cuando esos métodos no se implementan.

En TypeScript, copia shared/conformance.ts del directorio de ejemplos en tu suite de pruebas. En Python, el conjunto se incluye en el paquete:

import pytest
from claude_agent_sdk.testing import run_session_store_conformance


@pytest.mark.asyncio
async def test_my_store_conformance():
    await run_session_store_conformance(MyRedisStore)

Notas de comportamiento

Arquitectura de escritura dual

El almacén es un espejo, no un reemplazo. El subproceso de Claude Code siempre escribe primero en disco local; el SDK luego reenvía cada lote a append(). Si deseas que la copia local sea efímera, apunta CLAUDE_CONFIG_DIR a un directorio temporal en options.env. Debido a que el espejo depende de escrituras locales, sessionStore no se puede combinar con persistSession: false; el SDK lanza si estableces ambos. También lanza si se combina con enableFileCheckpointing, ya que los blobs de copia de seguridad del historial de archivos se escriben directamente en disco local y no se reflejan en el almacén.

Las escrituras de espejo son de mejor esfuerzo

Si append() rechaza o agota el tiempo de espera, el error se registra, se emite un mensaje { type: "system", subtype: "mirror_error" } en el iterador, y la consulta continúa. La transcripción local ya es duradera en disco, por lo que una interrupción del almacén no interrumpe al agente ni pierde datos localmente. Los lotes que fallan no se reintentan, por lo que monitorea mirror_error si necesitas detectar pérdida de datos del almacén.

`getSessionMessages` devuelve la cadena posterior a la compactación

getSessionMessages({ sessionStore }) devuelve la cadena de mensajes vinculada que el agente vería al reanudar. Después de la compactación automática, los turnos anteriores se reemplazan por un resumen, por lo que una sesión cuyo almacén contiene 503 entradas sin procesar puede devolver 18 mensajes desde getSessionMessages. Para el historial sin procesar completo, incluidos los turnos previos a la compactación y las entradas de metadatos, llama a store.load(key) directamente.

`forkSession` no es una copia byte

forkSession({ sessionStore }) lee las entradas de origen, reescribe cada campo sessionId y remapea UUIDs de mensajes, luego anexa las entradas transformadas bajo una clave nueva. Una copia a nivel de adaptador o un atajo CopyObject produciría una transcripción que aún hace referencia al ID de sesión anterior, por lo que el SDK no usa uno.

Transcripciones de subagente

Las transcripciones de subagente se reflejan bajo subpath: "subagents/agent-<id>". listSubagents({ sessionStore }) requiere que el adaptador implemente listSubkeys; getSubagentMessages({ sessionStore }) lo usa cuando está disponible pero vuelve al subpath directo cuando no está definido. La reanudación también llama a listSubkeys para restaurar archivos de subagente; sin él, solo se materializa la transcripción principal.

Retención

El SDK nunca elimina de tu almacén por su cuenta. La retención es responsabilidad del adaptador: implementa TTLs, políticas de ciclo de vida de S3 o limpieza programada según tus requisitos de cumplimiento. Las transcripciones locales bajo CLAUDE_CONFIG_DIR se barren independientemente por la configuración cleanupPeriodDays.

Compatible con

Las siguientes funciones del SDK aceptan una opción sessionStore y operan contra el almacén en lugar del sistema de archivos local cuando se proporciona: