~/.claude/projects/ sur le système de fichiers local. Un adaptateur SessionStore vous permet de mettre en miroir ces transcriptions vers votre propre backend, tel qu’un magasin d’objets, un magasin clé-valeur ou une base de données, afin qu’une session créée sur un hôte puisse être reprise sur un autre hôte exécuté à partir d’un répertoire de travail correspondant.
Raisons courantes d’utiliser un magasin de sessions :
- Déploiements multi-hôtes. Les fonctions serverless, les workers autoscalés et les exécuteurs CI ne partagent pas de système de fichiers. Un magasin partagé permet aux réplicas de reprendre les sessions les unes des autres.
- Durabilité. Les conteneurs locaux sont éphémères. Un magasin externe survit aux redémarrages et aux redéploiements.
- Conformité et audit. Conservez les transcriptions dans un stockage que vous gouvernez déjà, avec vos propres règles de rétention, chiffrement et contrôles d’accès.
L’interface SessionStore
Un SessionStore est un objet avec deux méthodes requises, append et load, et quatre méthodes optionnelles. Le SDK appelle append pour écrire les entrées de transcription lors d’une requête et load pour les relire pour la reprise.
SessionKey adresse une transcription. projectKey est un encodage stable et sûr pour le système de fichiers du répertoire de travail, sessionId est l’UUID de la session, et subpath est défini lorsque l’entrée appartient à une transcription de sous-agent ou à un fichier sidecar plutôt qu’à la conversation principale.
Parce que projectKey encode le répertoire de travail, reprenez ou continuez à partir du magasin à partir d’un répertoire de travail correspondant à l’exécution d’origine. En TypeScript, si vous définissez CLAUDE_CODE_PROJECT_DIR_NAME à côté de CLAUDE_CONFIG_DIR dans l’option env d’une requête, le SDK indexe les entrées de cette requête, et ses recherches resume et continue, par ce nom à la place. Parce que les assistants autonomes tels que listSessions et deleteSession ne prennent pas env et lisent l’environnement du processus, définissez CLAUDE_CONFIG_DIR et le même nom dans l’environnement du processus hôte également. Nécessite Agent SDK v0.3.234 ou ultérieur.
Traitez subpath comme un suffixe de clé opaque ; il suit la disposition sur disque, par exemple subagents/agent-<id>. Lorsque subpath n’est pas défini, la clé fait référence à la transcription principale.
Dans une
SessionSummaryEntry, mtime est l’heure d’écriture du stockage du sidecar et doit partager une source d’horloge avec les valeurs mtime que listSessions retourne. data est un état opaque appartenant au SDK ; persistez-le verbatim sans l’interpréter.
Construisez les entrées en appelant l’assistant exporté foldSessionSummary, fold_session_summary en Python, sur chaque lot à l’intérieur de append. Ignorez les lots dont la clé a un subpath ; les transcriptions de sous-agents ne doivent pas contribuer au résumé de la session principale. Le fold ne définit jamais mtime : horodatez-le au moment de la persistance, via l’argument options.mtime en TypeScript ou en réécrivant le champ sur l’entrée retournée en Python. Les appels append concurrents pour la même session peuvent être en concurrence sur le sidecar, donc sérialisez la lecture-fold-écriture avec une transaction, un compare-and-swap, ou un verrou par session ; le fold lui-même est pur.
Pour ce que le SDK fait avec la transcription que load retourne, voir Reprendre à partir du magasin.
Démarrage rapide
Le SDK expédie unInMemorySessionStore pour le développement et les tests. L’exemple ci-dessous exécute une requête avec le magasin attaché, capture l’ID de session du message de résultat, puis reprend à partir du magasin dans un deuxième appel query(). Le deuxième appel transmet la même instance de magasin plus resume, afin que le SDK charge la transcription à partir du magasin au lieu du système de fichiers local :
Écrivez votre propre adaptateur
Implémentezappend et load par rapport à votre backend. Ajoutez listSessions, listSessionSummaries, delete et listSubkeys si vous voulez que listSessions(), les lectures de métadonnées en un seul appel, deleteSession() et la reprise de sous-agent fonctionnent par rapport au magasin.
Les entrées transmises à append sont typées comme SessionStoreEntry (un objet { type: string; ... }). Traitez-les comme des valeurs JSON-safe opaques : persistez-les dans l’ordre et retournez-les de load dans le même ordre. load doit retourner des entrées qui sont deep-equal à ce qui a été ajouté ; la sérialisation byte-equal n’est pas requise, donc un backend qui réorganise les clés d’objet, comme un type de colonne JSON binaire, convient.
Implémentations de référence
Les deux référentiels SDK incluent des adaptateurs de référence exécutables sousexamples/session-stores/ en TypeScript et examples/session_stores/ en Python. Il y a un adaptateur par type de stockage, et chacun montre comment append et load se mappent sur ce type de backend. Ils ne sont pas publiés en tant que packages ; copiez l’adaptateur du type le plus proche de votre backend dans votre projet, installez le client de votre backend, et adaptez-le.
Chaque adaptateur prend une instance de client préconfigurée, afin que vous contrôliez les identifiants, TLS, la région et le pooling. L’exemple suivant câble l’adaptateur de magasin d’objets dans
query() et reprend ensuite à partir de celui-ci sur un autre hôte :
TypeScript
Validez votre adaptateur
Les deux SDK expédient une suite de conformité qui affirme le contrat comportemental queappend, load et les méthodes optionnelles doivent satisfaire. Les tests pour les méthodes optionnelles ignorent automatiquement lorsque ces méthodes ne sont pas implémentées.
En TypeScript, copiez shared/conformance.ts du répertoire d’exemples dans votre suite de tests. En Python, la suite est expédiée dans le package. Pour l’exécuter avec pytest, qui n’est pas une dépendance du SDK, installez d’abord pytest :
run_session_store_conformance appelle une fois par contrat pour construire un nouveau magasin :
Python
MyRedisStore elle-même, comme cet exemple le fait, fonctionne lorsque le constructeur ne prend aucun argument. Pour un adaptateur qui prend un client préconfiguré, transmettez plutôt une lambda qui construit le magasin. Parce que les contrats réutilisent les mêmes clés de session, chaque magasin que la fabrique retourne doit commencer avec un stockage vide, donc faites en sorte que la lambda provisionne un stockage de sauvegarde isolé par appel, comme un faux en mémoire frais, un préfixe de clé unique, ou une nouvelle base de données de test.
Notes de comportement
Architecture à double écriture
Le sous-processus Claude Code écrit toujours d’abord chaque lot d’entrées de transcription sur le disque local, puis le SDK transfère le même lot àappend() de votre magasin, de sorte que le magasin est un miroir de la transcription locale plutôt qu’un remplacement. Quelle copie survit à l’exécution dépend de la façon dont l’exécution a commencé :
- Session nouvelle, ou une reprise quand le magasin n’a rien pour la session : la transcription locale sous votre répertoire de configuration survit à l’exécution, et le magasin reçoit une copie.
- Exécution reprise à partir du magasin : la copie locale est supprimée à la fin de l’exécution, de sorte que le magasin détient la seule copie durable.
CLAUDE_CONFIG_DIR sur un répertoire temporaire dans options.env. Une exécution reprise à partir du magasin supprime déjà sa copie locale, elle n’a donc besoin d’aucun tel paramètre. En TypeScript, propagez également process.env dans env, puisque l’option env remplace l’environnement du sous-processus.
Si votre application se connecte via des fichiers dans le répertoire de configuration, tels que les identifiants OAuth ou un apiKeyHelper dans votre settings.json utilisateur, copiez d’abord ces fichiers dans le répertoire temporaire, ou définissez ANTHROPIC_API_KEY dans env à la place. Sinon, l’exécution échoue avec Not logged in.
Deux options entrent en conflit avec le miroir, et le SDK lève une exception au démarrage si vous combinez l’une ou l’autre avec un magasin :
persistSession: falseen TypeScript : désactive les écritures locales sur lesquelles le miroir est construit. Le SDK Python n’a pas d’option équivalente.- Sauvegarde de point de contrôle de fichier,
enableFileCheckpointingen TypeScript ouenable_file_checkpointingen Python : écrit ses sauvegardes de fichiers directement sur le disque local, et le SDK ne les met pas en miroir vers le magasin.
Reprise à partir du magasin
Quand vous passezresume, ou continue: true en TypeScript ou continue_conversation=True en Python, ensemble avec un magasin, le SDK demande au magasin une transcription avant de générer le sous-processus :
resume: le SDK demande la session dont vous avez passé l’ID.continue: trueoucontinue_conversation=True: le SDK demande la session la plus récente du magasin.
CLAUDE_CONFIG_DIR pointant là-bas, et supprime le répertoire quand l’exécution se termine. La transcription locale que cette exécution écrit est supprimée avec elle, c’est pourquoi le magasin détient la seule copie durable sur ce chemin.
Le SDK amorce également le répertoire temporaire avec des fichiers de votre répertoire de configuration réel. Ce qu’il copie diffère selon le langage :
- TypeScript : identifiants,
.claude.json, et votresettings.jsonutilisateur. Desettings.json, il supprime les clés qui se comportent mal sous un répertoire de configuration temporaire :enabledPlugins,extraKnownMarketplaces, son aliasadditionalMarketplaces, et toutCLAUDE_CONFIG_DIRdans le blocenvdu fichier. Avant Agent SDK v0.3.232, le SDK ne supprimait pas l’alias. L’authentification configurée dans les paramètres, telle queapiKeyHelper, fonctionne quand vous reprenez à partir du magasin. Avant Agent SDK v0.3.222, le SDK TypeScript copiait uniquement les identifiants et.claude.json. - Python : identifiants et
.claude.jsonuniquement, donc une application qui s’authentifie viaapiKeyHelperdans votresettings.jsonutilisateur échoue avecNot logged inlors de la reprise à partir d’un magasin. UnapiKeyHelperdans les paramètres gérés ou de projet fonctionne toujours, car Claude Code lit ces fichiers à partir d’emplacements queCLAUDE_CONFIG_DIRn’affecte pas.
resume: les deux SDK passent l’ID au sous-processus, qui reprend la transcription locale exactement commeresumele fait sans magasin.continue: trueen TypeScript : le SDK démarre une session nouvelle.continue_conversation=Trueen Python : le SDK continue à partir de la session locale la plus récente.
Les écritures en miroir sont au mieux
Siappend() rejette, le SDK réessaie le lot jusqu’à deux fois supplémentaires avec un délai court, pour un maximum de trois tentatives au total. Un appel qui expire n’est pas réessayé, car l’appel original peut toujours aboutir. Si le lot échoue toujours, le SDK enregistre l’erreur, émet un message { type: "system", subtype: "mirror_error" } dans l’itérateur, supprime le lot, et continue la requête. Parce qu’un lot réessayé peut redélivrer des entrées qui ont déjà abouti, dédupliquez par entry.uuid dans votre implémentation de append().
Une panne du magasin n’interrompt pas l’agent, puisque le sous-processus écrit localement d’abord. Surveillez mirror_error si vous devez détecter une perte de données du magasin. Sur une exécution reprise à partir du magasin, un lot supprimé n’a pas de copie survivante une fois l’exécution terminée.
getSessionMessages retourne la chaîne post-compaction
getSessionMessages({ sessionStore }) retourne la chaîne de messages liée que l’agent verrait à la reprise. Après la compaction automatique, les tours antérieurs sont remplacés par un résumé, donc une session dont le magasin contient 503 entrées brutes peut retourner 18 messages de getSessionMessages. Pour l’historique brut complet, y compris les tours pré-compaction et les entrées de métadonnées, appelez store.load(key) directement.
forkSession n’est pas une copie byte
forkSession({ sessionStore }) lit les entrées source, réécrit chaque champ sessionId et remapte les UUID de message, puis ajoute les entrées transformées sous une nouvelle clé. Une copie au niveau de l’adaptateur ou un raccourci CopyObject produirait une transcription qui référence toujours l’ancien ID de session, donc le SDK n’en utilise pas.
Transcriptions de sous-agents
Les transcriptions de sous-agents sont mises en miroir soussubpath: "subagents/agent-<id>". listSubagents({ sessionStore }) nécessite que l’adaptateur implémente listSubkeys ; getSubagentMessages({ sessionStore }) l’utilise quand disponible mais revient au subpath direct quand il n’est pas défini. La reprise appelle également listSubkeys pour restaurer les fichiers de sous-agents ; sans cela, seule la transcription principale est matérialisée.
Rétention
Le SDK ne supprime jamais de votre magasin de son propre chef. La rétention est la responsabilité de l’adaptateur : utilisez le mécanisme d’expiration ou de cycle de vie de votre backend, ou exécutez un nettoyage programmé, selon vos exigences de conformité. Les transcriptions locales sousCLAUDE_CONFIG_DIR sont balayées indépendamment par le paramètre cleanupPeriodDays, en suivant les règles de balayage de rétention. Une exécution reprise à partir du magasin ne laisse pas de transcription locale, donc pour ces exécutions la rétention de votre magasin est la seule rétention qu’il y a.
Supporté sur
Les fonctions SDK TypeScript suivantes acceptent une optionsessionStore et opèrent par rapport au magasin au lieu du système de fichiers local quand elle est fournie :
query()startup()listSessions()getSessionInfo()getSessionMessages()renameSession()tagSession()deleteSession()forkSession()listSubagents()getSubagentMessages()
session_store dans ClaudeAgentOptions pour exécuter query() par rapport à un magasin. Les opérations restantes ont chacune une fonction Python soutenue par un magasin qui prend le magasin comme argument : 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(), et fork_session_via_store(). startup() n’a pas d’équivalent Python. Les fonctions autonomes documentées dans la référence du SDK Python, telles que list_sessions(), lisent les fichiers de session locaux.
Ressources connexes
- Travailler avec les sessions : Continuer, reprendre et forker sans magasin personnalisé
- Héberger le SDK : Modèles de déploiement pour les environnements multi-hôtes
- TypeScript
Options: Référence complète des options - Implémentations de référence : Adaptateurs d’exemple exécutables pour un magasin d’objets, un magasin clé-valeur et une base de données, dans les deux référentiels SDK