---
title: Stream de eventos da sessão
url: https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming
description: Envie eventos, faça streaming de respostas e interrompa ou redirecione sua sessão durante a execução.
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

A comunicação com o Claude Managed Agents é baseada em eventos. Você abre um stream para acompanhar uma sessão, envia eventos para direcioná-la e responde a ela quando ela pausa aguardando entrada.

## Tipos de eventos

Os eventos fluem em duas direções: você envia eventos para o agente, e a sessão envia eventos de volta para você.

* **Eventos que você envia:** eventos `user.*` iniciam uma sessão e a conduzem à medida que ela progride. Eventos [`system.message`](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#send-system-messages) acrescentam contexto em nível de sistema.
* **Eventos que você recebe:** eventos de sessão, eventos de span e eventos do agente informam o estado da sessão e o progresso do agente.

Essas strings de tipo de evento seguem uma convenção de nomenclatura `{domain}.{action}`. Consulte [Tipos de eventos](https://platform.claude.com/docs/pt-BR/managed-agents/reference#event-types) na referência para o catálogo completo.

Os [tipos de eventos de webhook](https://platform.claude.com/docs/pt-BR/managed-agents/webhooks#supported-event-types) são separados, e alguns de seus nomes diferem dos do stream. Por exemplo, os webhooks usam `session.status_idled` em vez de `session.status_idle`.

## Fazer streaming de eventos

Faça "streaming" (streaming) dos eventos da sessão para receber atualizações em tempo real enquanto o agente trabalha. Um stream entrega apenas os eventos emitidos depois que ele é aberto, então abra o stream antes de enviar eventos para evitar uma "race condition" (condição de corrida).

<CodeGroup>
  ```bash cURL
  # Abra o stream antes de enviar o primeiro evento: só eventos posteriores são entregues.
  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
  # Abra o stream antes de enviar o primeiro evento: só eventos posteriores são entregues.
  ant beta:sessions:events stream --session-id "$SESSION_ID"
  ```

  ```python Python
  # Abra o stream primeiro e depois envie a mensagem do usuário
  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
  // Abra o stream primeiro e depois envie a mensagem do usuário
  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#
  // Abra o stream primeiro e depois envie a mensagem do usuário
  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
  	// Abra o stream primeiro e depois envie a mensagem do usuário
  	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:
  			// lista de tipo concreto: 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
  // Abra o stream primeiro e depois envie a mensagem do usuário
  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 -> {
                  // O campo `message` abrange todas as variantes de erro; leia-o do JSON bruto.
                  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;

  // Abra o stream primeiro e depois envie a mensagem do usuário
  $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
  # Abra o stream primeiro e depois envie a mensagem do usuário
  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
      # ignora outros tipos de evento
    end
  end
  ```
</CodeGroup>

A sessão informa erros por meio do evento `session.error`. Consulte [Tipos de eventos](https://platform.claude.com/docs/pt-BR/managed-agents/reference#event-types) para ver seus campos.

O texto de resposta do agente chega como eventos `agent.message` armazenados em buffer, cada um emitido somente depois que a requisição ao modelo que o produziu termina. Para renderizar o texto enquanto o modelo ainda o está gerando, consulte [Pré-visualizar respostas com deltas de eventos](https://platform.claude.com/docs/pt-BR/managed-agents/event-deltas).

### Reconectar sem perder eventos

Para se reconectar a uma sessão existente sem perder eventos, combine um novo stream com o histórico de eventos:

1. Abra um novo stream.
2. [Liste o histórico completo de eventos](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#list-past-events) para preencher um conjunto de IDs de eventos já vistos.
3. Acompanhe o stream ao vivo, ignorando quaisquer eventos já retornados pela lista do histórico.

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Este fluxo de trabalho precisa de mais lógica do que um único comando de shell. Use o [Claude SDK](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/overview) para executá-lo.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Este fluxo de trabalho precisa de mais lógica do que um único comando de shell. Use o [Claude SDK](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/overview) para executá-lo.
  </CodeGroupItem>

  ```python Python
  with client.beta.sessions.events.stream(session.id) as stream:
      # O stream está aberto e armazenando em buffer. Liste o histórico antes de acompanhar ao vivo.
      history = client.beta.sessions.events.list(session.id)
      seen_event_ids = {past_event.id for past_event in history}

      # Acompanhe eventos ao vivo, ignorando o que já foi visto
      for event in stream:
          if event.type == "event_start" or event.type == "event_delta":
              # As prévias de delta não estão habilitadas nesta conexão.
              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);

  // O stream está aberto e armazenando em buffer. Liste o histórico antes de acompanhar ao vivo.
  for await (const event of client.beta.sessions.events.list(session.id)) {
    seenEventIds.add(event.id);
  }

  // Acompanhe eventos ao vivo, ignorando qualquer um já visto
  tail: for await (const event of stream) {
    // Eventos de prévia (event_start/event_delta) não têm id de nível superior
    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);

  // O stream está aberto e armazenando em buffer. Liste o histórico antes de acompanhar ao vivo.
  HashSet<string> seenEventIds = [];
  var history = await client.Beta.Sessions.Events.List(session.ID);
  await foreach (var pastEvent in history.Paginate())
  {
      seenEventIds.Add(pastEvent.ID);
  }

  // Acompanha eventos ao vivo, ignorando o que já foi visto
  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()

  	// O stream está aberto e armazenando em buffer. Liste o histórico antes de acompanhar ao vivo.
  	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)
  	}

  	// Acompanha eventos ao vivo, ignorando os já vistos
  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:
  			// lista de tipo concreto: 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())) {
      // O stream está aberto e armazenando em buffer. Liste o histórico antes de acompanhar ao vivo.
      // Toda variante de evento tem `id`; leia-o do JSON bruto para deduplicar 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());
          }
      }

      // Acompanha eventos ao vivo; Set.add retorna false para IDs já vistos, pulando o replay.
      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);

  // O stream está aberto e armazenando em buffer. Liste o histórico antes de acompanhar ao vivo.
  $seenEventIds = [];
  foreach ($client->beta->sessions->events->list($session->id)->pagingEachItem() as $event) {
      $seenEventIds[$event->id] = true;
  }

  // Acompanhe os eventos ao vivo, ignorando o que já foi visto
  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)

  # O stream está aberto e armazenando em buffer. Liste o histórico antes de acompanhar ao vivo.
  seen_event_ids = Set.new
  client.beta.sessions.events.list(session.id).auto_paging_each { seen_event_ids << it.id }

  # Acompanha eventos ao vivo, pulando os já vistos — Set#add? retorna nil para duplicatas
  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
      # ignora outros tipos de evento
    end
  end
  ```
</CodeGroup>

## Enviar eventos

Envie um evento `user.message` para iniciar ou continuar o trabalho do agente:

<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>

Todo evento no histórico da sessão inclui um timestamp `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`), definido quando o evento termina de ser processado. Nos eventos que você envia, `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) é `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `time.Time{}`) enquanto o evento ainda está na fila atrás de eventos anteriores. As exceções são `user.define_outcome`, `user.custom_tool_result` e `user.tool_result`, que são processados no recebimento e ecoados de volta com `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) já preenchido.

## Responder quando a sessão fica ociosa

Um evento `session.status_idle` significa que o agente parou e está aguardando entrada. Seu `stop_reason.type` informa o motivo:

| `stop_reason.type` | Por que a sessão parou                                                                                                                                | O que fazer                                                                                                                                                              |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `end_turn`         | O agente terminou seu turno, ou [você o interrompeu](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#interrupt-the-agent). | [Envie um `user.message`](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#resume-an-idle-session) quando tiver mais trabalho para o agente.   |
| `requires_action`  | Uma ou mais chamadas de ferramenta precisam de uma resposta sua, como uma chamada de ferramenta personalizada ou uma solicitação de confirmação.      | [Responda a cada chamada de ferramenta bloqueante](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#answer-tool-calls-that-pause-the-session). |
| `budget_reached`   | O custo de tabela rastreado da sessão atingiu seu [orçamento](https://platform.claude.com/docs/pt-BR/managed-agents/budgets).                         | [Altere ou remova o orçamento](https://platform.claude.com/docs/pt-BR/managed-agents/budgets#resume-a-session-at-its-budget).                                            |

Nenhum evento que você envia retoma uma sessão pausada em seu orçamento. O trabalho que o orçamento pausou é retomado automaticamente quando você altera o orçamento para um valor acima do custo de tabela consumido, ou o remove. Quando o trabalho é retomado, a sessão emite um evento `workflow_run.status_running` para cada [execução de workflow que o orçamento pausou](https://platform.claude.com/docs/pt-BR/managed-agents/workflow-runs#budgets-and-limits). Uma execução que uma interrupção pausou permanece pausada; consulte [Retomar uma sessão em seu orçamento](https://platform.claude.com/docs/pt-BR/managed-agents/budgets#resume-a-session-at-its-budget). Consulte [Quando uma sessão atinge seu orçamento](https://platform.claude.com/docs/pt-BR/managed-agents/budgets#when-a-session-reaches-its-budget) para ver os eventos que marcam a pausa e os eventos que a sessão ainda aceita.

## Responder a chamadas de ferramenta que pausam a sessão

Uma sessão pausa quando o agente invoca uma [ferramenta personalizada](https://platform.claude.com/docs/pt-BR/managed-agents/tools#custom-tools), e quando uma chamada de ferramenta precisa da sua confirmação sob uma [política de permissões](https://platform.claude.com/docs/pt-BR/managed-agents/permission-policies). Ambas as pausas seguem a mesma sequência:

1. A sessão emite a chamada de ferramenta como um evento `agent.custom_tool_use`, `agent.tool_use` ou `agent.mcp_tool_use`.
2. A sessão pausa com um evento `session.status_idle` cujo `stop_reason.type` é `requires_action`. Os IDs dos eventos bloqueantes estão no array `stop_reason.event_ids`.
3. Para cada ID de evento bloqueante, envie um evento [`user.custom_tool_result`](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#return-a-custom-tool-result) ou [`user.tool_confirmation`](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#confirm-a-tool-call). Um resultado de ferramenta personalizada não precisa esperar pela etapa 2.
4. Depois que todos os eventos bloqueantes forem resolvidos, a sessão volta para `running`.

Em uma sessão multiagente, os eventos bloqueantes de um subagente são replicados na thread principal. Consulte [Permissões de ferramentas e ferramentas personalizadas](https://platform.claude.com/docs/pt-BR/managed-agents/session-threads#tool-permissions-and-custom-tools).

### Retornar um resultado de ferramenta personalizada

O evento `agent.custom_tool_use` contém o nome e a entrada da ferramenta. Execute a ferramenta no seu sistema. Em seguida, envie um evento `user.custom_tool_result`, passando o ID do evento no parâmetro `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`) junto com o conteúdo do resultado.

Você pode enviar o resultado assim que o evento `agent.custom_tool_use` chegar, sem esperar por `session.status_idle`. A sessão ainda emite `session.status_idle` com um motivo de parada `requires_action` para a chamada, e seu cliente pode ignorá-lo. Um segundo resultado para a mesma chamada é aceito e não tem efeito.

Quando você se [reconecta](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#reconnect-without-missing-events) a uma sessão pausada, `stop_reason.event_ids` no evento `session.status_idle` mais recente lista as chamadas a serem respondidas.

O exemplo a seguir responde a cada chamada à medida que ela chega:

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Este fluxo de trabalho precisa de mais lógica do que um único comando de shell. Use o [Claude SDK](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/overview) para executá-lo.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Este fluxo de trabalho precisa de mais lógica do que um único comando de shell. Use o [Claude SDK](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/overview) para executá-lo.
  </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":
                  # Execute a ferramenta
                  result = call_tool(event.name, event.input)

                  # Envie o resultado de volta
                  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": {
        // Executa a ferramenta
        const result = await callTool(event.name, event.input);

        // Envia o resultado de volta
        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)
      {
          // Executa a ferramenta
          var result = await CallTool(toolUse.Name, toolUse.Input);

          // Envia o resultado de volta
          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:
  			// Executa a ferramenta
  			result := callTool(event.Name, event.Input)
  			// Envia o resultado de volta
  			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 -> {
                  // Executa a ferramenta
                  var toolUse = event.asAgentCustomToolUse();
                  var result = callTool(toolUse.name(), toolUse.input());

                  // Envia o resultado de volta
                  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:
              // Executa a ferramenta
              $result = callTool($event->name, $event->input);

              // Envia o resultado de volta
              $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
      # Executa a ferramenta
      result = call_tool.call(event.name, event.input)
      # Envia o resultado de volta
      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>

Se o agente tiver [execuções de workflow](https://platform.claude.com/docs/pt-BR/managed-agents/workflow-runs) abertas, uma chamada de ferramenta personalizada pode chegar enquanto a sessão permanece `running`. O evento de ociosidade `requires_action` chega somente quando nenhuma das [threads da sessão](https://platform.claude.com/docs/pt-BR/managed-agents/session-threads) está trabalhando. Não espere por ele: responda a cada chamada quando seu evento `agent.custom_tool_use` chegar. O exemplo em [Acompanhar uma execução](https://platform.claude.com/docs/pt-BR/managed-agents/workflow-runs#follow-a-run) mostra como.

### Confirmar uma chamada de ferramenta

Envie um evento `user.tool_confirmation`, passando o ID do evento no parâmetro `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`). Defina `result` (csharp, go: `Result`) como `"allow"` ou `"deny"`. Consulte [Responder a solicitações de confirmação](https://platform.claude.com/docs/pt-BR/managed-agents/permission-policies#respond-to-confirmation-requests) para saber quais chamadas aguardam uma confirmação e como explicar uma negação.

O exemplo a seguir aprova todas as chamadas pendentes:

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Este fluxo de trabalho precisa de mais lógica do que um único comando de shell. Use o [Claude SDK](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/overview) para executá-lo.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Este fluxo de trabalho precisa de mais lógica do que um único comando de shell. Use o [Claude SDK](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/overview) para executá-lo.
  </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:
                          # Aprove a chamada de ferramenta pendente
                          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) {
      // Aprove a chamada de ferramenta pendente
      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)
          {
              // Aprove a chamada de ferramenta pendente
              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 {
  				// Aprove a chamada de ferramenta pendente
  				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())
          // Aprove cada chamada de ferramenta pendente
          .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) {
                      // Aprova a chamada de ferramenta pendente
                      $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|
          # Aprove a chamada de ferramenta pendente
          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>

O exemplo anterior aprova cada chamada depois que a sessão fica ociosa. Se o agente tiver [execuções de workflow](https://platform.claude.com/docs/pt-BR/managed-agents/workflow-runs) abertas, uma chamada de ferramenta pode aguardar sua confirmação enquanto a sessão permanece `running`. Não espere pelo evento de ociosidade: quando chegar um evento `agent.tool_use` ou `agent.mcp_tool_use` cujo [`evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`)](https://platform.claude.com/docs/pt-BR/managed-agents/permission-policies#see-how-each-call-was-evaluated) seja `ask`, responda a ele. O exemplo em [Acompanhar uma execução](https://platform.claude.com/docs/pt-BR/managed-agents/workflow-runs#follow-a-run) responde a chamadas de ferramentas personalizadas dessa forma, e sua introdução explica como adicionar confirmações.

## Retomar uma sessão ociosa

As sessões persistem entre interações. Para retomar uma sessão, envie um evento `user.message` para ela normalmente:

<CodeGroup>
  ```bash cURL
  # Em produção, passe o ID armazenado da sessão que você deseja retomar.
  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
  # Em produção, passe o ID armazenado da sessão que você deseja retomar.
  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
  # Retome uma sessão criada anteriormente enviando a ela um novo evento user.message.
  # Em produção, passe o ID armazenado da sessão que você deseja retomar.
  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
  // Retome uma sessão criada anteriormente enviando a ela um novo evento de usuário.
  // Em produção, passe o ID armazenado da sessão que você deseja retomar.
  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#
  // Retome uma sessão criada anteriormente pelo ID. Em produção, passe o
  // ID da sessão que você armazenou quando a sessão foi criada.
  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
  // Retome uma sessão criada anteriormente enviando a ela um novo evento
  // user.message. Em produção, passe o ID armazenado da sessão a retomar.
  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
  // Retome uma sessão criada anteriormente pelo ID. Em produção, passe o
  // ID de sessão que você armazenou quando a sessão foi criada.
  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
  // Retoma uma sessão criada anteriormente enviando a ela um novo evento user.message.
  // Em produção, passe o ID da sessão que você armazenou quando a sessão foi criada.
  $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
  # Retomar uma sessão é simplesmente enviar o próximo evento a ela. Em produção,
  # passe o ID da sessão que você armazenou quando a sessão foi criada.
  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>

O histórico da conversa é preservado, a menos que a sessão seja explicitamente excluída. Quando uma sessão fica ociosa, é criado um checkpoint do seu sandbox. O checkpoint preserva o estado completo do sandbox, incluindo o sistema de arquivos, os pacotes instalados e quaisquer arquivos que o agente criou.

<Note>
  O estado do sandbox é preservado por apenas 30 dias após a criação do sandbox, e a atividade não estende esse período. Após 30 dias, o estado do sandbox (arquivos, ferramentas instaladas e assim por diante) é irrecuperável, e uma sessão retomada começa a partir de um sandbox novo. Se o seu fluxo de trabalho depende do conteúdo do sandbox, faça com que o agente grave artefatos importantes em [saídas](https://platform.claude.com/docs/pt-BR/managed-agents/define-outcomes#retrieving-deliverables) antes que o período termine.
</Note>

## Interromper o agente

Envie um evento `user.interrupt` para parar o agente durante a execução e, em seguida, envie um evento `user.message` para redirecioná-lo:

<CodeGroup>
  ```bash cURL
  # O agente está analisando um arquivo no momento...
  # Interrompa com uma nova direção:
  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
  # O agente está analisando um arquivo no momento...
  # Interrompa com uma nova direção:
  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
  # O agente está analisando um arquivo no momento...
  # Interrompa com uma nova direção:
  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
  // O agente está analisando um arquivo no momento...
  // Interrompa com uma nova direção:
  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#
  // O agente está analisando um arquivo no momento...
  // Interrompa com uma nova direção:
  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
  // O agente está analisando um arquivo...
  // Interrompa com uma nova direção:
  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
  // O agente está analisando um arquivo no momento...
  // Interrompa com uma nova direção:
  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
  // O agente está analisando um arquivo no momento...
  // Interrompe com uma nova direção:
  $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
  # O agente está analisando um arquivo...
  # Interrompa com uma nova direção:
  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>

A chamada retorna assim que os eventos são enfileirados. A interrupção então entra em vigor nesta ordem:

1. O agente aplica a interrupção. Até lá, o `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) da interrupção permanece `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `time.Time{}`) e a sessão permanece `running`. Uma resposta do modelo em andamento para imediatamente, mas a interrupção pode levar mais tempo para ser aplicada enquanto chamadas de ferramenta estão em execução.
2. O evento `user.interrupt` aparece no stream, e o turno interrompido termina com um evento `session.status_idle`.
3. O agente inicia seu próximo turno com o `user.message` que você enviou após a interrupção.

O `stop_reason.type` do evento de ociosidade é `end_turn`, o mesmo valor de um turno que termina por conta própria. Se houver execuções de workflow abertas, a interrupção não encerra nenhuma delas. Uma execução em andamento pode manter a sessão `running`, então o evento `session.status_idle` da etapa 2 pode não chegar. Consulte [Interromper uma sessão com execuções abertas](https://platform.claude.com/docs/pt-BR/managed-agents/workflow-runs#interrupt-a-session-with-runs-open).

## Listar eventos anteriores

Recupere o histórico completo de eventos de uma sessão:

<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>

Passe um filtro `types` (curl: `types[]`; cli: `--type`; csharp, go: `Types`) para retornar apenas tipos de eventos específicos:

<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>

## Enviar mensagens do sistema

Em um [modelo compatível](https://platform.claude.com/docs/pt-BR/managed-agents/events-and-streaming#supported-models), envie um evento `system.message` para fornecer ao agente contexto privilegiado em nível de sistema. O contexto se aplica ao turno correspondente e a todos os turnos subsequentes. Use-o quando o agente precisar de orientação atualizada em nível de sistema no meio da sessão, por exemplo, uma persona diferente, restrições revisadas ou contexto obtido em tempo de execução.

O `content` (csharp, go: `Content`) do evento aceita de 1 a 1000 itens de texto. O conteúdo é acrescentado ao contexto de sistema da sessão como um turno `role: "system"`. Ele não substitui o "system prompt" (prompt do sistema) de nível superior, que é definido pelo campo `system` (csharp, go: `System`; ruby: `system_`) na definição do agente.

<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>

### Modelos compatíveis

`system.message` é compatível com estes modelos:

* 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

Se o modelo principal do agente não for compatível com injeção de sistema no meio da conversa, o evento é rejeitado com um erro de validação `model_does_not_support_mid_conversation_system`. Os modelos de subagentes não são verificados, porque `system.message` chega apenas à thread principal.

### Mensagens do sistema enquanto uma chamada de ferramenta está pendente

Enquanto a sessão está ociosa com um motivo de parada `requires_action`, um `system.message` deve vir depois de um evento de resultado de ferramenta na mesma requisição. Enviado sozinho ou com um `user.message`, ele é rejeitado até que os eventos de ferramenta pendentes sejam resolvidos.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Pré-visualizar respostas com deltas de eventos" icon="text" href="https://platform.claude.com/docs/pt-BR/managed-agents/event-deltas">
    Renderize o texto de resposta do agente enquanto o modelo ainda o está gerando.
  </Card>

  <Card title="Inspecionar sessões e acompanhar o uso" icon="magnifying-glass" href="https://platform.claude.com/docs/pt-BR/managed-agents/session-observability">
    Inspecione uma sessão no Claude Console e leia seu uso de tokens e custo de tabela.
  </Card>

  <Card title="Assinar webhooks" icon="link" href="https://platform.claude.com/docs/pt-BR/managed-agents/webhooks">
    Seja notificado quando eventos importantes acontecerem, sem polling.
  </Card>

  <Card title="Tipos de eventos" icon="book" href="https://platform.claude.com/docs/pt-BR/managed-agents/reference#event-types">
    Consulte todos os tipos de eventos que uma sessão pode enviar ou receber.
  </Card>
</CardGroup>
