Claude Platform Docs
Managed AgentsOrchestration avancée

Exécutions de workflow

Suivez les exécutions de workflow d'un agent : leurs états et événements, le moment où le travail est terminé, les requêtes pendant qu'une exécution est ouverte, les budgets et les limites.

Un « workflow » (flux de travail) est un programme qu'un agent écrit pour exécuter de nombreux agents et combiner ce qu'ils renvoient. Une « workflow run » (exécution de workflow) est l'exécution d'un workflow. Les workflows dynamiques sont la fonctionnalité qui permet à un agent d'écrire des workflows et de démarrer des exécutions. Vous l'activez ou la désactivez avec le paramètre workflows dans le bloc multiagent de l'agent.

Le serveur exécute un workflow en arrière-plan. Ses agents travaillent dans des fils de session que le serveur crée au fur et à mesure que le workflow en a besoin. Vous suivez les exécutions sur le flux d'événements de la session. Pour arrêter une exécution, demandez à l'agent de l'arrêter (voir Interrompre une session avec des exécutions ouvertes).

Fonctionnement des workflows dynamiques

L'agent que la session exécute écrit chaque workflow pour le travail que vous décrivez. Un workflow est un programme : il exécute d'autres agents, collecte ce que chacun renvoie et combine les résultats. Ainsi, l'agent peut prendre en charge une tâche trop volumineuse pour une seule conversation, comme l'examen de centaines de documents. Pendant une exécution, l'agent peut continuer à travailler ou terminer son tour, et il peut vérifier l'état de l'exécution.

Agent du fil principal
Exécution de workflow
Le serveur exécute le workflow en arrière-plan
Phase : Read the contracts
Fil d'agent
Fil d'agent
Fil d'agent
Les agents travaillent en même temps
Phase : Reconcile the findings
Fil d'agent
Un agent travaille avec les résultats
Le programme choisit ce qui s'exécute ici et peut répéter une étape
L'agent écrit un workflow (un programme) et démarre une exécution
Le programme transmet les résultats
Quand l'exécution se termine, l'agent lit ce qu'elle a fait

Le diagramme montre un exemple. Chaque workflow que l'agent écrit possède ses propres phases et agents. Une exécution comporte ces couches :

  • Exécution de workflow : Le serveur exécute le workflow en arrière-plan, sous la forme d'une exécution de workflow. Une session peut avoir plusieurs exécutions ouvertes en même temps.
  • Phases : Un workflow peut diviser son travail en phases. Une phase est une étape nommée de l'exécution, comme « Read the contracts ». Vous suivez la progression d'une exécution grâce à ses événements de phase.
  • Fils d'agent : Dans une phase, le programme exécute des agents. Chaque agent travaille dans son propre fil de session, sur un prompt que le programme a écrit. Un agent d'une exécution peut être un agent inline, que le programme définit lui-même, ou un agent prédéfini, que vous indiquez dans la liste predefined_agents de workflows. Pour savoir ce que montre chaque fil, consultez Les fils d'une exécution.

Le programme peut faire ce qui suit :

  • Exécuter des agents en même temps : Le programme peut exécuter de nombreux agents en même temps, ce qu'on appelle le « fanning out » (déploiement en éventail). Dans le diagramme, trois agents lisent des contrats dans la première phase.
  • Transmettre les résultats d'un agent à un autre : Chaque agent renvoie son résultat au programme. Le programme peut transmettre ce résultat à un autre agent. Dans le diagramme, l'agent de la deuxième phase travaille avec ce que les trois premiers ont renvoyé. Les agents d'une exécution travaillent aussi avec les mêmes fichiers, dans la « sandbox » (bac à sable) de la session.
  • Passer à l'étape suivante de lui-même : Le résultat d'un agent va au programme, et non à l'agent que la session exécute. Le programme détermine quels agents s'exécutent ensuite, et il écrit leurs prompts.
  • Répéter et choisir : À l'intérieur d'une phase, le programme peut répéter un travail et choisir son étape suivante en fonction de ce qu'un agent a renvoyé. Par exemple, il peut faire réviser un brouillon jusqu'à ce qu'une relecture soit validée ou qu'un nombre défini de tours soit épuisé. Dans le diagramme, le programme peut répéter une étape à l'intérieur de la deuxième phase.
  • Gérer un agent en échec : Lorsque l'un de ses agents échoue, le serveur exécute généralement cet agent une fois de plus, sur un nouveau fil, pendant que les autres agents de l'exécution continuent de travailler. S'il échoue à nouveau, le programme peut gérer l'échec ou le laisser mettre fin à l'exécution. Si le programme gère un échec, l'exécution peut tout de même se terminer avec completed ; demandez donc à l'agent que la session exécute de signaler ce qui a échoué.

Lorsque l'exécution se termine, l'agent que la session exécute obtient un tour pour lire ce que l'exécution a fait. Il peut alors vous répondre ou démarrer une autre exécution. Événements d'exécution liste les cas où ce tour arrive plus tard ou n'arrive pas.

Vous pouvez orienter la manière dont une exécution effectue le travail, par exemple la façon dont elle répartit le travail et ce qu'elle fait lorsqu'un agent échoue. Consultez Indiquer à l'agent quand utiliser une exécution.

Il n'y a pas d'étape d'approbation avant le démarrage d'une exécution : l'agent démarre une exécution dans le même tour que celui où il écrit le workflow. Pour examiner d'abord un plan, demandez à l'agent de décrire l'exécution et d'attendre votre feu vert. Au démarrage d'une exécution, workflow_run.created indique son nom, sa description et ses phases. Si une exécution que vous n'avez pas approuvée démarre, demandez à l'agent de l'arrêter (voir Interrompre une session avec des exécutions ouvertes).

Comment une exécution passe d'un état à l'autre

Une exécution démarre en cours (« running ») ou inactive (« idle »). Atteindre le budget, par exemple, met en pause une exécution en cours, ce qui la rend inactive ; augmenter ou supprimer le budget la fait alors reprendre, sauf si une interruption l'a aussi mise en pause. Une exécution en cours se termine lorsque son workflow se termine, que l'agent l'arrête, qu'elle échoue, que sa durée de vie s'écoule ou que la session est archivée. Une exécution inactive peut aussi se terminer, par exemple lorsque l'agent l'arrête ou que la session est archivée.

Une exécution est ouverte depuis son événement workflow_run.created jusqu'à son événement workflow_run.status_ended, qu'elle soit en cours ou inactive. Une exécution est inactive tant qu'elle est en pause, par exemple au budget de la session. Une exécution a une durée de vie, que l'agent peut définir lorsqu'il démarre l'exécution. Le temps qu'une exécution passe à attendre votre client compte dans cette durée de vie. Une pause n'empêche pas la durée de vie d'une exécution de s'écouler ; une exécution qui reste en pause peut donc se terminer avec timeout_error. Les événements suivants signalent le démarrage d'une exécution, ses phases et sa fin. Une pause au budget en envoie également un. Une pause après une interruption peut n'en envoyer aucun. Chaque événement workflow_run.* inclut workflow_run_id, qui vaut None uniquement sur un workflow_run.error lorsqu'aucune exécution n'a été créée.

Événements d'exécution

Les événements d'exécution arrivent sur le flux d'événements de la session, qui est le flux du fil principal, et la liste des événements de la session les renvoie également. Les événements d'exécution ne déclenchent pas de webhooks. Les événements de statut des fils de l'exécution arrivent sur le même flux. Chacun nomme son fil dans session_thread_id, et les fils d'une exécution sont ceux dont l'événement session.thread_created avait le workflow_run_id de l'exécution.

ÉvénementQuand il arriveQue faire
workflow_run.createdL'agent a démarré une exécution. Inclut workflow_run_id (wrun_…), le name et la description de l'exécution, ainsi que phases, les phases que le workflow déclare, chacune avec un id, un name et une description. Une description vaut None lorsque le workflow n'en fournit aucune. phases est toujours présent et peut être vide. Le name et la description de l'exécution et des phases sont du texte que le modèle a écrit ; ils peuvent donc reprendre des mots de votre requête. Le name d'une exécution peut également être attribué par le serveur.Enregistrez l'exécution comme ouverte. Affichez son name, ainsi que la progression par rapport à phases.
workflow_run.status_runningLorsque l'exécution commence à s'exécuter, ce qui peut survenir un certain temps après created, et chaque fois qu'elle reprend après une pause au budget. Une reprise après une interruption peut ne pas l'envoyer. Une exécution qui démarre inactive peut recevoir workflow_run.status_idle en premier.Affichez l'exécution comme en cours.
workflow_run.status_idleL'exécution a été mise en pause, par exemple au budget de la session. L'événement n'indique pas pourquoi. Une pause après une interruption peut ne pas l'envoyer.Pour continuer, consultez Coût et budgets ou Interrompre une session avec des exécutions ouvertes.
workflow_run.phase_started, workflow_run.phase_endedLe workflow est entré dans une phase ou en est sorti, ou la fin de l'exécution a clôturé une phase encore ouverte. L'événement de fin n'indique pas si le travail de la phase s'est terminé. Les deux incluent workflow_run_phase_id. L'événement de fin contient également phase_started_id, l'id de l'événement de début qu'il clôture. Aucun des deux ne contient le nom de la phase : recherchez-le par workflow_run_phase_id dans les phases de workflow_run.created.Mettez à jour la progression. Les phases s'exécutent une à la fois, dans l'ordre de phases, chacune au plus une fois, mais l'API ne le garantit pas. Associez la fin d'une phase à son début grâce à phase_started_id. Gérez le cas de plusieurs phases ouvertes, d'une phase qui ne figure pas dans phases et d'une phase listée qui ne démarre jamais, même dans une exécution qui va jusqu'à son terme. Chaque phase qui démarre se termine également, avant le workflow_run.status_ended de l'exécution.
workflow_run.status_endedL'exécution s'est terminée. Toujours le dernier des événements workflow_run.* de l'exécution. Inclut result.Lisez result (tableau suivant). L'agent obtient ensuite un tour pour lire comment l'exécution s'est terminée. Au budget, ou pendant que le fil principal attend votre client, ce tour arrive plus tard. Après une interruption, ce tour peut ne pas arriver : envoyez un user.message, ou lisez result vous-même. Après un archivage ou une terminaison, il n'arrive pas.
workflow_run.errorLe serveur signale une erreur d'une exécution, ou un démarrage qu'il a refusé. Une exécution qui se termine en error reçoit cet événement, avec la même erreur, avant son workflow_run.status_ended. Inclut error : un type et un message qui peut être journalisé sans risque. workflow_run_id vaut None lorsqu'aucune exécution n'a été créée.Journalisez-le, et ne le considérez pas comme la fin de l'exécution. Si workflow_run_id vaut None, aucune exécution n'a démarré. Sinon, continuez à suivre l'exécution jusqu'à son workflow_run.status_ended.
resultSignification
{"type": "completed"}Le workflow a fini de s'exécuter. Le résultat n'indique pas si le travail a réussi. Une exécution peut se terminer en completed même si du travail sur ses fils a échoué, ou si un fil n'a pas pu être créé. Pour trouver le travail en échec, lisez les événements de chacun des fils de l'exécution.
{"type": "stopped"}L'agent a arrêté l'exécution, ou la session a été archivée. L'événement n'indique pas lequel des deux. Ne considérez pas qu'il s'agit des seules causes possibles.
error avec timeout_errorL'exécution a atteint sa durée de vie, que l'agent peut définir.
error avec program_errorLe workflow a échoué. Son code a échoué, ou il a enfreint une règle des workflows, autre qu'une limite. Ou l'un des fils de l'exécution a échoué, ou n'a pas pu être créé, et le workflow a laissé cela mettre fin à l'exécution.
error avec thread_limit_errorL'exécution a dépassé sa limite sur les agents qu'un workflow démarre.
error avec unknown_errorLe serveur n'a pas pu poursuivre l'exécution, ou l'exécution a dépassé l'une des autres limites du serveur sur les workflows.

Un résultat d'erreur ressemble à {"type": "error", "error": {"type": "timeout_error", "message": "..."}}, où message peut être journalisé sans risque. Traitez un result.type non reconnu comme une exécution qui s'est terminée d'une autre manière, et un error.type non reconnu comme une erreur. Lorsqu'un élément dont dépend la session échoue, comme le modèle, un serveur MCP, des identifiants ou la facturation, le flux du fil en échec reçoit un session.error. Cela ne met pas fin à une exécution à lui seul. Mais si cela fait échouer l'un des fils de l'exécution, et que le workflow laisse cela mettre fin à l'exécution, l'exécution se termine avec program_error.

Par exemple, vous demandez à l'agent de révision de contrats lesquels de 300 contrats comportent une clause de changement de contrôle, et l'agent démarre une exécution :

  1. workflow_run.created nomme l'exécution « Find change-of-control clauses » et liste les phases « Read the contracts » et « Reconcile the findings » dans phases. Puis workflow_run.status_running suit.
  2. Des événements de phase marquent chaque phase, et chaque fil que l'exécution crée envoie session.thread_created avec le workflow_run_id de l'exécution.
  3. workflow_run.status_ended arrive avec result: {"type": "completed"}.
  4. L'agent répond : « 41 des 300 contrats en comportent une », et session.status_idle arrive avec end_turn.

Le premier événement de l'exécution liste ses phases :

{
  "type": "workflow_run.created",
  "id": "sevt_01abc...",
  "workflow_run_id": "wrun_01J8XkN5uT3vHpLqRfWdY2",
  "name": "Find change-of-control clauses",
  "description": "Reads each contract and lists those that have the clause.",
  "phases": [
    {
      "id": "wrph_01Kd3a1f3",
      "name": "Read the contracts",
      "description": "Reads each contract for the clause."
    },
    { "id": "wrph_01Kd3b7c9", "name": "Reconcile the findings", "description": null }
  ],
  "processed_at": "2026-10-09T14:01:45Z"
}

Chaque événement de phase nomme sa phase par workflow_run_phase_id. Il s'agit d'un id de phases, mais l'API ne le garantit pas :

{
  "type": "workflow_run.phase_started",
  "id": "sevt_01def...",
  "workflow_run_id": "wrun_01J8XkN5uT3vHpLqRfWdY2",
  "workflow_run_phase_id": "wrph_01Kd3a1f3",
  "processed_at": "2026-10-09T14:01:46Z"
}

Le dernier événement de l'exécution indique comment elle s'est terminée :

{
  "type": "workflow_run.status_ended",
  "id": "sevt_01ghi...",
  "workflow_run_id": "wrun_01J8XkN5uT3vHpLqRfWdY2",
  "result": { "type": "completed" },
  "processed_at": "2026-10-09T14:09:12Z"
}

Les fils d'une exécution

Chaque agent d'une exécution travaille dans son propre fil de session, que le serveur crée au fur et à mesure que le workflow en a besoin. Vous pouvez lister, lire et diffuser en streaming les fils d'une exécution comme n'importe quel fil enfant, et répondre à leurs appels d'outils depuis le flux principal. Pour les arrêter, demandez à l'agent d'arrêter l'exécution (voir Interrompre une session avec des exécutions ouvertes).

  • Regroupement : Un fil d'une exécution possède le workflow_run_id de l'exécution, tout comme l'événement session.thread_created qui l'annonce. Les autres fils, ainsi que les événements session.thread_created qui les annoncent, ont workflow_run_id défini sur None.
  • Agent : agent indique l'agent que le fil exécute. Pour un agent que vous avez indiqué dans la liste predefined_agents de workflows dans multiagent, agent contient l'id et la version de cet agent, comme sur le fil d'un sous-agent que vous avez indiqué. Pour un agent que le workflow définit (un agent inline), agent a le type inline et aucun id ni version. Il possède l'invite système que le workflow a écrite, et non celle de l'agent de la session. Il possède également le nom et la description que le workflow lui a donnés. Le serveur attribue un nom si le workflow n'en a donné aucun. Il utilise le modèle de l'agent de la session, l'agent que la session exécute. Ses outils, serveurs MCP et skills sont un sous-ensemble de ceux de l'agent de la session. Il les reçoit tous, mais l'API ne le garantit pas. Ses outils conservent leurs politiques d'autorisation.
  • Ce que les fils partagent : Les fils d'une exécution travaillent dans la sandbox de la session ; chaque fil travaille donc avec les mêmes fichiers. Cela inclut les fichiers d'un magasin de mémoire que la session monte. Un agent que le workflow définit utilise ses serveurs MCP avec les identifiants que la session résout pour eux. Chaque fil possède son propre historique de conversation.
  • Événements : Les événements session.thread_created, session.thread_status_running, session.thread_status_idle et session.thread_status_terminated d'un fil d'exécution arrivent aussi sur le flux principal (consultez Événements d'exécution). Ses événements de message restent sur son propre flux. Ses webhooks de fil sont envoyés comme pour n'importe quel fil enfant. Pour savoir ce que le flux propre du fil enregistre, consultez Événements des fils de session.
  • Phases : Aucun événement ni champ n'indique dans quelle phase un fil travaille, et les fils d'une même exécution peuvent avoir le même agent_name. Suivez la progression d'une exécution grâce à ses événements de phase, et distinguez ses fils par session_thread_id.
  • Archivage : Le serveur archive chaque fil au plus tard à la fin de son exécution. Il peut en archiver un plus tôt, dès que le fil renvoie son résultat ou que l'exécution n'en a plus besoin. Si le fil est encore en cours d'exécution ou attend votre client à ce moment-là, le serveur l'arrête d'abord. Un fil archivé reste dans la liste des fils, avec le statut terminated. Vous n'avez pas besoin d'archiver vous-même les fils d'une exécution.
  • Outils : Une exécution peut créer plusieurs fils pour la même portion de travail ; faites donc en sorte que les outils que vos agents appellent puissent être appelés deux fois sans risque.

Savoir quand le travail est terminé

Pendant qu'une exécution est en cours, attendez-vous à ce que la session reste running, même lorsqu'aucun de ses fils ne travaille. Elle passe à idle avec requires_action lorsqu'aucun fil ne travaille et qu'un fil attend votre client. Un état inactif à lui seul ne signifie pas que le travail est terminé. Le travail est terminé lorsque les deux conditions suivantes sont vraies :

  1. Chaque exécution dont vous avez vu la création a son workflow_run.status_ended.
  2. Ensuite, un session.status_idle arrive avec stop_reason end_turn, et ce n'est pas votre propre requête, comme une interruption, qui l'a provoqué. Après une interruption, ne comptez qu'un état inactif qui survient après votre prochain user.message ou user.define_outcome.
  • Exécutions en pause : Une exécution en pause ne maintient pas la session en running, de sorte que la session peut devenir inactive alors que l'exécution est encore ouverte. Au budget, par exemple, la session devient inactive avec budget_reached. Le travail n'est pas terminé tant que l'exécution ne s'est pas terminée.
  • Une autre exécution : L'agent peut démarrer une nouvelle exécution lorsqu'il lit un résultat, vérifiez donc à nouveau.
  • Résultats attendus : Si vous avez défini un résultat attendu, aucune évaluation ne démarre tant qu'une exécution est ouverte, qu'elle soit en cours ou inactive. Le tour au cours duquel l'agent lit le résultat de l'exécution peut en démarrer une.
  • retries_exhausted : Le tour de l'agent a échoué sur une erreur : les nouvelles tentatives ont été épuisées, ou l'erreur ne peut pas faire l'objet d'une nouvelle tentative, comme un échec de facturation. Une exécution peut encore être en cours lorsque cet état inactif survient. Si une exécution s'est terminée et que l'agent n'a pas encore lu son résultat, le serveur démarre un nouveau tour sans aucune entrée de votre part. La session repasse à running ; attendez donc le prochain état inactif. Si la session reste inactive, lisez le session.error qui l'a précédé et corrigez la cause. Envoyez ensuite un user.message, ou lisez vous-même le result de chaque exécution.

Suivre une exécution

Cet exemple suit une session depuis votre message jusqu'à la réponse de l'agent. Il ouvre le flux et envoie le message. Il fait ensuite ce qui suit :

  • Suit chaque exécution depuis son workflow_run.created jusqu'à son workflow_run.status_ended, et affiche chaque phase lorsqu'elle démarre.
  • Répond aux appels d'outils personnalisés à l'arrivée de chaque agent.custom_tool_use, car un fil d'une exécution peut attendre votre client pendant que la session reste running. Si les outils de votre agent demandent une confirmation, ajoutez une branche qui répond à chaque agent.tool_use ou agent.mcp_tool_use dont le evaluated_permission vaut ask. L'exemple n'en contient pas, car une branche qui autorise chaque appel transformerait always_ask en autorisation systématique.
  • S'arrête lorsque le travail est terminé : aucune exécution n'est ouverte, et la session devient inactive avec end_turn. Il s'arrête aussi si la session se termine. Sur un état inactif avec toute autre raison d'arrêt, à l'exception de requires_action, comme budget_reached, retries_exhausted ou refusal, il affiche la raison et s'arrête ; gérez donc ces cas dans votre propre code. Il s'arrête sur retries_exhausted même lorsque le serveur est sur le point de démarrer un nouveau tour de lui-même. Il continue d'attendre sur requires_action, et sur end_turn tant qu'une exécution est ouverte.
open_runs: dict[str, str] = {}  # workflow_run_id -> run name
phase_names: dict[tuple[str, str], str] = {}  # (run ID, phase ID) -> phase name

# Ouvrez d'abord le stream, puis envoyez le message utilisateur
with client.beta.sessions.events.stream(session_id) as stream:
    client.beta.sessions.events.send(
        session_id,
        events=[
            {
                "type": "user.message",
                "content": [
                    {
                        "type": "text",
                        "text": "Which contracts in /contracts have a change-of-control clause?",
                    },
                ],
            },
        ],
    )

    for event in stream:
        match event.type:
            case "workflow_run.created":
                open_runs[event.workflow_run_id] = event.name
                for phase in event.phases:
                    phase_names[event.workflow_run_id, phase.id] = phase.name
                print(f"Run started: {event.name}")
            case "workflow_run.phase_started":
                phase_id = event.workflow_run_phase_id
                key = (event.workflow_run_id, phase_id)
                print(f"  Phase: {phase_names.get(key, phase_id)}")
            case "workflow_run.status_ended":
                name = open_runs.pop(event.workflow_run_id, event.workflow_run_id)
                print(f"Run ended: {name} ({event.result.type})")
            case "agent.custom_tool_use":
                # Répondez à l'arrivée de l'événement. Le thread d'une exécution peut attendre votre
                # client pendant que la session reste en cours d'exécution.
                result = call_tool(event.name, event.input)
                try:
                    client.beta.sessions.events.send(
                        session_id,
                        events=[
                            {
                                "type": "user.custom_tool_result",
                                "custom_tool_use_id": event.id,
                                "content": [{"type": "text", "text": result}],
                            },
                        ],
                    )
                except anthropic.BadRequestError as error:
                    # Le serveur refuse un résultat qui arrive trop tard, après avoir
                    # archivé le thread de l'appel. Continuez à suivre l'exécution.
                    print(f"  Answer to {event.name} refused: {error.message}")
            case "session.status_idle":
                # Terminé quand toutes les exécutions sont finies et que l'agent a terminé son tour
                if not open_runs and event.stop_reason.type == "end_turn":
                    break
                # Un état idle avec requires_action attend votre client, donc continuez la lecture.
                # Pour toute autre raison d'arrêt, affichez-la et arrêtez.
                if event.stop_reason.type not in ("end_turn", "requires_action"):
                    print(f"Session idle: {event.stop_reason.type}")
                    break
            case "session.status_terminated":
                break

Interrompre une session avec des exécutions ouvertes

Envoyez user.interrupt sans session_thread_id, ou avec l'ID du fil principal. Cela arrête le tour de l'agent. Cela ne met fin à aucune exécution. Les exécutions de la session peuvent se mettre en pause ou continuer à s'exécuter, et leurs événements peuvent ne pas indiquer lequel des deux. La durée de vie d'une exécution en pause continue de s'écouler ; l'exécution peut donc se terminer avec timeout_error pendant qu'elle est en pause.

  • Appels d'outils en attente : Après l'interruption, un appel d'outil d'un fil d'exécution peut encore attendre votre client. Répondez à chacun d'eux. Pour annuler un appel qui demande une confirmation, refusez-le. Pour annuler un appel d'outil personnalisé, envoyez un résultat avec is_error défini sur true et un texte dans content qui en explique la raison. Tant que la session est idle avec requires_action, un user.message renvoie 400 ; répondez donc d'abord aux appels.
  • Pour arrêter les exécutions : Envoyez un user.message demandant à l'agent d'arrêter ses exécutions. Une exécution arrêtée se termine avec le result {"type": "stopped"}. Tant que la session est idle avec budget_reached, un user.message renvoie 400 jusqu'à ce que vous augmentiez ou supprimiez le budget. L'augmenter ou le supprimer fait aussi reprendre les exécutions que le budget a mises en pause, sauf si l'interruption les a aussi mises en pause.
  • Pour continuer : Envoyez un user.message demandant à l'agent de poursuivre ses exécutions. Après une interruption, les exécutions peuvent attendre ce message. Si la session est idle avec budget_reached, augmentez ou supprimez d'abord le budget.
  • Résultats des exécutions : Une exécution qui se termine après l'interruption envoie quand même workflow_run.status_ended.

Pendant qu'une exécution est ouverte

RequêtePendant qu'une exécution est ouverteQue faire
Archiver ou supprimer la sessionPeut renvoyer 400 tant qu'une exécution est ouverte, quel que soit le statut de la session. Le error.details.error_code de l'erreur peut être "workflow_run_open". Peut aussi réussir.Demandez à l'agent d'arrêter ses exécutions, ou attendez que chaque exécution soit terminée. Une exécution en pause ne se termine d'elle-même que lorsque sa durée de vie s'écoule. Envoyez ensuite la requête une fois la session idle. Un archivage qui réussit met fin à chaque exécution ouverte avec {"type": "stopped"}. Après un archivage, le workflow_run.status_ended d'une exécution, et le workflow_run.phase_ended d'une phase encore ouverte, n'arrivent pas sur le flux. Listez les événements de la session pour les lire. Après une suppression qui réussit, aucun événement workflow_run ne signale la fin des exécutions de la session.
Archiver l'un des fils d'une exécutionRenvoie 400 avec error.details.error_code: "workflow_run_open" tant que l'exécution est ouverte, en cours ou inactive, sauf si le serveur a déjà archivé le fil.Rien. Le serveur archive les fils d'une exécution.
Mettre à jour l'agent de la sessionRenvoie 400 avec error.details.error_code: "workflow_run_open" tant qu'une exécution est ouverte, même en pause. La mise à jour de l'agent sous-jacent est toujours acceptée, et la session conserve sa propre copie. Une requête qui envoie également d'autres champs, comme budget, est rejetée dans son intégralité.Attendez que chaque exécution ait son workflow_run.status_ended, ou demandez à l'agent d'arrêter ses exécutions.
Répondre à un appel d'outil ou à une confirmation d'outil provenant d'un fil d'une exécutionAutorisé. Il arrive sur le flux principal, et son session_thread_id nomme le fil.Répondez dès que l'événement arrive, en transmettant l'id de l'événement comme tool_use_id ou custom_tool_use_id. N'attendez pas session.status_idle : la session peut rester running pendant que les autres fils de l'exécution travaillent. Une fois que le serveur a archivé le fil, un résultat d'outil pour l'un de ses appels n'a aucun effet, et il peut renvoyer 400. Lorsqu'un résultat d'outil renvoie 400, trouvez le fil de l'appel dans la liste des fils. Si son statut est terminated, le résultat est arrivé trop tard ; abandonnez-le donc. Envoyez chaque résultat d'outil dans une requête distincte, car le serveur refuse une requête entière lorsqu'il refuse l'un de ses événements. Une confirmation d'outil qui arrive trop tard renvoie 200, ce qui ne signifie pas que l'outil s'est exécuté.

Reconstruire l'état des exécutions après la reconnexion

Reconstruisez l'état de chaque exécution à partir des événements de la session. Le flux ne rejoue pas ce que vous avez manqué : une nouvelle connexion ne délivre que les événements émis après son ouverture. Listez donc les événements avec un filtre types, avec une entrée pour chaque type d'événement, comme dans Lister les événements passés. Passez le next_page de chaque réponse comme page jusqu'à ce que next_page soit None ou absent. workflow_run.created, workflow_run.status_running, workflow_run.status_idle et workflow_run.status_ended donnent l'état de chaque exécution, à ceci près qu'une exécution mise en pause après une interruption peut encore apparaître comme en cours. workflow_run.phase_started et workflow_run.phase_ended permettent de reconstruire la progression. Une exécution sans aucun événement de statut n'a pas encore commencé à s'exécuter. Aucun endpoint ne liste les exécutions.

Coût et budgets

Les requêtes au modèle d'une exécution comptent dans le budget de la session. Une exécution n'a pas de prix propre. Les tokens que ses agents utilisent sont facturés comme les autres tokens de la session, aux tarifs de chaque modèle. Pour l'ensemble des frais d'une session, consultez Tarification de Claude Managed Agents.

  • Utilisation d'une exécution : Listez les fils de la session et additionnez les nombres de tokens dans usage des fils portant le workflow_run_id de l'exécution. La liste inclut les fils archivés, dont le statut est terminated, de sorte que les fils d'une exécution terminée sont comptabilisés. Passez le next_page de chaque réponse comme page jusqu'à ce que next_page soit None ou absent, et ignorez tout fil sans usage. Si vous additionnez plutôt le list_cost des fils, le total exclut le temps d'exécution de la session, et chaque montant est arrondi séparément.
  • Au budget : Chaque exécution ouverte se met en pause, et la session signale idle avec budget_reached, ou requires_action si un appel d'outil est également en attente. Chaque fil termine la requête de modèle qu'il a déjà commencée, de sorte qu'une exécution peut dépasser le budget d'une requête par fil actif. Augmenter ou supprimer le budget fait reprendre les exécutions qu'il a mises en pause, sauf si une interruption les a également mises en pause. Si l'utilisation de la session inclut un modèle sans tarif public, seule la suppression du budget le fait ; consultez Modèles sans tarif public. La durée de vie d'une exécution en pause continue de s'écouler, de sorte que l'exécution peut se terminer avec timeout_error pendant qu'elle est en pause.

Limites

LimiteValeurÀ la limite
Fils actifs simultanément dans une exécution64L'exécution n'en crée plus jusqu'à ce que l'un d'eux se termine. L'API ne garantit pas ce nombre.
Agents qu'un workflow démarre sur toute la durée de vie de l'exécution1 000Lorsque le workflow en demande davantage, le serveur ne démarre pas d'autre agent, et l'exécution se termine avec thread_limit_error. Le serveur peut réexécuter un agent en échec sur un nouveau fil, de sorte qu'une exécution peut avoir plus de 1 000 fils.
Durée de vie d'une exécution24 heures par défaut, ou la durée de vie que l'agent définitL'exécution se termine avec timeout_error. Aucun événement n'indique quelle durée de vie l'agent a définie.
Exécutions ouvertes simultanément dans une session10 par défautLe serveur refuse de démarrer une autre exécution. L'appel d'outil de l'agent reçoit une erreur, et vous recevez un workflow_run.error dont l'error.type est max_workflow_runs_error. Les exécutions inactives comptent dans la limite.

Le serveur raccourcit le name d'une exécution ou d'une phase à 64 caractères et sa description à 256. Le serveur applique aux workflows d'autres limites, ainsi que des règles, qui ne sont pas listées ici. Ce que vous voyez dépend du moment où le serveur détecte le problème :

Ce qui se passeCe que vous voyez
Le workflow dépasse l'une des autres limites lorsque l'agent démarre l'exécutionLe démarrage est refusé. Vous recevez un workflow_run.error, et aucune exécution.
L'exécution dépasse l'une des autres limites plus tardVous recevez un workflow_run.error, puis l'exécution peut se terminer avec unknown_error.
Le serveur détecte après le démarrage que le workflow enfreint une règle des workflows, autre qu'une limiteVous recevez un workflow_run.error, et l'exécution peut ensuite se terminer avec program_error.

Une session peut démarrer un nombre quelconque d'exécutions au cours de sa vie.

  • Démarrage des exécutions : Seul l'agent du fil principal de la session démarre des exécutions. Un agent travaillant dans le fil d'une exécution ne peut pas démarrer sa propre exécution, de sorte que les exécutions ne s'imbriquent pas.
  • Fin des exécutions : Aucun événement que vous envoyez ne met fin à une exécution ; l'archivage de la session le peut.
  • Les fils d'une exécution : Vous ne pouvez pas en arrêter un par son ID, ni en archiver un tant que son exécution est ouverte.
  • Limite de fils : Les fils d'une exécution sont exemptés de la limite de fils enfants de la session.
  • Visibilité : Vous ne voyez pas le code du workflow, mais vous pouvez demander le workflow à l'agent, comme le décrit l'astuce dans Les fils d'une exécution. Vous ne voyez pas non plus les appels d'outils que l'agent effectue pour démarrer et gérer les exécutions, ni le résultat que chaque fil renvoie au workflow.

Limites de débit

Le travail d'une exécution est comptabilisé dans les « rate limits » (limites de débit) dont votre organisation dispose déjà.

QuoiCompte dansQue faire
Les requêtes de votre client pour récupérer ou lister la session, ses fils et leurs événementsLa limite de lecture des endpoints Managed AgentsSuivez une exécution sur le flux d'événements de la session plutôt que par interrogation périodique.
Les requêtes au modèle provenant des fils d'une exécutionVos limites de débit de l'API Messages pour le modèle qu'utilise chaque fil, avec le reste de votre traficPrévoyez de la marge pour une exécution dans ces limites, ou demandez des limites plus élevées.

Lorsqu'une requête au modèle provenant de l'un des fils d'une exécution est soumise à une limite de débit, ou que le modèle est surchargé, le flux propre du fil peut recevoir un session.error de type model_rate_limited_error ou model_overloaded_error :

  • Si son retry_status.type vaut retrying, le serveur retente la requête, et le fil travaille toujours.
  • S'il vaut exhausted, le fil a échoué. Si le workflow laisse cet échec mettre fin à l'exécution, l'exécution se termine avec program_error, qui n'en nomme pas la cause. Lisez les événements des fils en échec pour la trouver.

Le serveur limite aussi la quantité de travail que l'ensemble des sessions de votre organisation effectuent chaque minute. Un fil qui atteint cette limite s'arrête, avec un session.error sur son propre flux dont le message mentionne une limite de débit. Attendez une minute avant de demander à l'agent de continuer.

Was this page helpful?