---
title: 使用事件增量預覽回應
url: https://platform.claude.com/docs/zh-TW/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/zh-TW/managed-agents/events-and-streaming)。每個事件只會在產生它的模型請求完成後才發出。「Event deltas」（事件增量）讓您能在模型仍在生成文字時，以即時預覽的方式逐步呈現該文字。

預覽是一種盡力而為的顯示輔助，緩衝的 `agent.message` 始終是權威紀錄。忽略預覽的用戶端仍會收到完整且正確的串流。

## 選擇啟用預覽

預覽是依每個串流連線選擇啟用的。請在您讀取的串流中加入 `event_deltas[]` 查詢參數，並針對每個您想預覽的事件類型重複一次。可接受的值為 `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/zh-TW/managed-agents/event-deltas#preview-session-thread-events)上。

`[]` 是 shell 的 glob 模式，因此每當您在 shell 中建構請求時，請為 URL 加上引號。範例將方括號百分比編碼為 `%5B%5D`，這樣也可行。

### 預覽事件

當預覽的事件開始時，串流會發出一個 `event_start`，其中帶有即將到來之事件的類型和 `id`：

```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/zh-TW/build-with-claude/streaming)不同的傳輸格式，而這種差異是刻意的。預覽的 `agent.message` 只會有一個 `event_start`，之後僅接著 `event_delta` 事件。沒有每個內容區塊的開始或停止事件，預覽事件本身也沒有停止事件。增量類型是 `content_delta`，而不是 `content_block_delta`。為 Messages API 撰寫的累加器程式碼無法原封不動地沿用。
</Note>

## 累加與調和

每個支援事件增量的 SDK 都包含一個[累加器輔助工具](https://platform.claude.com/docs/zh-TW/managed-agents/event-deltas#sdk-accumulator-helpers)，可為您處理 `index` 的記錄工作。當您需要自訂記錄方式時，本節中的手動模式適用於所有語言。請將其套用於產生的事件類型。

在手動模式中，將預覽文字保存在以 `(event_id, index)` 為鍵的暫存對應表中，並將緩衝事件視為紀錄。依每個模型請求調和兩者。

一個回合以單一 `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/zh-TW/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. 收到 `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` 仍然會抵達。

此模式依賴兩項保證：

* 以 `(event_id, index)` 為鍵，依抵達順序串接預覽的增量，會得到緩衝事件中 `content[index].text` 的前綴。它不一定是完整文字，因為增量可能會[在負載下被捨棄](https://platform.claude.com/docs/zh-TW/managed-agents/event-deltas#limitations)。
* 一個連線針對每個 `event_id` 最多發出一個 `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">
    此工作流程需要的邏輯超出單一 shell 命令所能處理的範圍。請使用 [Claude SDK](https://platform.claude.com/docs/zh-TW/cli-sdks-libraries/overview) 來執行。
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    此工作流程需要的邏輯超出單一 shell 命令所能處理的範圍。請使用 [Claude SDK](https://platform.claude.com/docs/zh-TW/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":
                  # 不會再有 delta 傳入。關閉所有
                  # 緩衝事件始終未抵達的預覽。
                  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 並開啟快照。Delta 與
        //    緩衝事件帶有相同的 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. 不會再有 delta 傳入。關閉任何從未調和的預覽。
        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.",
                  },
              ],
          },
      ],
  });

  // 依 (event id, content index) 累積預覽片段。隨後緩衝的
  // 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:
  			// 此請求不會再有更多 delta。累加器
  			// 會在此捨棄其快照，關閉任何從未
  			// 被緩衝的 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 -> {
                  // 不會再有 delta。關閉所有緩衝事件始終未抵達的預覽。
                  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
  # 選擇啟用事件 deltas：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
  # 才是權威版本，會取代 deltas 累積的任何內容。
  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
      # 不會再有 deltas。關閉任何從未調和的預覽。
      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/zh-TW/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/zh-TW/managed-agents/event-deltas#accumulate-and-reconcile)模式可照原樣套用。請為每個串流連線執行一個累加器實例。

<CodeGroup>
  ```bash cURL
  # thread 串流接受與工作階段串流相同的 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
  # thread 串流接受與 session 串流相同的 event_deltas 參數，
  # 每個要預覽的事件類型各使用一個 --event-delta 旗標。
  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#
  // 列出工作階段的 thread 並挑選子 thread：子 thread 的
  // parent_thread_id 不為 null，而主要 thread 的 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);

  // 子 thread 的串流接受與工作階段串流相同的
  // 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 參數；每個串流連線執行一個讀取迴圈。
  	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;

  // 列出工作階段的執行緒並選取子執行緒：子執行緒的 parentThreadID 不為 null，
  // 而主要執行緒的 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/zh-TW/managed-agents/reference#event-types) 時結束，這是在工作階段執行緒的回合完成且執行緒進入閒置狀態時發出的事件。

## 限制

* **盡力而為：** 在負載下，伺服器可能會捨棄某個事件的增量。發生這種情況時，您會收到文字的連續前綴，之後該事件不會再有任何增量。緩衝的 `agent.message` 仍會完整抵達。切勿將累積的預覽視為最終結果。
* **重新連線時不重播：** 增量只會在選擇啟用的連線開啟期間傳遞給該連線。這同樣適用於工作階段層級串流和每個工作階段執行緒串流。在模型請求開始後才開啟的連線，不會收到該進行中事件的任何增量。無法重新請求遺漏的增量。
* **單一執行緒，僅限文字：** 預覽涵蓋[連線正在讀取的執行緒](https://platform.claude.com/docs/zh-TW/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/zh-TW/managed-agents/events-and-streaming#reconnect-without-missing-events)操作：重新開啟串流並列出事件歷史記錄。歷史記錄包含您中斷連線期間發出的所有緩衝事件，包括您的預覽正在等待的 `agent.message`。 |
| 串流 URL 傳回 404                             | 路徑或某個 ID 錯誤，或者請求完全沒有帶上 managed-agents beta 標頭。執行緒端點受 beta 限制，因此沒有該標頭時它們並不存在。                                                                                                                          |
| 傳回指明 `event_deltas` 的 400                 | 只接受 `agent.message` 和 `agent.thinking`。                                                                                                                                                               |

## 後續步驟

<CardGroup cols={2}>
  <Card title="工作階段事件串流" icon="lightning" href="https://platform.claude.com/docs/zh-TW/managed-agents/events-and-streaming">
    傳送事件、串流回應，並在執行途中中斷或重新導向您的工作階段。
  </Card>

  <Card title="多代理協調" icon="stack" href="https://platform.claude.com/docs/zh-TW/managed-agents/multiagent-orchestration">
    在單一工作階段中協調多個代理。
  </Card>
</CardGroup>
