SpyBara
Go Premium

agent-sdk/session-storage.md 2026-06-09 06:34 UTC to 2026-06-10 23:57 UTC

287 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

Sitzungen in externem Speicher persistieren

Spiegeln Sie Sitzungstranskripte zu S3, Redis oder Ihrem eigenen Backend, damit jeder Host sie fortsetzen kann.

Standardmäßig schreibt das SDK Sitzungstranskripte in JSONL-Dateien unter ~/.claude/projects/ im lokalen Dateisystem. Ein SessionStore-Adapter ermöglicht es Ihnen, diese Transkripte in Ihrem eigenen Backend zu spiegeln, z. B. in S3, Redis oder einer Datenbank, sodass eine auf einem Host erstellte Sitzung auf einem anderen Host fortgesetzt werden kann.

Häufige Gründe für die Verwendung eines Session Store:

  • Multi-Host-Bereitstellungen. Serverlose Funktionen, automatisch skalierte Worker und CI-Runner teilen sich kein Dateisystem. Ein gemeinsamer Store ermöglicht es jedem Replikat, jede Sitzung fortzusetzen.
  • Dauerhaftigkeit. Lokale Container sind kurzlebig. Ein Store, der von S3 oder einer Datenbank unterstützt wird, übersteht Neustarts und Neubereitstellungen.
  • Compliance und Audit. Bewahren Sie Transkripte in Speicher auf, den Sie bereits kontrollieren, mit Ihren eigenen Aufbewahrungsrichtlinien, Verschlüsselung und Zugriffskontrolle.

Die `SessionStore`-Schnittstelle

Ein SessionStore ist ein Objekt mit zwei erforderlichen Methoden, append und load, und drei optionalen Methoden. Das SDK ruft append auf, um Transkripteinträge während einer Abfrage zu schreiben, und load, um sie zum Fortsetzen zurückzulesen.

// 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 adressiert ein Transkript. projectKey ist eine stabile, dateisystemsichere Kodierung des Arbeitsverzeichnisses, sessionId ist die Sitzungs-UUID, und subpath wird gesetzt, wenn der Eintrag zu einem Subagent-Transkript oder einer Sidecar-Datei statt zur Hauptkonversation gehört. Behandeln Sie subpath als einen undurchsichtigen Schlüsselsuffix; er folgt dem On-Disk-Layout, z. B. subagents/agent-<id>. Wenn subpath nicht definiert ist, bezieht sich der Schlüssel auf das Haupttranskript.

Methode Erforderlich Aufgerufen wenn
append Ja Nach jedem Batch von Transkripteinträgen, die lokal geschrieben werden. Einträge sind JSON-sichere Objekte, eine pro Zeile in der lokalen JSONL.
load Ja Einmal vor dem Spawnen des Subprozesses, wenn resume gesetzt ist. Geben Sie null zurück, wenn die Sitzung unbekannt ist.
listSessions Nein Von listSessions({ sessionStore }) und von query()/startup() mit continue: true. Wenn nicht definiert, werfen diese Aufrufe einen Fehler.
delete Nein Von deleteSession({ sessionStore }). Das Löschen des Hauptschlüssels (kein subpath) muss auf alle Unterschlüssel für diese Sitzung kaskadieren. Wenn nicht definiert, ist das Löschen ein No-Op, was für Append-Only-Backends geeignet ist.
listSubkeys Nein Während des Wiederaufnehmens, um Subagent-Transkripte zu entdecken. Wenn nicht definiert, wird nur das Haupttranskript wiederhergestellt.

Schnellstart

Das SDK wird mit einem InMemorySessionStore für Entwicklung und Tests ausgeliefert. Das folgende Beispiel führt eine Abfrage mit dem angehängten Store aus, erfasst die Sitzungs-ID aus der Ergebnismeldung und setzt dann aus dem Store in einem zweiten query()-Aufruf fort. Der zweite Aufruf übergibt die gleiche Store-Instanz plus resume, sodass das SDK das Transkript aus dem Store statt aus dem lokalen Dateisystem lädt:

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);
}
}

Schreiben Sie Ihren eigenen Adapter

Implementieren Sie append und load gegen Ihr Backend. Fügen Sie listSessions, delete und listSubkeys hinzu, wenn Sie möchten, dass listSessions(), deleteSession() und Subagent-Wiederaufnahme gegen den Store funktionieren.

Einträge, die an append übergeben werden, sind als SessionStoreEntry typisiert (ein { type: string; ... }-Objekt). Behandeln Sie sie als undurchsichtige JSON-sichere Werte: persistieren Sie sie in Reihenfolge und geben Sie sie von load in der gleichen Reihenfolge zurück. load muss Einträge zurückgeben, die tiefengleich mit dem sind, was angehängt wurde; Byte-gleiche Serialisierung ist nicht erforderlich, daher sind Backends wie Postgres jsonb, die Objektschlüssel neu ordnen, in Ordnung.

Referenzimplementierungen

Das TypeScript SDK-Repository enthält ausführbare Referenz-Adapter für S3, Redis und Postgres unter examples/session-stores/. Sie werden nicht auf npm veröffentlicht; kopieren Sie die src/-Datei, die Sie benötigen, in Ihr Projekt und installieren Sie den entsprechenden Backend-Client.

Adapter Backend-Client Speichermodell
S3SessionStore @aws-sdk/client-s3 Eine JSONL-Teildatei pro append(); load() listet auf, sortiert und verkettet.
RedisSessionStore ioredis RPUSH/LRANGE-Liste pro Transkript, plus einen sortierten Satz-Sitzungsindex.
PostgresSessionStore pg Eine Zeile pro Eintrag in einer jsonb-Tabelle, geordnet nach BIGSERIAL.

Jeder Adapter nimmt eine vorkonfigurierte Client-Instanz an, sodass Sie Anmeldedaten, TLS, Region und Pooling kontrollieren. Zum Beispiel mit 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" },
})) {
  // ...
}

Validieren Sie Ihren Adapter

Beide SDKs werden mit einer Konformitätssuite ausgeliefert, die den Verhaltensvertrag durchsetzt, den append, load und die optionalen Methoden erfüllen müssen. Tests für optionale Methoden werden automatisch übersprungen, wenn diese Methoden nicht implementiert sind.

In TypeScript kopieren Sie shared/conformance.ts aus dem Beispielverzeichnis in Ihre Test-Suite. In Python wird die Suite im Paket ausgeliefert:

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)

Verhaltenshinweise

Dual-Write-Architektur

Der Store ist ein Spiegel, kein Ersatz. Der Claude Code-Subprozess schreibt immer zuerst auf die lokale Festplatte; das SDK leitet dann jeden Batch an append() weiter. Wenn Sie möchten, dass die lokale Kopie kurzlebig ist, zeigen Sie CLAUDE_CONFIG_DIR auf ein temporäres Verzeichnis in options.env. Da der Spiegel von lokalen Schreibvorgängen abhängt, kann sessionStore nicht mit persistSession: false kombiniert werden; das SDK wirft einen Fehler, wenn Sie beide setzen. Es wirft auch einen Fehler, wenn es mit enableFileCheckpointing kombiniert wird, da Dateihistorie-Backup-Blobs direkt auf die lokale Festplatte geschrieben werden und nicht zum Store gespiegelt werden.

Spiegelschreibvorgänge sind Best-Effort

Wenn append() ablehnt oder eine Zeitüberschreitung auftritt, wird der Fehler protokolliert, eine { type: "system", subtype: "mirror_error" }-Meldung wird in den Iterator ausgegeben, und die Abfrage wird fortgesetzt. Das lokale Transkript ist bereits auf der Festplatte dauerhaft, daher unterbricht ein Store-Ausfall den Agenten nicht und verliert keine Daten lokal. Batches, die fehlschlagen, werden nicht erneut versucht, daher überwachen Sie auf mirror_error, wenn Sie Datenverluste im Store erkennen müssen.

`getSessionMessages` gibt die Post-Komprimierungs-Kette zurück

getSessionMessages({ sessionStore }) gibt die verknüpfte Nachrichtenkette zurück, die der Agent beim Wiederaufnehmen sehen würde. Nach der automatischen Komprimierung werden frühere Umdrehungen durch eine Zusammenfassung ersetzt, daher kann eine Sitzung, deren Store 503 rohe Einträge enthält, 18 Nachrichten von getSessionMessages zurückgeben. Für die vollständige Rohhistorie, einschließlich Pre-Komprimierungs-Umdrehungen und Metadateneinträge, rufen Sie store.load(key) direkt auf.

`forkSession` ist keine Byte-Kopie

forkSession({ sessionStore }) liest die Quelleinträge, schreibt jedes sessionId-Feld um und ordnet Nachrichten-UUIDs neu zu, dann hängt die transformierten Einträge unter einem neuen Schlüssel an. Eine Adapter-Ebenen-Kopie oder CopyObject-Verknüpfung würde ein Transkript erzeugen, das immer noch auf die alte Sitzungs-ID verweist, daher verwendet das SDK keine.

Subagent-Transkripte

Subagent-Transkripte werden unter subpath: "subagents/agent-<id>" gespiegelt. listSubagents({ sessionStore }) erfordert, dass der Adapter listSubkeys implementiert; getSubagentMessages({ sessionStore }) verwendet es, wenn verfügbar, fällt aber auf den direkten Subpath zurück, wenn er nicht definiert ist. Das Wiederaufnehmen ruft auch listSubkeys auf, um Subagent-Dateien wiederherzustellen; ohne es wird nur das Haupttranskript materialisiert.

Aufbewahrung

Das SDK löscht niemals von selbst aus Ihrem Store. Die Aufbewahrung ist die Verantwortung des Adapters: implementieren Sie TTLs, S3-Lebenszyklusrichtlinien oder geplante Bereinigung gemäß Ihren Compliance-Anforderungen. Lokale Transkripte unter CLAUDE_CONFIG_DIR werden unabhängig durch die cleanupPeriodDays-Einstellung bereinigt.

Unterstützt auf

Die folgenden SDK-Funktionen akzeptieren eine sessionStore-Option und arbeiten gegen den Store statt gegen das lokale Dateisystem, wenn es bereitgestellt wird: