SpyBara
Go Premium

agent-sdk/sessions.md 2026-09-27 23:59 UTC to 2026-09-28 22:01 UTC

This page contains 1 addition and 1 deletion.

2026
Wed 9 22:58 Mon 28 22:59

セッションの操作

セッションがエージェント会話履歴をどのように保持するか、および以前の実行に戻るために continue、resume、fork をいつ使用するかについて説明します。

セッションは、エージェントが動作している間に SDK が蓄積する会話履歴です。プロンプト、エージェントが行ったすべてのツール呼び出し、すべてのツール結果、およびすべてのレスポンスが含まれます。SDK はそれを自動的にディスクに書き込むため、後で戻ることができます。

セッションに戻るということは、エージェントが以前のコンテキストを完全に持っているということです。既に読んだファイル、既に実行した分析、既に行った決定があります。フォローアップの質問をしたり、中断から回復したり、別のアプローチを試すために分岐したりできます。

このガイドでは、アプリケーションに適切なアプローチを選択する方法、セッションを自動的に追跡する SDK インターフェース、セッション ID をキャプチャして resume と fork を手動で使用する方法、およびホスト間でセッションを再開する際に知っておくべきことについて説明します。

アプローチを選択する

必要なセッション処理の量は、アプリケーションの形状によって異なります。セッション管理は、コンテキストを共有する必要がある複数のプロンプトを送信する場合に関係します。単一の query() 呼び出し内では、エージェントは既に必要なだけのターンを実行し、権限プロンプトと AskUserQuestion はループ内で処理されます(呼び出しを終了しません)。

構築しているもの 使用するもの
ワンショットタスク:単一プロンプト、フォローアップなし 追加は不要です。1 つの query() 呼び出しで処理されます。
1 つのプロセス内のマルチターンチャット ClaudeSDKClient(Python)または continue: true(TypeScript)。SDK はセッションを自動的に追跡し、ID 処理は不要です。
プロセス再起動後に中断したところから再開 continue_conversation=True(Python)/ continue: true(TypeScript)。ディレクトリ内の最新セッションを再開し、ID は不要です。
特定の過去のセッション(最新ではない)を再開 セッション ID をキャプチャして resume に渡します。
元のセッションを失わずに別のアプローチを試す セッションをフォークします。
ステートレスタスク、ディスクに何も書き込みたくない persistSession: false(TypeScript のみ)を設定します。セッションは呼び出しの期間中メモリにのみ存在します。Python では、代わりに env オプションで CLAUDE_CODE_SKIP_PROMPT_HISTORY を設定してトランスクリプト書き込みを抑制します。

Continue、resume、および fork

Continue、resume、および fork は query() に設定するオプションフィールドです(Python では ClaudeAgentOptions、TypeScript では Options)。

Continue と resume はどちらも既存のセッションを取得して追加します。違いはそのセッションを見つける方法です:

  • Continue は現在のディレクトリ内の最新セッションを見つけます。何も追跡する必要はありません。アプリケーションが一度に 1 つの会話を実行する場合に適しています。
  • Resume は特定のセッション ID を取得します。ID を追跡します。複数のセッション(たとえば、マルチユーザーアプリケーションのユーザーごとに 1 つ)がある場合、または最新ではないセッションに戻りたい場合に必要です。

Fork は異なります。元の履歴のコピーで開始する新しいセッションを作成します。元のセッションは変更されません。別の方向を試しながら戻るオプションを保持するために fork を使用します。

自動セッション管理

両方の SDK は、呼び出し間でセッション状態を追跡するインターフェースを提供するため、ID を手動で渡す必要はありません。単一プロセス内のマルチターン会話にこれらを使用します。

Python:`ClaudeSDKClient`

ClaudeSDKClient はセッション ID を内部的に処理します。client.query() への各呼び出しは自動的に同じセッションを続行します。client.receive_response() を呼び出して、現在のクエリのメッセージを反復処理します。クライアントを非同期コンテキストマネージャーとして使用すると、接続のセットアップとティアダウンが自動的に処理されます。または、connect() と disconnect() を手動で呼び出すこともできます。

この例は、同じ client に対して 2 つのクエリを実行します。最初はエージェントにモジュールを分析するよう求め、2 番目はそのモジュールをリファクタリングするよう求めます。両方の呼び出しが同じクライアントインスタンスを通過するため、2 番目のクエリは明示的な resume またはセッション ID なしで最初のクエリから完全なコンテキストを持ちます:

import asyncio
from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    AssistantMessage,
    ResultMessage,
    TextBlock,
)


def print_response(message):
    """Print only the human-readable parts of a message."""
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, TextBlock):
                print(block.text)
    elif isinstance(message, ResultMessage):
        cost = (
            f"${message.total_cost_usd:.4f}"
            if message.total_cost_usd is not None
            else "N/A"
        )
        print(f"[done: {message.subtype}, cost: {cost}]")


async def main():
    options = ClaudeAgentOptions(
        allowed_tools=["Read", "Edit", "Glob", "Grep"],
    )

    async with ClaudeSDKClient(options=options) as client:
        # First query: client captures the session ID internally
        await client.query("Analyze the auth module")
        async for message in client.receive_response():
            print_response(message)

        # Second query: automatically continues the same session
        await client.query("Now refactor it to use JWT")
        async for message in client.receive_response():
            print_response(message)


asyncio.run(main())

各クエリは、エージェントのテキスト応答の後に結果メッセージからのステータス行(例:[done: success, cost: $0.0042])を出力します。

Python SDK リファレンスで ClaudeSDKClient とスタンドアロン query() 関数のどちらを使用するかについての詳細を参照してください。

TypeScript:`continue: true`

TypeScript SDK には、Python の ClaudeSDKClient のようなセッション保持クライアントオブジェクトがありません。代わりに、後続の各 query() 呼び出しで continue: true を渡すと、SDK は現在のディレクトリ内の最新セッションを見つけて再開します。ID 追跡は不要です。

この例は 2 つの別々の query() 呼び出しを行います。最初は新しいセッションを作成し、2 番目は continue: true を設定します。これは SDK にディスク上の最新セッションを見つけて再開するよう指示します。エージェントは最初の呼び出しから完全なコンテキストを持ちます:

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

// First query: creates a new session
try {
  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);
    }
  }
} catch (error) {
  // A single-shot query() throws after yielding an error result,
  // so the follow-up query below still runs.
  console.error(`Session ended with an error: ${error}`);
}

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

`query()` でセッションオプションを使用する

セッション ID をキャプチャする

Resume と fork にはセッション ID が必要です。結果メッセージ(Python では ResultMessage、TypeScript では SDKResultMessage)の session_id フィールドから読み取ります。これは成功またはエラーに関係なく、すべての結果に存在します。TypeScript では、ID は初期 SystemMessage の直接フィールドとしても利用可能です。Python では、SystemMessage.data 内にネストされています。

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
session_id = None

try:
async for message in query(
prompt="Analyze the auth module and suggest improvements",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep"],
),
):
if isinstance(message, ResultMessage):
session_id = message.session_id
if message.subtype == "success":
print(message.result)
except Exception as error:
# A single-shot query() raises after yielding an error result. If the
# failure was an error result, the loop above already captured session_id;
# connection or process failures yield no result message, so session_id stays None.
print(f"Session ended with an error: {error}")

print(f"Session ID: {session_id}")
return session_id


session_id = asyncio.run(main())

クエリが完了すると、スクリプトはエージェントの応答と、Session ID: 5b3f2c1a-8d4e-4f6b-9a7c-2e1d0f9b8a6c のような行を出力します。次のセクションでは、この ID を resume に渡します。

ID で再開する

セッション ID を resume に渡して、その特定のセッションに戻ります。エージェントはセッションが終了した場所から完全なコンテキストで再開します。再開の一般的な理由:

  • 完了したタスクをフォローアップします。 エージェントは既に何かを分析しました。今、ファイルを再度読み込まずにその分析に基づいて行動してほしいです。
  • 制限から回復します。 最初の実行は error_max_turns または error_max_budget_usd で終了しました(結果を処理するを参照)。より高い制限で再開します。単一ショットの query() 呼び出しでは、SDK はそのエラー結果を生成した後に発生するため、再開する前にエラーをキャッチします。
  • プロセスを再起動します。 シャットダウン前に ID をキャプチャし、会話を復元したいです。

この例は、セッション ID をキャプチャするからのセッションをフォローアッププロンプトで再開します。再開しているため、エージェントは既に以前の分析をコンテキストに持っています:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

session_id = "..."  # The ID you captured in the previous example


async def main():
# Earlier session analyzed the code; now build on that analysis
async for message in query(
prompt="Now implement the refactoring you suggested",
options=ClaudeAgentOptions(
resume=session_id,
allowed_tools=["Read", "Edit", "Write", "Glob", "Grep"],
),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)


asyncio.run(main())

以前の分析に基づいて構築された応答が表示されるはずです。これにより、エージェントが以前のコンテキストを保持したままセッションを再開したことが確認されます。

マシン間またはサーバーレス環境でセッションを再開するには、SessionStore アダプターを使用して共有ストレージにトランスクリプトをミラーリングします。

フォークして代替案を探索する

フォークは、元の履歴のコピーで開始する新しいセッションを作成しますが、その時点から分岐します。フォークは独自のセッション ID を取得します。元の ID と履歴は変更されません。2 つの独立したセッションが終わり、それぞれ別々に再開できます。

この例は、セッション ID をキャプチャするに基づいています。session_id で認証モジュールを既に分析し、JWT に焦点を当てたスレッドを失わずに OAuth2 を探索したいです。最初のブロックはセッションをフォークし、フォークの ID(forked_id)をキャプチャします。2 番目のブロックは元の session_id を再開して、JWT パスを続行します。これで、2 つの別々の履歴を指す 2 つのセッション ID があります:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

session_id = "..."  # The ID you captured in the previous example


async def main():
# Fork: branch from session_id into a new session
forked_id = None
try:
async for message in query(
prompt="Instead of JWT, outline how OAuth2 would work for the auth module",
options=ClaudeAgentOptions(
resume=session_id,
fork_session=True,
max_turns=5,
),
):
if isinstance(message, ResultMessage):
forked_id = message.session_id  # The fork's ID, distinct from session_id
if message.subtype == "success":
print(message.result)
except Exception as error:
# A single-shot query() raises after yielding an error result. If the
# failure was an error result, forked_id was already captured by the
# loop above; connection or process failures yield no result message.
print(f"Session ended with an error: {error}")

print(f"Forked session: {forked_id}")

# Original session is untouched; resuming it continues the JWT thread
try:
async for message in query(
prompt="Continue with the JWT approach",
options=ClaudeAgentOptions(resume=session_id),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
except Exception as error:
# A single-shot query() raises after yielding an error result.
print(f"Session ended with an error: {error}")


asyncio.run(main())

forkedId が元のセッション ID と異なることが表示されるはずです。元のセッションを再開すると、JWT スレッドが続行されます。これにより、フォークが元の履歴を変更しなかったことが確認されます。

ホスト間で再開する

セッションファイルは、それを作成したマシンに対してローカルです。別のホスト(CI ワーカー、一時的なコンテナ、サーバーレス)でセッションを再開するには、適切なアプローチを選択してください:

  • セッションストアを渡します。 sessionStore / session_store アダプターを接続して、SDK がトランスクリプトを独自のバックエンドにミラーリングし、別のホストがそれらを再開できるようにします。ストア検索キーは作業ディレクトリから派生するため、元の実行の cwd と一致する cwd から再開してください。

  • セッションファイルを移動します。 最初の実行から ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl を保持し、resume を呼び出す前に新しいホスト上の ~/.claude/projects/ の下の任意のディレクトリ内に復元します。

    Claude Code は現在のプロジェクトディレクトリを超えて検索して ID を見つけます。正確な検索順序と重複コピーの処理方法については、セッションを再開するを参照してください。v2.1.223 より前では、検索は現在のプロジェクトディレクトリとその git worktrees にスコープされていました。古い CLI をバンドルする SDK バージョンは引き続きこのように動作します。

  • セッション再開に依存しないでください。 必要な結果(分析出力、決定、ファイル差分)をアプリケーション状態としてキャプチャし、新しいセッションのプロンプトに渡します。これは多くの場合、トランスクリプトファイルを周りに配送するよりも堅牢です。

両方の SDK は、ディスク上のセッションを列挙し、メッセージを読み取るための関数を公開します。TypeScript では listSessions() と getSessionMessages()、Python では list_sessions() と get_session_messages()。これらを使用して、カスタムセッションピッカー、クリーンアップロジック、またはトランスクリプトビューアーを構築します。

両方の SDK は、個別のセッションを検索および変更するための関数も公開します。Python では get_session_info()、rename_session()、および tag_session()。TypeScript では getSessionInfo()、renameSession()、および tagSession()。これらを使用して、セッションをタグで整理するか、人間が読める形のタイトルを付けます。