---
title: セッションスレッド
url: https://platform.claude.com/docs/ja/managed-agents/session-threads
description: マルチエージェントセッションのスレッドを一覧表示、中断、アーカイブし、そのイベントを読み取り、スレッド全体でツール権限を処理します。
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

[マルチエージェントセッション](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration)では、各エージェントがそれぞれ独自の「**session thread**」（セッションスレッド）で作業します。このページでは、スレッドの一覧表示、中断、アーカイブの方法、スレッドが送信するイベント、およびスレッド全体でツール権限がどのように機能するかについて説明します。[ワークフロー実行](https://platform.claude.com/docs/ja/managed-agents/workflow-runs)もセッションスレッドを作成します。

## プライマリスレッドとセッションスレッド

「**session-level event stream**」（セッションレベルのイベントストリーム）（`/v1/sessions/{session_id}/events/stream`）は「**primary thread**」（プライマリスレッド）とみなされ、すべてのスレッドにわたるすべてのアクティビティの要約ビューを含みます。[サブエージェント](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#delegate-to-subagents)の完全なアクティビティは表示されませんが、その作業の開始と終了、およびツール権限リクエストなどのブロッキングイベントは表示されます。

**セッションスレッド**は、特定のエージェントのアクティビティを詳しく調べるための場所です。

セッションの `status` (csharp, go: `Status`) はすべてのエージェントアクティビティを集約したものです。少なくとも1つのスレッドが `running` であれば、セッション全体のステータスも `running` になります。実行中の[ワークフロー実行](https://platform.claude.com/docs/ja/managed-agents/workflow-runs)も、そのスレッドがいずれも作業していない間であっても、セッションを `running` に保つことがあります。作業中のスレッドがなく、いずれかのスレッドがクライアントを待機している場合、セッションは `idle` になります。[作業が完了したタイミングを知る](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#know-when-the-work-is-done)を参照してください。

[セッション予算](https://platform.claude.com/docs/ja/managed-agents/budgets)は、セッションのすべてのスレッドで共有される単一の上限です。上限に達すると、スレッドはそれぞれ独立して一時停止し、各スレッドのコストはそのスレッド自身が使用したモデルの価格で計算されます。

<Note>
  セッションは一度に最大25個の子スレッドを持つことができます。アイドル状態のスレッドはアーカイブするまでカウントされ、プライマリスレッドはカウントされません。プライマリスレッドのエージェントは単一のサブエージェントの複数のコピーを呼び出すことができ、1つの `agent` に関連付けられた複数のスレッドを作成します。[アドバイザー](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#give-the-session-an-advisor)の相談スレッドはこの制限の対象外です。[ワークフロー実行](https://platform.claude.com/docs/ja/managed-agents/workflow-runs)のスレッドも同様です。
</Note>

## スレッドを一覧表示する

セッションに関連付けられたすべてのスレッドを次のように一覧表示します。

<CodeGroup>
  ```bash cURL
  curl -fsS "https://api.anthropic.com/v1/sessions/$SESSION_ID/threads" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01"
  ```

  ```bash CLI
  ant beta:sessions:threads list --session-id "$SESSION_ID"
  ```

  ```python Python
  for thread in client.beta.sessions.threads.list(session.id):
      agent = thread.agent
      label = agent.type if agent.type == "advisor" else agent.name
      print(f"[{label}] {thread.status}")
  ```

  ```typescript TypeScript
  for await (const thread of client.beta.sessions.threads.list(session.id)) {
    const label = thread.agent.type === "advisor" ? thread.agent.type : thread.agent.name;
    console.log(`[${label}] ${thread.status}`);
  }
  ```

  ```csharp C#
  await foreach (var sessionThread in (await client.Beta.Sessions.Threads.List(session.ID)).Paginate())
  {
      var label = sessionThread.Agent.Name ?? sessionThread.Agent.Json.GetProperty("type").GetString();
      Console.WriteLine($"[{label}] {sessionThread.Status.Raw()}");
  }
  ```

  ```go Go
  threads := client.Beta.Sessions.Threads.ListAutoPaging(ctx, session.ID, anthropic.BetaSessionThreadListParams{})
  for threads.Next() {
  	thread := threads.Current()
  	label := cmp.Or(thread.Agent.Name, thread.Agent.Type)
  	fmt.Printf("[%s] %s\n", label, thread.Status)
  }
  if err := threads.Err(); err != nil {
  	panic(err)
  }
  ```

  ```java Java
  for (var thread : client.beta().sessions().threads().list(session.id()).autoPager()) {
      var agent = thread.agent();
      var label = agent.isAgent() ? agent.asAgent().name() : agent.type().asString();
      IO.println("[" + label + "] " + thread.status());
  }
  ```

  ```php PHP
  foreach ($client->beta->sessions->threads->list($session->id)->pagingEachItem() as $thread) {
      $label = $thread->agent instanceof \Anthropic\Beta\Agents\BetaManagedAgentsAdvisor
          ? $thread->agent->type
          : $thread->agent->name;
      echo "[{$label}] {$thread->status}\n";
  }
  ```

  ```ruby Ruby
  client.beta.sessions.threads.list(session.id).auto_paging_each do |thread|
    agent = thread.agent
    label = agent.type == :advisor ? agent.type : agent.name
    puts "[#{label}] #{thread.status}"
  end
  ```
</CodeGroup>

完全なリストにはプライマリスレッドが含まれます。プライマリスレッドの `parent_thread_id` (java: `parentThreadId`; php: `parentThreadID`; csharp, go: `ParentThreadID`) は `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) です。それ以外のすべてのスレッドは子スレッドです。`workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) は、[実行のスレッド](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#a-runs-threads)を除いて `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) です。

特定のステータスを持つスレッドのみを一覧表示するには、リクエストに `statuses[]` を追加し、複数のステータスを指定する場合は `?statuses[]=running&statuses[]=idle` のように繰り返します。省略すると、すべてのステータスのスレッドが返されます。

## セッションスレッドを中断する

特定のスレッドを停止するには、`session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) を指定して `user.interrupt` を送信します。`session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) を省略すると、プライマリを含むセッション内のアーカイブされていないすべてのスレッドが中断されます。動的ワークフローを含むセッションでは、中断によって実行が終了することはなく、実行のスレッドを指定した中断は何も停止しません。中断は他の子スレッドの保留中のツール呼び出しを閉じますが、実行スレッドの保留中のツール呼び出しを閉じるためにこれに頼らないでください。[実行が開いているセッションを中断する](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)を参照してください。

<CodeGroup>
  ```bash cURL
  curl -fsS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{"events": [{"type": "user.interrupt", "session_thread_id": "'"$THREAD_ID"'"}]}'
  ```

  ```bash CLI
  ant beta:sessions:events send \
    --session-id "$SESSION_ID" \
    --event "{type: user.interrupt, session_thread_id: $THREAD_ID}"
  ```

  ```python Python
  client.beta.sessions.events.send(
      session.id,
      events=[{"type": "user.interrupt", "session_thread_id": thread.id}],
  )
  ```

  ```typescript TypeScript
  await client.beta.sessions.events.send(session.id, {
    events: [{ type: "user.interrupt", session_thread_id: thread.id }]
  });
  ```

  ```csharp C#
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserInterruptEventParams
          {
              Type = BetaManagedAgentsUserInterruptEventParamsType.UserInterrupt,
              SessionThreadID = thread.ID,
          },
      ],
  });
  ```

  ```go Go
  if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  	Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  		OfUserInterrupt: &anthropic.BetaManagedAgentsUserInterruptEventParams{
  			Type:            anthropic.BetaManagedAgentsUserInterruptEventParamsTypeUserInterrupt,
  			SessionThreadID: anthropic.String(thread.ID),
  		},
  	}},
  }); err != nil {
  	panic(err)
  }
  ```

  ```java Java
  client.beta().sessions().events().send(
      session.id(),
      EventSendParams.builder()
          .addEvent(BetaManagedAgentsUserInterruptEventParams.builder()
              .type(BetaManagedAgentsUserInterruptEventParams.Type.USER_INTERRUPT)
              .sessionThreadId(thread.id())
              .build())
          .build());
  ```

  ```php PHP
  $client->beta->sessions->events->send(
      $session->id,
      events: [
          ['type' => 'user.interrupt', 'session_thread_id' => $thread->id],
      ],
  );
  ```

  ```ruby Ruby
  client.beta.sessions.events.send_(
    session.id,
    events: [{type: "user.interrupt", session_thread_id: thread.id}]
  )
  ```
</CodeGroup>

`requires_action` でブロックされているサブエージェントのスレッドに対しては、中断により保留中の各ツール呼び出しがエラーのツール結果（"Tool execution was interrupted before completion. Please retry."）で閉じられ、`stop_reason: end_turn` を伴う `session.thread_status_idle` が直接再送信されます。モデルはサンプリングされません。`end_turn` または `budget_reached` でアイドル状態の子スレッドに対しては、中断は何も行いません。終了したスレッドを指定した中断は400エラーを返します。中断された子スレッドは、ターン終了時に送信するレポートをプライマリスレッドのエージェントに送信しません。そのエージェントが子スレッドを待機している間は、`user.message` や別のスレッドのレポートなど、他の何かが届くまで次のターンを開始しません。

## セッションスレッドをアーカイブする

必要に応じて、作業が完了したセッションスレッドをアーカイブします。スレッドをアーカイブすると、25個の子スレッド制限の枠が解放されます。[ワークフロー実行](https://platform.claude.com/docs/ja/managed-agents/workflow-runs)のスレッドはサーバー自身がアーカイブします。それらをアーカイブする必要はなく、実行が開いている間はアーカイブできません。

<CodeGroup>
  ```bash cURL
  curl -fsS -X POST "https://api.anthropic.com/v1/sessions/$SESSION_ID/threads/$THREAD_ID/archive" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01"
  ```

  ```bash CLI
  ant beta:sessions:threads archive \
    --session-id "$SESSION_ID" \
    --thread-id "$THREAD_ID"
  ```

  ```python Python
  archived = client.beta.sessions.threads.archive(thread.id, session_id=session.id)
  print(archived.status, archived.archived_at)
  ```

  ```typescript TypeScript
  const archived = await client.beta.sessions.threads.archive(thread.id, {
    session_id: session.id
  });
  console.log(archived.status, archived.archived_at);
  ```

  ```csharp C#
  var archived = await client.Beta.Sessions.Threads.Archive(thread.ID, new() { SessionID = session.ID });
  Console.WriteLine($"{archived.Status} {archived.ArchivedAt}");
  ```

  ```go Go
  archived, err := client.Beta.Sessions.Threads.Archive(ctx, thread.ID, anthropic.BetaSessionThreadArchiveParams{
  	SessionID: session.ID,
  })
  if err != nil {
  	panic(err)
  }
  fmt.Println(archived.Status, archived.ArchivedAt)
  ```

  ```java Java
  var archived = client.beta().sessions().threads().archive(
      thread.id(),
      ThreadArchiveParams.builder()
          .sessionId(session.id())
          .build());
  IO.println(archived.status() + " " + archived.archivedAt().orElseThrow());
  ```

  ```php PHP
  $archived = $client->beta->sessions->threads->archive($thread->id, sessionID: $session->id);
  echo "{$archived->status} {$archived->archivedAt->format(DATE_ATOM)}\n";
  ```

  ```ruby Ruby
  archived = client.beta.sessions.threads.archive(thread.id, session_id: session.id)
  puts "#{archived.status} #{archived.archived_at}"
  ```
</CodeGroup>

アーカイブはスレッドが `idle` の場合にのみ成功します。`requires_action` で待機しているスレッドはアイドルとみなされ、直接アーカイブできます。実行中のスレッドのみ、先に中断する必要があります。

<CodeGroup>
  ```bash cURL
  # スレッドを中断してからアーカイブします
  curl -fsS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{"events": [{"type": "user.interrupt", "session_thread_id": "'"$THREAD_ID"'"}]}'

  curl -fsS -X POST "https://api.anthropic.com/v1/sessions/$SESSION_ID/threads/$THREAD_ID/archive" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01"
  ```

  ```bash CLI
  ant beta:sessions:events send \
    --session-id "$SESSION_ID" \
    --event "{type: user.interrupt, session_thread_id: $THREAD_ID}"

  ant beta:sessions:threads archive \
    --session-id "$SESSION_ID" \
    --thread-id "$THREAD_ID"
  ```

  ```python Python
  client.beta.sessions.events.send(
      session.id,
      events=[{"type": "user.interrupt", "session_thread_id": thread.id}],
  )
  archived = client.beta.sessions.threads.archive(thread.id, session_id=session.id)
  print(archived.status, archived.archived_at)
  ```

  ```typescript TypeScript
  await client.beta.sessions.events.send(session.id, {
    events: [{ type: "user.interrupt", session_thread_id: thread.id }]
  });
  const archived = await client.beta.sessions.threads.archive(thread.id, {
    session_id: session.id
  });
  console.log(archived.status, archived.archived_at);
  ```

  ```csharp C#
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserInterruptEventParams
          {
              Type = BetaManagedAgentsUserInterruptEventParamsType.UserInterrupt,
              SessionThreadID = thread.ID,
          },
      ],
  });
  archived = await client.Beta.Sessions.Threads.Archive(thread.ID, new() { SessionID = session.ID });
  Console.WriteLine($"{archived.Status} {archived.ArchivedAt}");
  ```

  ```go Go
  if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  	Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  		OfUserInterrupt: &anthropic.BetaManagedAgentsUserInterruptEventParams{
  			Type:            anthropic.BetaManagedAgentsUserInterruptEventParamsTypeUserInterrupt,
  			SessionThreadID: anthropic.String(thread.ID),
  		},
  	}},
  }); err != nil {
  	panic(err)
  }

  archived, err := client.Beta.Sessions.Threads.Archive(ctx, thread.ID, anthropic.BetaSessionThreadArchiveParams{
  	SessionID: session.ID,
  })
  if err != nil {
  	panic(err)
  }
  fmt.Println(archived.Status, archived.ArchivedAt)
  ```

  ```java Java
  client.beta().sessions().events().send(
      session.id(),
      EventSendParams.builder()
          .addEvent(BetaManagedAgentsUserInterruptEventParams.builder()
              .type(BetaManagedAgentsUserInterruptEventParams.Type.USER_INTERRUPT)
              .sessionThreadId(thread.id())
              .build())
          .build());

  archived = client.beta().sessions().threads().archive(
      thread.id(),
      ThreadArchiveParams.builder()
          .sessionId(session.id())
          .build());
  IO.println(archived.status() + " " + archived.archivedAt().orElseThrow());
  ```

  ```php PHP
  $client->beta->sessions->events->send(
      $session->id,
      events: [['type' => 'user.interrupt', 'session_thread_id' => $thread->id]],
  );
  $archived = $client->beta->sessions->threads->archive($thread->id, sessionID: $session->id);
  echo "{$archived->status} {$archived->archivedAt->format(DATE_ATOM)}\n";
  ```

  ```ruby Ruby
  client.beta.sessions.events.send_(
    session.id,
    events: [{type: "user.interrupt", session_thread_id: thread.id}]
  )
  archived = client.beta.sessions.threads.archive(thread.id, session_id: session.id)
  puts "#{archived.status} #{archived.archived_at}"
  ```
</CodeGroup>

## プライマリスレッドのイベント

これらのイベントは、`/v1/sessions/{session_id}/events/stream` のプライマリスレッド上でマルチエージェントのアクティビティを表示します。メッセージの方向を示すイベントは、そのイベントが表示されるストリームのスレッドを基準に命名されています。`agent.thread_message_received` は別のスレッドからこのスレッドにメッセージが届いたことを意味し、`agent.thread_message_sent` はこのスレッドがメッセージを送信したことを意味します。たとえば、プライマリスレッドのエージェントが委任したタスクは、子スレッド自身のストリームに `agent.thread_message_received` イベントとして届きます。

| タイプ                                | 説明                                                                                                                                                                                                                                                                                                    |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `session.thread_created`           | スレッドが作成されました。`session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) と `agent_name` (java, php: `agentName`; csharp, go: `AgentName`) を含みます。                                                                                                             |
| `session.thread_status_running`    | スレッドがアクティビティを開始しました。                                                                                                                                                                                                                                                                                  |
| `session.thread_status_idle`       | スレッドに関連付けられたエージェントが入力を待機しています。エージェントが停止した理由を示す `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) を含みます。                                                                                                                                                                               |
| `session.thread_status_terminated` | スレッドが終了し、それ以上の入力を受け付けません。たとえば、アーカイブされた場合や回復不能なエラーが発生した場合です。アドバイザースレッドも、その相談が終了すると終了します。                                                                                                                                                                                                               |
| `agent.thread_message_received`    | プライマリスレッド上で、サブエージェントがプライマリスレッドのエージェントにレポートまたは質問を送信しました。`from_session_thread_id` (java: `fromSessionThreadId`; php: `fromSessionThreadID`; csharp, go: `FromSessionThreadID`)、`from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`)、および `content` (csharp, go: `Content`) を含みます。 |
| `agent.thread_message_sent`        | プライマリスレッド上で、プライマリスレッドのエージェントがサブエージェントにタスクまたはフォローアップメッセージを送信しました。`to_session_thread_id` (java: `toSessionThreadId`; php: `toSessionThreadID`; csharp, go: `ToSessionThreadID`)、`to_agent_name` (java, php: `toAgentName`; csharp, go: `ToAgentName`)、および `content` (csharp, go: `Content`) を含みます。      |

アドバイザーの相談は、予約名 `anthropic.advisor` の下でこれらと同じスレッドイベントを発行します（スレッドのライフサイクルイベントでは `agent_name` (java, php: `agentName`; csharp, go: `AgentName`) として、アドバイスの配信では `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`) として）。一連の流れについては、[セッションにアドバイザーを与える](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#give-the-session-an-advisor)を参照してください。

[ワークフロー実行](https://platform.claude.com/docs/ja/managed-agents/workflow-runs)のスレッドは、プライマリストリーム上で次のように表示されます。

* **ライフサイクルイベント：** 各実行スレッドは、実行の `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) を伴う `session.thread_created` と、その `session.thread_status_running`、`session.thread_status_idle`、`session.thread_status_terminated` イベントを送信します。
* **メッセージイベント：** 実行スレッドのプロンプト（`agent.thread_message_received` イベント）は、そのスレッド自身のストリームにとどまります。
* **実行イベント：** `workflow_run.*` イベントもこのストリームに届きます。[実行イベント](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#run-events)を参照してください。
* **クライアントを待機するツール呼び出し：** クライアントを必要とする実行スレッドのツール呼び出しは、他の子スレッドと同様に、このストリームにクロスポストされます。[ツール権限とカスタムツール](https://platform.claude.com/docs/ja/managed-agents/session-threads#tool-permissions-and-custom-tools)を参照してください。

## セッションスレッドのイベント

重要なイベントはプライマリスレッドにプロキシされます。ただし、特定のエージェントの推論やツール呼び出しを調査したい場合もあるでしょう。その場合は、関連するセッションスレッドからイベントをストリーミングまたは一覧表示します。

各セッションスレッドは `/v1/sessions/{session_id}/threads/{thread_id}/stream` に独自のイベントストリームを持ち、セッションレベルのストリームと同じ `event_deltas[]` パラメータを受け付けるため、モデルが生成するサブエージェントのテキストをプレビューできます。接続は読み取っているスレッドのみをプレビューします。子スレッドのプレビューはセッションレベルのストリームには表示されないため、サブエージェントをリアルタイムで監視するには、そのスレッド自身のストリームを開いてください。プレビューのオプトイン、蓄積、照合については、[セッションスレッドのイベントをプレビューする](https://platform.claude.com/docs/ja/managed-agents/event-deltas#preview-session-thread-events)を参照してください。

ワークフロー実行では、サーバーはワークフロー、つまりプライマリスレッドのエージェントが作成するプログラムを実行します。実行の各スレッドでは、最初の `agent.thread_message_received` がワークフローが作成したプロンプトです。その `from_session_thread_id` (java: `fromSessionThreadId`; php: `fromSessionThreadID`; csharp, go: `FromSessionThreadID`) はプライマリスレッドのIDであり、APIはその `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`) を設定しません。APIはプロンプトのテキストを保証しないため、解析しないでください。プライマリスレッドのストリーム上にあるスレッドの `session.thread_status_terminated` イベントは、スレッドが完了したことを示します。スレッドがワークフローに返した結果を記録するイベントはありません。

スレッドのストリームは以前のイベントを再生しません。`session.thread_created` の直後は、実行のスレッドのイベントリストが空である場合があります。これは、サーバーがスレッドの最初のイベントをその後に書き込むためです。そのため、まずスレッドのストリームを開き、次にスレッドのイベントを一覧表示し、リストが返した `id` (csharp, go: `ID`) を持つストリーミングされたイベントはスキップしてください。

<Tabs>
  <Tab title="セッションスレッドのイベントをストリーミングする">
    <CodeGroup>
      ```bash cURL
      curl -fsSN "https://api.anthropic.com/v1/sessions/$SESSION_ID/threads/$THREAD_ID/stream?beta=true" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -H "anthropic-beta: managed-agents-2026-04-01"
      ```

      ```bash CLI
      ant beta:sessions:threads:events stream \
        --session-id "$SESSION_ID" \
        --thread-id "$THREAD_ID"
      ```

      ```python Python
      with client.beta.sessions.threads.events.stream(
          thread.id,
          session_id=session.id,
      ) as stream:
          for event in stream:
              match event.type:
                  case "agent.message":
                      for block in event.content:
                          if block.type == "text":
                              print(block.text, end="")
                  case "session.thread_status_idle":
                      break
      ```

      ```typescript TypeScript
      const stream = await client.beta.sessions.threads.events.stream(thread.id, {
        session_id: session.id
      });

      loop: for await (const event of stream) {
        switch (event.type) {
          case "agent.message":
            for (const block of event.content) {
              if (block.type === "text") {
                process.stdout.write(block.text);
              }
            }
            break;
          case "session.thread_status_idle":
            break loop;
        }
      }
      ```

      ```csharp C#
      await foreach (var evt in client.Beta.Sessions.Threads.Events.StreamStreaming(thread.ID, new() { SessionID = session.ID }))
      {
          if (evt.Value is BetaManagedAgentsAgentMessageEvent message)
          {
              foreach (var block in message.Content)
              {
                  if (block.Value is BetaManagedAgentsTextBlock textBlock)
                  {
                      Console.Write(textBlock.Text);
                  }
              }
          }
          else if (evt.Value is BetaManagedAgentsSessionThreadStatusIdleEvent)
          {
              break;
          }
      }
      ```

      ```go Go
      	stream := client.Beta.Sessions.Threads.Events.StreamEvents(ctx, thread.ID, anthropic.BetaSessionThreadEventStreamParams{
      		SessionID: session.ID,
      	})
      	defer stream.Close()

      loop:
      	for stream.Next() {
      		event := stream.Current()
      		switch event.Type {
      		case "agent.message":
      			for _, block := range event.AsAgentMessage().Content {
      				if block.Type == "text" {
      					fmt.Print(block.Text)
      				}
      			}
      		case "session.thread_status_idle":
      			break loop
      		}
      	}
      	if err := stream.Err(); err != nil {
      		panic(err)
      	}
      ```

      ```java Java
      try (var streamResponse = client.beta().sessions().threads().events().streamStreaming(
          thread.id(),
          EventStreamParams.builder().sessionId(session.id()).build()
      )) {
          loop:
          for (var event : (Iterable<BetaManagedAgentsStreamSessionThreadEvents>) streamResponse.stream()::iterator) {
              switch (event.type().value()) {
                  case AGENT_MESSAGE -> {
                      for (var block : event.asAgentMessage().content()) {
                          block.text().ifPresent(textBlock -> IO.print(textBlock.text()));
                      }
                  }
                  case SESSION_THREAD_STATUS_IDLE -> {
                      break loop;
                  }
              }
          }
      }
      ```

      ```php PHP
      $stream = $client->beta->sessions->threads->events->streamStream(
          $thread->id,
          sessionID: $session->id,
      );

      foreach ($stream as $event) {
          switch (true) {
              case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsAgentMessageEvent:
                  foreach ($event->content as $block) {
                      if ($block instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsTextBlock) {
                          echo $block->text;
                      }
                  }
                  break;
              case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionThreadStatusIdleEvent:
                  break 2;
          }
      }
      ```

      ```ruby Ruby
      client.beta.sessions.threads.events.stream_events(thread.id, session_id: session.id).each do |event|
        case event
        when Anthropic::Beta::Sessions::BetaManagedAgentsAgentMessageEvent
          event.content.each do |block|
            print block.text if block.is_a?(Anthropic::Beta::Sessions::BetaManagedAgentsTextBlock)
          end
        when Anthropic::Beta::Sessions::BetaManagedAgentsSessionThreadStatusIdleEvent
          break
        end
      end
      ```
    </CodeGroup>
  </Tab>

  <Tab title="セッションスレッドのイベントを一覧表示する">
    過去のすべてのセッションスレッドのイベントを一覧表示して、完全な履歴を取得します。

    <CodeGroup>
      ```bash cURL
      curl -fsS "https://api.anthropic.com/v1/sessions/$SESSION_ID/threads/$THREAD_ID/events" \
        -H "x-api-key: $ANTHROPIC_API_KEY" \
        -H "anthropic-version: 2023-06-01" \
        -H "anthropic-beta: managed-agents-2026-04-01"
      ```

      ```bash CLI
      ant beta:sessions:threads:events list \
        --session-id "$SESSION_ID" \
        --thread-id "$THREAD_ID"
      ```

      ```python Python
      for event in client.beta.sessions.threads.events.list(
          thread.id,
          session_id=session.id,
      ):
          print(f"[{event.type}] {event.processed_at}")
      ```

      ```typescript TypeScript
      for await (const event of client.beta.sessions.threads.events.list(thread.id, {
        session_id: session.id
      })) {
        console.log(`[${event.type}] ${event.processed_at}`);
      }
      ```

      ```csharp C#
      var page = await client.Beta.Sessions.Threads.Events.List(thread.ID, new() { SessionID = session.ID });
      await foreach (var evt in page.Paginate())
      {
          Console.WriteLine($"[{evt.Json.GetProperty("type").GetString()}] {evt.ProcessedAt}");
      }
      ```

      ```go Go
      pager := client.Beta.Sessions.Threads.Events.ListAutoPaging(ctx, thread.ID, anthropic.BetaSessionThreadEventListParams{
      	SessionID: session.ID,
      })
      for pager.Next() {
      	event := pager.Current()
      	fmt.Printf("[%s] %s\n", event.Type, event.ProcessedAt)
      }
      if err := pager.Err(); err != nil {
      	panic(err)
      }
      ```

      ```java Java
      for (var event : client.beta().sessions().threads().events().list(
              thread.id(),
              EventListParams.builder().sessionId(session.id()).build()
          ).autoPager()) {
          var type = event._json().orElseThrow() instanceof JsonObject json
              ? json.values().get("type").asStringOrThrow()
              : "unknown";
          var processedAt = event.processedAt().map(OffsetDateTime::toString).orElse("pending");
          IO.println("[" + type + "] " + processedAt);
      }
      ```

      ```php PHP
      foreach (
          $client->beta->sessions->threads->events->list(
              $thread->id,
              sessionID: $session->id,
          )->pagingEachItem() as $event
      ) {
          echo "[{$event->type}] {$event->processedAt->format(DATE_RFC3339)}\n";
      }
      ```

      ```ruby Ruby
      client.beta.sessions.threads.events.list(
        thread.id,
        session_id: session.id
      ).auto_paging_each do |event|
        puts "[#{event.type}] #{event.processed_at}"
      end
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## ツール権限とカスタムツール

ツール呼び出しを実行するための[権限](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming#tool-confirmation)や[カスタムツールの結果](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming#handling-custom-tool-calls)など、サブエージェントがクライアントから何かを必要とする場合、そのイベントは発生元のセッションスレッドを識別する `session_thread_id` とともに**プライマリスレッド**にクロスポストされます。ツール呼び出しは、`always_ask` の下、またはサーバーが判断に至らなかった場合の [`auto`](https://platform.claude.com/docs/ja/managed-agents/permission-policies#let-the-server-evaluate-each-call-with-auto) の下で、権限を必要とします。

```json
{
  "type": "session.thread_status_idle",
  "id": "sevt_01ABC...",
  "session_thread_id": "sthr_01DEF...",
  "agent_name": "code-reviewer",
  "stop_reason": {
    "type": "requires_action",
    "event_ids": ["sevt_01XYZ..."]
  }
}
```

`user.tool_confirmation`（`tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) を指定）または `user.custom_tool_result`（`custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`) を指定）を送信します。サーバーは応答を正しいスレッドに自動的にルーティングします。応答は、プライマリスレッドとサブエージェントのスレッドに異なる `id` (csharp, go: `ID`) 値で表示される場合があります。2つのコピーを照合するには、`id` (csharp, go: `ID`) ではなく、`type` (csharp, go: `Type`) と `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`)（または `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`)）を比較してください。

セッションは `running` のスレッドがない場合にのみ `idle` になるため、`session.status_idle` はサブエージェントの呼び出しからかなり後に届くことがあります。それを待つ必要はありません。クロスポストされた `agent.custom_tool_use` イベントが届いたらすぐに `user.custom_tool_result` を送信してください。

`auto` の下では、`user.message` イベントによって、サーバーが本来拒否する呼び出しを許可することがあります。サブエージェントのスレッド内のものは、あなたの意図としてはカウントされません。クライアントはそこにメッセージを送信せず、プライマリスレッドのエージェントがサブエージェントに送信するメッセージもカウントされません。サーバーが `auto` の下で呼び出しを拒否した場合、何もクロスポストされません。イベントとエラーのツール結果はサブエージェント自身の[スレッドストリーム](https://platform.claude.com/docs/ja/managed-agents/session-threads#session-thread-events)にのみ表示され、サブエージェントは実行を続けます。

次の例は、[ツール確認ハンドラー](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming#tool-confirmation)のイベントループ内に配置します。`stop_reason.event_ids` 内の各IDについて、呼び出しを許可する `user.tool_confirmation` を送信します。同じパターンが `user.custom_tool_result` にも適用され、これも対応する `agent.custom_tool_use` イベントが届いたらすぐに送信できます。

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    このワークフローには単一のシェルコマンド以上のロジックが必要です。実行するには [Claude SDK](https://platform.claude.com/docs/ja/cli-sdks-libraries/overview) を使用してください。
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    このワークフローには単一のシェルコマンド以上のロジックが必要です。実行するには [Claude SDK](https://platform.claude.com/docs/ja/cli-sdks-libraries/overview) を使用してください。
  </CodeGroupItem>

  ```python Python
  for event_id in stop.event_ids:
      client.beta.sessions.events.send(
          session.id,
          events=[
              {
                  "type": "user.tool_confirmation",
                  "tool_use_id": event_id,
                  "result": "allow",
              }
          ],
      )
  ```

  ```typescript TypeScript
  for (const eventId of stop.event_ids) {
    await client.beta.sessions.events.send(session.id, {
      events: [
        {
          type: "user.tool_confirmation",
          tool_use_id: eventId,
          result: "allow"
        }
      ]
    });
  }
  ```

  ```csharp C#
  foreach (var eventId in requiresAction.EventIds)
  {
      await client.Beta.Sessions.Events.Send(session.ID, new()
      {
          Events =
          [
              new BetaManagedAgentsUserToolConfirmationEventParams
              {
                  Type = BetaManagedAgentsUserToolConfirmationEventParamsType.UserToolConfirmation,
                  ToolUseID = eventId,
                  Result = BetaManagedAgentsUserToolConfirmationEventParamsResult.Allow,
              },
          ],
      });
  }
  ```

  ```go Go
  for _, eventID := range stopReason.EventIDs {
  	params := anthropic.BetaManagedAgentsUserToolConfirmationEventParams{
  		Type:      anthropic.BetaManagedAgentsUserToolConfirmationEventParamsTypeUserToolConfirmation,
  		ToolUseID: eventID,
  		Result:    anthropic.BetaManagedAgentsUserToolConfirmationEventParamsResultAllow,
  	}
  	if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  		Events: []anthropic.BetaManagedAgentsEventParamsUnion{{OfUserToolConfirmation: &params}},
  	}); err != nil {
  		panic(err)
  	}
  }
  ```

  ```java Java
  for (var eventId : pendingToolUseIds) {
      client.beta().sessions().events().send(
          session.id(),
          EventSendParams.builder()
              .addEvent(BetaManagedAgentsUserToolConfirmationEventParams.builder()
                  .type(BetaManagedAgentsUserToolConfirmationEventParams.Type.USER_TOOL_CONFIRMATION)
                  .toolUseId(eventId)
                  .result(BetaManagedAgentsUserToolConfirmationEventParams.Result.ALLOW)
                  .build())
              .build()
      );
  }
  ```

  ```php PHP
  foreach ($event->stopReason->eventIDs as $eventId) {
      $client->beta->sessions->events->send($session->id, events: [[
          'type' => 'user.tool_confirmation',
          'tool_use_id' => $eventId,
          'result' => 'allow',
      ]]);
  }
  ```

  ```ruby Ruby
  event_ids.each do |event_id|
    client.beta.sessions.events.send_(session.id, events: [{
      type: "user.tool_confirmation",
      tool_use_id: event_id,
      result: "allow"
    }])
  end
  ```
</CodeGroup>

前述のパターンは、アイドルイベントが列挙する呼び出しに応答します。プライマリストリーム上では、サブエージェントの `session.thread_status_idle` イベントが、その `stop_reason.event_ids` が列挙する `agent.tool_use` または `agent.mcp_tool_use` イベントより先に届くことがあります。イベントがまだ届いていない呼び出しに対する `user.tool_confirmation` は400を返すことがあります。これを避けるには、[`evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`)](https://platform.claude.com/docs/ja/managed-agents/permission-policies#see-how-each-call-was-evaluated) が `ask` である各呼び出しに、その呼び出し自身のイベントがプライマリストリームに届いた時点で応答してください。
