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é, ce qu'une exécution bloque, 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. Seul l'agent démarre une exécution. Aucun événement que vous envoyez n'en termine une ; l'archivage de la session le peut.
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.
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 listez dans
workflows.predefined_agents. 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 programme peut gérer l'échec ou le laisser mettre fin à l'exécution.
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.
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. La durée de vie d'une exécution est de 24 heures par défaut. L'agent peut définir une durée de vie plus courte 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, de sorte qu'une exécution qui reste en pause peut 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 aussi un. Une pause après une interruption peut n'en envoyer aucun. Chaque événement workflow_run.* inclut workflow_run_id, qui vaut null 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 aussi. 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énement | Quand il arrive | Que faire |
|---|---|---|
workflow_run.created | L'agent a démarré une exécution. Inclut workflow_run_id (wrun_…), le name et la description de l'exécution, et phases, les phases que le workflow déclare, chacune avec un id, un name et une description. Une description vaut null 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 écrit par le modèle, ils peuvent donc reprendre des mots de votre requête. Le name d'une exécution peut aussi être attribué par le serveur. | Enregistrez l'exécution comme ouverte. Affichez son name et la progression par rapport à phases. |
workflow_run.status_running | Lorsque 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_idle | L'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 Budgets et limites ou Interrompre une session avec des exécutions ouvertes. |
workflow_run.phase_started, workflow_run.phase_ended | Le 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. La fin comporte aussi phase_started_id, l'id de l'événement de début qu'elle 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 plus d'une phase ouverte, une phase qui ne figure pas dans phases et 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 aussi, avant le workflow_run.status_ended de l'exécution. |
workflow_run.status_ended | L'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.error | Le 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 null 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 null, aucune exécution n'a démarré. Sinon, continuez à suivre l'exécution jusqu'à son workflow_run.status_ended. |
result | Signification |
|---|---|
{"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, et des versions ultérieures pourraient ajouter d'autres causes. |
error avec timeout_error | L'exécution a atteint sa durée de vie : 24 heures par défaut, ou celle que l'agent a définie. |
error avec program_error | Le 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_error | L'exécution a dépassé sa limite sur les agents qu'un workflow démarre. |
error avec unknown_error | Le 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 :
workflow_run.creatednomme l'exécution « Find change-of-control clauses » et liste les phases « Read the contracts » et « Reconcile the findings » dansphases. Puisworkflow_run.status_runningsuit.- Des événements de phase marquent chaque phase, et chaque fil que l'exécution crée envoie
session.thread_createdavec leworkflow_run_idde l'exécution. workflow_run.status_endedarrive avecresult: {"type": "completed"}.- L'agent répond : « 41 des 300 contrats en comportent une », et
session.status_idlearrive avecend_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 lorsque 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 (consultez Interrompre une session avec des exécutions ouvertes). Vous ne pouvez pas en arrêter un par son ID, ni en archiver un tant que son exécution est ouverte.
- Regroupement : Un fil d'une exécution porte le
workflow_run_idde l'exécution, tout comme l'événementsession.thread_createdqui l'annonce. Les autres fils, et les événementssession.thread_createdqui les annoncent, ontworkflow_run_iddéfini ànull. - Agent :
agentindique l'agent que le fil exécute. Pour un agent que vous avez listé dansmultiagent.workflows.predefined_agents,agentcontient l'idet laversionde cet agent, comme sur le fil d'un sous-agent que vous avez listé. Pour un agent que le workflow définit (un agent inline),agenta letypeinlineet aucunidniversion. Il possède l'invite système que le workflow a écrite, et non celle de l'agent de session. Il possède aussi 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 session, l'agent que la session exécute. Ses outils, serveurs MCP et skills sont un sous-ensemble de ceux de l'agent de session. Il les obtient 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, de sorte que chaque fil travaille 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_idleetsession.thread_status_terminatedd'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 parsession_thread_id. - Limite de fils : Les fils d'une exécution sont exemptés de la limite de fils enfants de la session.
- Démarrage d'exécutions : Seul l'agent du fil principal de la session démarre des exécutions. Un agent travaillant dans un fil d'une exécution ne peut pas démarrer sa propre exécution, de sorte que les exécutions ne s'imbriquent pas.
- 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 en a fini avec lui. Si le fil est encore en cours 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. Tant que l'exécution est ouverte, une requête d'archivage d'un fil que le serveur n'a pas encore archivé renvoie 400 avecerror.details.error_code: "workflow_run_open". - Visibilité : Vous ne voyez pas le code du workflow, mais vous pouvez demander le workflow à l'agent, comme le décrit l'astuce après cette liste. 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.
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 :
- Chaque exécution dont vous avez vu la création a son
workflow_run.status_ended. - Après cela, un
session.status_idlearrive avec lestop_reasonend_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 prochainuser.messageouuser.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 avecbudget_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 sont é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 lesession.errorqui l'a précédé et corrigez la cause. Envoyez ensuite unuser.message, ou lisez vous-même leresultde 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.createdjusqu'à sonworkflow_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 resterunning. Si les outils de votre agent demandent une confirmation, ajoutez une branche qui répond à chaqueagent.tool_useouagent.mcp_tool_usedont l'evaluated_permissionvautask. L'exemple n'en contient pas, car une branche qui autorise chaque appel transformeraitalways_asken 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 derequires_action, commebudget_reached,retries_exhaustedourefusal, il affiche la raison et s'arrête ; gérez donc ces cas dans votre propre code. Il s'arrête surretries_exhaustedmême lorsque le serveur est sur le point de démarrer un nouveau tour de lui-même. Il continue d'attendre surrequires_action, et surend_turntant 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":
breakInterrompre 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 à s'écouler, de sorte que l'exécution peut 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. Pour annuler un appel qui demande une confirmation, refusez-le. Pour annuler un appel d'outil personnalisé, envoyez un résultat avec
is_errordéfini àtrueet un texte danscontentqui en explique la raison. Tant que la session estidleavecrequires_action, unuser.messagerenvoie 400 ; répondez donc d'abord aux appels. - Pour arrêter les exécutions : Envoyez un
user.messagedemandant à l'agent d'arrêter ses exécutions. Une exécution arrêtée se termine avec leresult{"type": "stopped"}. Tant que la session estidleavecbudget_reached, unuser.messagerenvoie 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.messagedemandant à l'agent de poursuivre ses exécutions. Après une interruption, les exécutions peuvent attendre ce message. Si la session estidleavecbudget_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ête | Pendant qu'une exécution est ouverte | Que faire |
|---|---|---|
| Archiver ou supprimer la session | Peut 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écution | Renvoie 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 session | Renvoie 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 aussi d'autres champs, comme budget, est rejetée en totalité. | 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écution | Autorisé. Il arrive sur le flux principal, et son session_thread_id nomme le fil. | Répondez dès l'arrivée de l'événement, en passant 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 une 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, une entrée types[] 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 null 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, sauf 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 encore aucun événement de statut n'a pas commencé à s'exécuter. Aucun endpoint ne liste les exécutions.
Budgets et limites
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
usagedes fils ayant leworkflow_run_idde l'exécution. La liste inclut les fils archivés, dont le statut estterminated, de sorte que les fils d'une exécution terminée sont comptés. Passez lenext_pagede chaque réponse commepagejusqu'à ce quenext_pagesoitnullou absent, et ignorez un fil dontusagevautnull. Si vous additionnez plutôt lelist_costdes 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
idleavecbudget_reached, ourequires_actionsi un appel d'outil est aussi en attente. Chaque fil termine la requête au 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 aussi mises en pause. Si l'utilisation de la session inclut un modèle sans tarif public, seule la suppression du budget le permet ; consultez Modèles sans tarif public.
| Limite | Valeur | À la limite |
|---|---|---|
| Fils actifs simultanément dans une exécution | 64 | L'exécution n'en crée plus jusqu'à ce que l'un d'eux se termine. L'API ne garantit pas ce nombre, il peut donc changer. |
| Agents qu'un workflow démarre sur toute la durée de vie de l'exécution | 1 000 | Lorsque 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écution | 24 heures par défaut, ou la durée de vie que l'agent définit | L'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 session | 10 par défaut | Le 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 passe | Ce que vous voyez |
|---|---|
| Le workflow dépasse l'une des autres limites lorsque l'agent démarre l'exécution | Le 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 tard | Vous 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 limite | Vous 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.
Limites de débit
Le travail d'une exécution compte dans les « rate limits » (limites de débit) dont votre organisation dispose déjà.
| Quoi | Compte dans | Que faire |
|---|---|---|
| Les requêtes de votre client pour récupérer ou lister la session, ses fils et leurs événements | La limite de lecture des endpoints Managed Agents | Suivez 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écution | Vos limites de débit de l'API Messages pour le modèle qu'utilise chaque fil, avec le reste de votre trafic | Pré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.typevautretrying, 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 avecprogram_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.
Une exécution peut créer plus d'un fil 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.
Was this page helpful?