SpyBara
Go Premium

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

2 added, 0 removed.

2026
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

Persistere le sessioni nell'archiviazione esterna

Eseguire il mirroring dei trascritti di sessione su S3, Redis o il vostro backend in modo che qualsiasi host possa riprendere le sessioni.

Per impostazione predefinita, l'SDK scrive i trascritti di sessione in file JSONL in ~/.claude/projects/ nel filesystem locale. Un adattatore SessionStore consente di eseguire il mirroring di questi trascritti nel vostro backend, come S3, Redis o un database, in modo che una sessione creata su un host possa essere ripresa su un altro.

Motivi comuni per utilizzare un session store:

  • Distribuzioni multi-host. Le funzioni serverless, i worker con scalabilità automatica e i runner CI non condividono un filesystem. Un store condiviso consente a qualsiasi replica di riprendere qualsiasi sessione.
  • Durabilità. I container locali sono effimeri. Uno store supportato da S3 o da un database sopravvive ai riavvii e ai ridistribuzioni.
  • Conformità e audit. Mantenete i trascritti nell'archiviazione che già controllate, con le vostre regole di conservazione, crittografia e controlli di accesso.

L'interfaccia `SessionStore`

Un SessionStore è un oggetto con due metodi obbligatori, append e load, e tre metodi facoltativi. L'SDK chiama append per scrivere le voci di trascritto durante una query e load per leggerle di nuovo per la ripresa.

// 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 indirizza un trascritto. projectKey è una codifica stabile e sicura per il filesystem della directory di lavoro, sessionId è l'UUID della sessione, e subpath è impostato quando la voce appartiene a un trascritto di subagent o a un file sidecar piuttosto che alla conversazione principale. Trattate subpath come una chiave suffisso opaca; segue il layout su disco, ad esempio subagents/agent-<id>. Quando subpath non è definito, la chiave si riferisce al trascritto principale.

Metodo Obbligatorio Chiamato quando
append Dopo che ogni batch di voci di trascritto viene scritto localmente. Le voci sono oggetti JSON-safe, uno per riga nel JSONL locale.
load Una volta prima che il subprocess venga generato, quando resume è impostato. Restituire null se la sessione è sconosciuta.
listSessions No Da listSessions({ sessionStore }) e da query()/startup() con continue: true. Se non definito, queste chiamate generano un'eccezione.
delete No Da deleteSession({ sessionStore }). L'eliminazione della chiave principale (nessun subpath) deve propagarsi a tutte le subchiavi per quella sessione. Se non definito, l'eliminazione è un'operazione nulla, che si adatta ai backend append-only.
listSubkeys No Durante la ripresa, per scoprire i trascritti dei subagent. Se non definito, viene ripristinato solo il trascritto principale.

Avvio rapido

L'SDK fornisce un InMemorySessionStore per lo sviluppo e i test. L'esempio seguente esegue una query con lo store allegato, acquisisce l'ID della sessione dal messaggio di risultato, quindi riprende dallo store in una seconda chiamata query(). La seconda chiamata passa la stessa istanza dello store più resume, in modo che l'SDK carichi il trascritto dallo store invece dal filesystem locale:

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 seconda query stampa un riepilogo dei file dalla prima query, il che mostra che l'agente ha ripreso con il contesto completo dallo store.

Scrivere il vostro adattatore

Implementate append e load rispetto al vostro backend. Aggiungete listSessions, delete e listSubkeys se desiderate che listSessions(), deleteSession() e la ripresa dei subagent funzionino rispetto allo store.

Le voci passate a append sono digitate come SessionStoreEntry (un oggetto { type: string; ... }). Trattate le come valori JSON-safe opachi: persistetele in ordine e restituitetele da load nello stesso ordine. load deve restituire voci che siano deep-equal a quelle aggiunte; la serializzazione byte-equal non è richiesta, quindi i backend come Postgres jsonb che riordinano le chiavi degli oggetti vanno bene.

Implementazioni di riferimento

Il repository TypeScript SDK include adattatori di riferimento eseguibili per S3, Redis e Postgres in examples/session-stores/. Non sono pubblicati su npm; copiate il file src/ di cui avete bisogno nel vostro progetto e installate il client backend corrispondente.

Adattatore Client backend Modello di archiviazione
S3SessionStore @aws-sdk/client-s3 Un file di parte JSONL per append(); load() elenca, ordina e concatena.
RedisSessionStore ioredis Lista RPUSH/LRANGE per trascritto, più un indice di set ordinato della sessione.
PostgresSessionStore pg Una riga per voce in una tabella jsonb, ordinata per BIGSERIAL.

Ogni adattatore accetta un'istanza client preconfigurata, in modo che controlliate le credenziali, TLS, la regione e il pooling. Ad esempio, 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" },
})) {
  // ...
}

Convalidare il vostro adattatore

Entrambi gli SDK forniscono una suite di conformità che asserisce il contratto comportamentale che append, load e i metodi facoltativi devono soddisfare. I test per i metodi facoltativi vengono saltati automaticamente quando questi metodi non sono implementati.

In TypeScript, copiate shared/conformance.ts dalla directory di esempio nella vostra suite di test. In Python, la suite è fornita nel pacchetto:

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)

Note sul comportamento

Architettura a doppia scrittura

Lo store è un mirror, non una sostituzione. Il subprocess Claude Code scrive sempre su disco locale per primo; l'SDK quindi invia ogni batch a append(). Se desiderate che la copia locale sia effimera, puntate CLAUDE_CONFIG_DIR a una directory temporanea in options.env. Poiché il mirror dipende dalle scritture locali, sessionStore non può essere combinato con persistSession: false; l'SDK genera un'eccezione se impostate entrambi. Genera anche un'eccezione se combinato con enableFileCheckpointing, poiché i blob di backup della cronologia dei file vengono scritti direttamente su disco locale e non vengono sottoposti a mirroring nello store.

Le scritture mirror sono best-effort

Se append() rifiuta o scade, l'errore viene registrato, un messaggio { type: "system", subtype: "mirror_error" } viene emesso nell'iteratore e la query continua. Il trascritto locale è già durevole su disco, quindi un'interruzione dello store non interrompe l'agente o perde dati localmente. I batch che non riescono non vengono ritentati, quindi monitorate mirror_error se dovete rilevare la perdita di dati dello store.

`getSessionMessages` restituisce la catena post-compattazione

getSessionMessages({ sessionStore }) restituisce la catena di messaggi collegati che l'agente vedrebbe al momento della ripresa. Dopo la compattazione automatica, i turni precedenti vengono sostituiti da un riepilogo, quindi una sessione il cui store contiene 503 voci grezze può restituire 18 messaggi da getSessionMessages. Per la cronologia grezza completa, inclusi i turni pre-compattazione e le voci di metadati, chiamate store.load(key) direttamente.

`forkSession` non è una copia byte

forkSession({ sessionStore }) legge le voci di origine, riscrive ogni campo sessionId e rimappa gli UUID dei messaggi, quindi aggiunge le voci trasformate sotto una nuova chiave. Una copia a livello di adattatore o un collegamento CopyObject produrrebbe un trascritto che fa ancora riferimento all'ID della sessione precedente, quindi l'SDK non ne utilizza uno.

Trascritti dei subagent

I trascritti dei subagent vengono sottoposti a mirroring in subpath: "subagents/agent-<id>". listSubagents({ sessionStore }) richiede che l'adattatore implementi listSubkeys; getSubagentMessages({ sessionStore }) lo utilizza quando disponibile ma ricade al subpath diretto quando non è definito. La ripresa chiama anche listSubkeys per ripristinare i file dei subagent; senza di esso, viene materializzato solo il trascritto principale.

Conservazione

L'SDK non elimina mai dal vostro store di sua iniziativa. La conservazione è responsabilità dell'adattatore: implementate TTL, politiche del ciclo di vita S3 o pulizia pianificata secondo i vostri requisiti di conformità. I trascritti locali in CLAUDE_CONFIG_DIR vengono puliti indipendentemente dall'impostazione cleanupPeriodDays.

Supportato su

Le seguenti funzioni SDK accettano un'opzione sessionStore e operano rispetto allo store invece del filesystem locale quando viene fornita: