Claude Platform Docs
Managed AgentsDéléguer du travail à votre agent

Flux d'événements de session

Envoyez des événements, diffusez les réponses en streaming, et interrompez ou redirigez votre session en cours d'exécution.

La communication avec Claude Managed Agents est basée sur les événements. Vous envoyez des événements utilisateur à l'agent, et vous recevez en retour des événements d'agent et de session pour suivre l'état.

Types d'événements

Les événements circulent dans deux directions.

  • Les événements utilisateur et les événements système sont ceux que vous envoyez à l'agent : les événements user.* démarrent une session et l'orientent au fur et à mesure de sa progression ; system.message ajoute un contexte de niveau système qui s'applique au tour qui l'accompagne et à tous les tours suivants.
  • Les événements de session, les événements de span et les événements d'agent vous sont envoyés pour vous offrir une observabilité sur l'état de votre session et la progression de l'agent. Les connexions de flux qui y souscrivent reçoivent également des deltas d'événements.

Les chaînes de type des événements de session, de span, d'agent, utilisateur et système suivent une convention de nommage {domain}.{action}. Les événements d'aperçu delta réservés au flux (event_start, event_delta) constituent l'exception. Consultez Types d'événements dans la référence pour le catalogue complet. Les types d'événements webhook sont distincts, et certains de leurs noms diffèrent de ceux du flux (par exemple, session.status_idled plutôt que session.status_idle).

Chaque événement persisté inclut un horodatage processed_at défini lorsque le traitement de l'événement se termine. Sur les événements que vous envoyez, processed_at est null tant que l'événement est encore en file d'attente derrière des événements antérieurs. Les exceptions sont user.define_outcome, user.custom_tool_result et user.tool_result, qui sont traités dès réception et renvoyés en écho avec processed_at déjà renseigné.

Intégration des événements

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

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",
                },
            ],
        },
    ],
)

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

# Agent is currently analyzing a file...
# Interrupt with a new direction:
client.beta.sessions.events.send(
    session.id,
    events=[
        {"type": "user.interrupt"},
        {
            "type": "user.message",
            "content": [
                {
                    "type": "text",
                    "text": "Instead, focus on fixing the bug in line 42.",
                },
            ],
        },
    ],
)

L'appel retourne dès que les événements sont mis en file d'attente, et le processed_at de l'interruption reste null jusqu'à ce que l'agent l'applique. Une réponse du modèle en cours s'arrête immédiatement. L'interruption peut prendre plus de temps à s'appliquer pendant que des appels d'outils sont en cours d'exécution, et la session reste running jusqu'à ce qu'elle le soit. L'événement user.interrupt apparaît ensuite sur le flux, et le tour interrompu se termine par un événement session.status_idle. Son stop_reason est end_turn, la même valeur que pour un tour qui se termine de lui-même ; il n'existe pas de raison d'arrêt spécifique à l'interruption. L'agent commence son tour suivant avec le user.message que vous avez envoyé après l'interruption.

Deltas d'événements

Par défaut, le texte de réponse de l'agent atteint le flux sous forme d'événements agent.message mis en mémoire tampon, chacun n'étant émis qu'une fois terminée la requête au modèle qui l'a produit. Les « event deltas » (deltas d'événements) vous permettent d'afficher ce texte de manière incrémentale, sous forme d'aperçu en direct, pendant que le modèle est encore en train de le générer. Un aperçu n'est pas la réponse : les aperçus sont une aide à l'affichage fournie au mieux, et l'agent.message mis en mémoire tampon constitue toujours l'enregistrement faisant autorité. Un client qui ignore les aperçus reçoit tout de même un flux complet et correct.

Souscrire aux aperçus

Les aperçus sont activés sur demande, par connexion de flux. Ajoutez le paramètre de requête event_deltas[] au flux que vous lisez, en le répétant une fois pour chaque type d'événement dont vous souhaitez un aperçu. Comme [] est un motif glob du shell, mettez l'URL entre guillemets chaque fois que vous construisez la requête dans un shell ; les exemples encodent les crochets en pourcentage sous la forme %5B%5D, ce qui fonctionne également. Les deux points de terminaison de flux acceptent le paramètre : le flux au niveau de la session à GET /v1/sessions/{session_id}/events/stream, et le flux propre à chaque thread de session à GET /v1/sessions/{session_id}/threads/{thread_id}/stream. Les valeurs acceptées sont agent.message et agent.thinking ; toute autre valeur renvoie une erreur 400, de même qu'une requête comportant plus de 100 valeurs. Les aperçus d'un sous-agent apparaissent sur le flux de thread propre à ce sous-agent.

Lorsqu'un événement faisant l'objet d'un aperçu commence, le flux émet un event_start portant le type et l'id de l'événement à venir :

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

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

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

Lorsqu'un événement agent.thinking fait l'objet d'un aperçu, seul l'event_start est émis. Aucun événement event_delta ne suit, et l'événement agent.thinking mis en mémoire tampon qui conclut l'aperçu ne porte aucun contenu de réflexion ; il s'agit d'un signal de progression, et non d'un porteur de contenu.

Contrairement aux événements persistés, event_start et event_delta n'ont ni id ni processed_at propres. Le seul identifiant qu'ils portent est l'id de l'événement dont ils donnent un aperçu.

Accumuler et réconcilier

Chaque SDK prenant en charge les deltas d'événements inclut un utilitaire d'accumulation qui gère pour vous la tenue des index. Les utilitaires Go, Java, Ruby et C# indexent également l'aperçu en cours d'accumulation par l'id de l'événement ; avec les utilitaires Python, TypeScript et PHP, vous tenez vous-même cette table de correspondance et intégrez chaque delta dans l'entrée correspondant à son id. Le modèle manuel fonctionne également dans tous les langages lorsque vous avez besoin d'une tenue personnalisée : appliquez-le aux types d'événements générés.

Dans le modèle manuel, traitez l'aperçu comme un tampon de travail et l'événement mis en mémoire tampon comme l'enregistrement de référence. Indexez le tampon par (event_id, index). Réconciliez par requête au modèle : un tour s'ouvre avec un unique événement session.status_running, puis, sur un tour qui se termine normalement, chaque requête au modèle produit, dans l'ordre, span.model_request_start, event_start, les événements event_delta, l'agent.message mis en mémoire tampon, et enfin span.model_request_end (dans l'onglet Événements de span). Sur le fil, voici la portion en aperçu de cette séquence, entrelacée avec les autres événements mis en mémoire tampon de la connexion :

event_start     {"event": {"type": "agent.message", "id": "sevt_01abc..."}}
event_delta     {"event_id": "sevt_01abc...", "delta": {"type": "content_delta", "index": 0, "content": {"type": "text", "text": "..."}}}
...
agent.message   {"id": "sevt_01abc...", "content": [...]}

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

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

Garanties sur lesquelles repose le modèle :

  • La concaténation des deltas d'un aperçu dans leur ordre d'arrivée, indexés par (event_id, index), donne un préfixe de content[index].text dans l'événement mis en mémoire tampon (un préfixe, pas nécessairement le texte entier, car des deltas peuvent être abandonnés sous charge).
  • Une connexion émet au plus un event_start par event_id, et l'événement mis en mémoire tampon est la dernière chose que cette connexion délivre pour cet id.
# Preview snapshots, keyed by event id. accumulate_managed_agents_event folds each
# event_start / event_delta into an agent.message snapshot; the buffered
# agent.message replaces it.
previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}

# Opt in to agent.message previews on this connection
with client.beta.sessions.events.stream(
    session.id, event_deltas=["agent.message"]
) as stream:
    client.beta.sessions.events.send(
        session.id,
        events=[
            {
                "type": "user.message",
                "content": [{"type": "text", "text": "Describe the repo in one sentence."}],
            },
        ],
    )

    for event in stream:
        match event.type:
            case "event_start":
                snapshot = accumulate_managed_agents_event(None, event)
                if snapshot is not None:
                    previews[event.event.id] = snapshot
                print(f"event_start             {event.event.type} {event.event.id}")
            case "event_delta":
                preview = accumulate_managed_agents_event(previews.get(event.event_id), event)
                if preview is not None:
                    previews[event.event_id] = preview
                    text = "".join(block.text for block in preview.content)
                    print(f"event_delta             preview: {text!r}")
            case "agent.message":
                # The buffered event is the record: it replaces and closes the preview
                preview = accumulate_managed_agents_event(previews.pop(event.id, None), event)
                text = "".join(block.text for block in preview.content)
                print(f"agent.message           {event.id} {text!r}")
            case "span.model_request_end":
                # No more deltas are coming. Close any preview whose
                # buffered event never arrived.
                for event_id in previews:
                    print(f"span.model_request_end  closing preview for {event_id}")
                previews.clear()
            case "session.status_idle":
                break

Aperçu des événements de thread de session

Dans une session multi-agents, chaque thread de session possède son propre flux d'événements à GET /v1/sessions/{session_id}/threads/{thread_id}/stream, et il accepte le même paramètre event_deltas[] avec les mêmes valeurs. Les aperçus sont limités au thread par conception : une connexion ne donne un aperçu que du thread qu'elle lit. Les aperçus d'un thread enfant sont délivrés sur le flux propre à cet enfant et ne sont jamais republiés sur le flux au niveau de la session, dont les aperçus restent limités au thread principal. Pour observer le texte d'un sous-agent au fur et à mesure que le modèle le génère, ouvrez le flux de thread de ce sous-agent.

Il est facile de se tromper sur le chemin du flux de thread : il s'agit de /threads/{thread_id}/stream, et non de /events/stream (qui n'existe qu'au niveau de la session), et il n'existe pas de point de terminaison /threads/{thread_id}/events/stream.

Les événements d'aperçu eux-mêmes ne changent pas. event_start et event_delta ont la même forme sur un flux de thread que sur le flux au niveau de la session, et le modèle accumuler et réconcilier s'applique tel qu'il est décrit. Le seul ajustement concerne la tenue : exécutez une instance d'accumulateur par connexion de flux.

# List the session's threads and pick a child: child threads carry a non-null
# parent_thread_id, and the primary thread's parent_thread_id is null.
child_thread = next(
    thread
    for thread in client.beta.sessions.threads.list(session.id)
    if thread.parent_thread_id is not None
)

# The child thread's stream takes the same event_deltas parameter as the
# session stream.
with client.beta.sessions.threads.events.stream(
    child_thread.id,
    session_id=session.id,
    event_deltas=["agent.message"],
) as stream:
    for event in stream:
        match event.type:
            case "event_delta":
                print(event.delta.content.text, end="")
            case "agent.message":
                # The buffered event is the authoritative record; render its content
                print()
                for block in event.content:
                    if block.type == "text":
                        print(block.text, end="")
                print()
            case "session.thread_status_idle":
                break

La boucle de lecture se termine sur session.thread_status_idle, l'événement émis lorsque le tour du thread de session se termine et que le thread devient inactif.

Limitations

Les aperçus sont optimisés pour la réactivité. Développez en tenant compte de ces contraintes :

  • Au mieux : sous charge, le serveur peut abandonner des deltas pour un événement. Lorsque c'est le cas, vous recevez un préfixe contigu du texte, puis plus aucun delta pour cet événement. L'agent.message mis en mémoire tampon arrive tout de même complet. Ne traitez jamais un aperçu accumulé comme définitif.
  • Pas de relecture à la reconnexion : les deltas ne sont délivrés qu'à la connexion qui y a souscrit, tant qu'elle est ouverte. Cela s'applique aussi bien au flux au niveau de la session qu'à chaque flux de thread de session, et une connexion ouverte après le début d'une requête au modèle ne reçoit aucun delta pour cet événement en cours. Si le flux est coupé, suivez la procédure de reconnexion de l'onglet Streaming des événements : rouvrez le flux et listez l'historique des événements. L'historique inclut tous les événements mis en mémoire tampon émis pendant que vous étiez déconnecté, y compris l'agent.message que votre aperçu attendait. Il n'existe aucun moyen de redemander les deltas manqués.
  • Un seul thread, texte uniquement : les aperçus couvrent le texte de l'assistant sur le thread que la connexion lit. L'utilisation d'outils, les résultats d'outils, les résultats MCP et l'activité sur tout autre thread de session ne font jamais l'objet d'un aperçu sur cette connexion.
  • agent.thinking limité au début : un aperçu agent.thinking n'émet que l'event_start pour signaler qu'un bloc de réflexion a commencé ; aucun événement event_delta ne le suit.
  • Jamais persistés : event_start et event_delta n'existent que sur le flux en direct. Ils n'apparaissent ni dans l'historique des événements de la session (GET /v1/sessions/{session_id}/events) ni dans l'historique des événements d'aucun thread de session.

Dépanner les aperçus

Si le flux ne se comporte pas comme vous l'attendez :

Vous observezCe que cela signifie
Un flux avec des événements mis en mémoire tampon mais aucun event_start ni event_deltaLa connexion que vous lisez n'a pas souscrit (event_deltas[] s'applique par connexion, et non par session), ou le tour n'a jamais touché le thread que vous recevez en streaming. Les aperçus sont limités au thread ; listez donc les threads de la session (GET /v1/sessions/{session_id}/threads) pour trouver celui qui s'est exécuté.
Une erreur 404 sur l'URL du fluxLe chemin ou un identifiant est incorrect, ou la requête ne porte aucun en-tête bêta managed-agents. Les points de terminaison de thread sont soumis à la bêta ; sans l'en-tête, ils n'existent donc pas.
Une erreur 400 mentionnant event_deltasSeuls agent.message et agent.thinking sont acceptés.

Scénarios supplémentaires

Gestion des appels d'outils personnalisés

Lorsque l'agent invoque un outil personnalisé :

  1. La session émet un événement agent.custom_tool_use contenant le nom de l'outil et son entrée.
  2. La session se met en pause avec un événement session.status_idle contenant stop_reason: requires_action. Les identifiants des événements bloquants se trouvent dans le tableau stop_reason.event_ids.
  3. Exécutez l'outil dans votre système et envoyez un événement user.custom_tool_result pour chacun, en passant l'identifiant de l'événement dans le paramètre custom_tool_use_id accompagné du contenu du résultat.
  4. Une fois tous les événements bloquants résolus, la session repasse à l'état running.
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:
                        # Look up the custom tool use event and execute it
                        tool_event = events_by_id[event_id]
                        result = call_tool(tool_event.name, tool_event.input)

                        # Send the result back
                        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 "end_turn":
                    break

Confirmation d'outil

Un appel d'outil attend votre confirmation sous une politique d'autorisation always_ask, ou sous auto lorsque le serveur ne parvient à aucune décision. Dans ce cas :

  1. La session émet un événement agent.tool_use ou agent.mcp_tool_use.
  2. La session se met en pause avec un événement session.status_idle dont le stop_reason.type est requires_action. Les ID des événements bloquants se trouvent dans le tableau stop_reason.event_ids.
  3. Envoyez un événement user.tool_confirmation pour chacun, en passant l'ID de l'événement dans le paramètre tool_use_id. Définissez result sur "allow" ou "deny". Utilisez deny_message pour expliquer un refus.
  4. Une fois tous les événements bloquants résolus, la session repasse à l'état running.

Chaque événement agent.tool_use et agent.mcp_tool_use porte evaluated_permission (allow, ask ou deny), et seuls les événements dont evaluated_permission vaut "ask" attendent une confirmation. La plupart des événements portent également un objet evaluation qui indique quelle politique a produit ce résultat, décrit dans Voir comment chaque appel a été évalué. Par exemple, un appel bash mis en pause sous une politique always_ask apparaît sur le flux comme suit :

{
  "type": "agent.tool_use",
  "id": "sevt_01def...",
  "name": "bash",
  "input": {
    "command": "pip install -r requirements.txt"
  },
  "evaluated_permission": "ask",
  "evaluation": {
    "type": "always_ask"
  },
  "processed_at": "2026-03-25T14:01:45Z"
}
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:
                        # Approve the pending tool call
                        client.beta.sessions.events.send(
                            session.id,
                            events=[
                                {
                                    "type": "user.tool_confirmation",
                                    "tool_use_id": event_id,
                                    "result": "allow",
                                },
                            ],
                        )
                case "end_turn":
                    break

Reprise d'une session inactive

Les sessions persistent entre les interactions. L'historique de conversation est conservé, sauf si la session est explicitement supprimée. Lorsqu'une session devient inactive, son sandbox fait l'objet d'un point de contrôle, ce qui préserve l'état complet du sandbox, y compris le système de fichiers, les paquets installés et tous les fichiers créés par l'agent. Cela vous permet de reprendre proprement après une période d'inactivité.

Pour reprendre une session, envoyez-lui un événement user.message comme d'habitude :

# Resume a previously created session by sending it a new user.message event.
# In production, pass the stored ID of the session you want to resume.
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.",
                },
            ],
        },
    ],
)

Atteinte du budget d'une session

Une session créée avec un budget se met en pause au lieu de dépasser ses dépenses. Lorsque le coût catalogue suivi de la session atteint le plafond, la plateforme met chaque thread en pause avant sa prochaine requête au modèle, et la session devient inactive avec un stop_reason de budget_reached au lieu de se terminer. La requête qui a fait passer le total au-delà du plafond s'exécute jusqu'à son terme, de sorte que le list_cost rapporté par l'instantané session.usage peut indiquer une valeur égale ou légèrement supérieure au plafond. Sur le flux, la pause arrive sous la forme de trois événements, dans l'ordre :

  1. session.thread_status_idle avec stop_reason: budget_reached, pour chaque thread au moment où il se met en pause.
  2. session.usage, un instantané de l'utilisation cumulée de la session et du coût catalogue suivi.
  3. session.status_idle avec stop_reason: budget_reached. L'événement session.usage précède toujours immédiatement cet état inactif.

Un thread dont la requête finale franchit le plafond et termine en même temps son tour rapporte end_turn sur son propre événement session.thread_status_idle, tandis que la session rapporte toujours budget_reached ; basez-vous sur le stop_reason au niveau de la session pour détecter la pause.

Tant que la session est à son plafond, elle n'accepte que les événements qui règlent le travail déjà en cours : user.tool_confirmation, user.tool_result, user.custom_tool_result et user.interrupt. Tout événement qui démarrerait un nouveau travail, y compris user.message, est rejeté avec une erreur 400 mentionnant cette liste. Lorsqu'une session comporte à la fois un thread en attente d'une demande d'outil et un thread en pause au plafond, le stop_reason au niveau de la session est requires_action, et non budget_reached : régler la demande ne déclenche pas de requête au modèle, répondez-y donc comme d'habitude.

Aucun événement ne reprend une session en pause à son plafond. Mettez plutôt à jour le budget de la session : modifier le plafond pour toute valeur supérieure au coût catalogue consommé, ou supprimer le budget en mettant à jour la session avec "budget": null, reprend automatiquement le travail en pause. Consultez Budgets de session pour savoir comment le coût catalogue est suivi et connaître la sémantique complète de mise à jour du budget.

Envoi de messages système

Envoyez un événement system.message pour fournir à l'agent un contexte privilégié de niveau système qui s'applique au tour qui l'accompagne et à tous les tours suivants. Contrairement au champ system de la définition de l'agent (qui définit l'invite système de premier niveau), le contenu de system.message est ajouté au contexte système de la session sous la forme d'un tour role: "system" au lieu de remplacer cette invite. Utilisez-le lorsque l'agent a besoin de directives de niveau système mises à jour en cours de session : une persona différente, des contraintes révisées ou un contexte récupéré à l'exécution qui doit façonner le comportement du modèle par la suite.

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

Tant que la session est inactive avec stop_reason: requires_action, un system.message n'est accepté que lorsqu'il suit un événement de résultat d'outil dans la même requête ; envoyé seul ou avec un user.message, il est rejeté jusqu'à ce que les événements d'outil en attente soient résolus. content accepte de 1 à 1000 éléments de texte.

Suivi de l'utilisation

L'objet session inclut un champ usage contenant l'utilisation cumulée de la session : le nombre de tokens, l'utilisation d'outils serveur, le temps actif et le coût catalogue suivi. Récupérez la session une fois qu'elle est devenue inactive pour lire les derniers totaux.

{
  "id": "sesn_01...",
  "status": "idle",
  "usage": {
    "input_tokens": 5000,
    "output_tokens": 3200,
    "cache_read_input_tokens": 20000,
    "cache_creation": {
      "ephemeral_5m_input_tokens": 2000,
      "ephemeral_1h_input_tokens": 0
    },
    "list_cost": {
      "amount": "187",
      "currency": "USD"
    },
    "active_seconds": 342.5,
    "server_tool_use": {
      "web_search_requests": 3,
      "web_fetch_requests": 0
    }
  }
}

input_tokens indique les tokens d'entrée non mis en cache et output_tokens indique le total des tokens de sortie sur l'ensemble des appels au modèle de la session. Le champ cache_read_input_tokens indique les tokens lus depuis le cache de prompts, et l'objet cache_creation détaille les tokens de création de cache par durée de vie du cache (ephemeral_5m_input_tokens et ephemeral_1h_input_tokens). Les entrées de cache utilisent par défaut un TTL de 5 minutes, de sorte que les tours consécutifs dans cette fenêtre bénéficient de lectures en cache, ce qui réduit le coût par token.

list_cost est la consommation cumulée de la session tarifée aux prix catalogue publics, sous forme d'un nombre entier de centimes dans une chaîne de caractères, accompagné d'un code de devise. active_seconds est le temps cumulé pendant lequel la session avait au moins un thread en cours d'exécution ; l'activité simultanée de threads concurrents n'est comptée qu'une seule fois, contrairement au champ active_seconds de l'objet stats de la session, qui additionne le temps actif propre à chaque thread. Ce chiffre dédupliqué est la durée sur laquelle le coût d'exécution de la session est tarifé. server_tool_use compte les requêtes d'outils exécutées côté serveur à des fins de tarification : les requêtes de recherche web sont intégrées au coût catalogue par requête, tandis que les requêtes de récupération web (web fetch) n'entraînent aucun frais par requête et ne sont pas mesurées, de sorte que web_fetch_requests affiche 0. Le champ usage propre à chaque thread de session contient également list_cost et active_seconds. Les chiffres par thread sont arrondis indépendamment et excluent le coût de temps d'exécution de la session ; leur somme ne correspond donc pas exactement au list_cost de la session. Le chiffre de la session fait autorité.

Vous n'avez pas besoin d'interroger la session pour observer ces totaux. L'événement session.usage transporte le même instantané cumulé (l'objet usage, plus le budget de la session, qui vaut null lorsque la session n'en a pas) sur le flux de la session et dans l'historique des événements. Il est émis lors des transitions vers l'état inactif plutôt que selon un minuteur : la session en émet un immédiatement avant de devenir inactive, quelle que soit la raison d'arrêt, et un lorsqu'un thread se met en pause en atteignant un budget de session. Un lecteur du flux voit ainsi le coût final d'un tour, ou du travail ayant atteint un budget, sans récupération supplémentaire.

Pour appliquer une limite de dépenses, définissez un budget de session plutôt que d'interroger l'utilisation et d'arrêter la session vous-même. La plateforme tarifie la consommation de la session en continu et met chaque thread en pause avant sa prochaine requête au modèle dès que le coût catalogue de la session atteint le plafond ; consultez Atteindre un budget de session pour voir à quoi cela ressemble sur le flux.

Observabilité dans la Console

La Claude Console inclut une visionneuse de sessions permettant d'inspecter ce qu'un agent a fait sans écrire de code. Dans la barre latérale de la Console, sous Managed Agents, sélectionnez Sessions pour voir toutes les sessions de l'espace de travail avec leur statut, leur agent, leur utilisation de tokens, leur coût et leur date de création, puis sélectionnez une session pour l'ouvrir. La visionneuse de sessions n'est accessible qu'aux développeurs et aux administrateurs. Elle affiche :

  • Mini-carte chronologique : une vue d'ensemble zoomable de l'activité de la session au fil du temps, avec une piste par thread dans les sessions multi-agents. Sélectionnez une piste pour afficher ce thread, ou sélectionnez un repère pour accéder directement à son événement.
  • Transcription : la conversation regroupée par requête au modèle, incluant la réflexion, les appels d'outils avec leurs entrées et résultats, et le texte des messages au fur et à mesure de leur streaming. Vous pouvez filtrer les événements et les copier ou les télécharger au format JSON.
  • Inspecteur : un panneau latéral redimensionnable contenant des détails sur la session, répartis en cinq onglets :
    • Session affiche les détails et métadonnées de la session, son coût cumulé au fil du temps, ainsi que les dépenses par rapport au budget de la session lorsqu'il est défini.
    • Events liste chaque événement brut du thread actuel dans l'ordre où le serveur l'a envoyé ; sélectionnez un événement pour voir son JSON. Un message diffusé en streaming pendant que la page était ouverte dispose également d'une vue Deltas de ses deltas d'événements.
    • Tools liste les outils avec lesquels les agents de la session sont configurés, ainsi que le nombre d'appels, les échecs et la durée médiane ; sélectionnez un outil pour voir ses appels et accéder à l'un d'eux dans la transcription.
    • Resources liste les fichiers, dépôts et magasins de mémoire montés à leurs chemins dans le conteneur, y compris les mémoires de chaque magasin et les modifications que cette session y a apportées, ainsi que les fichiers que l'agent a écrits dans /mnt/session/outputs et les skills attachées aux agents de la session.
    • Threads liste chaque thread avec son statut, la taille de son contexte et son coût. Sélectionnez un thread pour afficher ses détails, tels que l'agent, le modèle, l'utilisation du contexte et le coût.

Ajoutez ?event={event_id} à l'URL d'une session pour ouvrir la session à un événement spécifique.

Avec ant beta:sessions connect, vous pouvez ouvrir le même visualiseur depuis la CLI ant ou suivre la session dans votre terminal. Consultez Se connecter à une session Managed Agents depuis votre terminal.

Conseils de débogage

  • Vérifiez les événements de session : les erreurs de session sont transmises via l'événement session.error.
  • Examinez les résultats des outils : les échecs d'exécution d'outils expliquent souvent un comportement inattendu de l'agent.
  • Suivez l'utilisation des tokens : surveillez la consommation de tokens pour optimiser les prompts et réduire les coûts.
  • Utilisez les invites système : ajoutez des instructions de journalisation à l'invite système pour que l'agent explique son raisonnement.
  • Dépannez les aperçus : si un flux ayant activé les deltas d'événements ne se comporte pas comme prévu, consultez Dépanner les aperçus.

Was this page helpful?