~/.claude/projects/ nel filesystem locale. Un adattatore SessionStore consente di eseguire il mirroring di questi trascritti nel vostro backend, come un object store, un key-value store o un database, in modo che una sessione creata su un host possa essere ripresa su un altro host in esecuzione da una directory di lavoro corrispondente.
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 alle repliche di riprendere le sessioni reciproche.
- Durabilità. I container locali sono effimeri. Uno store esterno 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 quattro metodi facoltativi. L’SDK chiama append per scrivere le voci di trascritto durante una query e load per leggerle di nuovo per la ripresa.
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.
Poiché projectKey codifica la directory di lavoro, riprendere o continuare dal negozio da una directory di lavoro che corrisponda all’esecuzione originale. In TypeScript, se impostate CLAUDE_CODE_PROJECT_DIR_NAME accanto a CLAUDE_CONFIG_DIR nell’opzione env di una query, l’SDK codifica le voci di quella query e le sue ricerche resume e continue per quel nome. Poiché helper autonomi come listSessions e deleteSession non accettano env e leggono l’ambiente del processo, impostate CLAUDE_CONFIG_DIR e lo stesso nome nell’ambiente del processo host. Richiede Agent SDK v0.3.234 o successivo.
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.
In una
SessionSummaryEntry, mtime è il tempo di scrittura dell’archiviazione del sidecar e deve condividere una fonte di clock con i valori mtime che listSessions restituisce. data è uno stato di proprietà dell’SDK opaco; persistetelo verbatim senza interpretarlo.
Costruite le voci chiamando l’helper esportato foldSessionSummary, fold_session_summary in Python, su ogni batch all’interno di append. Saltate i batch la cui chiave ha un subpath; i trascritti dei subagent non devono contribuire al riepilogo della sessione principale. Il fold non imposta mai mtime: contrassegnatelo al momento della persistenza, tramite l’argomento options.mtime in TypeScript o sovrascrivendo il campo sulla voce restituita in Python. Le chiamate append simultanee per la stessa sessione possono correre sul sidecar, quindi serializzate la lettura-fold-scrittura con una transazione, un compare-and-swap, o un blocco per sessione; il fold stesso è puro.
Per ciò che l’SDK fa con il trascritto che load restituisce, vedere Riprendere dal negozio.
Avvio rapido
L’SDK fornisce unInMemorySessionStore 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:
Scrivere il vostro adattatore
Implementateappend e load rispetto al vostro backend. Aggiungete listSessions, listSessionSummaries, delete e listSubkeys se desiderate che listSessions(), letture di metadati in una sola chiamata, 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 un backend che riordina le chiavi degli oggetti, come un tipo di colonna JSON binaria, va bene.
Implementazioni di riferimento
Entrambi i repository SDK includono adattatori di riferimento eseguibili inexamples/session-stores/ in TypeScript e examples/session_stores/ in Python. C’è un adattatore per tipo di archiviazione, e ognuno mostra come append e load si mappano su quel tipo di backend. Non sono pubblicati come pacchetti; copiate l’adattatore per il tipo più vicino al vostro backend nel vostro progetto, installate il client del vostro backend, e adattatelo.
Ogni adattatore accetta un’istanza client preconfigurata, in modo che controlliate le credenziali, TLS, la regione e il pooling. L’esempio seguente collega l’adattatore object-store in
query() e quindi riprende da esso su un altro host:
TypeScript
Convalidare il vostro adattatore
Entrambi gli SDK forniscono una suite di conformità che asserisce il contratto comportamentale cheappend, 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. Per eseguirla con pytest, che non è una dipendenza dell’SDK, installate prima pytest:
run_session_store_conformance chiama una volta per contratto per costruire un nuovo store:
Python
MyRedisStore stessa, come fa questo esempio, funziona quando il costruttore non accetta argomenti. Per un adattatore che accetta un client preconfigurato, passate invece una lambda che costruisce lo store. Poiché i contratti riutilizzano le stesse chiavi di sessione, ogni store che la factory restituisce deve iniziare con archiviazione vuota, quindi fate in modo che la lambda fornisca archiviazione di supporto isolata per ogni chiamata, come un nuovo fake in memoria, un prefisso di chiave univoco o un nuovo database di test.
Note sul comportamento
Architettura a doppia scrittura
Il subprocess Claude Code scrive sempre ogni batch di voci di trascritto su disco locale per primo, e l’SDK quindi invia lo stesso batch aappend() del vostro store, quindi lo store è un mirror del trascritto locale piuttosto che una sostituzione per esso. Quale copia sopravvive all’esecuzione dipende da come è stata avviata l’esecuzione:
- Sessione nuova, o una ripresa quando lo store non ha nulla per la sessione: il trascritto locale nella vostra directory di configurazione sopravvive all’esecuzione, e lo store riceve una copia.
- Esecuzione ripresa dallo store: la copia locale viene eliminata alla fine dell’esecuzione, quindi lo store contiene l’unica copia durevole.
CLAUDE_CONFIG_DIR a una directory temporanea in options.env. Un’esecuzione ripresa dallo store elimina già la sua copia locale, quindi non ha bisogno di tale impostazione. In TypeScript, diffondete anche process.env in env, poiché l’opzione env sostituisce l’ambiente del subprocess.
Se la vostra app accede tramite file nella directory di configurazione, come credenziali OAuth o un apiKeyHelper nel vostro settings.json utente, copiate prima quei file nella directory temporanea, oppure impostate ANTHROPIC_API_KEY in env invece. Altrimenti l’esecuzione fallisce con Not logged in.
Due opzioni entrano in conflitto con il mirror, e l’SDK genera un’eccezione all’avvio se combinate una di esse con uno store:
persistSession: falsein TypeScript: disattiva le scritture locali su cui è costruito il mirror. L’SDK Python non ha un’opzione equivalente.- File checkpointing,
enableFileCheckpointingin TypeScript oenable_file_checkpointingin Python: scrive i suoi backup di file direttamente su disco locale, e l’SDK non li esegue il mirroring nello store.
Ripresa dallo store
Quando passateresume, o continue: true in TypeScript o continue_conversation=True in Python, insieme a uno store, l’SDK chiede allo store un trascritto prima di generare il subprocess:
resume: l’SDK chiede la sessione il cui ID avete passato.continue: trueocontinue_conversation=True: l’SDK chiede la sessione più recente dello store.
CLAUDE_CONFIG_DIR che punta lì, ed elimina la directory quando l’esecuzione termina. Il trascritto locale che quell’esecuzione scrive viene eliminato con essa, motivo per cui lo store contiene l’unica copia durevole su questo percorso.
L’SDK semina anche la directory temporanea con file dalla vostra directory di configurazione reale. Ciò che copia differisce per linguaggio:
- TypeScript: credenziali,
.claude.json, e il vostrosettings.jsonutente. Dasettings.jsonrimuove le chiavi che si comportano male in una directory di configurazione temporanea:enabledPlugins,extraKnownMarketplaces, il suo aliasadditionalMarketplaces, e qualsiasiCLAUDE_CONFIG_DIRnel bloccoenvdel file. Prima di Agent SDK v0.3.232, l’SDK non rimuoveva l’alias. L’autenticazione configurata nelle impostazioni, comeapiKeyHelper, funziona quando riprendete dallo store. Prima di Agent SDK v0.3.222, l’SDK TypeScript copiava solo credenziali e.claude.json. - Python: solo credenziali e
.claude.json, quindi un’app che si autentica tramiteapiKeyHelpernel vostrosettings.jsonutente fallisce conNot logged inquando riprende da uno store. UnapiKeyHelpernelle impostazioni gestite o di progetto funziona ancora, perché Claude Code legge quei file da posizioni cheCLAUDE_CONFIG_DIRnon influenza.
resume: entrambi gli SDK passano l’ID al subprocess, che riprende il trascritto locale esattamente comeresumefa senza uno store.continue: truein TypeScript: l’SDK avvia una sessione nuova.continue_conversation=Truein Python: l’SDK continua dalla sessione locale più recente.
Le scritture mirror sono best-effort
Seappend() rifiuta, l’SDK ritenta il batch fino a due volte in più con un breve backoff, per un massimo di tre tentativi in totale. Una chiamata che scade non viene ritentata, poiché la chiamata originale potrebbe comunque arrivare. Se il batch continua a fallire, l’SDK registra l’errore, emette un messaggio { type: "system", subtype: "mirror_error" } nell’iteratore, scarta il batch e continua la query. Poiché un batch ritentato può ri-consegnare voci che hanno già raggiunto la destinazione, deduplicare per entry.uuid nella vostra implementazione di append().
Un’interruzione dello store non interrompe l’agente, poiché il subprocess scrive localmente per primo. Monitorate mirror_error se dovete rilevare la perdita di dati dello store. Su un’esecuzione ripresa dallo store, un batch scartato non ha una copia sopravvivente una volta che l’esecuzione termina.
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 insubpath: "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 inCLAUDE_CONFIG_DIR vengono puliti indipendentemente dall’impostazione cleanupPeriodDays, seguendo le regole di pulizia della conservazione. Un’esecuzione ripresa dallo store non lascia alcun trascritto locale, quindi per quelle esecuzioni la conservazione del vostro store è l’unica conservazione che esiste.
Supportato su
Le seguenti funzioni SDK TypeScript accettano un’opzionesessionStore e operano rispetto allo store invece del filesystem locale quando viene fornita:
query()startup()listSessions()getSessionInfo()getSessionMessages()renameSession()tagSession()deleteSession()forkSession()listSubagents()getSubagentMessages()
session_store in ClaudeAgentOptions per eseguire query() rispetto a uno store. Le operazioni rimanenti hanno ciascuna una funzione Python supportata da store che accetta lo store come argomento: list_sessions_from_store(), get_session_info_from_store(), get_session_messages_from_store(), list_subagents_from_store(), get_subagent_messages_from_store(), rename_session_via_store(), tag_session_via_store(), delete_session_via_store() e fork_session_via_store(). startup() non ha un equivalente Python. Le funzioni standalone documentate nel riferimento Python SDK, come list_sessions(), leggono i file di sessione locali.
Risorse correlate
- Lavorare con le sessioni: Continuare, riprendere e fare un fork senza uno store personalizzato
- Ospitare l’SDK: Modelli di distribuzione per ambienti multi-host
- TypeScript
Options: Riferimento completo delle opzioni - Implementazioni di riferimento: Adattatori di esempio eseguibili per uno store di oggetti, uno store chiave-valore e un database, in entrambi i repository SDK