~/.claude/projects/ no sistema de arquivos local. Um adaptador SessionStore permite que você espelhe essas transcrições para seu próprio backend, como um armazenamento de objetos, um armazenamento de chave-valor ou um banco de dados, para que uma sessão criada em um host possa ser retomada em outro host executando a partir de um diretório de trabalho correspondente.
Razões comuns para usar um session store:
- Implantações multi-host. Funções serverless, workers com autoscaling e runners de CI não compartilham um sistema de arquivos. Um store compartilhado permite que réplicas retomem as sessões umas das outras.
- Durabilidade. Contêineres locais são efêmeros. Um store externo sobrevive a reinicializações e redeploys.
- Conformidade e auditoria. Mantenha transcrições em armazenamento que você já governa, com suas próprias regras de retenção, criptografia e controles de acesso.
A interface SessionStore
Um SessionStore é um objeto com dois métodos obrigatórios, append e load, e quatro métodos opcionais. O SDK chama append para escrever entradas de transcrição durante uma consulta e load para lê-las novamente para retomada.
SessionKey endereça uma transcrição. projectKey é uma codificação estável e segura para sistema de arquivos do diretório de trabalho, sessionId é o UUID da sessão, e subpath é definido quando a entrada pertence a uma transcrição de subagente ou arquivo sidecar em vez da conversa principal.
Como projectKey codifica o diretório de trabalho, retome ou continue a partir do armazenamento de um diretório de trabalho que corresponda ao da execução original. No TypeScript, se você definir CLAUDE_CODE_PROJECT_DIR_NAME ao lado de CLAUDE_CONFIG_DIR na opção env de uma consulta, o SDK codifica as entradas dessa consulta, e suas buscas de resume e continue, por esse nome. Como auxiliares independentes como listSessions e deleteSession não recebem env e leem o ambiente do processo, defina CLAUDE_CONFIG_DIR e o mesmo nome no ambiente do processo host também. Requer Agent SDK v0.3.234 ou posterior.
Trate subpath como um sufixo de chave opaco; ele segue o layout em disco, por exemplo subagents/agent-<id>. Quando subpath é indefinido, a chave se refere à transcrição principal.
Em um
SessionSummaryEntry, mtime é o tempo de escrita do armazenamento do sidecar e deve compartilhar uma fonte de relógio com os valores mtime que listSessions retorna. data é um estado opaco de propriedade do SDK; persista-o verbatim sem interpretá-lo.
Construa as entradas chamando o auxiliar exportado foldSessionSummary, fold_session_summary em Python, em cada lote dentro de append. Pule lotes cuja chave tem um subpath; transcrições de subagentes não devem contribuir para o resumo da sessão principal. O fold nunca define mtime: carimbe-o no tempo de persistência, através do argumento options.mtime no TypeScript ou sobrescrevendo o campo na entrada retornada em Python. Chamadas append concorrentes para a mesma sessão podem correr no sidecar, então serialize a leitura-fold-escrita com uma transação, um compare-and-swap, ou um lock por sessão; o fold em si é puro.
Para o que o SDK faz com a transcrição que load retorna, veja Retomar do armazenamento.
Início rápido
O SDK fornece umInMemorySessionStore para desenvolvimento e testes. O exemplo abaixo executa uma consulta com o store anexado, captura o ID da sessão da mensagem de resultado e depois retoma do store em uma segunda chamada query(). A segunda chamada passa a mesma instância de store mais resume, para que o SDK carregue a transcrição do store em vez do sistema de arquivos local:
Escreva seu próprio adaptador
Implementeappend e load contra seu backend. Adicione listSessions, listSessionSummaries, delete e listSubkeys se você quiser que listSessions(), leituras de metadados em uma única chamada, deleteSession() e retomada de subagentes funcionem contra o store.
As entradas passadas para append são digitadas como SessionStoreEntry (um objeto { type: string; ... }). Trate-as como valores JSON-safe opacos: persista-as em ordem e retorne-as de load na mesma ordem. load deve retornar entradas que sejam deep-equal ao que foi anexado; serialização byte-equal não é necessária, então um backend que reordena chaves de objeto, como um tipo de coluna JSON binária, é adequado.
Implementações de referência
Ambos os repositórios do SDK incluem adaptadores de referência executáveis emexamples/session-stores/ em TypeScript e examples/session_stores/ em Python. Há um adaptador por tipo de armazenamento, e cada um mostra como append e load mapeiam para esse tipo de backend. Eles não são publicados como pacotes; copie o adaptador para o tipo mais próximo do seu backend para seu projeto, instale o cliente do seu backend e adapte-o.
Cada adaptador recebe uma instância de cliente pré-configurada, para que você controle credenciais, TLS, região e pooling. O exemplo a seguir conecta o adaptador de armazenamento de objetos em
query() e depois retoma a partir dele em outro host:
TypeScript
Valide seu adaptador
Ambos os SDKs fornecem um conjunto de conformidade que afirma o contrato comportamental queappend, load e os métodos opcionais devem satisfazer. Testes para métodos opcionais pulam automaticamente quando esses métodos não são implementados.
Em TypeScript, copie shared/conformance.ts do diretório de exemplos para seu conjunto de testes. Em Python, o conjunto é fornecido no pacote. Para executá-lo com pytest, que não é uma dependência do SDK, instale o pytest primeiro:
run_session_store_conformance chama uma vez por contrato para construir um armazenamento novo:
Python
MyRedisStore em si, como este exemplo faz, funciona quando o construtor não recebe argumentos. Para um adaptador que recebe um cliente pré-configurado, passe um lambda que constrói o armazenamento em vez disso. Como os contratos reutilizam as mesmas chaves de sessão, cada armazenamento que a fábrica retorna deve começar com armazenamento vazio, então faça o lambda provisionar armazenamento de suporte isolado por chamada, como um novo falso na memória, um prefixo de chave único ou um novo banco de dados de teste.
Notas de comportamento
Arquitetura de escrita dupla
O subprocess Claude Code sempre escreve cada lote de entradas de transcrição no disco local primeiro, e o SDK então encaminha o mesmo lote paraappend() do seu store, então o store é um espelho da transcrição local em vez de uma substituição para ela. Qual cópia sobrevive à execução depende de como a execução foi iniciada:
- Sessão nova, ou uma retomada quando o store não tem nada para a sessão: a transcrição local sob seu diretório de configuração sobrevive à execução, e o store recebe uma cópia.
- Execução retomada do store: a cópia local é deletada ao final da execução, então o store mantém a única cópia durável.
CLAUDE_CONFIG_DIR para um diretório temporário em options.env. Uma execução retomada do store já deleta sua cópia local, então não precisa de tal configuração. Em TypeScript, espalhe process.env em env também, já que a opção env substitui o ambiente do subprocess.
Se seu aplicativo faz login através de arquivos no diretório de configuração, como credenciais OAuth ou um apiKeyHelper em seu settings.json de usuário, copie esses arquivos para o diretório temporário primeiro, ou defina ANTHROPIC_API_KEY em env em vez disso. Caso contrário, a execução falha com Not logged in.
Duas opções entram em conflito com o espelho, e o SDK lança na inicialização se você combinar qualquer uma com um store:
persistSession: falseem TypeScript: desativa as escritas locais nas quais o espelho é construído. O SDK Python não tem opção equivalente.- Checkpointing de arquivo,
enableFileCheckpointingem TypeScript ouenable_file_checkpointingem Python: escreve seus backups de arquivo diretamente no disco local, e o SDK não os espelha para o store.
Retomar do store
Quando você passaresume, ou continue: true em TypeScript ou continue_conversation=True em Python, junto com um store, o SDK pede ao store uma transcrição antes de spawnar o subprocess:
resume: o SDK pede a sessão cujo ID você passou.continue: trueoucontinue_conversation=True: o SDK pede a sessão mais nova do store.
CLAUDE_CONFIG_DIR apontando para lá, e deleta o diretório quando a execução termina. A transcrição local que essa execução escreve é deletada com ele, que é por que o store mantém a única cópia durável neste caminho.
O SDK também semeia o diretório temporário com arquivos do seu diretório de configuração real. O que ele copia difere por linguagem:
- TypeScript: credenciais,
.claude.json, e seusettings.jsonde usuário. Desettings.jsonele remove as chaves que se comportam mal em um diretório de configuração temporário:enabledPlugins,extraKnownMarketplaces, seu aliasadditionalMarketplaces, e qualquerCLAUDE_CONFIG_DIRno blocoenvdo arquivo. Antes do Agent SDK v0.3.232, o SDK não removia o alias. Autenticação configurada em configurações, comoapiKeyHelper, funciona quando você retoma do store. Antes do Agent SDK v0.3.222, o SDK TypeScript copiava apenas credenciais e.claude.json. - Python: apenas credenciais e
.claude.json, então um aplicativo que se autentica através deapiKeyHelperem seusettings.jsonde usuário falha comNot logged inao retomar de um store. UmapiKeyHelperem configurações gerenciadas ou de projeto ainda funciona, porque Claude Code lê esses arquivos de locais queCLAUDE_CONFIG_DIRnão afeta.
resume: ambos os SDKs passam o ID através para o subprocess, que retoma a transcrição local exatamente comoresumefaz sem um store.continue: trueem TypeScript: o SDK inicia uma sessão nova.continue_conversation=Trueem Python: o SDK continua da sessão local mais nova.
Escritas de espelho são best-effort
Seappend() rejeita, o SDK tenta novamente o lote até mais duas vezes com um backoff curto, para no máximo três tentativas no total. Uma chamada que expira não é retentada, já que a chamada original ainda pode chegar. Se o lote ainda falhar, o SDK registra o erro, emite uma mensagem { type: "system", subtype: "mirror_error" } para o iterador, descarta o lote, e continua a consulta. Como um lote retentado pode reentrega entradas que já chegaram, deduplicar por entry.uuid em sua implementação de append().
Uma interrupção de store não interrompe o agente, já que o subprocess escreve localmente primeiro. Monitore mirror_error se você precisar detectar perda de dados de store. Em uma execução retomada do store, um lote descartado não tem cópia sobrevivente uma vez que a execução termina.
getSessionMessages retorna a cadeia pós-compactação
getSessionMessages({ sessionStore }) retorna a cadeia de mensagens vinculada que o agente veria ao retomar. Após auto-compactação, turnos anteriores são substituídos por um resumo, então uma sessão cujo store contém 503 entradas brutas pode retornar 18 mensagens de getSessionMessages. Para o histórico bruto completo, incluindo turnos pré-compactação e entradas de metadados, chame store.load(key) diretamente.
forkSession não é uma cópia byte
forkSession({ sessionStore }) lê as entradas de origem, reescreve cada campo sessionId e remapeia UUIDs de mensagem, depois anexa as entradas transformadas sob uma nova chave. Uma cópia em nível de adaptador ou atalho CopyObject produziria uma transcrição que ainda referencia o ID de sessão antigo, então o SDK não usa um.
Transcrições de subagentes
Transcrições de subagentes são espelhadas emsubpath: "subagents/agent-<id>". listSubagents({ sessionStore }) requer que o adaptador implemente listSubkeys; getSubagentMessages({ sessionStore }) o usa quando disponível, mas volta para o subpath direto quando é indefinido. Retomada também chama listSubkeys para restaurar arquivos de subagentes; sem ele, apenas a transcrição principal é materializada.
Retenção
O SDK nunca deleta de seu store por conta própria. Retenção é responsabilidade do adaptador: use o mecanismo de expiração ou ciclo de vida do seu backend, ou execute limpeza agendada, de acordo com seus requisitos de conformidade. Transcrições locais emCLAUDE_CONFIG_DIR são limpas independentemente pela configuração cleanupPeriodDays, seguindo as regras de limpeza de retenção. Uma execução retomada do store não deixa transcrição local, então para essas execuções a retenção do seu store é a única retenção que existe.
Suportado em
As seguintes funções do SDK TypeScript aceitam uma opçãosessionStore e operam contra o store em vez do sistema de arquivos local quando fornecido:
query()startup()listSessions()getSessionInfo()getSessionMessages()renameSession()tagSession()deleteSession()forkSession()listSubagents()getSubagentMessages()
session_store em ClaudeAgentOptions para executar query() contra um store. As operações restantes cada uma têm uma função Python com suporte a store que recebe o store como argumento: 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() não tem equivalente em Python. As funções autônomas documentadas na referência do SDK Python, como list_sessions(), leem arquivos de sessão locais.
Recursos relacionados
- Trabalhar com sessões: Continuar, retomar e fazer fork sem um store personalizado
- Hospedar o SDK: Padrões de implantação para ambientes multi-host
- TypeScript
Options: Referência completa de opções - Implementações de referência: Adaptadores de exemplo executáveis para um object store, um key-value store e um banco de dados, em ambos os repositórios do SDK