---
title: Flux d'événements de session
url: https://platform.claude.com/docs/fr/managed-agents/events-and-streaming
description: Envoyez des événements, diffusez les réponses en streaming, et interrompez ou redirigez votre session en cours d'exécution.
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

La communication avec Claude Managed Agents est basée sur les événements. Vous ouvrez un flux pour suivre une session, envoyez des événements pour la diriger, et lui répondez lorsqu'elle se met en pause en attente d'une entrée.

## Types d'événements

Les événements circulent dans deux directions : vous envoyez des événements à l'agent, et la session vous renvoie des événements.

* **Événements que vous envoyez :** les événements `user.*` démarrent une session et l'orientent au fil de sa progression. Les événements [`system.message`](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#send-system-messages) ajoutent du contexte au niveau système.
* **Événements que vous recevez :** les événements de session, les événements de span et les événements d'agent rendent compte de l'état de la session et de la progression de l'agent.

Ces chaînes de type d'événement suivent une convention de nommage `{domain}.{action}`. Consultez [Types d'événements](https://platform.claude.com/docs/fr/managed-agents/reference#event-types) dans la référence pour le catalogue complet.

Les [types d'événements webhook](https://platform.claude.com/docs/fr/managed-agents/webhooks#supported-event-types) sont distincts, et certains de leurs noms diffèrent de ceux du flux. Par exemple, les webhooks utilisent `session.status_idled` plutôt que `session.status_idle`.

## Diffuser les événements en streaming

Diffusez en « streaming » (diffusion en flux) les événements de la session pour recevoir des mises à jour en temps réel pendant que l'agent travaille. Un flux ne délivre que les événements émis après son ouverture ; ouvrez donc le flux avant d'envoyer des événements afin d'éviter une « race condition » (situation de concurrence).

<CodeGroup>
  ```bash cURL
  # Ouvrez le flux avant d'envoyer le premier événement : seuls les événements ultérieurs sont livrés.
  curl --fail-with-body -sS -N \
    "https://api.anthropic.com/v1/sessions/$SESSION_ID/events/stream?beta=true" \
    -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
  # Ouvrez le stream avant d'envoyer le premier événement : seuls les événements ultérieurs sont livrés.
  ant beta:sessions:events stream --session-id "$SESSION_ID"
  ```

  ```python Python
  # Ouvrir d'abord le stream, puis envoyer le message utilisateur
  with client.beta.sessions.events.stream(session.id) as stream:
      client.beta.sessions.events.send(
          session.id,
          events=[
              {
                  "type": "user.message",
                  "content": [{"type": "text", "text": "Summarize the repo README"}],
              },
          ],
      )

      for event in stream:
          match event.type:
              case "agent.message":
                  for block in event.content:
                      if block.type == "text":
                          print(block.text, end="")
              case "session.status_idle":
                  break
              case "session.error":
                  error_message = event.error.message if event.error else "unknown"
                  print(f"\n[Error: {error_message}]")
                  break
  ```

  ```typescript TypeScript
  // Ouvrir d'abord le stream, puis envoyer le message utilisateur
  const stream = await client.beta.sessions.events.stream(session.id);
  await client.beta.sessions.events.send(session.id, {
    events: [
      {
        type: "user.message",
        content: [{ type: "text", text: "Summarize the repo README" }]
      }
    ]
  });

  events: for await (const event of stream) {
    switch (event.type) {
      case "agent.message":
        for (const block of event.content) {
          if (block.type === "text") {
            process.stdout.write(block.text);
          }
        }
        break;
      case "session.status_idle":
        break events;
      case "session.error":
        console.log(`\n[Error: ${event.error?.message ?? "unknown"}]`);
        break events;
    }
  }
  ```

  ```csharp C#
  // Ouvrir d'abord le stream, puis envoyer le message utilisateur
  using var stream = await client.Beta.Sessions.Events.WithRawResponse.StreamStreaming(session.ID);
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserMessageEventParams
          {
              Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage,
              Content =
              [
                  new BetaManagedAgentsTextBlock
                  {
                      Type = BetaManagedAgentsTextBlockType.Text,
                      Text = "Summarize the repo README",
                  },
              ],
          },
      ],
  });

  await foreach (var streamEvent in stream.Enumerate())
  {
      if (streamEvent.Value is BetaManagedAgentsAgentMessageEvent message)
      {
          foreach (var block in message.Content)
          {
              if (block.Value is BetaManagedAgentsTextBlock textBlock)
              {
                  Console.Write(textBlock.Text);
              }
          }
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionStatusIdleEvent)
      {
          break;
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionErrorEvent error)
      {
          Console.WriteLine($"\n[Error: {error.Error?.Message ?? "unknown"}]");
          break;
      }
  }
  ```

  ```go Go
  	// Ouvrir d'abord le stream, puis envoyer le message utilisateur
  	stream := client.Beta.Sessions.Events.StreamEvents(ctx, session.ID, anthropic.BetaSessionEventStreamParams{})
  	defer stream.Close()

  	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: "Summarize the repo README",
  					},
  				}},
  			},
  		}},
  	}); err != nil {
  		panic(err)
  	}

  events:
  	for stream.Next() {
  		switch event := stream.Current().AsAny().(type) {
  		case anthropic.BetaManagedAgentsAgentMessageEvent:
  			// liste à type concret : BetaManagedAgentsTextBlock
  			for _, block := range event.Content {
  				fmt.Print(block.Text)
  			}
  		case anthropic.BetaManagedAgentsSessionStatusIdleEvent:
  			break events
  		case anthropic.BetaManagedAgentsSessionErrorEvent:
  			fmt.Printf("\n[Error: %s]\n", cmp.Or(event.Error.Message, "unknown"))
  			break events
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  ```

  ```java Java
  // Ouvrir d'abord le stream, puis envoyer le message utilisateur
  try (var stream = client.beta().sessions().events().streamStreaming(session.id())) {
      client.beta().sessions().events().send(
          session.id(),
          EventSendParams.builder()
              .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
                  .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
                  .addTextContent("Summarize the repo README")
                  .build())
              .build()
      );

      Iterable<BetaManagedAgentsStreamSessionEvents> events = stream.stream()::iterator;
      events:
      for (var event : events) {
          switch (event.type().value()) {
              case AGENT_MESSAGE -> event.asAgentMessage().content().forEach(block -> block.text().ifPresent(textBlock -> IO.print(textBlock.text())));
              case SESSION_STATUS_IDLE -> {
                  break events;
              }
              case SESSION_ERROR -> {
                  // Le champ `message` couvre toutes les variantes d'erreur ; lisez-le depuis le JSON brut.
                  var errorMessage =
                      event.asSessionError().error()._json().orElse(null) instanceof JsonObject json
                          ? json.values().get("message").asStringOrThrow()
                          : "unknown";
                  IO.println("\n[Error: " + errorMessage + "]");
                  break events;
              }
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\Sessions\Events\ManagedAgentsAgentMessageEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsSessionErrorEvent;
  use Anthropic\Beta\Sessions\Events\ManagedAgentsTextBlock;

  // Ouvrez d'abord le stream, puis envoyez le message utilisateur.
  $stream = $client->beta->sessions->events->streamStream($session->id);
  $client->beta->sessions->events->send(
      $session->id,
      events: [
          [
              'type' => 'user.message',
              'content' => [['type' => 'text', 'text' => 'Summarize the repo README']],
          ],
      ],
  );

  foreach ($stream as $event) {
      match (true) {
          $event instanceof ManagedAgentsAgentMessageEvent => array_walk(
              $event->content,
              static fn ($block) => $block instanceof ManagedAgentsTextBlock ? print($block->text) : null,
          ),
          $event instanceof ManagedAgentsSessionErrorEvent => printf("\n[Error: %s]", $event->error?->message ?? 'unknown'),
          default => null,
      };
      if ($event->type === 'session.status_idle' || $event->type === 'session.error') {
          break;
      }
  }
  $stream->close();
  ```

  ```ruby Ruby
  # Ouvrir d'abord le stream, puis envoyer le message utilisateur
  stream = client.beta.sessions.events.stream_events(session.id)

  client.beta.sessions.events.send_(
    session.id,
    events: [{
      type: "user.message",
      content: [{type: "text", text: "Summarize the repo README"}]
    }]
  )

  stream.each do |event|
    case event
    when Anthropic::Beta::Sessions::BetaManagedAgentsAgentMessageEvent
      event.content.each { print it.text }
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      break
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionErrorEvent
      puts "\n[Error: #{event.error&.message || "unknown"}]"
      break
    else
      # ignorer les autres types d'événements
    end
  end
  ```
</CodeGroup>

La session signale les erreurs via l'événement `session.error`. Consultez [Types d'événements](https://platform.claude.com/docs/fr/managed-agents/reference#event-types) pour ses champs.

Le texte de réponse de l'agent arrive sous forme d'événements `agent.message` mis en mémoire tampon, chacun n'étant émis qu'une fois terminée la requête au modèle qui l'a produit. Pour afficher le texte pendant que le modèle le génère encore, consultez [Prévisualiser les réponses avec les deltas d'événements](https://platform.claude.com/docs/fr/managed-agents/event-deltas).

### Se reconnecter sans manquer d'événements

Pour vous reconnecter à une session existante sans manquer d'événements, combinez un nouveau flux avec l'historique des événements :

1. Ouvrez un nouveau flux.
2. [Listez l'historique complet des événements](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#list-past-events) pour initialiser un ensemble d'identifiants d'événements déjà vus.
3. Suivez le flux en direct, en ignorant tous les événements déjà renvoyés par la liste de l'historique.

<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
  with client.beta.sessions.events.stream(session.id) as stream:
      # Le stream est ouvert et met en mémoire tampon. Lister l'historique avant de suivre le direct.
      history = client.beta.sessions.events.list(session.id)
      seen_event_ids = {past_event.id for past_event in history}

      # Suivre les événements en direct, en ignorant ceux déjà vus
      for event in stream:
          if event.type == "event_start" or event.type == "event_delta":
              # Les aperçus de deltas ne sont pas activés sur cette connexion.
              continue
          if event.id in seen_event_ids:
              continue
          seen_event_ids.add(event.id)
          match event.type:
              case "agent.message":
                  for block in event.content:
                      if block.type == "text":
                          print(block.text, end="")
              case "session.status_idle":
                  break
  ```

  ```typescript TypeScript
  const seenEventIds = new Set<string>();
  const stream = await client.beta.sessions.events.stream(session.id);

  // Le stream est ouvert et met en tampon. Lister l'historique avant de suivre le direct.
  for await (const event of client.beta.sessions.events.list(session.id)) {
    seenEventIds.add(event.id);
  }

  // Suivre les événements en direct, en ignorant ceux déjà vus
  tail: for await (const event of stream) {
    // Les événements d'aperçu (event_start/event_delta) n'ont pas d'id de premier niveau
    if (event.type === "event_start" || event.type === "event_delta") {
      continue;
    }
    if (seenEventIds.has(event.id)) {
      continue;
    }
    seenEventIds.add(event.id);
    switch (event.type) {
      case "agent.message":
        for (const block of event.content) {
          if (block.type === "text") {
            process.stdout.write(block.text);
          }
        }
        break;
      case "session.status_idle":
        break tail;
    }
  }
  ```

  ```csharp C#
  using var stream = await client.Beta.Sessions.Events.WithRawResponse.StreamStreaming(session.ID);

  // Le stream est ouvert et met en tampon. Lister l'historique avant de suivre le direct.
  HashSet<string> seenEventIds = [];
  var history = await client.Beta.Sessions.Events.List(session.ID);
  await foreach (var pastEvent in history.Paginate())
  {
      seenEventIds.Add(pastEvent.ID);
  }

  // Suivre les événements en direct, en ignorant ceux déjà vus
  await foreach (var streamEvent in stream.Enumerate())
  {
      if (!seenEventIds.Add(streamEvent.ID))
      {
          continue;
      }
      if (streamEvent.Value is BetaManagedAgentsAgentMessageEvent message)
      {
          foreach (var block in message.Content)
          {
              if (block.Value is BetaManagedAgentsTextBlock textBlock)
              {
                  Console.Write(textBlock.Text);
              }
          }
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionStatusIdleEvent)
      {
          break;
      }
  }
  ```

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

  	// Le stream est ouvert et met en tampon. Lister l'historique avant de suivre le direct.
  	seenEventIDs := map[string]struct{}{}
  	history := client.Beta.Sessions.Events.ListAutoPaging(ctx, session.ID, anthropic.BetaSessionEventListParams{})
  	for history.Next() {
  		seenEventIDs[history.Current().ID] = struct{}{}
  	}
  	if err := history.Err(); err != nil {
  		panic(err)
  	}

  	// Suivre les événements en direct, en ignorant ceux déjà vus
  tail:
  	for stream.Next() {
  		event := stream.Current()
  		if _, seen := seenEventIDs[event.ID]; seen {
  			continue
  		}
  		seenEventIDs[event.ID] = struct{}{}
  		switch event := event.AsAny().(type) {
  		case anthropic.BetaManagedAgentsAgentMessageEvent:
  			// liste à type concret : BetaManagedAgentsTextBlock
  			for _, block := range event.Content {
  				fmt.Print(block.Text)
  			}
  		case anthropic.BetaManagedAgentsSessionStatusIdleEvent:
  			break tail
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  ```

  ```java Java
  try (var stream = client.beta().sessions().events().streamStreaming(session.id())) {
      // Le stream est ouvert et met en tampon. Lister l'historique avant de suivre le direct.
      // Chaque variante d'événement porte un `id` ; lisez-le depuis le JSON brut pour dédupliquer entre variantes.
      var seenEventIds = new HashSet<String>();
      for (var pastEvent : client.beta().sessions().events().list(session.id()).autoPager()) {
          if (pastEvent._json().orElseThrow() instanceof JsonObject json) {
              seenEventIds.add(json.values().get("id").asStringOrThrow());
          }
      }

      // Suivre les événements en direct ; Set.add renvoie false pour les ID déjà vus, ignorant la relecture.
      stream.stream()
          .filter(event -> event._json().orElseThrow() instanceof JsonObject json
              && seenEventIds.add(json.values().get("id").asStringOrThrow()))
          .takeWhile(event -> !event.isSessionStatusIdle())
          .filter(BetaManagedAgentsStreamSessionEvents::isAgentMessage)
          .forEach(event -> event.asAgentMessage().content()
              .forEach(block -> block.text().ifPresent(textBlock -> IO.print(textBlock.text()))));
  }
  ```

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

  $stream = $client->beta->sessions->events->streamStream($session->id);

  // Le stream est ouvert et met en tampon. Listez l'historique avant de suivre le direct.
  $seenEventIds = [];
  foreach ($client->beta->sessions->events->list($session->id)->pagingEachItem() as $event) {
      $seenEventIds[$event->id] = true;
  }

  // Suivez les événements en direct, en ignorant ceux déjà vus.
  foreach ($stream as $event) {
      if (isset($seenEventIds[$event->id])) {
          continue;
      }
      $seenEventIds[$event->id] = true;
      match (true) {
          $event instanceof ManagedAgentsAgentMessageEvent => array_walk(
              $event->content,
              static fn ($block) => $block instanceof ManagedAgentsTextBlock ? print($block->text) : null,
          ),
          default => null,
      };
      if ($event->type === 'session.status_idle') {
          break;
      }
  }
  $stream->close();
  ```

  ```ruby Ruby
  stream = client.beta.sessions.events.stream_events(session.id)

  # Le stream est ouvert et met en tampon. Lister l'historique avant de suivre le direct.
  seen_event_ids = Set.new
  client.beta.sessions.events.list(session.id).auto_paging_each { seen_event_ids << it.id }

  # Suivre les événements en direct en ignorant ceux déjà vus — Set#add? renvoie nil pour les doublons
  stream.each do |event|
    next unless seen_event_ids.add?(event.id)
    case event
    when Anthropic::Beta::Sessions::BetaManagedAgentsAgentMessageEvent
      event.content.each { print it.text }
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      break
    else
      # ignorer les autres types d'événements
    end
  end
  ```
</CodeGroup>

## Envoyer des événements

Envoyez un événement `user.message` pour démarrer ou poursuivre le travail de l'agent :

<CodeGroup>
  ```bash cURL
  curl --fail-with-body -sS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{
      "events": [
        {
          "type": "user.message",
          "content": [
            {"type": "text", "text": "Analyze the performance of the sort function in utils.py"}
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
  events:
    - type: user.message
      content:
        - type: text
          text: Analyze the performance of the sort function in utils.py
  YAML
  ```

  ```python Python
  client.beta.sessions.events.send(
      session.id,
      events=[
          {
              "type": "user.message",
              "content": [
                  {
                      "type": "text",
                      "text": "Analyze the performance of the sort function in utils.py",
                  },
              ],
          },
      ],
  )
  ```

  ```typescript TypeScript
  await client.beta.sessions.events.send(session.id, {
    events: [
      {
        type: "user.message",
        content: [
          {
            type: "text",
            text: "Analyze the performance of the sort function in utils.py"
          }
        ]
      }
    ]
  });
  ```

  ```csharp C#
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserMessageEventParams
          {
              Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage,
              Content =
              [
                  new BetaManagedAgentsTextBlock
                  {
                      Type = BetaManagedAgentsTextBlockType.Text,
                      Text = "Analyze the performance of the sort function in utils.py",
                  },
              ],
          },
      ],
  });
  ```

  ```go Go
  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: "Analyze the performance of the sort function in utils.py",
  				},
  			}},
  		},
  	}},
  }); err != nil {
  	panic(err)
  }
  ```

  ```java Java
  client.beta().sessions().events().send(
      session.id(),
      EventSendParams.builder()
          .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
              .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
              .addTextContent("Analyze the performance of the sort function in utils.py")
              .build())
          .build());
  ```

  ```php PHP
  $client->beta->sessions->events->send(
      $session->id,
      events: [
          [
              'type' => 'user.message',
              'content' => [
                  [
                      'type' => 'text',
                      'text' => 'Analyze the performance of the sort function in utils.py',
                  ],
              ],
          ],
      ],
  );
  ```

  ```ruby Ruby
  client.beta.sessions.events.send_(
    session.id,
    events: [
      {
        type: "user.message",
        content: [
          {
            type: "text",
            text: "Analyze the performance of the sort function in utils.py"
          }
        ]
      }
    ]
  )
  ```
</CodeGroup>

Chaque événement de l'historique de la session comporte un horodatage `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`), défini lorsque le traitement de l'événement se termine. Sur les événements que vous envoyez, `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) vaut `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `time.Time{}`) tant que l'événement est encore en file d'attente derrière des événements antérieurs. Les exceptions sont `user.define_outcome`, `user.custom_tool_result` et `user.tool_result`, qui sont traités dès leur réception et renvoyés avec `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) déjà renseigné.

## Répondre lorsque la session devient inactive

Un événement `session.status_idle` signifie que l'agent s'est arrêté et attend une entrée. Son `stop_reason.type` indique pourquoi :

| `stop_reason.type` | Pourquoi la session s'est arrêtée                                                                                                                     | Que faire                                                                                                                                                                        |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `end_turn`         | L'agent a terminé son tour, ou [vous l'avez interrompu](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#interrupt-the-agent). | [Envoyez un `user.message`](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#resume-an-idle-session) lorsque vous avez davantage de travail pour l'agent. |
| `requires_action`  | Un ou plusieurs appels d'outils nécessitent une réponse de votre part, comme un appel d'outil personnalisé ou une demande de confirmation.            | [Répondez à chaque appel d'outil bloquant](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#answer-tool-calls-that-pause-the-session).                    |
| `budget_reached`   | Le coût catalogue suivi de la session a atteint son [budget](https://platform.claude.com/docs/fr/managed-agents/budgets).                             | [Modifiez ou supprimez le budget](https://platform.claude.com/docs/fr/managed-agents/budgets#resume-a-session-at-its-budget).                                                    |

Aucun événement que vous envoyez ne reprend une session mise en pause à son budget. Le travail que le budget a mis en pause reprend automatiquement lorsque vous modifiez le budget pour une valeur supérieure au coût catalogue consommé, ou que vous le supprimez. Lorsque le travail reprend, la session émet un événement `workflow_run.status_running` pour chaque [exécution de workflow que le budget a mise en pause](https://platform.claude.com/docs/fr/managed-agents/workflow-runs#budgets-and-limits). Une exécution mise en pause par une interruption reste en pause ; consultez [Reprendre une session à son budget](https://platform.claude.com/docs/fr/managed-agents/budgets#resume-a-session-at-its-budget). Consultez [Lorsqu'une session atteint son budget](https://platform.claude.com/docs/fr/managed-agents/budgets#when-a-session-reaches-its-budget) pour les événements qui marquent la pause et les événements que la session accepte encore.

## Répondre aux appels d'outils qui mettent la session en pause

Une session se met en pause lorsque l'agent invoque un [outil personnalisé](https://platform.claude.com/docs/fr/managed-agents/tools#custom-tools), et lorsqu'un appel d'outil nécessite votre confirmation en vertu d'une [politique d'autorisation](https://platform.claude.com/docs/fr/managed-agents/permission-policies). Les deux pauses suivent la même séquence :

1. La session émet l'appel d'outil sous forme d'événement `agent.custom_tool_use`, `agent.tool_use` ou `agent.mcp_tool_use`.
2. La session se met en pause avec un événement `session.status_idle` dont le `stop_reason.type` est `requires_action`. Les identifiants des événements bloquants se trouvent dans le tableau `stop_reason.event_ids`.
3. Pour chaque identifiant d'événement bloquant, envoyez un événement [`user.custom_tool_result`](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#return-a-custom-tool-result) ou [`user.tool_confirmation`](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#confirm-a-tool-call). Un résultat d'outil personnalisé n'a pas besoin d'attendre l'étape 2.
4. Une fois tous les événements bloquants résolus, la session repasse à l'état `running`.

Dans une session multiagent, les événements bloquants d'un sous-agent sont également publiés sur le fil principal. Consultez [Autorisations d'outils et outils personnalisés](https://platform.claude.com/docs/fr/managed-agents/session-threads#tool-permissions-and-custom-tools).

### Renvoyer un résultat d'outil personnalisé

L'événement `agent.custom_tool_use` contient le nom et l'entrée de l'outil. Exécutez l'outil dans votre système. Envoyez ensuite un événement `user.custom_tool_result`, en passant l'identifiant de l'événement dans le paramètre `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`) avec le contenu du résultat.

Vous pouvez envoyer le résultat dès que l'événement `agent.custom_tool_use` arrive, sans attendre `session.status_idle`. La session émet tout de même `session.status_idle` avec une raison d'arrêt `requires_action` pour l'appel, et votre client peut l'ignorer. Un second résultat pour le même appel est accepté et n'a aucun effet.

Lorsque vous vous [reconnectez](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#reconnect-without-missing-events) à une session en pause, `stop_reason.event_ids` sur le dernier événement `session.status_idle` liste les appels auxquels répondre.

L'exemple suivant répond à chaque appel dès son arrivée :

<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
  with client.beta.sessions.events.stream(session.id) as stream:
      for event in stream:
          match event.type:
              case "agent.custom_tool_use":
                  # Exécuter l'outil
                  result = call_tool(event.name, event.input)

                  # Renvoyer le résultat
                  client.beta.sessions.events.send(
                      session.id,
                      events=[
                          {
                              "type": "user.custom_tool_result",
                              "custom_tool_use_id": event.id,
                              "content": [{"type": "text", "text": result}],
                          },
                      ],
                  )
              case "session.status_idle":
                  if event.stop_reason and event.stop_reason.type == "end_turn":
                      break
  ```

  ```typescript TypeScript
  const stream = await client.beta.sessions.events.stream(session.id);

  loop: for await (const event of stream) {
    switch (event.type) {
      case "agent.custom_tool_use": {
        // Exécuter l'outil
        const result = await callTool(event.name, event.input);

        // Renvoyer le résultat
        await client.beta.sessions.events.send(session.id, {
          events: [
            {
              type: "user.custom_tool_result",
              custom_tool_use_id: event.id,
              content: [{ type: "text", text: result }]
            }
          ]
        });
        break;
      }
      case "session.status_idle":
        if (event.stop_reason.type === "end_turn") {
          break loop;
        }
        break;
    }
  }
  ```

  ```csharp C#
  await foreach (var streamEvent in client.Beta.Sessions.Events.StreamStreaming(session.ID))
  {
      if (streamEvent.Value is BetaManagedAgentsAgentCustomToolUseEvent toolUse)
      {
          // Exécuter l'outil
          var result = await CallTool(toolUse.Name, toolUse.Input);

          // Renvoyer le résultat
          await client.Beta.Sessions.Events.Send(session.ID, new()
          {
              Events =
              [
                  new BetaManagedAgentsUserCustomToolResultEventParams
                  {
                      Type = BetaManagedAgentsUserCustomToolResultEventParamsType.UserCustomToolResult,
                      CustomToolUseID = toolUse.ID,
                      Content =
                      [
                          new BetaManagedAgentsTextBlock
                          {
                              Type = BetaManagedAgentsTextBlockType.Text,
                              Text = result,
                          },
                      ],
                  },
              ],
          });
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionStatusIdleEvent idle
          && idle.StopReason?.Value is BetaManagedAgentsSessionEndTurn)
      {
          break;
      }
  }
  ```

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

  loop:
  	for stream.Next() {
  		switch event := stream.Current().AsAny().(type) {
  		case anthropic.BetaManagedAgentsAgentCustomToolUseEvent:
  			// Exécuter l'outil
  			result := callTool(event.Name, event.Input)
  			// Renvoyer le résultat
  			if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  				Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  					OfUserCustomToolResult: &anthropic.BetaManagedAgentsUserCustomToolResultEventParams{
  						Type:            anthropic.BetaManagedAgentsUserCustomToolResultEventParamsTypeUserCustomToolResult,
  						CustomToolUseID: event.ID,
  						Content: []anthropic.BetaManagedAgentsUserCustomToolResultEventParamsContentUnion{{
  							OfText: &anthropic.BetaManagedAgentsTextBlockParam{
  								Type: anthropic.BetaManagedAgentsTextBlockTypeText,
  								Text: result,
  							},
  						}},
  					},
  				}},
  			}); err != nil {
  				panic(err)
  			}
  		case anthropic.BetaManagedAgentsSessionStatusIdleEvent:
  			if _, ok := event.StopReason.AsAny().(anthropic.BetaManagedAgentsSessionEndTurn); ok {
  				break loop
  			}
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  ```

  ```java Java
  try (var stream = client.beta().sessions().events().streamStreaming(session.id())) {
      loop:
      for (var event : (Iterable<BetaManagedAgentsStreamSessionEvents>) stream.stream()::iterator) {
          switch (event.type().value()) {
              case AGENT_CUSTOM_TOOL_USE -> {
                  // Exécuter l'outil
                  var toolUse = event.asAgentCustomToolUse();
                  var result = callTool(toolUse.name(), toolUse.input());

                  // Renvoyer le résultat
                  client.beta().sessions().events().send(
                      session.id(),
                      EventSendParams.builder()
                          .addEvent(BetaManagedAgentsUserCustomToolResultEventParams.builder()
                              .type(BetaManagedAgentsUserCustomToolResultEventParams.Type.USER_CUSTOM_TOOL_RESULT)
                              .customToolUseId(toolUse.id())
                              .addTextContent(result)
                              .build())
                          .build());
              }
              case SESSION_STATUS_IDLE -> {
                  if (event.asSessionStatusIdle().stopReason().isEndTurn()) {
                      break loop;
                  }
              }
          }
      }
  }
  ```

  ```php PHP
  $stream = $client->beta->sessions->events->streamStream($session->id);

  foreach ($stream as $event) {
      switch (true) {
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsAgentCustomToolUseEvent:
              // Exécuter l'outil
              $result = callTool($event->name, $event->input);

              // Renvoyer le résultat
              $client->beta->sessions->events->send(
                  $session->id,
                  events: [
                      [
                          'type' => 'user.custom_tool_result',
                          'custom_tool_use_id' => $event->id,
                          'content' => [['type' => 'text', 'text' => $result]],
                      ],
                  ],
              );
              break;
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionStatusIdleEvent:
              if ($event->stopReason instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionEndTurn) {
                  break 2;
              }
              break;
      }
  }
  ```

  ```ruby Ruby
  client.beta.sessions.events.stream_events(session.id).each do |event|
    case event
    when Anthropic::Beta::Sessions::BetaManagedAgentsAgentCustomToolUseEvent
      # Exécuter l'outil
      result = call_tool.call(event.name, event.input)
      # Renvoyer le résultat
      client.beta.sessions.events.send_(
        session.id,
        events: [
          {
            type: "user.custom_tool_result",
            custom_tool_use_id: event.id,
            content: [{type: "text", text: result}]
          }
        ]
      )
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      break if event.stop_reason.is_a?(Anthropic::Beta::Sessions::BetaManagedAgentsSessionEndTurn)
    end
  end
  ```
</CodeGroup>

Si l'agent a des [exécutions de workflow](https://platform.claude.com/docs/fr/managed-agents/workflow-runs) ouvertes, un appel d'outil personnalisé peut arriver alors que la session reste `running`. L'événement d'inactivité `requires_action` n'arrive que lorsqu'aucun des [fils de la session](https://platform.claude.com/docs/fr/managed-agents/session-threads) n'est en cours de travail. Ne l'attendez pas : répondez à chaque appel lorsque son événement `agent.custom_tool_use` arrive. L'exemple de [Suivre une exécution](https://platform.claude.com/docs/fr/managed-agents/workflow-runs#follow-a-run) montre comment procéder.

### Confirmer un appel d'outil

Envoyez un événement `user.tool_confirmation`, en passant l'identifiant de l'événement dans le paramètre `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`). Définissez `result` (csharp, go: `Result`) sur `"allow"` ou `"deny"`. Consultez [Répondre aux demandes de confirmation](https://platform.claude.com/docs/fr/managed-agents/permission-policies#respond-to-confirmation-requests) pour savoir quels appels attendent une confirmation et comment expliquer un refus.

L'exemple suivant approuve chaque appel en attente :

<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
  with client.beta.sessions.events.stream(session.id) as stream:
      for event in stream:
          if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
              match stop_reason.type:
                  case "requires_action":
                      for event_id in stop_reason.event_ids:
                          # Approuver l'appel d'outil en attente
                          client.beta.sessions.events.send(
                              session.id,
                              events=[
                                  {
                                      "type": "user.tool_confirmation",
                                      "tool_use_id": event_id,
                                      "result": "allow",
                                  },
                              ],
                          )
                  case "end_turn":
                      break
  ```

  ```typescript TypeScript
  const stream = await client.beta.sessions.events.stream(session.id);

  for await (const event of stream) {
    if (event.type !== "session.status_idle") {
      continue;
    }
    if (event.stop_reason.type === "end_turn") {
      break;
    }
    if (event.stop_reason.type !== "requires_action") {
      continue;
    }

    for (const eventId of event.stop_reason.event_ids) {
      // Approuver l'appel d'outil en attente
      await client.beta.sessions.events.send(session.id, {
        events: [
          {
            type: "user.tool_confirmation",
            tool_use_id: eventId,
            result: "allow"
          }
        ]
      });
    }
  }
  ```

  ```csharp C#
  await foreach (var streamEvent in client.Beta.Sessions.Events.StreamStreaming(session.ID))
  {
      if (streamEvent.Value is not BetaManagedAgentsSessionStatusIdleEvent idle) continue;

      if (idle.StopReason?.Value is BetaManagedAgentsSessionRequiresAction requiresAction)
      {
          foreach (var eventId in requiresAction.EventIds)
          {
              // Approuver l'appel d'outil en attente
              await client.Beta.Sessions.Events.Send(session.ID, new()
              {
                  Events =
                  [
                      new BetaManagedAgentsUserToolConfirmationEventParams
                      {
                          Type = BetaManagedAgentsUserToolConfirmationEventParamsType.UserToolConfirmation,
                          ToolUseID = eventId,
                          Result = BetaManagedAgentsUserToolConfirmationEventParamsResult.Allow,
                      },
                  ],
              });
          }
      }
      else if (idle.StopReason?.Value is BetaManagedAgentsSessionEndTurn)
      {
          break;
      }
  }
  ```

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

  loop:
  	for stream.Next() {
  		event, ok := stream.Current().AsAny().(anthropic.BetaManagedAgentsSessionStatusIdleEvent)
  		if !ok {
  			continue
  		}
  		switch stopReason := event.StopReason.AsAny().(type) {
  		case anthropic.BetaManagedAgentsSessionRequiresAction:
  			for _, eventID := range stopReason.EventIDs {
  				// Approuver l'appel d'outil en attente
  				if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  					Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  						OfUserToolConfirmation: &anthropic.BetaManagedAgentsUserToolConfirmationEventParams{
  							Type:      anthropic.BetaManagedAgentsUserToolConfirmationEventParamsTypeUserToolConfirmation,
  							ToolUseID: eventID,
  							Result:    anthropic.BetaManagedAgentsUserToolConfirmationEventParamsResultAllow,
  						},
  					}},
  				}); err != nil {
  					panic(err)
  				}
  			}
  		case anthropic.BetaManagedAgentsSessionEndTurn:
  			break loop
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  ```

  ```java Java
  try (var stream = client.beta().sessions().events().streamStreaming(session.id())) {
      stream.stream()
          .filter(BetaManagedAgentsStreamSessionEvents::isSessionStatusIdle)
          .map(idleEvent -> idleEvent.asSessionStatusIdle().stopReason())
          .takeWhile(stopReason -> !stopReason.isEndTurn())
          .filter(stopReason -> stopReason.isRequiresAction())
          .flatMap(stopReason -> stopReason.asRequiresAction().eventIds().stream())
          // Approuver chaque appel d'outil en attente
          .forEach(toolUseId -> client.beta().sessions().events().send(
              session.id(),
              EventSendParams.builder()
                  .addEvent(BetaManagedAgentsUserToolConfirmationEventParams.builder()
                      .type(BetaManagedAgentsUserToolConfirmationEventParams.Type.USER_TOOL_CONFIRMATION)
                      .toolUseId(toolUseId)
                      .result(BetaManagedAgentsUserToolConfirmationEventParams.Result.ALLOW)
                      .build())
                  .build()));
  }
  ```

  ```php PHP
  $stream = $client->beta->sessions->events->streamStream($session->id);

  foreach ($stream as $event) {
      if ($event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionStatusIdleEvent && $event->stopReason) {
          switch (true) {
              case $event->stopReason instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionRequiresAction:
                  foreach ($event->stopReason->eventIDs as $eventId) {
                      // Approuver l'appel d'outil en attente
                      $client->beta->sessions->events->send(
                          $session->id,
                          events: [
                              [
                                  'type' => 'user.tool_confirmation',
                                  'tool_use_id' => $eventId,
                                  'result' => 'allow',
                              ],
                          ],
                      );
                  }
                  break;
              case $event->stopReason instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionEndTurn:
                  break 2;
          }
      }
  }
  ```

  ```ruby Ruby
  client.beta.sessions.events.stream_events(session.id).each do |event|
    case event
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      stop_reason = event.stop_reason
      case stop_reason
      when Anthropic::Beta::Sessions::BetaManagedAgentsSessionRequiresAction
        stop_reason.event_ids.each do |event_id|
          # Approuver l'appel d'outil en attente
          client.beta.sessions.events.send_(
            session.id,
            events: [
              {type: "user.tool_confirmation", tool_use_id: event_id, result: "allow"}
            ]
          )
        end
      when Anthropic::Beta::Sessions::BetaManagedAgentsSessionEndTurn
        break
      end
    end
  end
  ```
</CodeGroup>

L'exemple précédent approuve chaque appel après que la session est devenue inactive. Si l'agent a des [exécutions de workflow](https://platform.claude.com/docs/fr/managed-agents/workflow-runs) ouvertes, un appel d'outil peut attendre votre confirmation alors que la session reste `running`. N'attendez pas l'événement d'inactivité : lorsqu'un événement `agent.tool_use` ou `agent.mcp_tool_use` arrive dont le champ [`evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`)](https://platform.claude.com/docs/fr/managed-agents/permission-policies#see-how-each-call-was-evaluated) vaut `ask`, répondez-y. L'exemple de [Suivre une exécution](https://platform.claude.com/docs/fr/managed-agents/workflow-runs#follow-a-run) répond aux appels d'outils personnalisés de cette manière, et son introduction explique comment ajouter des confirmations.

## Reprendre une session inactive

Les sessions persistent entre les interactions. Pour reprendre une session, envoyez-lui un événement `user.message` comme d'habitude :

<CodeGroup>
  ```bash cURL
  # En production, passez l'ID stocké de la session que vous souhaitez reprendre.
  curl --fail-with-body -sS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{
      "events": [
        {
          "type": "user.message",
          "content": [
            {"type": "text", "text": "Now run the tests against the changes you made earlier."}
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  # En production, passez l'ID stocké de la session que vous souhaitez reprendre.
  ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
  events:
    - type: user.message
      content:
        - type: text
          text: Now run the tests against the changes you made earlier.
  YAML
  ```

  ```python Python
  # Reprendre une session précédemment créée en lui envoyant un nouvel événement user.message.
  # En production, passez l'ID stocké de la session que vous souhaitez reprendre.
  client.beta.sessions.events.send(
      session.id,
      events=[
          {
              "type": "user.message",
              "content": [
                  {
                      "type": "text",
                      "text": "Now run the tests against the changes you made earlier.",
                  },
              ],
          },
      ],
  )
  ```

  ```typescript TypeScript
  // Reprendre une session précédemment créée en lui envoyant un nouvel événement utilisateur.
  // En production, passez l'ID stocké de la session que vous souhaitez reprendre.
  await client.beta.sessions.events.send(session.id, {
    events: [
      {
        type: "user.message",
        content: [
          {
            type: "text",
            text: "Now run the tests against the changes you made earlier."
          }
        ]
      }
    ]
  });
  ```

  ```csharp C#
  // Reprendre une session précédemment créée par son ID. En production, passez
  // l'ID de session que vous avez stocké lors de la création de la session.
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserMessageEventParams
          {
              Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage,
              Content =
              [
                  new BetaManagedAgentsTextBlock
                  {
                      Type = BetaManagedAgentsTextBlockType.Text,
                      Text = "Now run the tests against the changes you made earlier.",
                  },
              ],
          },
      ],
  });
  ```

  ```go Go
  // Reprendre une session créée précédemment en lui envoyant un nouvel événement
  // user.message. En production, passez l'ID stocké de la session à reprendre.
  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: "Now run the tests against the changes you made earlier.",
  				},
  			}},
  		},
  	}},
  }); err != nil {
  	panic(err)
  }
  ```

  ```java Java
  // Reprendre une session précédemment créée par son ID. En production, passez
  // l'ID de session que vous avez stocké lors de la création de la session.
  client.beta().sessions().events().send(
      session.id(),
      EventSendParams.builder()
          .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
              .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
              .addTextContent("Now run the tests against the changes you made earlier.")
              .build())
          .build());
  ```

  ```php PHP
  // Reprendre une session créée précédemment en lui envoyant un nouvel événement user.message.
  // En production, passez l'ID de session enregistré lors de la création de la session.
  $client->beta->sessions->events->send(
      $session->id,
      events: [
          [
              'type' => 'user.message',
              'content' => [
                  [
                      'type' => 'text',
                      'text' => 'Now run the tests against the changes you made earlier.',
                  ],
              ],
          ],
      ],
  );
  ```

  ```ruby Ruby
  # Reprendre une session consiste simplement à lui envoyer l'événement suivant. En production,
  # passez l'ID de session que vous avez stocké lors de la création de la session.
  client.beta.sessions.events.send_(
    session.id,
    events: [
      {
        type: "user.message",
        content: [
          {type: "text", text: "Now run the tests against the changes you made earlier."}
        ]
      }
    ]
  )
  ```
</CodeGroup>

L'historique de conversation est conservé sauf si la session est explicitement supprimée. Lorsqu'une session devient inactive, son sandbox fait l'objet d'un point de contrôle. Le point de contrôle préserve l'état complet du sandbox, y compris le système de fichiers, les paquets installés et tous les fichiers créés par l'agent.

<Note>
  L'état du sandbox n'est conservé que pendant 30 jours après la création du sandbox, et l'activité ne prolonge pas cette période. Au-delà de 30 jours, l'état du sandbox (fichiers, outils installés, etc.) est irrécupérable, et une session reprise démarre à partir d'un nouveau sandbox. Si votre workflow dépend du contenu du sandbox, demandez à l'agent d'écrire les artefacts importants dans les [sorties](https://platform.claude.com/docs/fr/managed-agents/define-outcomes#retrieving-deliverables) avant la fin de cette période.
</Note>

## Interrompre l'agent

Envoyez un événement `user.interrupt` pour arrêter l'agent en cours d'exécution, puis envoyez un événement `user.message` pour le rediriger :

<CodeGroup>
  ```bash cURL
  # L'agent est en train d'analyser un fichier...
  # Interrompre avec une nouvelle instruction :
  curl --fail-with-body -sS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{
      "events": [
        {"type": "user.interrupt"},
        {
          "type": "user.message",
          "content": [
            {"type": "text", "text": "Instead, focus on fixing the bug in line 42."}
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  # L'agent est en train d'analyser un fichier...
  # Interrompre avec une nouvelle direction :
  ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
  events:
    - type: user.interrupt
    - type: user.message
      content:
        - type: text
          text: Instead, focus on fixing the bug in line 42.
  YAML
  ```

  ```python Python
  # L'agent est en train d'analyser un fichier...
  # Interrompre avec une nouvelle direction :
  client.beta.sessions.events.send(
      session.id,
      events=[
          {"type": "user.interrupt"},
          {
              "type": "user.message",
              "content": [
                  {
                      "type": "text",
                      "text": "Instead, focus on fixing the bug in line 42.",
                  },
              ],
          },
      ],
  )
  ```

  ```typescript TypeScript
  // L'agent est en train d'analyser un fichier...
  // Interrompre avec une nouvelle direction :
  await client.beta.sessions.events.send(session.id, {
    events: [
      { type: "user.interrupt" },
      {
        type: "user.message",
        content: [
          {
            type: "text",
            text: "Instead, focus on fixing the bug in line 42."
          }
        ]
      }
    ]
  });
  ```

  ```csharp C#
  // L'agent est en train d'analyser un fichier...
  // Interrompre avec une nouvelle direction :
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserInterruptEventParams
          {
              Type = BetaManagedAgentsUserInterruptEventParamsType.UserInterrupt,
          },
          new BetaManagedAgentsUserMessageEventParams
          {
              Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage,
              Content =
              [
                  new BetaManagedAgentsTextBlock
                  {
                      Type = BetaManagedAgentsTextBlockType.Text,
                      Text = "Instead, focus on fixing the bug in line 42.",
                  },
              ],
          },
      ],
  });
  ```

  ```go Go
  // L'agent analyse actuellement un fichier...
  // Interrompre avec une nouvelle directive :
  if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  	Events: []anthropic.BetaManagedAgentsEventParamsUnion{
  		{
  			OfUserInterrupt: &anthropic.BetaManagedAgentsUserInterruptEventParams{
  				Type: anthropic.BetaManagedAgentsUserInterruptEventParamsTypeUserInterrupt,
  			},
  		},
  		{
  			OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{
  				Type: anthropic.BetaManagedAgentsUserMessageEventParamsTypeUserMessage,
  				Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{{
  					OfText: &anthropic.BetaManagedAgentsTextBlockParam{
  						Type: anthropic.BetaManagedAgentsTextBlockTypeText,
  						Text: "Instead, focus on fixing the bug in line 42.",
  					},
  				}},
  			},
  		},
  	},
  }); err != nil {
  	panic(err)
  }
  ```

  ```java Java
  // L'agent est en train d'analyser un fichier...
  // Interrompre avec une nouvelle direction :
  client.beta().sessions().events().send(
      session.id(),
      EventSendParams.builder()
          .addEvent(BetaManagedAgentsUserInterruptEventParams.builder()
              .type(BetaManagedAgentsUserInterruptEventParams.Type.USER_INTERRUPT)
              .build())
          .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
              .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
              .addTextContent("Instead, focus on fixing the bug in line 42.")
              .build())
          .build());
  ```

  ```php PHP
  // L'agent est en train d'analyser un fichier...
  // Interrompre avec une nouvelle consigne :
  $client->beta->sessions->events->send(
      $session->id,
      events: [
          ['type' => 'user.interrupt'],
          [
              'type' => 'user.message',
              'content' => [
                  [
                      'type' => 'text',
                      'text' => 'Instead, focus on fixing the bug in line 42.',
                  ],
              ],
          ],
      ],
  );
  ```

  ```ruby Ruby
  # L'agent est en train d'analyser un fichier...
  # Interrompre avec une nouvelle direction :
  client.beta.sessions.events.send_(
    session.id,
    events: [
      {type: "user.interrupt"},
      {
        type: "user.message",
        content: [
          {type: "text", text: "Instead, focus on fixing the bug in line 42."}
        ]
      }
    ]
  )
  ```
</CodeGroup>

L'appel retourne dès que les événements sont mis en file d'attente. L'interruption prend ensuite effet dans cet ordre :

1. L'agent applique l'interruption. Jusque-là, le `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) de l'interruption reste `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `time.Time{}`) et la session reste à l'état `running`. Une réponse du modèle en cours s'arrête immédiatement, mais l'interruption peut mettre plus de temps à s'appliquer pendant que des appels d'outils sont en cours d'exécution.
2. L'événement `user.interrupt` apparaît sur le flux, et le tour interrompu se termine par un événement `session.status_idle`.
3. L'agent commence son tour suivant avec le `user.message` que vous avez envoyé après l'interruption.

Le `stop_reason.type` de l'événement d'inactivité est `end_turn`, la même valeur que pour un tour qui se termine de lui-même. Si des exécutions de workflow sont ouvertes, l'interruption n'en termine aucune. Une exécution en cours peut maintenir la session à l'état `running`, de sorte que l'événement `session.status_idle` de l'étape 2 pourrait ne pas arriver. Consultez [Interrompre une session avec des exécutions ouvertes](https://platform.claude.com/docs/fr/managed-agents/workflow-runs#interrupt-a-session-with-runs-open).

## Lister les événements passés

Récupérez l'historique complet des événements d'une session :

<CodeGroup>
  ```bash cURL
  curl --fail-with-body -sS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json"
  ```

  ```bash CLI
  ant beta:sessions:events list --session-id "$SESSION_ID" --format jsonl
  ```

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

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

  ```csharp C#
  var events = await client.Beta.Sessions.Events.List(session.ID);
  foreach (var sessionEvent in events.Items)
  {
      Console.WriteLine($"[{sessionEvent.Json.GetProperty("type").GetString()}] {sessionEvent.ProcessedAt}");
  }
  ```

  ```go Go
  events, err := client.Beta.Sessions.Events.List(ctx, session.ID, anthropic.BetaSessionEventListParams{})
  if err != nil {
  	panic(err)
  }
  for _, event := range events.Data {
  	fmt.Printf("[%s] %s\n", event.Type, event.ProcessedAt)
  }
  ```

  ```java Java
  var events = client.beta().sessions().events().list(session.id());
  for (var event : events.data()) {
      var eventJson = event._json().orElseThrow().convert(JsonNode.class);
      var processedAt = eventJson.path("processed_at");
      IO.println("[" + eventJson.get("type").asText() + "] "
          + (processedAt.isTextual() ? processedAt.asText() : "null"));
  }
  ```

  ```php PHP
  $events = $client->beta->sessions->events->list($session->id);
  foreach ($events->data as $event) {
      $processedAt = ($event->processedAt ?? null)?->format(DATE_RFC3339) ?? 'null';
      echo "[{$event->type}] {$processedAt}\n";
  }
  ```

  ```ruby Ruby
  events = client.beta.sessions.events.list(session.id)
  events.data.each { puts "[#{it.type}] #{it.processed_at}" }
  ```
</CodeGroup>

Transmettez un filtre `types` (curl: `types[]`; cli: `--type`; csharp, go: `Types`) pour ne renvoyer que des types d'événements spécifiques :

<CodeGroup>
  ```bash cURL
  curl --fail-with-body -sS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true&types[]=agent.tool_use&types[]=agent.tool_result" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01"
  ```

  ```bash CLI
  ant beta:sessions:events list --session-id "$SESSION_ID" \
    --type agent.tool_use --type agent.tool_result \
    --format jsonl
  ```

  ```python Python
  events = client.beta.sessions.events.list(
      session.id,
      types=["agent.tool_use", "agent.tool_result"],
  )
  for event in events.data:
      print(f"[{event.type}] {event.processed_at}")
  ```

  ```typescript TypeScript
  const events = await client.beta.sessions.events.list(session.id, {
    types: ["agent.tool_use", "agent.tool_result"]
  });
  for (const event of events.data) {
    console.log(`[${event.type}] ${event.processed_at}`);
  }
  ```

  ```csharp C#
  var events = await client.Beta.Sessions.Events.List(session.ID, new()
  {
      Types = ["agent.tool_use", "agent.tool_result"],
  });
  foreach (var sessionEvent in events.Items)
  {
      Console.WriteLine($"[{sessionEvent.Json.GetProperty("type").GetString()}] {sessionEvent.ProcessedAt}");
  }
  ```

  ```go Go
  events, err := client.Beta.Sessions.Events.List(ctx, session.ID, anthropic.BetaSessionEventListParams{
  	Types: []anthropic.BetaManagedAgentsSessionEventType{
  		anthropic.BetaManagedAgentsSessionEventTypeAgentToolUse,
  		anthropic.BetaManagedAgentsSessionEventTypeAgentToolResult,
  	},
  })
  if err != nil {
  	panic(err)
  }
  for _, event := range events.Data {
  	fmt.Printf("[%s] %s\n", event.Type, event.ProcessedAt)
  }
  ```

  ```java Java
  var events = client.beta().sessions().events().list(
      session.id(),
      EventListParams.builder()
          .addType(BetaManagedAgentsSessionEventType.AGENT_TOOL_USE)
          .addType(BetaManagedAgentsSessionEventType.AGENT_TOOL_RESULT)
          .build());
  for (var event : events.data()) {
      event.agentToolUse().ifPresent(toolUse ->
          IO.println("[" + toolUse.type() + "] " + toolUse.processedAt()));
      event.agentToolResult().ifPresent(toolResult ->
          IO.println("[" + toolResult.type() + "] " + toolResult.processedAt()));
  }
  ```

  ```php PHP
  $events = $client->beta->sessions->events->list(
      $session->id,
      types: ['agent.tool_use', 'agent.tool_result'],
  );
  foreach ($events->data as $event) {
      $processedAt = ($event->processedAt ?? null)?->format(DATE_RFC3339) ?? 'null';
      echo "[{$event->type}] {$processedAt}\n";
  }
  ```

  ```ruby Ruby
  events = client.beta.sessions.events.list(
    session.id,
    types: ["agent.tool_use", "agent.tool_result"]
  )
  events.data.each { puts "[#{it.type}] #{it.processed_at}" }
  ```
</CodeGroup>

## Envoyer des messages système

Sur un [modèle pris en charge](https://platform.claude.com/docs/fr/managed-agents/events-and-streaming#supported-models), envoyez un événement `system.message` pour fournir à l'agent un contexte privilégié au niveau système. Le contexte s'applique au tour qui l'accompagne et à tous les tours suivants. Utilisez-le lorsque l'agent a besoin de directives système mises à jour en cours de session, par exemple un persona différent, des contraintes révisées ou un contexte récupéré à l'exécution.

Le champ `content` (csharp, go: `Content`) de l'événement accepte de 1 à 1000 éléments de texte. Le contenu est ajouté au contexte système de la session sous forme de tour `role: "system"`. Il ne remplace pas l'« system prompt » (invite système) de premier niveau, définie par le champ `system` (csharp, go: `System`; ruby: `system_`) de la définition de l'agent.

<CodeGroup>
  ```bash cURL
  curl --fail-with-body -sS "https://api.anthropic.com/v1/sessions/$SESSION_ID/events?beta=true" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{
      "events": [
        {
          "type": "system.message",
          "content": [
            {"type": "text", "text": "The current timezone of the user is America/New_York."}
          ]
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
  events:
    - type: system.message
      content:
        - type: text
          text: "The user's current timezone is America/New_York."
  YAML
  ```

  ```python Python
  client.beta.sessions.events.send(
      session.id,
      events=[
          {
              "type": "system.message",
              "content": [
                  {
                      "type": "text",
                      "text": "The user's current timezone is America/New_York.",
                  },
              ],
          },
      ],
  )
  ```

  ```typescript TypeScript
  await client.beta.sessions.events.send(session.id, {
    events: [
      {
        type: "system.message",
        content: [
          {
            type: "text",
            text: "The user's current timezone is America/New_York."
          }
        ]
      }
    ]
  });
  ```

  ```csharp C#
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsSystemMessageEventParams
          {
              Type = BetaManagedAgentsSystemMessageEventParamsType.SystemMessage,
              Content =
              [
                  new BetaManagedAgentsSystemContentBlock
                  {
                      Type = BetaManagedAgentsSystemContentBlockType.Text,
                      Text = "The user's current timezone is America/New_York.",
                  },
              ],
          },
      ],
  });
  ```

  ```go Go
  if _, err := client.Beta.Sessions.Events.Send(ctx, session.ID, anthropic.BetaSessionEventSendParams{
  	Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  		OfSystemMessage: &anthropic.BetaManagedAgentsSystemMessageEventParams{
  			Type: anthropic.BetaManagedAgentsSystemMessageEventParamsTypeSystemMessage,
  			Content: []anthropic.BetaManagedAgentsSystemContentBlockParam{{
  				Type: anthropic.BetaManagedAgentsSystemContentBlockTypeText,
  				Text: "The user's current timezone is America/New_York.",
  			}},
  		},
  	}},
  }); err != nil {
  	panic(err)
  }
  ```

  ```java Java
  client.beta().sessions().events().send(
      session.id(),
      EventSendParams.builder()
          .addEvent(BetaManagedAgentsSystemMessageEventParams.builder()
              .type(BetaManagedAgentsSystemMessageEventParams.Type.SYSTEM_MESSAGE)
              .addTextContent("The user's current timezone is America/New_York.")
              .build())
          .build());
  ```

  ```php PHP
  $client->beta->sessions->events->send(
      $session->id,
      events: [
          [
              'type' => 'system.message',
              'content' => [
                  [
                      'type' => 'text',
                      'text' => "The user's current timezone is America/New_York.",
                  ],
              ],
          ],
      ],
  );
  ```

  ```ruby Ruby
  client.beta.sessions.events.send_(
    session.id,
    events: [
      {
        type: "system.message",
        content: [
          {type: "text", text: "The user's current timezone is America/New_York."}
        ]
      }
    ]
  )
  ```
</CodeGroup>

### Modèles pris en charge

`system.message` est pris en charge par ces modèles :

* Claude Fable 5.1
* Claude Mythos 5.1
* Claude Fable 5
* Claude Mythos 5
* Claude Opus 5.5
* Claude Opus 5
* Claude Opus 4.8
* Claude Sonnet 5.5
* Claude Haiku 5.5

Si le modèle principal de l'agent ne prend pas en charge l'injection système en cours de conversation, l'événement est rejeté avec une erreur de validation `model_does_not_support_mid_conversation_system`. Les modèles des sous-agents ne sont pas vérifiés, car `system.message` n'arrive que sur le fil principal.

### Messages système lorsqu'un appel d'outil est en attente

Lorsque la session est inactive avec une raison d'arrêt `requires_action`, un `system.message` doit suivre un événement de résultat d'outil dans la même requête. Envoyé seul ou avec un `user.message`, il est rejeté jusqu'à ce que les événements d'outils en attente soient résolus.

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Prévisualiser les réponses avec les deltas d'événements" icon="text" href="https://platform.claude.com/docs/fr/managed-agents/event-deltas">
    Affichez le texte de réponse de l'agent pendant que le modèle le génère encore.
  </Card>

  <Card title="Inspecter les sessions et suivre l'utilisation" icon="magnifying-glass" href="https://platform.claude.com/docs/fr/managed-agents/session-observability">
    Inspectez une session dans la Claude Console et consultez son utilisation de tokens et son coût catalogue.
  </Card>

  <Card title="S'abonner aux webhooks" icon="link" href="https://platform.claude.com/docs/fr/managed-agents/webhooks">
    Soyez notifié lorsque des événements majeurs se produisent, sans interrogation périodique.
  </Card>

  <Card title="Types d'événements" icon="book" href="https://platform.claude.com/docs/fr/managed-agents/reference#event-types">
    Consultez chaque type d'événement qu'une session peut envoyer ou recevoir.
  </Card>
</CardGroup>
