---
title: イベントデルタでレスポンスをプレビューする
url: https://platform.claude.com/docs/ja/managed-agents/event-deltas
description: モデルがまだ生成している間に、エージェントのレスポンステキストをライブプレビューとしてレンダリングします。
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

デフォルトでは、エージェントのレスポンステキストは、バッファリングされた `agent.message` イベントとして[セッションイベントストリーム](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming)に届きます。各イベントは、それを生成したモデルリクエストが完了した後にのみ発行されます。「event delta」（イベントデルタ）を使用すると、モデルがまだテキストを生成している間に、そのテキストをライブプレビューとして段階的にレンダリングできます。

プレビューはベストエフォートの表示補助であり、バッファリングされた `agent.message` が常に正式な記録です。プレビューを無視するクライアントでも、完全で正しいストリームを受信できます。

## プレビューをオプトインする

プレビューはストリーム接続ごとのオプトインです。読み取っているストリームに `event_deltas[]` クエリパラメータを追加し、プレビューしたいイベントタイプごとに1回ずつ繰り返します。受け付けられる値は `agent.message` と `agent.thinking` です。それ以外の値を指定すると400エラーが返され、100個を超える値を含むリクエストも同様です。

両方のストリームエンドポイントがこのパラメータを受け付けます。

* **セッションレベルのストリーム：** `GET /v1/sessions/{session_id}/events/stream`
* **セッションスレッドのストリーム：** `GET /v1/sessions/{session_id}/threads/{thread_id}/stream`

サブエージェントのプレビューは、[そのサブエージェント自身のスレッドストリーム](https://platform.claude.com/docs/ja/managed-agents/event-deltas#preview-session-thread-events)に表示されます。

`[]` はシェルのグロブパターンであるため、シェルでリクエストを構築する場合は必ずURLを引用符で囲んでください。例では角括弧を `%5B%5D` としてパーセントエンコードしていますが、これも機能します。

### プレビューイベント

プレビュー対象のイベントが開始されると、ストリームは次に来るイベントのタイプと `id` を含む `event_start` を発行します。

```json
{
  "type": "event_start",
  "event": {
    "type": "agent.message",
    "id": "sevt_01abc..."
  }
}
```

`agent.message` の場合、開始の後に増分テキストを含む `event_delta` イベントが続きます。各デルタは、拡張対象のイベントを `event_id` で、拡張対象のコンテンツブロックを `delta.index` で示します。

```json
{
  "type": "event_delta",
  "event_id": "sevt_01abc...",
  "delta": {
    "type": "content_delta",
    "index": 0,
    "content": {
      "type": "text",
      "text": "Here is the summary"
    }
  }
}
```

`agent.thinking` の場合、思考ブロックが開始されたことを示すシグナルとして `event_start` のみが発行されます。`event_delta` イベントは続きません。プレビューを締めくくるバッファリングされた `agent.thinking` イベントは進捗シグナルであり、思考内容は含まれません。

永続化されるイベントとは異なり、`event_start` と `event_delta` には独自の `id` や `processed_at` がありません。これらが持つ唯一の識別子は、プレビュー対象のイベントの `id` です。また、これらのタイプ文字列は、永続化されるイベントの `{domain}.{action}` 命名規則の例外でもあります。

<Note>
  イベントデルタは[メッセージのストリーミング](https://platform.claude.com/docs/ja/build-with-claude/streaming)とは異なるワイヤーフォーマットを使用しており、この違いは意図的なものです。プレビューされる `agent.message` には単一の `event_start` があり、その後には `event_delta` イベントのみが続きます。コンテンツブロックごとの開始・停止イベントはなく、プレビュー対象のイベント自体の停止イベントもありません。デルタタイプは `content_block_delta` ではなく `content_delta` です。Messages API 向けに書かれたアキュムレータコードは、そのままでは流用できません。
</Note>

## 蓄積と照合

イベントデルタをサポートするすべてのSDKには、`index` の管理を代行する[アキュムレータヘルパー](https://platform.claude.com/docs/ja/managed-agents/event-deltas#sdk-accumulator-helpers)が含まれています。独自の管理が必要な場合は、このセクションの手動パターンがすべての言語で機能します。生成されたイベントタイプに適用してください。

手動パターンでは、プレビューテキストを `(event_id, index)` をキーとする一時的なマップに保持し、バッファリングされたイベントを記録として扱います。この2つをモデルリクエストごとに照合します。

ターンは単一の `session.status_running` イベントで始まります。正常に完了するターンでは、各モデルリクエストが次のイベントを順番に生成します。

1. `span.model_request_start`
2. `event_start`
3. `event_delta` イベント
4. バッファリングされた `agent.message`
5. [`span.model_request_end`](https://platform.claude.com/docs/ja/managed-agents/reference#event-types)（Span events タブ内）

ワイヤー上では、これはそのシーケンスのうちプレビューされる部分であり、接続の他のバッファリングされたイベントと交互に配置されます。

```text wrap
event_start     {"event": {"type": "agent.message", "id": "sevt_01abc..."}}
event_delta     {"event_id": "sevt_01abc...", "delta": {"type": "content_delta", "index": 0, "content": {"type": "text", "text": "..."}}}
...
agent.message   {"id": "sevt_01abc...", "content": [...]}
```

`event_delta` の行は、テキストフラグメントごとに1回繰り返されます。各イベントを到着時に処理します。

1. `event_start` では、通知された `id` を記録します。識別子は常に一致します。`event_start.event.id`、すべての `event_delta.event_id`、およびバッファリングされた `agent.message` の `id` は同じ値です。
2. 各 `event_delta` では、`delta.content.text` を `(event_id, delta.index)` のエントリに追加し、現在のテキストをレンダリングします。ある `index` に対する最初のデルタがそのエントリを作成します。
3. バッファリングされた `agent.message` が到着したら、`id` で照合し、蓄積されたプレビューを破棄して、代わりにメッセージのコンテンツをレンダリングします。
4. `span.model_request_end` では、バッファリングされたイベントによって照合されていないプレビューをすべて閉じます。それに対するデルタはこれ以上届きません。ターンがエラーになったり中断されたりした場合、バッファリングされたイベントは届かない可能性がありますが、`span.model_request_end` は届きます。

このパターンは2つの保証に依存しています。

* `(event_id, index)` をキーとして、プレビューのデルタを到着順に連結すると、バッファリングされたイベントの `content[index].text` のプレフィックスが得られます。デルタは[負荷時に破棄される](https://platform.claude.com/docs/ja/managed-agents/event-deltas#limitations)可能性があるため、必ずしもテキスト全体になるとは限りません。
* 1つの接続は `event_id` ごとに最大1つの `event_start` を発行し、バッファリングされたイベントは、その接続がその `id` に対して配信する最後のものです。

### SDKアキュムレータヘルパー

各SDKのヘルパーは `index` (csharp, go: `Index`) の管理を処理します。Go、Java、Ruby、C# のヘルパーは、蓄積中のプレビューをイベントの `id` (csharp, go: `ID`) でキー付けすることも行います。Python、TypeScript、PHP のヘルパーでは、そのマップを自分で保持し、各デルタをその `id` (csharp, go: `ID`) のエントリに取り込んでください。

次の例では、`agent.message` のプレビューをオプトインし、バッファリングされたイベントと照合します。

<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
  # イベント ID をキーとするプレビューのスナップショット。accumulate_managed_agents_event は各
  # event_start / event_delta を agent.message のスナップショットに畳み込みます。バッファされた
  # agent.message がそれを置き換えます。
  previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}

  # この接続で agent.message のプレビューを有効にします
  with client.beta.sessions.events.stream(
      session.id, event_deltas=["agent.message"]
  ) as stream:
      client.beta.sessions.events.send(
          session.id,
          events=[
              {
                  "type": "user.message",
                  "content": [
                      {"type": "text", "text": "Describe the repo in one sentence."}
                  ],
              },
          ],
      )

      for event in stream:
          match event.type:
              case "event_start":
                  snapshot = accumulate_managed_agents_event(None, event)
                  if snapshot is not None:
                      previews[event.event.id] = snapshot
                  print(f"event_start             {event.event.type} {event.event.id}")
              case "event_delta":
                  preview = accumulate_managed_agents_event(
                      previews.get(event.event_id), event
                  )
                  if preview is not None:
                      previews[event.event_id] = preview
                      text = "".join(block.text for block in preview.content)
                      print(f"event_delta             preview: {text!r}")
              case "agent.message":
                  # バッファされたイベントが正式な記録です。プレビューを置き換えて閉じます
                  preview = accumulate_managed_agents_event(
                      previews.pop(event.id, None), event
                  )
                  text = "".join(block.text for block in preview.content)
                  print(f"agent.message           {event.id} {text!r}")
              case "span.model_request_end":
                  # これ以上デルタは届きません。バッファされたイベントが
                  # 届かなかったプレビューを閉じます。
                  for event_id in previews:
                      print(f"span.model_request_end  closing preview for {event_id}")
                  previews.clear()
              case "session.status_idle":
                  break
  ```

  ```typescript TypeScript
  // イベント id をキーとするプレビューのスナップショットです。`accumulateManagedAgentsEvent` は
  // event_start / event_delta のプレビューを agent.message スナップショットに畳み込みます。
  const previews = new Map<string, BetaManagedAgentsAgentMessageEvent>();

  // この接続に限り agent.message のプレビューを有効にします
  const stream = await client.beta.sessions.events.stream(session.id, {
    event_deltas: ["agent.message"]
  });
  await client.beta.sessions.events.send(session.id, {
    events: [
      {
        type: "user.message",
        content: [{ type: "text", text: "Summarize the repo README" }]
      }
    ]
  });

  deltas: for await (const event of stream) {
    switch (event.type) {
      case "event_start": {
        // 1. 通知された id を記録し、スナップショットを開きます。デルタと
        //    バッファされたイベントは同じ id を持ちます。
        const preview = accumulateManagedAgentsEvent(undefined, event);
        if (preview) {
          previews.set(event.event.id, preview);
        }
        console.log(`event_start             ${event.event.type} ${event.event.id}`);
        break;
      }
      case "event_delta": {
        // 2. フラグメントをスナップショットに畳み込み、レンダリングします
        const preview = accumulateManagedAgentsEvent(previews.get(event.event_id), event);
        if (preview) {
          previews.set(event.event_id, preview);
          const text = preview.content
            .map((block) => (block.type === "text" ? block.text : ""))
            .join("");
          console.log(`event_delta             preview: ${JSON.stringify(text)}`);
        }
        break;
      }
      case "agent.message": {
        // 3. バッファされたイベントが正式な記録です。プレビューを置き換えて閉じます
        const message = accumulateManagedAgentsEvent(previews.get(event.id), event);
        previews.delete(event.id);
        const text = message.content
          .map((block) => (block.type === "text" ? block.text : ""))
          .join("");
        console.log(`agent.message           ${event.id} ${JSON.stringify(text)}`);
        break;
      }
      case "span.model_request_end":
        // 4. これ以上デルタは来ません。照合されなかったプレビューを閉じます。
        for (const eventId of previews.keys()) {
          console.log(`span.model_request_end  closing preview for ${eventId}`);
        }
        previews.clear();
        break;
      case "session.status_idle":
        break deltas;
    }
  }
  stream.controller.abort();
  ```

  ```csharp C#
  // イベントデルタを有効化します：agent.message イベントは生成中にプレビューされます。
  using var stream = await client.Beta.Sessions.Events.WithRawResponse.StreamStreaming(
      session.ID,
      new() { EventDeltas = [BetaManagedAgentsDeltaType.AgentMessage] }
  );
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserMessageEventParams
          {
              Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage,
              Content =
              [
                  new BetaManagedAgentsTextBlock
                  {
                      Type = BetaManagedAgentsTextBlockType.Text,
                      Text = "Write a haiku about event streams.",
                  },
              ],
          },
      ],
  });

  // プレビュー断片を (イベント ID, コンテンツインデックス) ごとに蓄積します。後続の
  // バッファ済み agent.message は完全なコンテンツを持つため、蓄積したプレビューに
  // 追記するのではなく置き換えます。
  Dictionary<string, SortedDictionary<long, string>> previews = [];

  await foreach (var streamEvent in stream.Enumerate())
  {
      if (streamEvent.TryPickStartEvent(out var start))
      {
          // この ID のイベントに対して開かれたプレビューです。このストリームは
          // agent.message のデルタのみ有効化しています。TryPick* は例外ではなく false を返すため、
          // 他のプレビュー種別（今後追加されるものを含む）はスキップされます。
          if (start.Event.TryPickAgentMessage(out var preview))
          {
              Console.WriteLine($"event_start             {preview.Type.Raw()} {preview.ID}");
          }
      }
      else if (streamEvent.TryPickDeltaEvent(out var delta))
      {
          // 新しいインデックスなら挿入し、既存のインデックスなら追記します
          if (!previews.TryGetValue(delta.EventID, out var fragments))
          {
              previews[delta.EventID] = fragments = [];
          }
          var index = delta.Delta.Index ?? 0;
          fragments[index] = fragments.GetValueOrDefault(index, "") + delta.Delta.Content.Text;
          Console.WriteLine($"event_delta             preview: {fragments[index]}");
      }
      else if (streamEvent.TryPickAgentMessageEvent(out var message))
      {
          // デルタはベストエフォートです：プレビューを破棄し、バッファ済みイベントを使用します
          previews.Remove(message.ID);
          var text = string.Concat(message.Content.Select(block =>
              block.TryPickBetaManagedAgentsTextBlock(out var textBlock) ? textBlock.Text : ""));
          Console.WriteLine($"agent.message           {message.ID} {text}");
      }
      else if (streamEvent.TryPickSpanModelRequestEndEvent(out _))
      {
          // これ以上デルタは来ません。照合されなかったプレビューを閉じます。
          foreach (var eventId in previews.Keys)
          {
              Console.WriteLine($"span.model_request_end  closing preview for {eventId}");
          }
          previews.Clear();
      }
      else if (streamEvent.TryPickSessionStatusIdleEvent(out _))
      {
          break;
      }
  }
  ```

  ```go Go
  	// agent.message イベントの増分プレビューを有効にします
  	stream := client.Beta.Sessions.Events.StreamEvents(ctx, session.ID, anthropic.BetaSessionEventStreamParams{
  		EventDeltas: []anthropic.BetaManagedAgentsDeltaType{
  			anthropic.BetaManagedAgentsDeltaTypeAgentMessage,
  		},
  	})

  	if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  		Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  			OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{
  				Type: anthropic.BetaManagedAgentsUserMessageEventParamsTypeUserMessage,
  				Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{{
  					OfText: &anthropic.BetaManagedAgentsTextBlockParam{
  						Type: anthropic.BetaManagedAgentsTextBlockTypeText,
  						Text: "Write a haiku about the ocean.",
  					},
  				}},
  			},
  		}},
  	}); err != nil {
  		panic(err)
  	}

  	// アキュムレーターは event_start / event_delta の断片を
  	// イベント ID ごとの agent.message スナップショットにまとめます。ゼロ値のまま使用できます。
  	var previews anthropic.BetaManagedAgentsEventAccumulator

  deltas:
  	for stream.Next() {
  		event := stream.Current()
  		previews.Accumulate(event)

  		switch event := event.AsAny().(type) {
  		case anthropic.BetaManagedAgentsStartEvent:
  			fmt.Printf("event_start             %s %s\n", event.Event.Type, event.Event.ID)
  		case anthropic.BetaManagedAgentsDeltaEvent:
  			fmt.Printf("event_delta             preview: %q\n", previews.AgentMessageText(event.EventID))
  		case anthropic.BetaManagedAgentsAgentMessageEvent:
  			// バッファされたイベントは完全なコンテンツを持ちます。アキュムレーターは
  			// プレビューをそれで置き換えます
  			fmt.Printf("agent.message           %s %q\n", event.ID, previews.AgentMessageText(event.ID))
  		case anthropic.BetaManagedAgentsSpanModelRequestEndEvent:
  			// このリクエストではこれ以上デルタは来ません。アキュムレーターは
  			// ここでスナップショットを破棄し、バッファされた agent.message で
  			// 照合されなかったプレビューを閉じます。
  			fmt.Println("span.model_request_end  no more deltas for this request")
  		case anthropic.BetaManagedAgentsSessionStatusIdleEvent:
  			break deltas
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  	stream.Close()
  ```

  ```java Java
  // プレビューテキスト。イベント ID、次にコンテンツインデックスをキーとします。バッファ済みの agent.message で置き換えられます。
  Map<String, Map<Long, StringBuilder>> previews = new HashMap<>();

  // この接続で agent.message のプレビューを有効にします
  try (var stream = client.beta().sessions().events().streamStreaming(
          session.id(),
          EventStreamParams.builder()
              .addEventDelta(BetaManagedAgentsDeltaType.AGENT_MESSAGE)
              .build()
  )) {
      client.beta().sessions().events().send(
          session.id(),
          EventSendParams.builder()
              .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
                  .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
                  .addTextContent("Describe the repo in one sentence.")
                  .build())
              .build()
      );

      Iterable<BetaManagedAgentsStreamSessionEvents> events = stream.stream()::iterator;
      deltas:
      for (var event : events) {
          switch (event.type().value()) {
              case EVENT_START -> {
                  if (event.asEventStart().event().isAgentMessage()) {
                      var preview = event.asEventStart().event().asAgentMessage();
                      IO.println("event_start             " + preview.type().asString() + " " + preview.id());
                  }
              }
              case EVENT_DELTA -> {
                  var eventDelta = event.asEventDelta();
                  var fragment = eventDelta.delta();
                  var buffer = previews
                      .computeIfAbsent(eventDelta.eventId(), _ -> new HashMap<>())
                      .computeIfAbsent(fragment.index().orElse(0L), _ -> new StringBuilder());
                  buffer.append(fragment.content().text());
                  IO.println("event_delta             preview: " + buffer);
              }
              case AGENT_MESSAGE -> {
                  // バッファ済みイベントが正式な記録です。プレビューを破棄し、そのコンテンツを描画します
                  var message = event.asAgentMessage();
                  previews.remove(message.id());
                  var text = message.content().stream()
                      .flatMap(block -> block.text().stream())
                      .map(textBlock -> textBlock.text())
                      .collect(Collectors.joining());
                  IO.println("agent.message           " + message.id() + " " + text);
              }
              case SPAN_MODEL_REQUEST_END -> {
                  // これ以上デルタは届きません。バッファ済みイベントが届かなかったプレビューを閉じます。
                  previews.keySet().forEach(eventId ->
                      IO.println("span.model_request_end  closing preview for " + eventId));
                  previews.clear();
              }
              case SESSION_STATUS_IDLE -> {
                  break deltas;
              }
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\Sessions\BetaManagedAgentsDeltaEvent;
  use Anthropic\Beta\Sessions\BetaManagedAgentsDeltaType;
  use Anthropic\Beta\Sessions\BetaManagedAgentsStartEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsAgentMessageEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSessionStatusIdleEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSpanModelRequestEndEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsTextBlock;
  use Anthropic\Lib\Sessions\EventAccumulator;

  // イベント ID をキーとするプレビュースナップショット。EventAccumulator::accumulate() は各
  // event_start / event_delta を agent.message スナップショットに追加し、バッファされた
  // agent.message がそれを置き換えます。
  $previews = [];

  // agent.message スナップショットまたはイベントのテキスト
  $textOf = fn (ManagedAgentsAgentMessageEvent $message): string => implode(
      '',
      array_map(
          fn ($block) => $block->text,
          array_filter(
              $message->content,
              fn ($block) => $block instanceof ManagedAgentsTextBlock,
          ),
      ),
  );

  // この接続で agent.message プレビューを有効にします
  $stream = $client->beta->sessions->events->streamStream(
      $session->id,
      eventDeltas: [BetaManagedAgentsDeltaType::AGENT_MESSAGE],
  );

  $client->beta->sessions->events->send(
      $session->id,
      events: [
          [
              'type' => 'user.message',
              'content' => [['type' => 'text', 'text' => 'Describe the repo in one sentence.']],
          ],
      ],
  );

  foreach ($stream as $event) {
      switch (true) {
          case $event instanceof BetaManagedAgentsStartEvent:
              $snapshot = EventAccumulator::accumulate(null, $event);
              if ($snapshot !== null) {
                  $previews[$event->event->id] = $snapshot;
              }
              printf("event_start             %s %s\n", $event->event->type, $event->event->id);
              break;
          case $event instanceof BetaManagedAgentsDeltaEvent:
              // 既に置き換えられたか閉じられたプレビューへの遅延デルタはスキップします
              if (!isset($previews[$event->eventID])) {
                  break; // Break switch statement
              }
              $previews[$event->eventID] = EventAccumulator::accumulate($previews[$event->eventID], $event);
              printf("event_delta             preview: %s\n", json_encode($textOf($previews[$event->eventID])));
              break;
          case $event instanceof ManagedAgentsAgentMessageEvent:
              // バッファされたイベントが正式な記録です。プレビューを置き換えて閉じます
              unset($previews[$event->id]);
              printf("agent.message           %s %s\n", $event->id, json_encode($textOf($event)));
              break;
          case $event instanceof ManagedAgentsSpanModelRequestEndEvent:
              // これ以上デルタは届きません。バッファされたイベントが
              // 届かなかったプレビューをすべて閉じます。
              foreach (array_keys($previews) as $eventID) {
                  printf("span.model_request_end  closing preview for %s\n", $eventID);
              }
              $previews = [];
              break;
          case $event instanceof ManagedAgentsSessionStatusIdleEvent:
              break 2; // Break foreach loop
      }
  }
  $stream->close();
  ```

  ```ruby Ruby
  # イベントデルタを有効化します：agent.message のプレビューが増分フラグメントとしてストリーミングされます。
  stream = client.beta.sessions.events.stream_events(
    session.id,
    event_deltas: [Anthropic::Beta::BetaManagedAgentsDeltaType::AGENT_MESSAGE]
  )

  client.beta.sessions.events.send_(
    session.id,
    events: [{
      type: "user.message",
      content: [{type: "text", text: "Give a one-sentence project tagline."}]
    }]
  )

  # プレビューのフラグメントを (event_id, index) ごとに、明示的にミュータブルな
  # (`+""`) バッファに蓄積し、`<<` でその場で追記できるようにします。同じ id を持つ
  # バッファ済みの agent.message が正であり、デルタで構築した内容を置き換えます。
  buffers = Hash.new do |by_event, event_id|
    by_event[event_id] = Hash.new { |fragments, index| fragments[index] = +"" }
  end

  stream.each do |event|
    case event
    when Anthropic::Beta::BetaManagedAgentsStartEvent
      puts "event_start             #{event.event.type} #{event.event.id}"
    when Anthropic::Beta::BetaManagedAgentsDeltaEvent
      delta = event.delta
      fragment = delta.content.text
      buffers[event.event_id][delta.index || 0] << fragment
      puts "event_delta             preview: #{buffers[event.event_id][delta.index || 0].inspect}"
    when Anthropic::Beta::Sessions::BetaManagedAgentsAgentMessageEvent
      # 置換：蓄積したプレビューを破棄し、完全なイベントを描画します。
      buffers.delete(event.id)
      puts "agent.message           #{event.id} #{event.content.map(&:text).join.inspect}"
    when Anthropic::Beta::Sessions::BetaManagedAgentsSpanModelRequestEndEvent
      # これ以上デルタは来ません。照合されなかったプレビューを閉じます。
      buffers.each_key { |event_id| puts "span.model_request_end  closing preview for #{event_id}" }
      buffers.clear
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      break
    else
      # その他のイベントタイプは無視します
    end
  end
  ```
</CodeGroup>

## セッションスレッドのイベントをプレビューする

[マルチエージェント](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration)セッションでは、各セッションスレッドが独自のイベントストリームを持ちます。このストリームも同じ値で同じ `event_deltas[]` パラメータを受け付けます。

接続は、読み取っているスレッドのみをプレビューします。セッションレベルのストリームはプライマリスレッドをプレビューし、子スレッドのプレビューがそこにクロスポストされることはありません。モデルが生成するサブエージェントのテキストを確認するには、そのサブエージェントのスレッドストリームを開いてください。

スレッドストリームのパスは `/threads/{thread_id}/stream` で終わります。`/events/stream` はセッションレベルにのみ存在するため、`/threads/{thread_id}/events/stream` エンドポイントはありません。

`event_start` と `event_delta` は、スレッドストリームでもセッションレベルのストリームと同じ形式であり、[蓄積と照合](https://platform.claude.com/docs/ja/managed-agents/event-deltas#accumulate-and-reconcile)のパターンはそのまま適用されます。ストリーム接続ごとに1つのアキュムレータインスタンスを実行してください。

<CodeGroup>
  ```bash cURL
  # スレッドストリームはセッションストリームと同じ event_deltas[] パラメーターを受け取ります。
  # 角括弧をパーセントエンコード(%5B%5D)し、URL を引用符で囲んでください。
  curl --fail-with-body -sS -N \
    "https://api.anthropic.com/v1/sessions/$SESSION_ID/threads/$THREAD_ID/stream?beta=true&event_deltas%5B%5D=agent.message" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "accept: text/event-stream"
  ```

  ```bash CLI
  # スレッドストリームはセッションストリームと同じ event_deltas パラメーターを受け取り、
  # プレビューするイベントタイプごとに --event-delta フラグを 1 つ指定します。
  ant beta:sessions:threads:events stream \
    --session-id "$SESSION_ID" \
    --thread-id "$THREAD_ID" \
    --event-delta agent.message
  ```

  ```python Python
  # セッションのスレッドを一覧取得して子を選びます。子スレッドは parent_thread_id が null 以外で、
  # プライマリスレッドの parent_thread_id は null です。
  child_thread = next(
      thread
      for thread in client.beta.sessions.threads.list(session.id)
      if thread.parent_thread_id is not None
  )

  # 子スレッドのストリームは、セッションストリームと同じ event_deltas パラメーターを
  # 受け取ります。
  with client.beta.sessions.threads.events.stream(
      child_thread.id,
      session_id=session.id,
      event_deltas=["agent.message"],
  ) as stream:
      for event in stream:
          match event.type:
              case "event_delta":
                  print(event.delta.content.text, end="")
              case "agent.message":
                  # バッファされたイベントが正式な記録です。その内容をレンダリングします
                  print()
                  for block in event.content:
                      if block.type == "text":
                          print(block.text, end="")
                  print()
              case "session.thread_status_idle":
                  break
  ```

  ```typescript TypeScript
  // セッションのスレッドを一覧表示して子を選びます：子スレッドの parent_thread_id は非 null で、
  // プライマリスレッドの parent_thread_id は null です。
  let childThreadId: string | undefined;
  for await (const thread of client.beta.sessions.threads.list(session.id)) {
    if (thread.parent_thread_id !== null) {
      childThreadId = thread.id;
      break;
    }
  }
  if (!childThreadId) {
    throw new Error("No child thread found");
  }

  // 子スレッドのストリームは、セッションストリームと同じ event_deltas パラメータを
  // 受け取ります。
  const stream = await client.beta.sessions.threads.events.stream(childThreadId, {
    session_id: session.id,
    event_deltas: ["agent.message"]
  });

  threadDeltas: for await (const event of stream) {
    switch (event.type) {
      case "event_delta":
        process.stdout.write(event.delta.content.text);
        break;
      case "agent.message": {
        // バッファされたイベントが正式な記録です。その内容をレンダリングします。
        process.stdout.write("\n");
        const text = event.content
          .map((block) => (block.type === "text" ? block.text : ""))
          .join("");
        console.log(text);
        break;
      }
      case "session.thread_status_idle":
        break threadDeltas;
    }
  }
  stream.controller.abort();
  ```

  ```csharp C#
  // セッションのスレッドを一覧表示して子を選びます：子スレッドは parent_thread_id が
  // null 以外で、プライマリスレッドの parent_thread_id は null です。
  var threads = await client.Beta.Sessions.Threads.List(session.ID);
  var childThread = threads.Items.First(thread => thread.ParentThreadID is not null);

  // 子スレッドのストリームは、セッションストリームと同じ event_deltas
  // パラメーターを受け取ります。
  using var stream = await client.Beta.Sessions.Threads.Events.WithRawResponse.StreamStreaming(
      childThread.ID,
      new() { SessionID = session.ID, EventDeltas = [BetaManagedAgentsDeltaType.AgentMessage] }
  );

  await foreach (var streamEvent in stream.Enumerate())
  {
      if (streamEvent.TryPickDeltaEvent(out var delta))
      {
          Console.Write(delta.Delta.Content.Text);
      }
      else if (streamEvent.TryPickAgentMessageEvent(out var message))
      {
          // バッファ済みイベントが正式な記録です。そのコンテンツを描画します。
          Console.WriteLine();
          var text = string.Concat(message.Content.Select(block =>
              block.TryPickBetaManagedAgentsTextBlock(out var textBlock) ? textBlock.Text : ""));
          Console.WriteLine(text);
      }
      else if (streamEvent.TryPickSessionThreadStatusIdleEvent(out _))
      {
          break;
      }
  }
  ```

  ```go Go
  	// セッションのスレッドを一覧取得して子を選びます: 子スレッドは parent_thread_id が非 null で、
  	// プライマリスレッドの parent_thread_id は null です。
  	var childThreadID string
  	threads := client.Beta.Sessions.Threads.ListAutoPaging(ctx, session.ID, anthropic.BetaSessionThreadListParams{})
  	for threads.Next() {
  		if thread := threads.Current(); thread.ParentThreadID != "" {
  			childThreadID = thread.ID
  			break
  		}
  	}
  	if err := threads.Err(); err != nil {
  		panic(err)
  	}

  	// 子スレッドのストリームはセッションストリームと同じ event_deltas パラメーターを
  	// 受け取ります。ストリーム接続ごとに読み取りループを1つ実行します。
  	stream := client.Beta.Sessions.Threads.Events.StreamEvents(ctx, childThreadID, anthropic.BetaSessionThreadEventStreamParams{
  		SessionID: session.ID,
  		EventDeltas: []anthropic.BetaManagedAgentsDeltaType{
  			anthropic.BetaManagedAgentsDeltaTypeAgentMessage,
  		},
  	})

  threadDeltas:
  	for stream.Next() {
  		switch event := stream.Current().AsAny().(type) {
  		case anthropic.BetaManagedAgentsDeltaEvent:
  			fmt.Print(event.Delta.Content.Text)
  		case anthropic.BetaManagedAgentsAgentMessageEvent:
  			// バッファされたイベントが正式な記録です。そのコンテンツをレンダリングします。
  			fmt.Println()
  			// 具象型のリスト: BetaManagedAgentsTextBlock
  			for _, block := range event.Content {
  				fmt.Print(block.Text)
  			}
  			fmt.Println()
  		case anthropic.BetaManagedAgentsSessionThreadStatusIdleEvent:
  			break threadDeltas
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  	stream.Close()
  ```

  ```java Java
  // セッションのスレッドを一覧取得し、子スレッドを選びます。子スレッドは parent_thread_id が null でなく、
  // プライマリスレッドの parent_thread_id は null です。
  var childThread = client.beta().sessions().threads().list(session.id()).autoPager().stream()
      .filter(thread -> thread.parentThreadId().isPresent())
      .findFirst()
      .orElseThrow();

  // 子スレッドのストリームはセッションストリームと同じ event_deltas パラメーターを受け取ります。
  // その params クラスはセッションレベルのものと単純名が同じなので、完全修飾します。
  try (var stream = client.beta().sessions().threads().events().streamStreaming(
          childThread.id(),
          com.anthropic.models.beta.sessions.threads.events.EventStreamParams.builder()
              .sessionId(session.id())
              .addEventDelta(BetaManagedAgentsDeltaType.AGENT_MESSAGE)
              .build()
  )) {
      Iterable<BetaManagedAgentsStreamSessionThreadEvents> events = stream.stream()::iterator;
      threadDeltas:
      for (var event : events) {
          switch (event.type().value()) {
              case EVENT_DELTA -> IO.print(event.asEventDelta().delta().content().text());
              case AGENT_MESSAGE -> {
                  // バッファ済みイベントが正式な記録です。そのコンテンツを描画します。
                  IO.println();
                  event.asAgentMessage().content().forEach(block -> block.text().ifPresent(textBlock -> IO.print(textBlock.text())));
                  IO.println();
              }
              case SESSION_THREAD_STATUS_IDLE -> {
                  break threadDeltas;
              }
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\Sessions\BetaManagedAgentsDeltaEvent;
  use Anthropic\Beta\Sessions\BetaManagedAgentsDeltaType;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsAgentMessageEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSessionThreadStatusIdleEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsTextBlock;

  // セッションのスレッドを一覧取得して子を選びます。子スレッドは null でない
  // parentThreadID を持ち、プライマリスレッドの parentThreadID は null です。
  $childThread = null;
  foreach ($client->beta->sessions->threads->list($session->id)->pagingEachItem() as $thread) {
      if ($thread->parentThreadID !== null) {
          $childThread = $thread;
          break;
      }
  }

  // 子スレッドのストリームは、セッションストリームと同じ eventDeltas パラメータを
  // 受け取ります。
  $stream = $client->beta->sessions->threads->events->streamStream(
      $childThread->id,
      sessionID: $session->id,
      eventDeltas: [BetaManagedAgentsDeltaType::AGENT_MESSAGE],
  );

  foreach ($stream as $event) {
      switch (true) {
          case $event instanceof BetaManagedAgentsDeltaEvent:
              echo $event->delta->content->text;
              break;
          case $event instanceof ManagedAgentsAgentMessageEvent:
              // バッファされたイベントが正式な記録です。その内容をレンダリングします
              echo "\n";
              foreach ($event->content as $block) {
                  if ($block instanceof ManagedAgentsTextBlock) {
                      echo $block->text;
                  }
              }
              echo "\n";
              break;
          case $event instanceof ManagedAgentsSessionThreadStatusIdleEvent:
              break 2; // Break foreach loop
      }
  }
  $stream->close();
  ```

  ```ruby Ruby
  # セッションのスレッドを一覧取得して子を選びます：子スレッドは parent_thread_id が非 null で、
  # プライマリスレッドの parent_thread_id は null です。
  child_thread = client.beta.sessions.threads.list(session.id).to_enum.find { it.parent_thread_id }

  # 子スレッドのストリームは、セッションのストリームと同じ event_deltas
  # パラメーターを受け取ります。
  stream = client.beta.sessions.threads.events.stream_events(
    child_thread.id,
    session_id: session.id,
    event_deltas: [Anthropic::Beta::BetaManagedAgentsDeltaType::AGENT_MESSAGE]
  )

  stream.each do |event|
    case event
    when Anthropic::Beta::BetaManagedAgentsDeltaEvent
      print event.delta.content.text
    when Anthropic::Beta::Sessions::BetaManagedAgentsAgentMessageEvent
      # バッファ済みのイベントが正式な記録です。その内容を描画します。
      puts
      event.content.each { print it.text }
      puts
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionThreadStatusIdleEvent
      break
    else
      # その他のイベントタイプは無視します
    end
  end
  ```
</CodeGroup>

読み取りループは、セッションスレッドのターンが終了してスレッドがアイドル状態になったときに発行されるイベントである [`session.thread_status_idle`](https://platform.claude.com/docs/ja/managed-agents/reference#event-types) で終了します。

## 制限事項

* **ベストエフォート：** 負荷がかかっている場合、サーバーはイベントのデルタを破棄することがあります。その場合、テキストの連続したプレフィックスを受信した後、そのイベントに対するデルタはそれ以上届きません。バッファリングされた `agent.message` は引き続き完全な形で届きます。蓄積されたプレビューを最終的なものとして扱わないでください。
* **再接続時のリプレイなし：** デルタは、オプトインした接続が開いている間にのみ、その接続に配信されます。これはセッションレベルのストリームと各セッションスレッドのストリームの両方に当てはまります。モデルリクエストの開始後に開かれた接続は、その処理中のイベントに対するデルタを受信しません。見逃したデルタを再リクエストする方法はありません。
* **1つのスレッド、テキストのみ：** プレビューは、[接続が読み取っているスレッド](https://platform.claude.com/docs/ja/managed-agents/event-deltas#preview-session-thread-events)上のアシスタントテキストを対象とします。ツール使用、ツール結果、MCP の結果はプレビューされません。
* **永続化されない：** `event_start` と `event_delta` はライブストリーム上にのみ存在します。セッションのイベント履歴（`GET /v1/sessions/{session_id}/events`）や、どのセッションスレッドのイベント履歴にも表示されません。

## プレビューのトラブルシューティング

| 表示される内容                                                   | 意味                                                                                                                                                                                                                                     |
| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| バッファリングされたイベントはあるが、`event_start` や `event_delta` がないストリーム | 読み取っている接続がオプトインしていないか、ターンがストリーミング中のスレッドに一度も関与していません。`event_deltas[]` はセッションごとではなく接続ごとに適用されます。どのスレッドが実行されたかを確認するには、セッションのスレッドを一覧表示してください（`GET /v1/sessions/{session_id}/threads`）。                                                      |
| プレビュー中に切断されるストリーム                                         | デルタはリプレイされません。[再接続手順](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming#reconnect-without-missing-events)に従ってください。ストリームを再度開き、イベント履歴を一覧表示します。履歴には、切断中に発行されたバッファリングされたイベントが含まれ、プレビューが待っていた `agent.message` も含まれます。 |
| ストリームURLで404                                              | パスまたはIDが間違っているか、リクエストに managed-agents のベータヘッダーがまったく含まれていません。スレッドエンドポイントはベータ限定のため、ヘッダーがないと存在しません。                                                                                                                                       |
| `event_deltas` を示す400                                     | `agent.message` と `agent.thinking` のみが受け付けられます。                                                                                                                                                                                        |

## 次のステップ

<CardGroup cols={2}>
  <Card title="セッションイベントストリーム" icon="lightning" href="https://platform.claude.com/docs/ja/managed-agents/events-and-streaming">
    イベントを送信し、レスポンスをストリーミングし、実行中のセッションを中断またはリダイレクトします。
  </Card>

  <Card title="マルチエージェントオーケストレーション" icon="stack" href="https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration">
    単一のセッション内で複数のエージェントを連携させます。
  </Card>
</CardGroup>
