---
title: Flusso di eventi della sessione
url: https://platform.claude.com/docs/it/managed-agents/events-and-streaming
description: Invia eventi, trasmetti le risposte in streaming e interrompi o reindirizza la tua sessione durante l'esecuzione.
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

La comunicazione con Claude Managed Agents è basata sugli eventi. Apri uno stream per seguire una sessione, invii eventi per dirigerla e le rispondi quando si mette in pausa in attesa di input.

## Tipi di eventi

Gli eventi fluiscono in due direzioni: tu invii eventi all'agente e la sessione ti invia eventi di ritorno.

* **Eventi che invii:** gli eventi `user.*` avviano una sessione e la guidano mentre procede. Gli eventi [`system.message`](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#send-system-messages) aggiungono contesto a livello di sistema.
* **Eventi che ricevi:** gli eventi di sessione, gli eventi di span e gli eventi dell'agente riportano lo stato della sessione e i progressi dell'agente.

Queste stringhe di tipo di evento seguono una convenzione di denominazione `{domain}.{action}`. Consulta [Tipi di eventi](https://platform.claude.com/docs/it/managed-agents/reference#event-types) nel riferimento per il catalogo completo.

I [tipi di eventi dei webhook](https://platform.claude.com/docs/it/managed-agents/webhooks#supported-event-types) sono separati e alcuni dei loro nomi differiscono da quelli dello stream. Ad esempio, i webhook usano `session.status_idled` anziché `session.status_idle`.

## Trasmettere eventi in streaming

Trasmetti in "streaming" (flusso continuo) gli eventi dalla sessione per ricevere aggiornamenti in tempo reale mentre l'agente lavora. Uno stream consegna solo gli eventi emessi dopo la sua apertura, quindi apri lo stream prima di inviare eventi per evitare una "race condition" (condizione di competizione).

<CodeGroup>
  ```bash cURL
  # Apri lo stream prima di inviare il primo evento: vengono consegnati solo gli eventi successivi.
  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
  # Apri lo stream prima di inviare il primo evento: vengono consegnati solo gli eventi successivi.
  ant beta:sessions:events stream --session-id "$SESSION_ID"
  ```

  ```python Python
  # Apri prima lo stream, poi invia il messaggio dell'utente
  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
  // Apri prima lo stream, poi invia il messaggio dell'utente
  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#
  // Apri prima lo stream, poi invia il messaggio dell'utente
  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
  	// Apri prima lo stream, poi invia il messaggio dell'utente
  	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 a 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
  // Apri prima lo stream, poi invia il messaggio dell'utente
  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 -> {
                  // Il campo `message` copre tutte le varianti di errore; leggilo dal JSON grezzo.
                  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;

  // Apri prima lo stream, poi invia il messaggio dell'utente
  $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
  # Apri prima lo stream, poi invia il messaggio dell'utente
  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 gli altri tipi di evento
    end
  end
  ```
</CodeGroup>

La sessione segnala gli errori tramite l'evento `session.error`. Consulta [Tipi di eventi](https://platform.claude.com/docs/it/managed-agents/reference#event-types) per i suoi campi.

Il testo della risposta dell'agente arriva come eventi `agent.message` bufferizzati, ciascuno emesso solo dopo il completamento della richiesta al modello che lo ha prodotto. Per visualizzare il testo mentre il modello lo sta ancora generando, consulta [Anteprima delle risposte con i delta degli eventi](https://platform.claude.com/docs/it/managed-agents/event-deltas).

### Riconnettersi senza perdere eventi

Per riconnetterti a una sessione esistente senza perdere eventi, combina un nuovo stream con la cronologia degli eventi:

1. Apri un nuovo stream.
2. [Elenca la cronologia completa degli eventi](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#list-past-events) per popolare un insieme di ID di eventi già visti.
3. Segui lo stream in tempo reale, saltando tutti gli eventi già restituiti dall'elenco della cronologia.

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Questo flusso di lavoro richiede più logica di un singolo comando shell. Usa il [Claude SDK](https://platform.claude.com/docs/it/cli-sdks-libraries/overview) per eseguirlo.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Questo flusso di lavoro richiede più logica di un singolo comando shell. Usa il [Claude SDK](https://platform.claude.com/docs/it/cli-sdks-libraries/overview) per eseguirlo.
  </CodeGroupItem>

  ```python Python
  with client.beta.sessions.events.stream(session.id) as stream:
      # Lo stream è aperto e in buffering. Elenca la cronologia prima di seguire il live.
      history = client.beta.sessions.events.list(session.id)
      seen_event_ids = {past_event.id for past_event in history}

      # Segui gli eventi live, saltando quelli già visti
      for event in stream:
          if event.type == "event_start" or event.type == "event_delta":
              # Le anteprime dei delta non sono abilitate su questa connessione.
              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);

  // Lo stream è aperto e in buffering. Elenca la cronologia prima di seguire il live.
  for await (const event of client.beta.sessions.events.list(session.id)) {
    seenEventIds.add(event.id);
  }

  // Segui gli eventi live, saltando quelli già visti
  tail: for await (const event of stream) {
    // Gli eventi di anteprima (event_start/event_delta) non hanno un id di primo livello
    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);

  // Lo stream è aperto e in buffering. Elenca la cronologia prima di seguire il live.
  HashSet<string> seenEventIds = [];
  var history = await client.Beta.Sessions.Events.List(session.ID);
  await foreach (var pastEvent in history.Paginate())
  {
      seenEventIds.Add(pastEvent.ID);
  }

  // Segui gli eventi live, saltando quelli già visti
  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()

  	// Lo stream è aperto e in buffering. Elenca la cronologia prima di seguire gli eventi live.
  	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)
  	}

  	// Segui gli eventi live, saltando quelli già visti
  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 a 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())) {
      // Lo stream è aperto e in buffering. Elenca la cronologia prima di seguire gli eventi live.
      // Ogni variante di evento ha `id`; leggilo dal JSON grezzo per deduplicare tra le varianti.
      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());
          }
      }

      // Segui gli eventi live; Set.add restituisce false per gli ID già visti, saltando il 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);

  // Lo stream è aperto e in buffering. Elenca la cronologia prima di seguire gli eventi live.
  $seenEventIds = [];
  foreach ($client->beta->sessions->events->list($session->id)->pagingEachItem() as $event) {
      $seenEventIds[$event->id] = true;
  }

  // Segui gli eventi live, saltando quelli già visti
  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)

  # Lo stream è aperto e in buffering. Elenca la cronologia prima di seguire gli eventi live.
  seen_event_ids = Set.new
  client.beta.sessions.events.list(session.id).auto_paging_each { seen_event_ids << it.id }

  # Segui gli eventi live, saltando quelli già visti — Set#add? restituisce nil per i duplicati
  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 gli altri tipi di evento
    end
  end
  ```
</CodeGroup>

## Inviare eventi

Invia un evento `user.message` per avviare o continuare il lavoro dell'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>

Ogni evento nella cronologia della sessione include un timestamp `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`), impostato quando l'evento termina l'elaborazione. Negli eventi che invii, `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) è `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `time.Time{}`) finché l'evento è ancora in coda dietro eventi precedenti. Le eccezioni sono `user.define_outcome`, `user.custom_tool_result` e `user.tool_result`, che vengono elaborati alla ricezione e restituiti con `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) già popolato.

## Rispondere quando la sessione diventa inattiva

Un evento `session.status_idle` significa che l'agente si è fermato ed è in attesa di input. Il suo `stop_reason.type` indica il motivo:

| `stop_reason.type` | Perché la sessione si è fermata                                                                                                                              | Cosa fare                                                                                                                                                              |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `end_turn`         | L'agente ha terminato il suo turno, oppure [lo hai interrotto](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#interrupt-the-agent). | [Invia un `user.message`](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#resume-an-idle-session) quando hai altro lavoro per l'agente.        |
| `requires_action`  | Una o più chiamate agli strumenti richiedono una tua risposta, come una chiamata a uno strumento personalizzato o una richiesta di conferma.                 | [Rispondi a ogni chiamata agli strumenti bloccante](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#answer-tool-calls-that-pause-the-session). |
| `budget_reached`   | Il costo di listino tracciato della sessione ha raggiunto il suo [budget](https://platform.claude.com/docs/it/managed-agents/budgets).                       | [Modifica o rimuovi il budget](https://platform.claude.com/docs/it/managed-agents/budgets#resume-a-session-at-its-budget).                                             |

Nessun evento che invii riprende una sessione messa in pausa al raggiungimento del budget. Il lavoro messo in pausa dal budget riprende automaticamente quando modifichi il budget impostandolo a un valore superiore al costo di listino consumato, oppure lo rimuovi. Quando il lavoro riprende, la sessione emette un evento `workflow_run.status_running` per ogni [esecuzione di workflow messa in pausa dal budget](https://platform.claude.com/docs/it/managed-agents/workflow-runs#budgets-and-limits). Un'esecuzione messa in pausa da un'interruzione rimane in pausa; consulta [Riprendere una sessione al raggiungimento del budget](https://platform.claude.com/docs/it/managed-agents/budgets#resume-a-session-at-its-budget). Consulta [Quando una sessione raggiunge il suo budget](https://platform.claude.com/docs/it/managed-agents/budgets#when-a-session-reaches-its-budget) per gli eventi che segnalano la pausa e gli eventi che la sessione accetta ancora.

## Rispondere alle chiamate agli strumenti che mettono in pausa la sessione

Una sessione si mette in pausa quando l'agente invoca uno [strumento personalizzato](https://platform.claude.com/docs/it/managed-agents/tools#custom-tools) e quando una chiamata a uno strumento richiede la tua conferma in base a una [policy di autorizzazione](https://platform.claude.com/docs/it/managed-agents/permission-policies). Entrambe le pause seguono la stessa sequenza:

1. La sessione emette la chiamata allo strumento come evento `agent.custom_tool_use`, `agent.tool_use` o `agent.mcp_tool_use`.
2. La sessione si mette in pausa con un evento `session.status_idle` il cui `stop_reason.type` è `requires_action`. Gli ID degli eventi bloccanti si trovano nell'array `stop_reason.event_ids`.
3. Per ogni ID di evento bloccante, invia un evento [`user.custom_tool_result`](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#return-a-custom-tool-result) o [`user.tool_confirmation`](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#confirm-a-tool-call). Il risultato di uno strumento personalizzato non deve attendere il passaggio 2.
4. Una volta risolti tutti gli eventi bloccanti, la sessione torna allo stato `running`.

In una sessione multiagente, gli eventi bloccanti di un subagente vengono ripubblicati anche sul thread principale. Consulta [Autorizzazioni degli strumenti e strumenti personalizzati](https://platform.claude.com/docs/it/managed-agents/session-threads#tool-permissions-and-custom-tools).

### Restituire il risultato di uno strumento personalizzato

L'evento `agent.custom_tool_use` contiene il nome e l'input dello strumento. Esegui lo strumento nel tuo sistema. Quindi invia un evento `user.custom_tool_result`, passando l'ID dell'evento nel parametro `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`) insieme al contenuto del risultato.

Puoi inviare il risultato non appena arriva l'evento `agent.custom_tool_use`, senza attendere `session.status_idle`. La sessione emette comunque `session.status_idle` con un motivo di arresto `requires_action` per la chiamata, e il tuo client può ignorarlo. Un secondo risultato per la stessa chiamata viene accettato e non ha alcun effetto.

Quando ti [riconnetti](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#reconnect-without-missing-events) a una sessione in pausa, `stop_reason.event_ids` sull'ultimo evento `session.status_idle` elenca le chiamate a cui rispondere.

L'esempio seguente risponde a ogni chiamata man mano che arriva:

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Questo flusso di lavoro richiede più logica di un singolo comando shell. Usa il [Claude SDK](https://platform.claude.com/docs/it/cli-sdks-libraries/overview) per eseguirlo.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Questo flusso di lavoro richiede più logica di un singolo comando shell. Usa il [Claude SDK](https://platform.claude.com/docs/it/cli-sdks-libraries/overview) per eseguirlo.
  </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":
                  # Esegui lo strumento
                  result = call_tool(event.name, event.input)

                  # Invia il risultato
                  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": {
        // Esegui lo strumento
        const result = await callTool(event.name, event.input);

        // Invia il risultato
        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)
      {
          // Esegui lo strumento
          var result = await CallTool(toolUse.Name, toolUse.Input);

          // Invia il risultato
          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:
  			// Esegui lo strumento
  			result := callTool(event.Name, event.Input)
  			// Invia il risultato
  			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 -> {
                  // Esegui lo strumento
                  var toolUse = event.asAgentCustomToolUse();
                  var result = callTool(toolUse.name(), toolUse.input());

                  // Invia il risultato
                  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:
              // Esegui lo strumento
              $result = callTool($event->name, $event->input);

              // Invia il risultato
              $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
      # Esegui lo strumento
      result = call_tool.call(event.name, event.input)
      # Invia il risultato
      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 l'agente ha [esecuzioni di workflow](https://platform.claude.com/docs/it/managed-agents/workflow-runs) aperte, una chiamata a uno strumento personalizzato può arrivare mentre la sessione rimane `running`. L'evento di inattività `requires_action` arriva solo quando nessuno dei [thread della sessione](https://platform.claude.com/docs/it/managed-agents/session-threads) è al lavoro. Non attenderlo: rispondi a ogni chiamata quando arriva il relativo evento `agent.custom_tool_use`. L'esempio in [Seguire un'esecuzione](https://platform.claude.com/docs/it/managed-agents/workflow-runs#follow-a-run) mostra come fare.

### Confermare una chiamata a uno strumento

Invia un evento `user.tool_confirmation`, passando l'ID dell'evento nel parametro `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`). Imposta `result` (csharp, go: `Result`) su `"allow"` o `"deny"`. Consulta [Rispondere alle richieste di conferma](https://platform.claude.com/docs/it/managed-agents/permission-policies#respond-to-confirmation-requests) per sapere quali chiamate attendono una conferma e come spiegare un rifiuto.

L'esempio seguente approva ogni chiamata in sospeso:

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Questo flusso di lavoro richiede più logica di un singolo comando shell. Usa il [Claude SDK](https://platform.claude.com/docs/it/cli-sdks-libraries/overview) per eseguirlo.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Questo flusso di lavoro richiede più logica di un singolo comando shell. Usa il [Claude SDK](https://platform.claude.com/docs/it/cli-sdks-libraries/overview) per eseguirlo.
  </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:
                          # Approva la chiamata allo strumento in sospeso
                          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) {
      // Approva la chiamata allo strumento in sospeso
      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)
          {
              // Approva la chiamata allo strumento in sospeso
              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 {
  				// Approva la chiamata allo strumento in sospeso
  				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())
          // Approva ogni chiamata a strumento in sospeso
          .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) {
                      // Approva la chiamata allo strumento in sospeso
                      $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|
          # Approva la chiamata allo strumento in sospeso
          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'esempio precedente approva ogni chiamata dopo che la sessione diventa inattiva. Se l'agente ha [esecuzioni di workflow](https://platform.claude.com/docs/it/managed-agents/workflow-runs) aperte, una chiamata a uno strumento può attendere la tua conferma mentre la sessione rimane `running`. Non attendere l'evento di inattività: quando arriva un evento `agent.tool_use` o `agent.mcp_tool_use` il cui [`evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`)](https://platform.claude.com/docs/it/managed-agents/permission-policies#see-how-each-call-was-evaluated) è `ask`, rispondi. L'esempio in [Seguire un'esecuzione](https://platform.claude.com/docs/it/managed-agents/workflow-runs#follow-a-run) risponde in questo modo alle chiamate agli strumenti personalizzati, e la sua introduzione spiega come aggiungere le conferme.

## Riprendere una sessione inattiva

Le sessioni persistono tra un'interazione e l'altra. Per riprendere una sessione, inviale un evento `user.message` come di consueto:

<CodeGroup>
  ```bash cURL
  # In produzione, passa l'ID memorizzato della sessione che vuoi riprendere.
  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
  # In produzione, passa l'ID memorizzato della sessione che vuoi riprendere.
  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
  # Riprendi una sessione creata in precedenza inviandole un nuovo evento user.message.
  # In produzione, passa l'ID memorizzato della sessione che vuoi riprendere.
  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
  // Riprendi una sessione creata in precedenza inviandole un nuovo evento utente.
  // In produzione, passa l'ID memorizzato della sessione che vuoi riprendere.
  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#
  // Riprendi una sessione creata in precedenza tramite ID. In produzione, passa
  // l'ID di sessione che hai memorizzato quando la sessione è stata creata.
  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
  // Riprendi una sessione creata in precedenza inviandole un nuovo evento
  // user.message. In produzione, passa l'ID memorizzato della sessione da riprendere.
  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
  // Riprendi una sessione creata in precedenza tramite ID. In produzione, passa
  // l'ID di sessione che hai memorizzato quando la sessione è stata creata.
  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
  // Riprendi una sessione creata in precedenza inviandole un nuovo evento user.message.
  // In produzione, passa l'ID di sessione salvato al momento della creazione della sessione.
  $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
  # Riprendere una sessione significa semplicemente inviarle l'evento successivo. In produzione,
  # passa l'ID di sessione che hai memorizzato quando la sessione è stata creata.
  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>

La cronologia della conversazione viene conservata a meno che la sessione non venga eliminata esplicitamente. Quando una sessione diventa inattiva, viene creato un checkpoint della sua sandbox. Il checkpoint conserva lo stato completo della sandbox, inclusi il filesystem, i pacchetti installati e tutti i file creati dall'agente.

<Note>
  Lo stato della sandbox viene conservato solo per 30 giorni dalla creazione della sandbox, e l'attività non estende questo periodo. Dopo 30 giorni lo stato della sandbox (file, strumenti installati e così via) non è più recuperabile, e una sessione ripresa parte da una sandbox nuova. Se il tuo workflow dipende dai contenuti della sandbox, fai in modo che l'agente scriva gli artefatti importanti negli [output](https://platform.claude.com/docs/it/managed-agents/define-outcomes#retrieving-deliverables) prima della scadenza del periodo.
</Note>

## Interrompere l'agente

Invia un evento `user.interrupt` per fermare l'agente durante l'esecuzione, quindi prosegui con un evento `user.message` per reindirizzarlo:

<CodeGroup>
  ```bash cURL
  # L'agente sta attualmente analizzando un file...
  # Interrompi con una nuova direzione:
  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'agente sta attualmente analizzando un file...
  # Interrompi con una nuova direzione:
  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'agente sta attualmente analizzando un file...
  # Interrompi con una nuova direzione:
  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'agente sta attualmente analizzando un file...
  // Interrompi con una nuova direzione:
  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'agente sta attualmente analizzando un file...
  // Interrompi con una nuova direzione:
  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'agente sta attualmente analizzando un file...
  // Interrompi con una nuova direzione:
  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'agente sta attualmente analizzando un file...
  // Interrompi con una nuova direzione:
  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'agente sta analizzando un file...
  // Interrompi con una nuova direzione:
  $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'agente sta attualmente analizzando un file...
  # Interrompi con una nuova direzione:
  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>

La chiamata restituisce il controllo non appena gli eventi vengono messi in coda. L'interruzione ha quindi effetto in questo ordine:

1. L'agente applica l'interruzione. Fino ad allora, il `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) dell'interruzione rimane `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `time.Time{}`) e la sessione rimane `running`. Una risposta del modello in corso si ferma immediatamente, ma l'applicazione dell'interruzione può richiedere più tempo mentre sono in esecuzione chiamate agli strumenti.
2. L'evento `user.interrupt` compare nello stream e il turno interrotto termina con un evento `session.status_idle`.
3. L'agente inizia il turno successivo con il `user.message` che hai inviato dopo l'interruzione.

Il `stop_reason.type` dell'evento di inattività è `end_turn`, lo stesso valore di un turno che termina da solo. Se ci sono esecuzioni di workflow aperte, l'interruzione non ne termina nessuna. Un'esecuzione in corso può mantenere la sessione `running`, quindi l'evento `session.status_idle` del passaggio 2 potrebbe non arrivare. Consulta [Interrompere una sessione con esecuzioni aperte](https://platform.claude.com/docs/it/managed-agents/workflow-runs#interrupt-a-session-with-runs-open).

## Elencare gli eventi passati

Recupera la cronologia completa degli eventi di una sessione:

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

Passa un filtro `types` (curl: `types[]`; cli: `--type`; csharp, go: `Types`) per restituire solo tipi di eventi specifici:

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

## Inviare messaggi di sistema

Su un [modello supportato](https://platform.claude.com/docs/it/managed-agents/events-and-streaming#supported-models), invia un evento `system.message` per fornire all'agente un contesto privilegiato a livello di sistema. Il contesto si applica al turno corrispondente e a tutti i turni successivi. Usalo quando l'agente ha bisogno di indicazioni aggiornate a livello di sistema durante la sessione, ad esempio una persona diversa, vincoli rivisti o contesto recuperato in fase di esecuzione.

Il `content` (csharp, go: `Content`) dell'evento accetta da 1 a 1000 elementi di testo. Il contenuto viene aggiunto al contesto di sistema della sessione come turno `role: "system"`. Non sostituisce il "system prompt" (prompt di sistema) di primo livello, impostato dal campo `system` (csharp, go: `System`; ruby: `system_`) nella definizione dell'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>

### Modelli supportati

`system.message` è supportato da questi modelli:

* 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 il modello principale dell'agente non supporta l'inserimento di messaggi di sistema a metà conversazione, l'evento viene rifiutato con un errore di validazione `model_does_not_support_mid_conversation_system`. I modelli dei subagenti non vengono verificati, perché `system.message` arriva solo sul thread principale.

### Messaggi di sistema mentre una chiamata a uno strumento è in sospeso

Mentre la sessione è inattiva con un motivo di arresto `requires_action`, un `system.message` deve seguire un evento di risultato dello strumento nella stessa richiesta. Se inviato da solo o con un `user.message`, viene rifiutato finché gli eventi degli strumenti in sospeso non vengono risolti.

## Passaggi successivi

<CardGroup cols={2}>
  <Card title="Anteprima delle risposte con i delta degli eventi" icon="text" href="https://platform.claude.com/docs/it/managed-agents/event-deltas">
    Visualizza il testo della risposta dell'agente mentre il modello lo sta ancora generando.
  </Card>

  <Card title="Ispezionare le sessioni e monitorare l'utilizzo" icon="magnifying-glass" href="https://platform.claude.com/docs/it/managed-agents/session-observability">
    Ispeziona una sessione nella Claude Console e consulta il suo utilizzo di token e il costo di listino.
  </Card>

  <Card title="Iscriversi ai webhook" icon="link" href="https://platform.claude.com/docs/it/managed-agents/webhooks">
    Ricevi notifiche quando si verificano eventi importanti senza polling.
  </Card>

  <Card title="Tipi di eventi" icon="book" href="https://platform.claude.com/docs/it/managed-agents/reference#event-types">
    Consulta ogni tipo di evento che una sessione può inviare o ricevere.
  </Card>
</CardGroup>
