---
title: Prévisualiser les réponses avec les deltas d'événements
url: https://platform.claude.com/docs/fr/managed-agents/event-deltas
description: Affichez le texte de réponse de l'agent sous forme d'aperçu en direct pendant que le modèle est encore en train de le générer.
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

Par défaut, le texte de réponse de l'agent parvient au [flux d'événements de session](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming) sous forme d'événements `agent.message` mis en mémoire tampon. Chacun n'est émis qu'une fois terminée la requête au modèle qui l'a produit. Les « event deltas » (deltas d'événements) vous permettent d'afficher ce texte de manière incrémentale, sous forme d'aperçu en direct, pendant que le modèle est encore en train de le générer.

Les aperçus sont une aide à l'affichage fournie au mieux, et le `agent.message` mis en mémoire tampon constitue toujours l'enregistrement de référence. Un client qui ignore les aperçus reçoit tout de même un flux complet et correct.

## Activer les aperçus

Les aperçus s'activent par connexion de flux. Ajoutez le paramètre de requête `event_deltas[]` au flux que vous lisez, et répétez-le une fois pour chaque type d'événement que vous souhaitez prévisualiser. Les valeurs acceptées sont `agent.message` et `agent.thinking`. Toute autre valeur renvoie une erreur 400, tout comme une requête comportant plus de 100 valeurs.

Les deux points de terminaison de flux acceptent ce paramètre :

* **Flux au niveau de la session :** `GET /v1/sessions/{session_id}/events/stream`
* **Flux de fil de session :** `GET /v1/sessions/{session_id}/threads/{thread_id}/stream`

Les aperçus d'un sous-agent apparaissent sur [le propre flux de fil de ce sous-agent](https://platform.claude.com/docs/fr/managed-agents/event-deltas#preview-session-thread-events).

`[]` est un motif de glob du shell, donc mettez l'URL entre guillemets chaque fois que vous construisez la requête dans un shell. Les exemples encodent les crochets en pourcentage sous la forme `%5B%5D`, ce qui fonctionne également.

### Événements d'aperçu

Lorsqu'un événement prévisualisé commence, le flux émet un `event_start` portant le type et l'`id` de l'événement à venir :

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

Pour `agent.message`, le début est suivi d'événements `event_delta` portant du texte incrémental. Chaque delta désigne l'événement qu'il prolonge dans `event_id` et le bloc de contenu qu'il prolonge dans `delta.index` :

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

Pour `agent.thinking`, seul l'`event_start` est émis, pour signaler qu'un bloc de réflexion a commencé. Aucun événement `event_delta` ne suit. L'événement `agent.thinking` mis en mémoire tampon qui conclut l'aperçu est un signal de progression et ne contient aucun contenu de réflexion.

Contrairement aux événements persistés, `event_start` et `event_delta` n'ont pas d'`id` ni de `processed_at` propres. Le seul identifiant qu'ils portent est l'`id` de l'événement qu'ils prévisualisent. Leurs chaînes de type font également exception à la convention de nommage `{domain}.{action}` des événements persistés.

<Note>
  Les deltas d'événements utilisent un format de transmission différent de celui du [streaming de messages](https://platform.claude.com/docs/fr/build-with-claude/streaming), et cette différence est intentionnelle. Un `agent.message` prévisualisé reçoit un seul `event_start` suivi uniquement d'événements `event_delta`. Il n'y a pas d'événements de début ou de fin par bloc de contenu, ni d'événement de fin pour l'événement prévisualisé lui-même. Le type de delta est `content_delta`, et non `content_block_delta`. Le code d'accumulation écrit pour l'API Messages ne peut pas être réutilisé tel quel.
</Note>

## Accumuler et réconcilier

Chaque SDK qui prend en charge les deltas d'événements inclut un [assistant d'accumulation](https://platform.claude.com/docs/fr/managed-agents/event-deltas#sdk-accumulator-helpers) qui gère pour vous la comptabilité des `index`. Le modèle manuel de cette section fonctionne dans tous les langages lorsque vous avez besoin d'une comptabilité personnalisée. Appliquez-le aux types d'événements générés.

Dans le modèle manuel, conservez le texte d'aperçu dans une table temporaire indexée par `(event_id, index)`, et traitez l'événement mis en mémoire tampon comme l'enregistrement de référence. Réconciliez les deux pour chaque requête au modèle.

Un tour s'ouvre avec un seul événement `session.status_running`. Lors d'un tour qui se termine normalement, chaque requête au modèle produit ensuite ces événements, dans l'ordre :

1. `span.model_request_start`
2. `event_start`
3. Les événements `event_delta`
4. Le `agent.message` mis en mémoire tampon
5. [`span.model_request_end`](https://platform.claude.com/docs/fr/managed-agents/reference#event-types) (dans l'onglet Span events)

Sur le réseau, voici la partie prévisualisée de cette séquence, entrelacée avec les autres événements mis en mémoire tampon de la connexion :

```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": [...]}
```

La ligne `event_delta` se répète une fois par fragment de texte. Traitez chaque événement à son arrivée :

1. Sur `event_start`, notez l'`id` annoncé. Les identifiants concordent toujours : `event_start.event.id`, chaque `event_delta.event_id` et l'`id` du `agent.message` mis en mémoire tampon ont la même valeur.
2. Sur chaque `event_delta`, ajoutez `delta.content.text` à l'entrée située à `(event_id, delta.index)` et affichez le texte en cours. Le premier delta pour un `index` crée cette entrée.
3. Lorsque le `agent.message` mis en mémoire tampon arrive, associez-le par `id`, supprimez l'aperçu accumulé et affichez plutôt le contenu du message.
4. Sur `span.model_request_end`, fermez tout aperçu qui n'a pas été réconcilié par son événement mis en mémoire tampon. Aucun autre delta n'arrivera pour lui. Si le tour rencontre une erreur ou est interrompu, l'événement mis en mémoire tampon pourrait ne jamais arriver, mais `span.model_request_end` arrive quand même.

Ce modèle repose sur deux garanties :

* La concaténation des deltas d'un aperçu dans leur ordre d'arrivée, indexés par `(event_id, index)`, donne un préfixe de `content[index].text` dans l'événement mis en mémoire tampon. Ce n'est pas nécessairement le texte entier, car des deltas peuvent être [abandonnés en cas de charge](https://platform.claude.com/docs/fr/managed-agents/event-deltas#limitations).
* Une connexion émet au plus un `event_start` par `event_id`, et l'événement mis en mémoire tampon est le dernier élément que cette connexion délivre pour cet `id`.

### Assistants d'accumulation des SDK

L'assistant de chaque SDK gère la comptabilité des `index` (csharp, go: `Index`). Les assistants Go, Java, Ruby et C# indexent également l'aperçu en cours d'accumulation par l'`id` (csharp, go: `ID`) de l'événement. Avec les assistants Python, TypeScript et PHP, gérez vous-même cette table et intégrez chaque delta dans l'entrée correspondant à son `id` (csharp, go: `ID`).

Les exemples suivants activent les aperçus `agent.message` et les réconcilient avec l'événement mis en mémoire tampon :

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Ce flux de travail nécessite plus de logique qu'une seule commande shell. Utilisez le [SDK Claude](https://platform.claude.com/docs/fr/cli-sdks-libraries/overview) pour l'exécuter.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Ce flux de travail nécessite plus de logique qu'une seule commande shell. Utilisez le [SDK Claude](https://platform.claude.com/docs/fr/cli-sdks-libraries/overview) pour l'exécuter.
  </CodeGroupItem>

  ```python Python
  # Instantanés d'aperçu, indexés par id d'événement. accumulate_managed_agents_event intègre chaque
  # event_start / event_delta dans un instantané agent.message ; l'agent.message
  # mis en tampon le remplace.
  previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}

  # Activer les aperçus agent.message sur cette connexion
  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":
                  # L'événement mis en tampon fait foi : il remplace et clôt l'aperçu
                  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":
                  # Plus aucun delta n'arrivera. Fermer tout aperçu dont
                  # l'événement mis en tampon n'est jamais arrivé.
                  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
  // Instantanés d'aperçu, indexés par id d'événement. `accumulateManagedAgentsEvent`
  // intègre les aperçus event_start / event_delta dans un instantané agent.message.
  const previews = new Map<string, BetaManagedAgentsAgentMessageEvent>();

  // Activer les aperçus agent.message pour cette connexion uniquement
  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. Noter l'id annoncé et ouvrir l'instantané. Les deltas et l'
        //    événement mis en tampon portent le même 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. Intégrer le fragment dans l'instantané et l'afficher
        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. L'événement mis en tampon fait foi : il remplace et clôt l'aperçu
        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. Plus aucun delta n'arrivera. Clore tout aperçu jamais réconcilié.
        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#
  // Activer les deltas d'événements : les événements agent.message sont prévisualisés au fil de leur production.
  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.",
                  },
              ],
          },
      ],
  });

  // Accumuler les fragments de prévisualisation par (id d'événement, index de contenu). Le
  // agent.message mis en tampon qui suit porte le contenu complet, il remplace donc la
  // prévisualisation accumulée au lieu de s'y ajouter.
  Dictionary<string, SortedDictionary<long, string>> previews = [];

  await foreach (var streamEvent in stream.Enumerate())
  {
      if (streamEvent.TryPickStartEvent(out var start))
      {
          // Une prévisualisation ouverte pour l'événement portant cet id. Ce stream n'active que
          // les deltas agent.message ; TryPick* renvoie false au lieu de lever une exception,
          // donc les autres types de prévisualisation (y compris ceux ajoutés plus tard) sont ignorés.
          if (start.Event.TryPickAgentMessage(out var preview))
          {
              Console.WriteLine($"event_start             {preview.Type.Raw()} {preview.ID}");
          }
      }
      else if (streamEvent.TryPickDeltaEvent(out var delta))
      {
          // Insérer à un nouvel index, ajouter à un index existant
          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))
      {
          // Les deltas sont au mieux : abandonner la prévisualisation et utiliser l'événement en tampon
          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 _))
      {
          // Plus aucun delta n'arrivera ; fermer toute prévisualisation jamais réconciliée.
          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
  	// Activer les aperçus incrémentaux des événements 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)
  	}

  	// L'accumulateur regroupe les fragments event_start / event_delta en
  	// instantanés agent.message par event-id. La valeur zéro est prête à l'emploi.
  	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:
  			// L'événement mis en tampon porte le contenu complet : l'accumulateur
  			// remplace l'aperçu par celui-ci
  			fmt.Printf("agent.message           %s %q\n", event.ID, previews.AgentMessageText(event.ID))
  		case anthropic.BetaManagedAgentsSpanModelRequestEndEvent:
  			// Plus aucun delta n'arrivera pour cette requête. L'accumulateur
  			// abandonne ici ses instantanés, fermant tout aperçu jamais
  			// réconcilié par un agent.message mis en tampon.
  			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
  // Texte d'aperçu, indexé par ID d'événement puis index de contenu. L'agent.message en tampon le remplace.
  Map<String, Map<Long, StringBuilder>> previews = new HashMap<>();

  // Activer les aperçus agent.message sur cette connexion
  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 -> {
                  // L'événement en tampon fait foi : supprimer son aperçu, afficher son contenu
                  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 -> {
                  // Plus aucun delta n'arrivera. Fermer tout aperçu dont l'événement en tampon n'est jamais arrivé.
                  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;

  // Instantanés d'aperçu, indexés par id d'événement. EventAccumulator::accumulate() ajoute chaque
  // event_start / event_delta à un instantané agent.message ; l'agent.message
  // mis en tampon le remplace.
  $previews = [];

  // Le texte d'un instantané ou d'un événement agent.message
  $textOf = fn (ManagedAgentsAgentMessageEvent $message): string => implode(
      '',
      array_map(
          fn ($block) => $block->text,
          array_filter(
              $message->content,
              fn ($block) => $block instanceof ManagedAgentsTextBlock,
          ),
      ),
  );

  // Activez les aperçus agent.message sur cette connexion.
  $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:
              // Ignorez un delta tardif pour un aperçu déjà remplacé ou fermé.
              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:
              // L'événement mis en tampon fait foi : il remplace et ferme l'aperçu.
              unset($previews[$event->id]);
              printf("agent.message           %s %s\n", $event->id, json_encode($textOf($event)));
              break;
          case $event instanceof ManagedAgentsSpanModelRequestEndEvent:
              // Plus aucun delta n'arrivera. Fermez tout aperçu dont
              // l'événement mis en tampon n'est jamais arrivé.
              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
  # Activer les deltas d'événements : les aperçus agent.message arrivent en fragments incrémentaux.
  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."}]
    }]
  )

  # Accumuler les fragments d'aperçu par (event_id, index) dans des tampons explicitement mutables
  # (`+""`) pour que `<<` puisse ajouter sur place. L'agent.message mis en tampon avec
  # le même id fait autorité et remplace ce que les deltas ont construit.
  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
      # Remplacer : abandonner l'aperçu accumulé et afficher l'événement complet.
      buffers.delete(event.id)
      puts "agent.message           #{event.id} #{event.content.map(&:text).join.inspect}"
    when Anthropic::Beta::Sessions::BetaManagedAgentsSpanModelRequestEndEvent
      # Plus aucun delta n'arrivera. Fermer tout aperçu jamais réconcilié.
      buffers.each_key { |event_id| puts "span.model_request_end  closing preview for #{event_id}" }
      buffers.clear
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      break
    else
      # ignorer les autres types d'événements
    end
  end
  ```
</CodeGroup>

## Prévisualiser les événements des fils de session

Dans une session [multi-agents](https://platform.claude.com/docs/fr/managed-agents/multiagent-orchestration), chaque fil de session possède son propre flux d'événements. Il accepte le même paramètre `event_deltas[]` avec les mêmes valeurs.

Une connexion ne prévisualise que le fil qu'elle lit. Le flux au niveau de la session prévisualise le fil principal, et les aperçus d'un fil enfant n'y sont jamais republiés. Pour suivre le texte d'un sous-agent pendant que le modèle le génère, ouvrez le flux de fil de ce sous-agent.

Le chemin d'un flux de fil se termine par `/threads/{thread_id}/stream`. `/events/stream` n'existe qu'au niveau de la session, il n'y a donc pas de point de terminaison `/threads/{thread_id}/events/stream`.

`event_start` et `event_delta` ont la même forme sur un flux de fil que sur le flux au niveau de la session, et le modèle [accumuler et réconcilier](https://platform.claude.com/docs/fr/managed-agents/event-deltas#accumulate-and-reconcile) s'applique tel quel. Exécutez une instance d'accumulateur par connexion de flux.

<CodeGroup>
  ```bash cURL
  # Le flux du thread accepte le même paramètre event_deltas[] que le flux de session.
  # Encodez les crochets en pourcentage (%5B%5D) et mettez l'URL entre guillemets.
  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
  # Le stream de thread accepte le même paramètre event_deltas que le stream de session,
  # un flag --event-delta par type d'événement à prévisualiser.
  ant beta:sessions:threads:events stream \
    --session-id "$SESSION_ID" \
    --thread-id "$THREAD_ID" \
    --event-delta agent.message
  ```

  ```python Python
  # Lister les threads de la session et choisir un enfant : les threads enfants ont un
  # parent_thread_id non nul, et le parent_thread_id du thread principal est null.
  child_thread = next(
      thread
      for thread in client.beta.sessions.threads.list(session.id)
      if thread.parent_thread_id is not None
  )

  # Le stream du thread enfant accepte le même paramètre event_deltas que le
  # stream de session.
  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":
                  # L'événement mis en tampon fait foi ; afficher son contenu
                  print()
                  for block in event.content:
                      if block.type == "text":
                          print(block.text, end="")
                  print()
              case "session.thread_status_idle":
                  break
  ```

  ```typescript TypeScript
  // Lister les threads de la session et choisir un enfant : les threads enfants ont un
  // parent_thread_id non nul, et le parent_thread_id du thread principal est nul.
  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");
  }

  // Le stream du thread enfant accepte le même paramètre event_deltas que le
  // stream de session.
  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": {
        // L'événement mis en tampon fait foi ; afficher son contenu.
        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#
  // Lister les threads de la session et choisir un enfant : les threads enfants ont un
  // parent_thread_id non nul, et le parent_thread_id du thread principal est nul.
  var threads = await client.Beta.Sessions.Threads.List(session.ID);
  var childThread = threads.Items.First(thread => thread.ParentThreadID is not null);

  // Le stream du thread enfant accepte le même paramètre event_deltas que le
  // stream de session.
  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))
      {
          // L'événement en tampon fait foi ; afficher son contenu.
          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
  	// Lister les threads de la session et choisir un enfant : les threads enfants ont un
  	// parent_thread_id non nul, et le parent_thread_id du thread principal est nul.
  	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)
  	}

  	// Le stream du thread enfant accepte le même paramètre event_deltas que le
  	// stream de session ; exécuter une boucle de lecture par connexion de stream.
  	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:
  			// L'événement mis en tampon fait foi ; afficher son contenu.
  			fmt.Println()
  			// liste à type concret : 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
  // Lister les threads de la session et choisir un enfant : les threads enfants ont un
  // parent_thread_id non nul, et le parent_thread_id du thread principal est null.
  var childThread = client.beta().sessions().threads().list(session.id()).autoPager().stream()
      .filter(thread -> thread.parentThreadId().isPresent())
      .findFirst()
      .orElseThrow();

  // Le stream du thread enfant accepte le même paramètre event_deltas que le stream
  // de session. Sa classe de params a le même nom simple que celle de session, donc la qualifier.
  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 -> {
                  // L'événement en tampon est l'enregistrement qui fait foi ; afficher son contenu.
                  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;

  // Listez les threads de la session et choisissez un enfant : les threads enfants ont un
  // parentThreadID non nul, et le parentThreadID du thread principal est nul.
  $childThread = null;
  foreach ($client->beta->sessions->threads->list($session->id)->pagingEachItem() as $thread) {
      if ($thread->parentThreadID !== null) {
          $childThread = $thread;
          break;
      }
  }

  // Le stream du thread enfant accepte le même paramètre eventDeltas que le
  // stream de la session.
  $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:
              // L'événement mis en tampon est l'enregistrement de référence ; affichez son contenu.
              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
  # Lister les threads de la session et choisir un enfant : les threads enfants ont un
  # parent_thread_id non nul, et le parent_thread_id du thread principal est nul.
  child_thread = client.beta.sessions.threads.list(session.id).to_enum.find { it.parent_thread_id }

  # Le stream du thread enfant accepte le même paramètre event_deltas que le
  # stream de session.
  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
      # L'événement mis en tampon fait autorité ; afficher son contenu.
      puts
      event.content.each { print it.text }
      puts
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionThreadStatusIdleEvent
      break
    else
      # ignorer les autres types d'événements
    end
  end
  ```
</CodeGroup>

La boucle de lecture se termine sur [`session.thread_status_idle`](https://platform.claude.com/docs/fr/managed-agents/reference#event-types), l'événement émis lorsque le tour du fil de session se termine et que le fil devient inactif.

## Limitations

* **Au mieux :** en cas de charge, le serveur peut abandonner des deltas pour un événement. Dans ce cas, vous recevez un préfixe contigu du texte, puis plus aucun delta pour cet événement. Le `agent.message` mis en mémoire tampon arrive tout de même complet. Ne considérez jamais un aperçu accumulé comme définitif.
* **Pas de relecture à la reconnexion :** les deltas ne sont délivrés qu'à la connexion qui les a activés, tant qu'elle est ouverte. Cela s'applique aussi bien au flux au niveau de la session qu'à chaque flux de fil de session. Une connexion ouverte après le début d'une requête au modèle ne reçoit aucun delta pour cet événement en cours. Il n'existe aucun moyen de redemander les deltas manqués.
* **Un seul fil, texte uniquement :** les aperçus couvrent le texte de l'assistant sur [le fil que lit la connexion](https://platform.claude.com/docs/fr/managed-agents/event-deltas#preview-session-thread-events). L'utilisation d'outils, les résultats d'outils et les résultats MCP ne sont jamais prévisualisés.
* **Jamais persistés :** `event_start` et `event_delta` n'existent que sur le flux en direct. Ils n'apparaissent pas dans l'historique des événements de la session (`GET /v1/sessions/{session_id}/events`) ni dans l'historique des événements d'aucun fil de session.

## Dépanner les aperçus

| Ce que vous voyez                                                                          | Ce que cela signifie                                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Un flux avec des événements mis en mémoire tampon mais sans `event_start` ni `event_delta` | La connexion que vous lisez n'a pas activé les aperçus, ou le tour n'a jamais concerné le fil que vous diffusez. `event_deltas[]` s'applique par connexion, et non par session. Pour savoir quel fil s'est exécuté, listez les fils de la session (`GET /v1/sessions/{session_id}/threads`).                                                                                                  |
| Un flux qui s'interrompt pendant un aperçu                                                 | Les deltas ne sont pas rejoués. Suivez la [procédure de reconnexion](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#reconnect-without-missing-events) : rouvrez le flux et listez l'historique des événements. L'historique inclut tous les événements mis en mémoire tampon émis pendant votre déconnexion, y compris le `agent.message` qu'attendait votre aperçu. |
| Une erreur 404 sur l'URL du flux                                                           | Le chemin ou un identifiant est incorrect, ou la requête ne comporte aucun en-tête bêta managed-agents. Les points de terminaison de fil sont soumis à la bêta, donc sans l'en-tête ils n'existent pas.                                                                                                                                                                                       |
| Une erreur 400 mentionnant `event_deltas`                                                  | Seuls `agent.message` et `agent.thinking` sont acceptés.                                                                                                                                                                                                                                                                                                                                      |

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Flux d'événements de session" icon="lightning" href="https://platform.claude.com/docs/fr/managed-agents/events-and-streaming">
    Envoyez des événements, diffusez des réponses en streaming, et interrompez ou redirigez votre session en cours d'exécution.
  </Card>

  <Card title="Orchestration multi-agents" icon="stack" href="https://platform.claude.com/docs/fr/managed-agents/multiagent-orchestration">
    Coordonnez plusieurs agents au sein d'une même session.
  </Card>
</CardGroup>
