- Published on
Managed Agent Scaling: Detach Your Brain
- Authors

- Name
- aimode.news
- @aimode_news
Recevez la newsletter des développeurs
Mises à jour de produits, procédures, projecteurs de la communauté et bien plus encore. Livré mensuellement dans votre boîte de réception.
Démarrez avec les agents gérés Claude en suivant nos documents.
Un sujet récurrent sur le blog d'ingénierie est la manière de créer des agents efficaces et de concevoir des harnais pour un travail à long terme. Un fil conducteur de ce travail est qu’il exploite des hypothèses codées sur ce que Claude ne peut pas faire seul. Cependant, ces hypothèses doivent être fréquemment remises en question car elles peuvent devenir obsolètes à mesure que les modèles s’améliorent.
À titre d’exemple, lors de travaux antérieurs, nous avons constaté que Claude Sonnet 4.5 terminait les tâches prématurément lorsqu’il sentait que sa limite de contexte approchait – un comportement parfois appelé « anxiété contextuelle ». Nous avons résolu ce problème en ajoutant des réinitialisations de contexte au harnais. Mais lorsque nous avons utilisé le même harnais sur Claude Opus 4.5, nous avons constaté que ce comportement avait disparu. Les réinitialisations étaient devenues un poids mort.
Nous nous attendons à ce que les harnais continuent d’évoluer. Nous avons donc créé des agents gérés : un service hébergé dans la plateforme Claude qui exécute des agents à long terme en votre nom via un petit ensemble d'interfaces destinées à durer plus longtemps que toute implémentation particulière, y compris celles que nous exécutons aujourd'hui.
Construire des agents gérés signifiait résoudre un vieux problème informatique : comment concevoir un système pour des « programmes encore impensés ». Il y a plusieurs décennies, les systèmes d'exploitation ont résolu ce problème en virtualisant le matériel en abstractions (processus, fichiers) suffisamment générales pour des programmes qui n'existaient pas encore. Les abstractions ont survécu au matériel. La lecture()
La commande ne sait pas si elle accède à un pack de disques des années 1970 ou à un SSD moderne. Les abstractions du dessus sont restées stables tandis que les implémentations du dessous ont changé librement.
Les agents gérés suivent le même modèle. Nous avons virtualisé les composants d'un agent : une session (le journal en ajout uniquement de tout ce qui s'est passé), un harnais (la boucle qui appelle Claude et achemine les appels de l'outil de Claude vers l'infrastructure appropriée) et un bac à sable (un environnement d'exécution où Claude peut exécuter du code et modifier des fichiers). Cela permet d’échanger l’implémentation de chacun sans perturber les autres. Nous avons une opinion sur la forme de ces interfaces, et non sur ce qui se cache derrière elles.
Nous avons commencé par placer tous les composants de l'agent dans un seul conteneur, ce qui signifiait que la session, le harnais d'agent et le bac à sable partageaient tous un environnement. Cette approche présentait des avantages, notamment le fait que les modifications de fichiers sont des appels système directs et qu'il n'y avait aucune limite de service à concevoir.
Mais en regroupant tout dans un seul conteneur, nous nous sommes heurtés à un vieux problème d’infrastructure : nous avions adopté un animal de compagnie. Dans l’analogie entre animaux de compagnie et bétail, un animal de compagnie est un individu nommé et soigné que vous ne pouvez pas vous permettre de perdre, alors que les bovins sont interchangeables. Dans notre cas, le serveur est devenu cet animal de compagnie ; si un conteneur échouait, la session était perdue. Si un conteneur ne répondait plus, nous devions le soigner.
Les conteneurs de soins impliquaient le débogage des sessions bloquées qui ne répondaient pas. Notre seule fenêtre d'accès était le flux d'événements WebSocket, mais cela ne pouvait pas nous dire où les échecs se produisaient, ce qui signifiait qu'un bug dans le faisceau, une perte de paquet dans le flux d'événements ou un conteneur se déconnectant se présentaient tous de la même manière. Pour comprendre ce qui n'allait pas, un ingénieur a dû ouvrir un shell à l'intérieur du conteneur, mais comme ce conteneur contenait souvent également des données utilisateur, cette approche signifiait essentiellement que nous n'avions pas la capacité de déboguer.
Un deuxième problème était que le harnais supposait que tout ce sur quoi Claude travaillait vivait dans le conteneur avec lui. Lorsque les clients nous demandaient de connecter Claude à leur cloud privé virtuel, ils devaient soit appairer leur réseau avec le nôtre, soit exécuter notre harnais dans leur propre environnement. Une hypothèse inhérente au harnais est devenue un problème lorsque nous avons voulu le connecter à différentes infrastructures.
La solution à laquelle nous sommes arrivés a été de dissocier ce que nous considérions comme le « cerveau » (Claude et son harnais) des « mains » (bacs à sable et outils qui effectuent des actions) et de la « session » (le journal des événements de la session). Chacune est devenue une interface qui faisait peu d’hypothèses sur les autres, et chacune pouvait échouer ou être remplacée indépendamment.
Le harnais quitte le conteneur. En dissociant le cerveau des mains, le harnais ne vivait plus à l'intérieur du conteneur. Il a appelé le conteneur de la même manière qu'il a appelé n'importe quel autre outil : exécuter (nom, entrée) → chaîne
. Le conteneur est devenu du bétail. Si le conteneur tombait en panne, le harnais détectait la panne comme une erreur d'appel d'outil et la renvoyait à Claude. Si Claude décidait de réessayer, un nouveau conteneur pourrait être réinitialisé avec une recette standard : provision({resources})
. Nous n’avons plus eu à remettre en état les conteneurs défaillants.
Récupération après une défaillance du harnais. Le harnais est également devenu du bétail. Étant donné que le journal de session se trouve à l'extérieur du harnais, rien dans le harnais n'a besoin de survivre à un crash. En cas d'échec, un nouveau peut être redémarré avec wake(sessionId)
, utilisez getSession(id)
pour récupérer le journal des événements et reprendre le dernier événement. Pendant la boucle de l'agent, le harnais écrit dans la session avec submitEvent(id, event)
afin de conserver une trace durable des événements.
La frontière de sécurité. Dans la conception couplée, tout code non fiable généré par Claude était exécuté dans le même conteneur que les informations d'identification. Il suffisait donc d'une injection rapide pour convaincre Claude de lire son propre environnement. Une fois qu'un attaquant dispose de ces jetons, il peut créer de nouvelles sessions sans restriction et leur déléguer du travail. Une portée étroite est une atténuation évidente, mais cela code une hypothèse sur ce que Claude ne peut pas faire avec un jeton limité – et Claude devient de plus en plus intelligent. Le correctif structurel consistait à garantir que les jetons ne soient jamais accessibles depuis le bac à sable où s'exécute le code généré par Claude.
Nous avons utilisé deux modèles pour garantir cela. L'authentification peut être regroupée avec une ressource ou conservée dans un coffre-fort en dehors du bac à sable. Pour Git, nous utilisons le jeton d'accès de chaque référentiel pour cloner le dépôt lors de l'initialisation du bac à sable et le connecter à la télécommande git locale. Git pousser
et tire
travailler depuis l’intérieur du bac à sable sans que l’agent ne manipule le jeton lui-même. Pour les outils personnalisés, nous prenons en charge MCP et stockons les jetons OAuth dans un coffre-fort sécurisé. Claude appelle les outils MCP via un proxy dédié ; ce proxy récupère un jeton associé à la session. Le proxy peut ensuite récupérer les informations d'identification correspondantes dans le coffre-fort et appeler le service externe. Le harnais n'est jamais informé des informations d'identification.
Les tâches à long terme dépassent souvent la longueur de la fenêtre contextuelle de Claude, et les méthodes standard pour résoudre ce problème impliquent toutes des décisions irréversibles sur ce qu'il faut conserver. Nous avons exploré ces techniques dans des travaux antérieurs sur l’ingénierie du contexte. Par exemple, le compactage permet à Claude d'enregistrer un résumé de sa fenêtre de contexte et l'outil de mémoire permet à Claude d'écrire le contexte dans des fichiers, permettant ainsi l'apprentissage au fil des sessions. Cela peut être associé à un découpage du contexte, qui supprime de manière sélective les jetons tels que les anciens résultats d'outils ou les blocs de réflexion.
Mais les décisions irréversibles de conserver ou d’éliminer sélectivement le contexte peuvent conduire à des échecs. Il est difficile de savoir de quels jetons les prochains tours auront besoin. Si les messages sont transformés par une étape de compactage, le harnais supprime les messages compactés de la fenêtre contextuelle de Claude, et ceux-ci ne sont récupérables que s'ils sont stockés. Des travaux antérieurs ont exploré des moyens de résoudre ce problème en stockant le contexte en tant qu'objet vivant en dehors de la fenêtre contextuelle. Par exemple, le contexte peut être un objet dans un REPL auquel le LLM accède par programme en écrivant du code pour le filtrer ou le découper.
Dans les agents gérés, la session offre le même avantage, en servant d’objet contextuel vivant en dehors de la fenêtre contextuelle de Claude. Mais plutôt que d'être stocké dans le bac à sable ou dans REPL, le contexte est stocké de manière durable dans le journal de session. L'interface, getEvents(),
permet au cerveau d'interroger le contexte en sélectionnant des tranches de position du flux d'événements. L'interface peut être utilisée de manière flexible, permettant au cerveau de reprendre là où il a arrêté de lire, de rembobiner quelques événements avant un moment spécifique pour voir l'avance, ou de relire le contexte avant une action spécifique.
Tous les événements récupérés peuvent également être transformés dans le harnais avant d'être transmis à la fenêtre contextuelle de Claude. Ces transformations peuvent être tout ce que le harnais encode, y compris l'organisation du contexte pour obtenir un taux de réussite élevé du cache et l'ingénierie du contexte. Nous avons séparé les problèmes de stockage de contexte récupérable dans la session et de gestion de contexte arbitraire dans le harnais, car nous ne pouvons pas prédire quelle ingénierie de contexte spécifique sera requise dans les futurs modèles. Les interfaces intègrent cette gestion du contexte et garantissent uniquement que la session est durable et disponible pour l'interrogation.
Beaucoup de cerveaux. Le découplage du cerveau des mains a résolu l'une de nos premières plaintes de clients. Lorsque les équipes voulaient que Claude travaille avec des ressources dans leur propre VPC, la seule solution était de comparer leur réseau avec le nôtre, car le conteneur contenant le harnais supposait que chaque ressource se trouvait à côté de lui. Une fois le harnais retiré du conteneur, cette hypothèse a disparu. Le même changement a eu un impact sur les performances. Lorsque nous avons initialement placé le cerveau dans un conteneur, cela signifiait que plusieurs cerveaux nécessitaient autant de conteneurs. Pour chaque cerveau, aucune inférence ne pouvait avoir lieu tant que ce conteneur n'était pas approvisionné ; chaque session payait à l'avance le coût complet de configuration du conteneur. Chaque session, même celles qui ne toucheraient jamais le bac à sable, devait cloner le dépôt, démarrer le processus, récupérer les événements en attente sur nos serveurs.
Ce temps mort est exprimé en time-to-first-token (TTFT), qui mesure le temps d'attente d'une session entre l'acceptation du travail et la production de son premier jeton de réponse. TTFT est la latence que l’utilisateur ressent le plus intensément.
Découpler le cerveau des mains signifie que les conteneurs sont provisionnés par le cerveau via un appel d'outil (execute(name, input) → string)
seulement s'ils sont nécessaires. Ainsi, une session qui n’avait pas besoin d’un conteneur dans l’immédiat n’en a pas attendu un. L'inférence pourrait démarrer dès que la couche d'orchestration extrairait les événements en attente du journal de session. Grâce à cette architecture, notre p50 TTFT a chuté d'environ 60 % et notre p95 de plus de 90 %. S'adapter à de nombreux cerveaux signifiait simplement démarrer de nombreux harnais apatrides et les connecter aux mains uniquement si nécessaire.
Beaucoup de mains. Nous voulions également pouvoir connecter chaque cerveau à plusieurs mains. En pratique, cela signifie que Claude doit raisonner sur de nombreux environnements d'exécution et décider où envoyer le travail – une tâche cognitive plus difficile que d'opérer dans un seul shell. Nous avons commencé avec le cerveau dans un seul conteneur car les modèles précédents n'en étaient pas capables. À mesure que l’intelligence évoluait, le conteneur unique devenait plutôt une limitation : lorsque ce conteneur tombait en panne, nous perdions l’état de chaque main dans laquelle le cerveau atteignait.
Découpler le cerveau des mains fait de chaque main un outil, exécuter (nom, saisie) → chaîne
: un nom et une entrée entrent et une chaîne est renvoyée. Cette interface prend en charge n'importe quel outil personnalisé, n'importe quel serveur MCP et nos propres outils. Le harnais ne sait pas si le bac à sable est un conteneur, un téléphone ou un émulateur Pokémon. Et comme aucune main n’est couplée à un cerveau, les cerveaux peuvent se transmettre des mains.
Le défi auquel nous avons été confrontés est ancien : comment concevoir un système pour des « programmes encore impensés ». Les systèmes d'exploitation ont duré des décennies en virtualisant le matériel en abstractions suffisamment générales pour des programmes qui n'existaient pas encore. Avec les agents gérés, nous avions pour objectif de concevoir un système pouvant accueillir les futurs harnais, bacs à sable ou autres composants autour de Claude.
Managed Agents est un méta-harnais dans le même esprit, sans opinion sur le harnais spécifique dont Claude aura besoin dans le futur. Il s’agit plutôt d’un système doté d’interfaces générales qui permettent de nombreux exploits différents. Par exemple, Claude Code est un excellent outil que nous utilisons largement dans toutes les tâches. Nous avons également montré que les agents spécifiques à une tâche excellent dans des domaines restreints. Les agents gérés peuvent s’adapter à n’importe lequel d’entre eux, correspondant à l’intelligence de Claude au fil du temps.
La conception de méta-harnais signifie avoir une opinion sur les interfaces autour de Claude : nous nous attendons à ce que Claude ait besoin de la capacité de manipuler l'état (la session) et d'effectuer des calculs (le bac à sable). Nous nous attendons également à ce que Claude ait besoin de la capacité de s'adapter à de nombreux cerveaux et à plusieurs mains. Nous avons conçu les interfaces de manière à ce qu'elles puissent fonctionner de manière fiable et sécurisée sur de longues périodes. Mais nous ne faisons aucune hypothèse sur le nombre ou l’emplacement des cerveaux ou des mains dont Claude aura besoin.
Écrit par Lance Martin, Gabe Cemaj et Michael Cohen. Merci à Nodir Turakulov et Jeremy Fox pour leurs conversations utiles sur ces sujets. Un merci spécial à l'équipe Agents API et à Jake Eaton pour leurs contributions.
Mises à jour de produits, procédures, projecteurs de la communauté et bien plus encore. Livré mensuellement dans votre boîte de réception.