Skip to main content

Persist Sessions ไปยัง External Storage

Mirror session transcripts ไปยัง S3, Redis หรือ backend ของคุณเองเพื่อให้ host ใดก็ตามสามารถ resume ได้

โดยค่าเริ่มต้น SDK จะเขียน session transcripts เป็นไฟล์ JSONL ภายใต้ ~/.claude/projects/ บน local filesystem adapter SessionStore ช่วยให้คุณ mirror transcripts เหล่านั้นไปยัง backend ของคุณเอง เช่น S3, Redis หรือ database เพื่อให้ session ที่สร้างบน host หนึ่งสามารถ resume บน host อื่นได้

เหตุผลทั่วไปในการใช้ session store:

  • Multi-host deployments. Serverless functions, autoscaled workers และ CI runners ไม่แชร์ filesystem shared store ช่วยให้ replica ใดก็ตามสามารถ resume session ใดก็ตามได้
  • Durability. Local containers เป็น ephemeral store ที่ backed ด้วย S3 หรือ database รอดจากการ restart และ redeploy
  • Compliance และ audit. เก็บ transcripts ใน storage ที่คุณ govern อยู่แล้ว พร้อม retention rules, encryption และ access controls ของคุณเอง

Interface SessionStore

SessionStore คือ object ที่มีสองวิธีที่จำเป็น append และ load และสามวิธีที่เป็น optional SDK จะเรียก append เพื่อเขียน transcript entries ระหว่าง query และ load เพื่ออ่านกลับมาสำหรับ resume

TypeScript
// Export จาก @anthropic-ai/claude-agent-sdk เป็น
// 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[]>;
};
Python
# Export จาก claude_agent_sdk เป็น
# SessionStore, SessionKey, SessionStoreEntry.

class SessionKey(TypedDict):
project_key: str
session_id: str
subpath: NotRequired[str]

class SessionStore(Protocol):
# Required
async def append(
self, key: SessionKey, entries: list[SessionStoreEntry]
) -> None: ...
async def load(self, key: SessionKey) -> list[SessionStoreEntry] | None: ...

# Optional — omit หรือ raise NotImplementedError
async def list_sessions(
self, project_key: str
) -> list[SessionStoreListEntry]: ...
async def delete(self, key: SessionKey) -> None: ...
async def list_subkeys(self, key: SessionListSubkeysKey) -> list[str]: ...

SessionKey ระบุ transcript หนึ่งอัน projectKey เป็น stable, filesystem-safe encoding ของ working directory, sessionId เป็น session UUID และ subpath จะถูกตั้งเมื่อ entry เป็นของ subagent transcript หรือ sidecar file แทน main conversation

MethodRequiredเรียกเมื่อ
appendYesหลังจากแต่ละ batch ของ transcript entries ถูกเขียน locally
loadYesครั้งเดียวก่อน subprocess spawn เมื่อตั้ง resume
listSessionsNoโดย listSessions({ sessionStore }) และโดย query()/startup() พร้อม continue: true
deleteNoโดย deleteSession({ sessionStore })
listSubkeysNoระหว่าง resume เพื่อค้นพบ subagent transcripts

Quick Start

SDK มาพร้อม InMemorySessionStore สำหรับการพัฒนาและทดสอบ ตัวอย่างด้านล่างรัน query พร้อม store ที่แนบ, capture session ID จาก result message จากนั้น resume จาก store ใน query() call ที่สอง:

TypeScript
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 จาก store agent มี context เต็มจาก 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);
}
}
Python
import asyncio
from claude_agent_sdk import (
ClaudeAgentOptions,
InMemorySessionStore,
ResultMessage,
query,
)

store = InMemorySessionStore()


async def main():
session_id = None
async for message in query(
prompt="List the Python files under src/",
options=ClaudeAgentOptions(session_store=store),
):
if isinstance(message, ResultMessage):
session_id = message.session_id

# Resume จาก store agent มี context เต็มจาก call แรก
async for message in query(
prompt="Summarize what those files do",
options=ClaudeAgentOptions(session_store=store, resume=session_id),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)


asyncio.run(main())

เขียน Adapter ของคุณเอง

Implement append และ load กับ backend ของคุณ เพิ่ม listSessions, delete และ listSubkeys หากต้องการให้ listSessions(), deleteSession() และ subagent resume ทำงานกับ store

Entries ที่ส่งไปยัง append มี type เป็น SessionStoreEntry (object { type: string; ... }) ให้ treat เป็น opaque JSON-safe values: persist ตามลำดับและส่งคืนจาก load ในลำดับเดิม

Reference Implementations

TypeScript SDK repository มี reference adapters ที่รันได้สำหรับ S3, Redis และ Postgres ภายใต้ examples/session-stores/

AdapterBackend clientStorage model
S3SessionStore@aws-sdk/client-s3ไฟล์ JSONL part หนึ่งต่อ append(); load() list, sort และ concatenate
RedisSessionStoreioredisRPUSH/LRANGE list ต่อ transcript บวก sorted-set session index
PostgresSessionStorepgแถวต่อ entry ใน jsonb table เรียงตาม BIGSERIAL

Adapter แต่ละตัวรับ pre-configured client instance ดังนั้นคุณควบคุม credentials, TLS, region และ pooling ตัวอย่างกับ S3:

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

// ภายหลัง อาจบน host อื่น:
for await (const message of query({
prompt: "Continue where we left off",
options: { sessionStore: store, resume: "previous-session-id" },
})) {
// ...
}

Validate Adapter ของคุณ

ทั้งสอง SDKs มาพร้อม conformance suite ที่ assert contract พฤติกรรมที่ append, load และ optional methods ต้องปฏิบัติตาม

ใน TypeScript ให้ copy shared/conformance.ts จาก example directory เข้า test suite ของคุณ ใน Python, suite มาพร้อมใน package:

Python
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)

หมายเหตุพฤติกรรม

Dual-write Architecture

Store เป็น mirror ไม่ใช่ตัวแทน Claude Code subprocess เขียนไปยัง local disk ก่อนเสมอ SDK จะ forward แต่ละ batch ไปยัง append() หากต้องการให้ local copy เป็น ephemeral ให้ชี้ CLAUDE_CONFIG_DIR ไปยัง temp directory ใน options.env

Mirror Writes เป็น Best-effort

หาก append() ปฏิเสธหรือหมดเวลา error จะถูก log, message { type: "system", subtype: "mirror_error" } จะถูก emit เข้า iterator และ query จะดำเนินต่อ local transcript ยังคง durable บน disk ดังนั้น store outage จะไม่ขัดแย้ง agent หรือสูญเสียข้อมูล locally

getSessionMessages ส่งคืน Post-compaction Chain

getSessionMessages({ sessionStore }) ส่งคืน linked message chain ที่ agent จะเห็นเมื่อ resume หลังจาก auto-compaction turns ก่อนหน้าจะถูกแทนที่ด้วย summary ดังนั้น session ที่ store เก็บ 503 raw entries อาจส่งคืน 18 messages จาก getSessionMessages

forkSession ไม่ใช่ Byte Copy

forkSession({ sessionStore }) อ่าน source entries, เขียนทับทุก field sessionId และ remap message UUIDs จากนั้น append transformed entries ภายใต้ key ใหม่

Subagent Transcripts

Subagent transcripts ถูก mirror ภายใต้ subpath: "subagents/agent-<id>" listSubagents({ sessionStore }) ต้องการ adapter เพื่อ implement listSubkeys

Retention

SDK ไม่ลบจาก store ของคุณเอง Retention เป็นความรับผิดชอบของ adapter: implement TTLs, S3 lifecycle policies หรือ scheduled cleanup ตามความต้องการ compliance ของคุณ

รองรับโดย

SDK functions ต่อไปนี้รับ option sessionStore และทำงานกับ store แทน local filesystem เมื่อ provide:

Resources ที่เกี่ยวข้อง