L'agent de recherche a trouvé le compte du client, a confirmé le plan et a extrait les quatre dernières factures. Il a transféré le dossier à l'agent de facturation avec un résumé d'une ligne : « Le client souhaite un remboursement. » L'agent de facturation, qui ne sait désormais rien du compte, du plan ou des factures, commence par demander l'ID du compte.
Chaque fait recueilli par le premier agent a été ignoré à la limite de transfert. C'est le problème de la transmission, et cela vous coûte deux fois : une fois en appels API dupliqués, une fois en erreurs qui proviennent du second agent travaillant avec moins d'informations que le premier.
Ce guide couvre ce qui doit survivre à un transfert, les trois façons dont les équipes passent l'état et quand chacune fonctionne, pourquoi les résumés perdent plus d'informations que ce à quoi les gens s'attendent, et comment tester qu'un transfert a bien communiqué ce qu'il prétendait. Notre article sur pourquoi les agents tombent en panne en production considère la perte d'état comme un mode de défaillance principal ; ceci en est la version multi-agent.
Apidog est mentionné parce que la solution la moins coûteuse est généralement d'arrêter de passer des données et de passer des identifiants à la place, ce qui ne fonctionne que si chaque agent peut récupérer le même enregistrement de la même manière.
Ce qui doit réellement franchir la limite
Pas tout. Un transfert qui copie l'intégralité de la conversation est aussi défectueux qu'un transfert qui ne copie rien, juste dans l'autre sens : le second agent hérite d'une fenêtre de contexte complète et doit déterminer quelles parties sont pertinentes.
Quatre catégories méritent d'être séparées.
Identifiants. ID de compte, ID de commande, ID de tâche, numéros de ticket. Ceux-ci sont petits, stables et permettent à l'agent récepteur de récupérer tout ce dont il a besoin. Ils sont la chose la plus précieuse à transmettre et la plus fréquemment omise.
Décisions déjà prises. « Le client est éligible à un remboursement selon la politique 3. » L'agent récepteur ne doit pas remettre cela en question. Si c'est le cas, vous vous retrouvez avec deux agents en désaccord au sein d'une même tâche.
Contraintes. Limites budgétaires, approbations accordées, actions déjà effectuées. Perdre ces informations conduit à ce qu'une tâche soit facturée deux fois ou à ce qu'une même approbation soit demandée une seconde fois. Cela s'accorde directement avec notre article sur l'idempotence pour les agents IA.
Questions ouvertes. Ce que le premier agent n'a pas pu résoudre. Transmettre cela explicitement empêche le second agent de faire des suppositions silencieuses.
Ce qui n'a pas besoin de traverser : les réponses API brutes, le compte rendu du raisonnement et tout ce que l'agent récepteur peut récupérer par lui-même en un seul appel.
Trois façons de transmettre l'état
Transmettre la conversation complète. Simple, et cela fonctionne pour deux agents dans une tâche courte. Cela échoue dès que le transcript est long, car l'agent récepteur dépense la majeure partie de son budget à lire l'historique et les faits pertinents sont enfouis au milieu. Notre article sur maintenir les réponses des outils hors de la fenêtre de contexte explique pourquoi ce milieu est précisément l'endroit où les modèles perdent des informations.
Transmettre un résumé. Le premier agent rédige un message de transfert ; le second commence à partir de celui-ci. C'est le comportement par défaut dans la plupart des frameworks et il est lossy d'une manière spécifique : les modèles résument en privilégiant le récit et en s'éloignant des identifiants. Demandez un résumé et vous obtenez « le client est abonné depuis deux ans et est frustré » au lieu de « compte 8812, plan pro, quatre factures, remboursement approuvé pour la facture inv_44. »
Transmettre un objet de transfert structuré. Le premier agent remplit un schéma. Le second lit des champs, pas de la prose. Cela demande plus de travail à configurer et c'est la solution qui tient la route.
{
"task_id": "task_2026_08_26_0031",
"from_agent": "research",
"to_agent": "billing",
"entities": {
"customer_id": "cus_8812",
"invoice_ids": ["inv_41", "inv_42", "inv_43", "inv_44"],
"subscription_id": "sub_119"
},
"decisions": [
{ "decision": "refund_eligible", "value": true, "basis": "politique 3.2, facturé deux fois en un cycle" }
],
"constraints": {
"max_refund_cents": 4900,
"human_approval_granted": false,
"actions_taken": ["read_invoices"]
},
"open_questions": ["Le client n'a pas confirmé quelle facture rembourser"],
"summary": "Le client cus_8812 a été doublement facturé en août. Le remboursement d'une facture est approuvé selon la politique 3.2, jusqu'à 4900 cents. En attente du choix de facture du client."
}
La prose apparaît toujours, dans le champ `summary`, car elle véhicule des nuances que le schéma ne contient pas. Elle se trouve aux côtés des champs structurés plutôt que de les remplacer, ce qui est tout l'intérêt.
Validez l'objet avant l'exécution du transfert. Si `customer_id` est manquant, échouez bruyamment à la limite plutôt que de laisser le second agent le découvrir trois appels plus tard.
Transmettre des références, pas des charges utiles
La version la plus robuste d'un transfert ne transmet presque aucune donnée. Elle transmet des identifiants, et l'agent récepteur récupère ce dont il a besoin.
Cela fonctionne pour trois raisons. L'état reste à jour, donc si quelque chose a changé entre les deux agents, le second voit la valeur actuelle plutôt qu'une copie obsolète. Le transfert reste petit, quelques centaines d'octets au lieu de dizaines de milliers de tokens. Et la piste d'audit s'améliore, car chaque lecture apparaît comme un appel API plutôt que comme du texte copié entre les invites.
Cela ne requiert qu'une chose : chaque agent peut atteindre la même API avec les bonnes permissions. Ce n'est pas gratuit. Chaque agent a besoin de ses propres identifiants limités à ce qu'il fait, ce qui est l'argument de notre article sur les clés API à moindre privilège pour les agents IA. Un agent de facturation détenant un jeton de recherche en lecture seule ne peut pas émettre le remboursement, et un agent de recherche détenant le jeton de facturation est un problème de rayon d'explosion.
Là où une nouvelle récupération serait coûteuse ou lente, mettez l'enregistrement en cache dans votre orchestrateur et passez une référence à l'entrée du cache. L'agent récepteur demande toujours les données explicitement, donc le modèle reste le même, mais la seconde lecture est bon marché.
Là où les transferts échouent réellement
Quatre défaillances couvrent la plupart des incidents.
L'identifiant omis. Le résumé dit « le client » et ne donne jamais d'ID, de sorte que le second agent recherche par nom, trouve deux correspondances et choisit la mauvaise. Prévenez cela en validant que les ID d'entité requis sont présents avant d'autoriser le transfert.
L'action répétée. Le premier agent a déjà envoyé l'e-mail. Le transfert ne l'enregistre pas. Le second agent l'envoie à nouveau. Enregistrez les `actions_taken` dans l'objet de transfert et vérifiez-les avant toute écriture, avec le soutien des clés d'idempotence qui rendent une répétition inoffensive.
L'approbation perdue. Un humain a approuvé un remboursement pendant que le premier agent était en cours d'exécution. Le second agent, ne le sachant pas, redemande. Les utilisateurs interprètent la seconde invite comme un système qui n'écoute pas. Portez les approbations comme des contraintes explicites et traitez-les comme étant liées à la tâche plutôt qu'à l'agent.
L'invention confiante. L'agent récepteur a besoin d'une valeur que le transfert n'a pas transmise, et plutôt que de la demander, il en invente une qui correspond au récit. C'est l'échec le plus dangereux car il ressemble à une tâche terminée. La défense est le champ `open_questions` plus une règle stricte dans l'invite de l'agent récepteur : si un identifiant requis est absent, arrêtez-vous et demandez.
Les boucles aggravent les quatre. Lorsqu'un agent A passe à B et que B repasse à A, l'état se dégrade à chaque passage, comme une photocopie de photocopie. Limitez le nombre de sauts et transportez l'objet de tâche original à travers chacun d'eux plutôt que de le reconstruire à chaque limite.
Testez la limite, pas seulement les agents
Les transferts sont des points d'intégration, testez-les donc comme des points d'intégration.
Affirmez sur l'objet de transfert. Exécutez le premier agent contre un scénario fixe et vérifiez l'objet qu'il produit : identifiants requis présents, décisions enregistrées, actions listées. Il s'agit d'une assertion déterministe sur une charge utile structurée, même si l'agent qui l'a produite n'est pas déterministe, ce qui en fait un test utilisable. L'approche générale se trouve dans notre guide sur le test des agents non déterministes.
Testez le récepteur de manière isolée. Alimentez l'agent de facturation avec un objet de transfert fait main et vérifiez ce qu'il fait. Puis alimentez-le avec un objet délibérément cassé, avec l'ID client supprimé, et confirmez qu'il demande plutôt que de deviner. Ce second test est celui qui détecte l'invention.
Exécutez les deux contre des mocks. Un test de transfert qui émet de vrais remboursements est un test que vous n'exécuterez qu'une seule fois. Orientez les deux agents vers des points d'extrémité simulés afin que la suite puisse s'exécuter à chaque changement, en suivant notre article sur l'exécution d'agents contre des mocks plutôt que la production. Dans Apidog, les mocks proviennent de la même définition d'API appelée par les deux agents, de sorte qu'ils ne divergent jamais.
Enregistrez chaque transfert. Enregistrez l'objet complet à chaque limite avec l'ID de la tâche. Lorsqu'une exécution multi-agent tourne mal, le journal de transfert vous indique quel agent avait l'information et lequel l'a perdue, ce qui est généralement l'intégralité de l'enquête. Notre article sur le traçage des appels d'outils d'agent IA couvre ce qui doit figurer d'autre dans cet enregistrement.
Ce que les frameworks vous apportent
La plupart des frameworks d'orchestration fournissent une primitive de transfert, et il est utile de savoir ce que chacun d'eux déplace réellement au-delà de la limite avant de s'y fier.
La documentation de transfert du SDK OpenAI Agents modélise un transfert comme un outil que l'agent peut appeler, ce qui signifie que le modèle décide quand le contrôle est transféré. C'est pratique, et cela place la décision dans la partie la moins déterministe de votre système, alors associez-la à une validation à la sortie.
Le guide multi-agent de LangGraph adopte une approche opposée : l'état est un objet graphique explicite que chaque nœud lit et écrit. Cela correspond étroitement au transfert structuré décrit ci-dessus, et le travail principal qui vous reste est de décider quels champs sont obligatoires.
L'article d'Anthropic sur la construction d'un système de recherche multi-agent mérite d'être lu pour les détails opérationnels, en particulier sur la quantité d'instructions dont un sous-agent a besoin avant de pouvoir travailler utilement de manière autonome.
Le fil conducteur commun : chaque framework déplacera quelque chose. Aucun d'entre eux ne décide pour vous quels faits sont porteurs de charge. Cette liste vous appartient, et c'est ce qu'il faut examiner lorsque l'exécution échoue.
Gardez l'objet de tâche en dehors de la conversation
Un changement structurel prévient toute une famille de bugs. Stockez l'état de la tâche dans un endroit durable, indexé par l'ID de tâche, et faites en sorte que chaque agent le lise et l'écrive plutôt que de le passer par des messages.
La conversation est un mauvais conteneur pour l'état. Elle est compactée, tronquée et réécrite par la fonction de résumé, et aucune de ces opérations ne sait quels champs vous ne pouvez pas vous permettre de perdre. Une ligne dans une base de données n'a pas ce problème.
Le modèle est simple. Au début d'un tour, l'agent charge l'objet de tâche. Lorsqu'il effectue une action, il l'ajoute à `actions_taken` et enregistre. Lors du transfert, il passe l'ID de la tâche, et l'agent récepteur charge le même objet. Rien d'important ne transite par l'invite, donc rien d'important ne peut être résumé et perdu.
Cela vous donne également un point de reprise. Si une exécution échoue à l'étape quatre, l'objet de tâche contient toujours tout ce que les trois premières étapes ont établi, et la nouvelle tentative repart de là plutôt que de zéro.
Où la plateforme peut maintenir l'état
Si vos agents s'exécutent en tant que runtimes CLI sur des machines de développeurs, l'objet de tâche durable décrit ci-dessus est quelque chose que vous construisez. Certaines plateformes de gestion de travail d'agents le modélisent déjà, et il est utile de savoir à quoi cela ressemble avant de créer le vôtre.
Sharkly est un système de gestion du travail pour les personnes et les agents, construit précisément autour de cette unité. Une tâche (Task) contient l'objectif, le statut, la personne responsable, l'Agent ou l'Équipe (Crew) assigné(e) pour l'exécuter, les commentaires, ainsi que l'état d'exécution et le résultat de l'agent. Une Équipe associe un Agent leader à d'autres Agents et personnes, de sorte qu'une tâche nécessitant plusieurs spécialistes est assignée à un groupe réutilisable plutôt que d'être passée de main en main via des invites. Parce que l'état réside dans la tâche plutôt que dans une conversation, un transfert entre deux agents ne dépend pas de la capacité de l'un d'eux à bien résumer.
Les runtimes restent ceux que vous utilisez déjà. Claude Code, Codex et les autres exécutent le travail sur un ordinateur que vous enregistrez ; la plateforme fournit l'enregistrement de la tâche, l'assignation et la boucle de révision autour d'eux. Si vous construisez vous-même le modèle de tâche durable, la documentation Sharkly est une référence utile pour savoir quels champs s'avèrent importants.
Une liste de contrôle pour les transferts
- Un schéma défini existe pour le transfert, et il est validé à la limite.
- Les identifiants d'entité sont des champs obligatoires, pas facultatifs.
- Les décisions incluent leur justification, afin que le récepteur ne refasse pas le raisonnement.
- Les actions déjà effectuées sont enregistrées et vérifiées avant toute écriture.
- Les approbations et les budgets accompagnent la tâche, pas l'agent.
- Les questions ouvertes sont explicites, et le récepteur demande plutôt que de supposer.
- Les données sont transmises par référence là où une nouvelle récupération est bon marché.
- Le nombre de sauts est plafonné, et l'objet de tâche original survit à chaque saut.
- Chaque transfert est enregistré avec l'ID de la tâche.
- Les tests de limite s'exécutent en CI contre des mocks, y compris un transfert délibérément incomplet.
La plupart des échecs multi-agents ne sont pas des échecs de raisonnement. Ils sont un fait qui existait chez un agent et non chez le suivant. Concevez la limite comme une interface, avec un schéma et des tests, et le second agent cessera de poser des questions auxquelles le premier a déjà répondu. Téléchargez Apidog pour conserver les mocks et les tests de limite à côté de l'API dont dépendent les deux agents.
Foire aux questions
Un transfert structuré vaut-il la peine pour deux agents ? Pour deux agents dans une tâche courte, passer la conversation est généralement suffisant. L'objet structuré devient indispensable à partir de trois agents ou plus, pour des tâches longues, ou partout où un transfert franchit une limite de processus ou d'exécution.
Le modèle doit-il écrire l'objet de transfert ou le code doit-il le construire ? Le code là où c'est possible. Les identifiants, les actions effectuées et les approbations doivent être renseignés par votre orchestrateur à partir de ce qui s'est réellement passé, et non à partir du souvenir du modèle. Laissez le modèle n'écrire que le `summary` et les questions ouvertes.
Comment arrêter la dégradation du contexte dans une boucle ? Portez un seul objet de tâche tout au long de l'exécution et mettez-le à jour, plutôt que de le régénérer à chaque limite. Ensuite, plafonnez les sauts. Si une tâche en nécessite plus qu'une poignée, la décomposition est probablement erronée.
Qu'en est-il des frameworks avec un support de transfert intégré ? Utilisez-les, et vérifiez ce qu'ils transfèrent réellement. Beaucoup ne transmettent que l'historique des messages et rien d'autre, ce qui signifie que les identifiants ne survivent que s'ils apparaissent dans le texte. Ajoutez une charge utile structurée en plus de ce que le framework transporte.
Les sous-agents ont-ils besoin d'identifiants API séparés ? Oui, limités à ce que chacun d'eux fait. Partager une clé puissante entre les agents supprime votre capacité à limiter les dommages et à identifier quel agent a effectué un appel. Notre article sur les clés API à moindre privilège pour les agents couvre la configuration.
Quelle quantité d'informations le champ de résumé doit-il contenir ? Quelques phrases, couvrant l'intention et les nuances que les champs structurés ne peuvent pas contenir. S'il commence à lister des ID et des montants, ceux-ci appartiennent aux champs structurés où ils peuvent être validés.
