claude-agent-sdk : Work with sessions

0 阅读8分钟

Work with sessions 使用会话

翻译:code.claude.com/docs/en/age…

How sessions persist agent conversation history, and when to use continue, resume, and fork to return to a prior run.
会话如何保持智能体(agent)的对话历史,以及何时使用 continue(继续)、resume(恢复)和 fork(分支)来回到之前的运行状态。

A session is the conversation history the SDK accumulates while your agent works. It contains your prompt, every tool call the agent made, every tool result, and every response. The SDK writes it to disk automatically so you can return to it later.

会话(Session)是指 SDK 在智能体工作期间积累的对话历史。它包含了你的提示词(prompt)、智能体发起的每一次工具调用、每一次工具执行结果以及每一次响应。SDK 会自动将其写入磁盘,以便你后续可以随时返回查看。

Returning to a session means the agent has full context from before: files it already read, analysis it already performed, decisions it already made. You can ask a follow-up question, recover from an interruption, or branch off to try a different approach.

回到之前的会话意味着智能体拥从前完整的上下文信息,包括:它已经读取过的文件、已经完成的分析,以及已经做出的决策。你可以接着进行追问、从中断处恢复,或者开辟新的分支尝试不同的方案。

image.png

This guide covers how to pick the right approach for your app, the SDK interfaces that track sessions automatically, how to capture session IDs and use resume and fork manually, and what to know about resuming sessions across hosts.
本指南旨在介绍如何为你的应用程序选择最合适的方法、SDK 中自动跟踪会话的接口、如何手动获取会话 ID 并使用‘恢复(resume)’与‘分支(fork)’功能,以及在跨主机恢复会话时需要注意的事项。

Choose an approach 选择方案

How much session handling you need depends on your application’s shape. Session management comes into play when you send multiple prompts that should share context. Within a single query() call, the agent already takes as many turns as it needs, and permission prompts and AskUserQuestion are handled in-loop (they don’t end the call).

你需要的会话处理程度,取决于你的应用程序形态。当你发送多个需要共享上下文的提示词(prompt)时,会话管理就派上用场了。在单次 query() 调用中,智能体会自动根据需要进行多轮对话,且权限确认提示及 AskUserQuestion(询问用户问题)都会在循环内完成处理(它们不会导致单次调用结束)。

没问题,已为你调整为“英文在前,中文在后(换行显示)”的格式:

What you’re building
你正在构建什么
What to use
推荐方案
One-shot task: single prompt, no follow-up
一次性任务:单次提示词,无后续跟进
Nothing extra. One query() call handles it.
无需额外配置,单次 query() 调用即可。
Multi-turn chat in one process
单进程内的多轮对话
Use ClaudeSDKClient (Python) or continue: true (TypeScript). The SDK tracks the session for you with no ID handling.
使用 ClaudeSDKClient (Python) 或 continue: true (TypeScript)。SDK 会自动跟踪会话,无需处理 ID。
Pick up where you left off after a process restart
进程重启后从中断处继续
Use continue_conversation=True (Python) / continue: true (TypeScript). Resumes the most recent session in the directory, no ID needed.
使用 continue_conversation=True (Python) / continue: true (TypeScript)。恢复目录中最近的会话,无需 ID。
Resume a specific past session (not the most recent)
恢复特定的历史会话(非最近一次)
Capture the session ID and pass it to resume.
获取会话 ID 并将其传递给 resume
Try an alternative approach without losing the original
尝试替代方案且不丢失原会话
Fork the session.
对会话进行 fork(分支)。
Stateless task, don’t want anything written to disk (TypeScript only)
无状态任务,不希望写入磁盘(仅限 TypeScript)
Set persistSession: false. The session exists only in memory for the duration of the call. Python always persists to disk.
设置 persistSession: false。会话仅在调用期间存在于内存中。Python 版本始终会持久化到磁盘。

Continue(继续)、Resume(恢复)与 Fork(分支)

Continue, resume, and fork are option fields you set on query() (ClaudeAgentOptions in Python, Options in TypeScript).

Continue、Resume 和 Fork 是你在调用 query() 时可设置的选项字段(在 Python 中对应 ClaudeAgentOptions,在 TypeScript 中对应 Options)。

Continue and resume both pick up an existing session and add to it. The difference is how they find that session:
Continueresume 都是拾取现有会话并向其添加内容。它们的区别在于如何找到该会话:

  • Continue finds the most recent session in the current directory. You don't track anything. Works well when your app runs one conversation at a time.
  • Continue:查找当前目录中最近的会话。你无需跟踪任何内容。适用于应用程序一次只运行一个对话的情况。
  • Resume takes a specific session ID. You track the ID. Required when you have multiple sessions (for example, one per user in a multi-user app) or want to return to one that isn't the most recent.
  • Resume:需要一个特定的会话 ID。你需要跟踪该 ID。当你拥有多个会话(例如,多用户应用程序中每个用户一个会话)或者想要返回到非最近的会话时,就需要使用此功能。

Fork is different: it creates a new session that starts with a copy of the original's history. The original stays unchanged. Use fork to try a different direction while keeping the option to go back.

Fork 则不同:它创建一个新的会话,并以原始会话的历史记录作为副本。原始会话保持不变。使用 fork 可以尝试不同的方向,同时保留返回原点的选项。

Automatic session management 自动会话管理

Both SDKs offer an interface that tracks session state for you across calls, so you don't pass IDs around manually. Use these for multi-turn conversations within a single process.

这两个 SDK(Python 和 TypeScript)都提供了一个接口,可以自动为你追踪跨调用的会话状态,因此你无需手动传递 ID。对于同一进程内的多轮对话,请直接使用这些接口。

TypeScript: continue: true

The stable TypeScript SDK (the query() function used throughout these docs, sometimes called V1) doesn’t have a session-holding client object like Python’s ClaudeSDKClient. Instead, pass continue: true on each subsequent query() call and the SDK picks up the most recent session in the current directory. No ID tracking required.

稳定的 TypeScript SDK(即本指南中通用的 query() 函数,有时也称为 V1 版本)不像 Python 的 ClaudeSDKClient 那样拥有持有会话状态的客户端对象。相反,你需要在后续的每次 query() 调用中传入 continue: true,SDK 就会自动拾取当前目录中最近一次的会话。无需进行任何 ID 追踪

This example makes two separate query() calls. The first creates a fresh session; the second sets continue: true, which tells the SDK to find and resume the most recent session on disk. The agent has full context from the first call:
以下示例进行了两次独立的 query() 调用。第一次调用会创建一个全新的会话;第二次调用设置了 continue: true,这会告知 SDK 在磁盘上查找并恢复最近一次的会话。因此,Agent 会完整继承第一次调用时的上下文

import { query } from "@anthropic-ai/claude-agent-sdk";

// First query: creates a new session
for await (const message of query({
  prompt: "Analyze the auth module",
  options: { allowedTools: ["Read", "Glob", "Grep"] }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

// Second query: continue: true resumes the most recent session
for await (const message of query({
  prompt: "Now refactor it to use JWT",
  options: {
    continue: true,
    allowedTools: ["Read", "Edit", "Write", "Glob", "Grep"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Use session options with query()query() 中使用会话选项

Capture the session ID 获取会话 ID (Session ID)

Resume and fork require a session ID. Read it from the session_id field on the result message (ResultMessage in Python, SDKResultMessage in TypeScript), which is present on every result regardless of success or error. In TypeScript the ID is also available earlier as a direct field on the init SystemMessage; in Python it’s nested inside SystemMessage.data.
Resume(恢复)和 Fork(分支)操作都需要用到会话 ID。你可以从结果消息的 session_id 字段中获取该 ID(在 Python 中为 ResultMessage,在 TypeScript 中为 SDKResultMessage)。无论查询是成功还是失败,每个结果中都会包含此字段。 在 TypeScript 中,该 ID 也可以在初始化时作为 SystemMessage 的直接字段及早获取;而在 Python 中,它则嵌套在 SystemMessage.data 内部。

import { query } from "@anthropic-ai/claude-agent-sdk";

let sessionId: string | undefined;

for await (const message of query({
  prompt: "Analyze the auth module and suggest improvements",
  options: { allowedTools: ["Read", "Glob", "Grep"] }
})) {
  if (message.type === "result") {
    sessionId = message.session_id;
    if (message.subtype === "success") {
      console.log(message.result);
    }
  }
}

console.log(`Session ID: ${sessionId}`);

Resume by ID 通过 ID 恢复会话

Pass a session ID to resume to return to that specific session. The agent picks up with full context from wherever the session left off. Common reasons to resume:

将会话 ID 传给 resume 参数,即可返回到特定的会话。Agent 会从该会话中断的地方继续,并保留完整的上下文。以下是恢复会话的常见原因:

  • Follow up on a completed task. The agent already analyzed something; now you want it to act on that analysis without re-reading files.
  • 跟进已完成的任务:Agent 已经完成了一项分析任务,现在你希望它基于该分析采取行动,而无需重新读取文件。
  • Recover from a limit. The first run ended with error_max_turns or error_max_budget_usd (see Handle the result); resume with a higher limit.
  • 从限额错误中恢复:如果第一次运行因 error_max_turns(最大轮次限制)或 error_max_budget_usd(最大预算限制)而中断(详见“处理结果”部分),你可以通过提高限额来恢复会话。
  • Restart your process. You captured the ID before shutdown and want to restore the conversation.
  • 重启你的进程:你在程序关闭前捕获了会话 ID,并希望在之后恢复之前的对话。

This example resumes the session fro m Capture the session ID with a follow-up prompt. Because you’re resuming, the agent already has the prior analysis in context:
以下示例通过传入上一节“获取会话 ID”中得到的 ID,配合后续的提示词(prompt)来恢复会话。由于你是在进行“恢复”操作,Agent 已经掌握了之前的分析内容:

// Earlier session analyzed the code; now build on that analysis
for await (const message of query({
  prompt: "Now implement the refactoring you suggested",
  options: {
    resume: sessionId,
    allowedTools: ["Read", "Edit", "Write", "Glob", "Grep"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

image.png To resume sessions across machines or in serverless environments, mirror transcripts to shared storage with a SessionStore adapter.

若要在不同机器之间或无服务器(Serverless)环境中恢复会话,请使用 SessionStore 适配器将对话记录(transcripts)同步至共享存储中。

Fork to explore alternatives 通过分支 (Fork) 探索替代方案

Forking creates a new session that starts with a copy of the original's history but diverges from that point. The fork gets its own session ID; the original's ID and history stay unchanged. You end up with two independent sessions you can resume separately.

“分支”(Fork)操作会创建一个新会话,该会话以原会话的历史记录副本为起点,并从该点开始走向不同的方向。分支后的会话拥有独立的会话 ID;原始会话的 ID 和历史记录保持不变。最终,你将获得两个互不干扰的独立会话,你可以分别对它们进行后续的恢复(Resume)操作。

image.png

This example builds on Capture the session ID: you’ve already analyzed an auth module in session_id and want to explore OAuth2 without losing the JWT-focused thread. The first block forks the session and captures the fork's ID (forked_id); the second block resumes the original session_id to continue down the JWT path. You now have two session IDs pointing at two separate histories:
此示例建立在获取会话 ID(链接地址)的基础之上:假设你已经在 session_id 中分析过一个身份验证模块,现在你既想探索 OAuth2,又不想中断原本关于 JWT 的讨论思路。第一个代码块用于分支会话并捕获新分支的 ID (forked_id);第二个代码块则恢复原始的 session_id,以继续沿着 JWT 的路径进行对话。现在,你拥有了两个分别指向两条独立对话历史的会话 ID:

// Fork: branch from sessionId into a new session
let forkedId: string | undefined;

for await (const message of query({
  prompt: "Instead of JWT, implement OAuth2 for the auth module",
  options: {
    resume: sessionId,
    forkSession: true
  }
})) {
  if (message.type === "system" && message.subtype === "init") {
    forkedId = message.session_id; // The fork's ID, distinct from sessionId
  }
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

console.log(`Forked session: ${forkedId}`);

// Original session is untouched; resuming it continues the JWT thread
for await (const message of query({
  prompt: "Continue with the JWT approach",
  options: { resume: sessionId }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Resume across hosts 跨主机恢复会话

Session files are local to the machine that created them. To resume a session on a different host (CI workers, ephemeral containers, serverless), you have two options:

会话文件在创建它的机器上是本地存储的。若要在不同的主机(如 CI 工作节点、临时容器、Serverless 环境)上恢复会话,你有两种选择:

  • Move the session file. Persist ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl from the first run and restore it to the same path on the new host before calling resume. The cwd must match.
  • 迁移会话文件:从第一次运行中持久化存储 ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl 文件,并在调用 resume 之前将其恢复到新主机上的相同路径。注意:cwd(当前工作目录)必须保持一致。
  • Don't rely on session resume. Capture the results you need (analysis output, decisions, file diffs) as application state and pass them into a fresh session's prompt. This is often more robust than shipping transcript files around.
  • 不要依赖会话恢复:将你所需的关键结果(分析输出、决策过程、文件差异)捕获为应用程序状态,并在开启新会话时将其作为提示词(prompt)传入。这种方式通常比在不同环境间传输对话记录文件更为稳健。

Both SDKs expose functions for enumerating sessions on disk and reading their messages: listSessions() and getSessionMessages() in TypeScript, list_sessions() and get_session_messages() in Python. Use them to build custom session pickers, cleanup logic, or transcript viewers.

两个 SDK 都提供了列举磁盘会话及读取会话消息的函数:TypeScript 中的 listSessions()getSessionMessages(),以及 Python 中的 list_sessions()get_session_messages()。你可以利用这些函数构建自定义的会话选择器、清理逻辑或对话记录查看器。

Both SDKs also expose functions for looking up and mutating individual sessions: get_session_info(), rename_session(), and tag_session() in Python, and getSessionInfo(), renameSession(), and tagSession() in TypeScript. Use them to organize sessions by tag or give them human-readable titles.

此外,两个 SDK 还提供了用于查询和修改单个会话的函数:Python 中的 get_session_info()rename_session()tag_session(),以及 TypeScript 中的 getSessionInfo()renameSession()tagSession()。你可以使用它们通过标签来组织会话,或为会话设置易于阅读的标题。