🚀 Exécution de Graph avec Claude : file & MCP (async)14 min de lecture2 745 mots

🚀 Exécution de Graph avec Claude : file & MCP (async)

Découvrez comment exécuter un Graph avec Claude : MCP, orchestration d’agents IA, file & exécution asynchrone. Gérer attente, annulation, reprises.

exécution de Graph avec ClaudeMCPorchestration d’agents IAclé d’idempotenceexécution asynchrone
🚀 Exécution de Graph avec Claude : file & MCP (async)

Pourquoi Claude reçoit un ticket plutôt que le résultat d'un Graph

Quand Claude demande à osFoundry d'exécuter un Graph, la réponse ne correspond pas forcément au résultat du programme. La commande run_graph_session enfile une exécution et renvoie un identifiant. L'agent peut ensuite consulter l'avancement et récupérer la sortie via une autre commande. Sur le coup, ça surprend : dans une conversation, on donne une instruction puis on reçoit une réponse. Ici, l'exécution passe par un autre processus et, en pratique, par une autre machine.

Ce n'est pas seulement un détail « d'interface ». Le moteur du Graph, les modèles locaux, les fichiers et les autorisations vivent sur le bureau du propriétaire. C'est donc ce bureau qui reçoit les commandes, les exécute, puis transmet le résultat. Pour l'agent, ça veut dire : une attente, des vérifications supplémentaires, et des cas à gérer si le poste est hors ligne ou si une réponse ne remonte pas.

Voici comment fonctionne cette architecture, ce que montrent des simulations, et les règles pratiques à en tirer. Les chiffres cités ne sont pas des mesures « de prod » : ils viennent d'un modèle de relais et d'un serveur de remplacement, et le code serveur n'est pas public.

Pourquoi Claude reçoit-il un ticket plutôt qu'un résultat ?

La description publique de run_graph_session parle clairement de mise en file : l'outil planifie une exécution sur le bureau en ligne du propriétaire. Elle précise aussi que le résultat et la progression se récupèrent avec get_graph_run. Autrement dit, la première réponse confirme surtout que la demande a été prise en charge ; elle ne dit pas que le Graph a démarré, ni qu'il est terminé.

La raison vient d'où l'exécution peut réellement avoir lieu. Un Graph est un programme JavaScript exécuté par le moteur du bureau. Il peut enchaîner des étapes conditionnelles, lancer des agents en parallèle, faire des tentatives limitées ou appeler d'autres Graphs. Et comme le processus local dispose aussi des modèles, des dossiers et des autorisations associées, un serveur distant ne peut pas « juste » exécuter le même script sans reconstruire tout cet environnement.

Le code client confirme cette séparation : run_graph_now, utilisé par l'interface des Graphs, transmet le script au moteur de flotte local. Ce moteur impose notamment un plafond de jetons. Le serveur peut bien exposer les Graphs et organiser les demandes, mais l'exécution dépend d'une session durable associée à un appareil.

Une session de Graph identifiée localement par un identifiant qui commence par gs_ correspond donc à un Graph enregistré sur un appareil. Pour qu'il apparaisse côté relais, son propriétaire doit le partager avec un projet connecté. Une liste vide n'indique pas automatiquement un bug : ça peut simplement vouloir dire qu'aucune session n'a été partagée.

Le ticket est une réponse d'architecture

Le protocole découpe trois actions : démarrer, lire l'état, et éventuellement annuler. run_graph_session et cancel_graph_run exigent la permission osfoundry:run. La consultation des sessions et des résultats relève de osfoundry:read. Cette séparation rend le modèle de droits plus clair qu'un outil « tout-en-un » qui ferait tout à la fois.

Mais côté conversation, ça demande une discipline. Claude doit conserver le command_id, interroger l'état, puis décider quand attendre ou quand arrêter. Si la description de l'outil ne détaille pas cette séquence, l'agent peut facilement traiter le ticket comme si c'était le résultat final, ou multiplier des vérifications inutiles.

Comment le bureau récupère-t-il et exécute-t-il les commandes ?

Le serveur n'appelle pas le bureau directement. C'est le bureau qui consulte périodiquement s'il y a du travail, via une connexion sortante. Ce mécanisme passe bien derrière un routeur ou un pare-feu sans ouvrir de port entrant, et évite aussi de dépendre d'une connexion persistante qui peut se casser quand le réseau change.

Dans le client observé, le relais est intégré à la fenêtre principale du bureau. Environ toutes les 20 secondes (et après un changement de partage), il synchronise les sessions autorisées. Il saute un cycle si le précédent est encore en cours, renvoie d'abord des résultats gardés localement après un échec, puis récupère les commandes en attente pour chaque projet activé. La synchronisation pousse au maximum 100 métadonnées de sessions par projet.

Avant de lancer une commande, le bureau refait un contrôle : le projet est-il toujours activé, la session est-elle toujours partagée, et l'identifiant du Graph n'a-t-il pas changé ? Si une condition ne tient plus, la commande est annulée au lieu d'être exécutée. Ce contrôle « au dernier moment » est important : un partage valide au moment où la demande part peut être retiré avant que le bureau ne récupère le travail.

Si tout passe, le relais lance run_graph_now et surveille l'annulation toutes les trois secondes. Ensuite, il publie un résultat borné. Notez aussi que ce relais traite les exécutions en série : envoyer plusieurs appels en même temps ne veut pas dire que le bureau va démarrer plusieurs Graphs en parallèle.

Une architecture adaptée aux postes propriétaires

Le choix du modèle privilégie le contrôle local et une mise en place simple. Le propriétaire conserve ses fichiers et ses outils sur son appareil : le serveur orchestre les demandes, mais ne prend pas la main sur l'environnement d'exécution. Ça colle bien aux cas où les Graphs utilisent des ressources locales ou des validations manuelles.

En échange, la disponibilité dépend de celle du poste. Un ordinateur fermé, en veille ou déconnecté ne peut pas récupérer de nouvelles commandes. Elles restent en attente jusqu'au retour. Pour un usage « métier », il faut donc distinguer la disponibilité de l'orchestrateur (le serveur) de celle du worker (le bureau qui exécute).

Combien de temps faut-il attendre et quand vérifier le résultat ?

Le délai dépend d'abord de la cadence de consultation du relais. Si le bureau interroge toutes les 20 secondes, une demande qui arrive juste après un cycle peut attendre presque 20 secondes.

Dans une simulation de 2 000 exécutions, avec une phase aléatoire par rapport au cycle, l'attente entre « mise en file » et « démarrage » donnait en moyenne 9,8 secondes (et médiane identique), avec un 95e percentile à 18,9 secondes.

Ce délai est le prix d'un modèle où le poste initie les connexions. Le réduire accélère la prise en charge, mais augmente le nombre de requêtes et l'activité côté relais. L'augmenter économise des échanges, au prix d'une attente initiale plus longue. Il n'y a pas « un » intervalle optimal : un Graph interactif n'a pas les mêmes contraintes qu'un traitement lancé pour tourner la nuit.

Le second délai vient du traitement en série. Dans la simulation, les durées des Graphs étaient synthétiques : distribution lognormale, médiane à 60 secondes, minimum 5 secondes. Avec cinq commandes mises en file ensemble, le premier résultat arrivait à 75 secondes en médiane, mais le dernier à 399 secondes en médiane (et 776 secondes au 95e percentile). Ces chiffres ne prétendent pas décrire les performances réelles d'osFoundry : ils servent à illustrer l'effet d'un seul worker qui enchaîne.

Donc si vous cherchez du parallélisme, faire cinq appels à l'outil n'est pas forcément la meilleure stratégie. Quand le moteur le permet, il vaut mieux structurer le parallélisme à l'intérieur du Graph, avec ses propres limites de concurrence et son plafond de jetons. Sinon, on transforme juste une file locale en goulot d'étranglement.

Choisir une cadence de vérification utile

Le client observé ne reçoit pas de notification push pour les résultats. Il doit appeler get_graph_run. La simulation compare plusieurs stratégies sur 2 000 exécutions :

Vérification par le client Appels moyens par exécution Retard moyen de détection
Toutes les 2 secondes 47,1 1,0 seconde
Toutes les 5 secondes 19,1 2,5 secondes
Toutes les 15 secondes 6,7 7,5 secondes
Toutes les 30 secondes 3,6 14,9 secondes
Attendre 20 secondes, puis vérifier toutes les 10 secondes 8,8 5,0 secondes

Vérifier toutes les deux secondes coûte cher en appels d'outils pour gagner quelques secondes sur une tâche qui dure souvent autour d'une minute. Le backoff exponentiel n'est pas automatiquement la meilleure solution : dans cette simulation, il finit par atteindre une cadence de 30 secondes et détecte donc le résultat plus tard qu'une stratégie fixe, calibrée sur la durée habituelle des Graphs.

Une règle simple, en pratique : attendre environ un intervalle de relais avant la première vérification, puis vérifier à une cadence modérée. Comme ça, l'agent évite de demander « ça y est ? » pendant une fenêtre où le Graph n'a même pas eu le temps de démarrer. Ensuite, la cadence doit refléter votre durée attendue, le coût des appels et l'importance d'obtenir une réponse vite.

Que changent l'annulation, l'idempotence et la déconnexion ?

Ces mécanismes couvrent les pannes qui se produisent entre le moment où l'agent fait la demande et celui où le travail se termine en local. Ce n'est pas du cosmétique : un Graph peut envoyer un courriel, écrire un fichier ou déclencher une action difficile à annuler. Une répétition accidentelle peut donc avoir un impact métier, pas seulement « perdre du temps ».

Annuler une commande ne revient pas toujours au mĂŞme

Une commande encore en attente peut être annulée côté serveur avant que le Graph démarre. Dans une simulation où l'annulation se produit à un instant aléatoire entre 0 et 40 secondes après mise en file, 523 des 2 000 commandes restaient en attente et n'ont jamais été exécutées.

Pour une commande déjà en cours, le relais doit repérer le signal lors de son contrôle périodique, puis demander au moteur local d'arrêter. Le délai moyen simulé jusqu'à l'état terminal est de deux secondes, avec un maximum de 3,5 secondes.

Attention : annuler ne « défait » pas forcément ce qui a déjà été produit. Si le Graph a déjà envoyé un message avant de s'arrêter, l'arrêt du reste du programme ne rappelle pas ce message. Les Graphs doivent donc être conçus avec les interruptions possibles et, si nécessaire, des étapes compensatoires.

La clé d'idempotence limite les doublons

run_graph_session demande une clé d'idempotence de 8 à 128 caractères. L'idée est de permettre au client de renvoyer la même demande après une réponse perdue, sans créer une nouvelle exécution. Dans la simulation, avec 30 % de réponses perdues, une nouvelle clé à chaque tentative a généré 266 à 302 commandes pour 200 exécutions attendues. En réutilisant la même clé, le nombre d'exécutions en file restait autour de 200.

Le gain est surtout important quand il y a des effets secondaires. Si le client ne sait pas si la première demande a été reçue, il faut pouvoir réessayer sans risquer d'envoyer deux fois un courriel ou de répéter une opération. En pratique : générer la clé une fois par intention métier, puis la réutiliser pour toutes les tentatives liées à cette intention.

Le relais doit conserver les résultats avant de les transmettre

Le travail en attente peut survivre à une déconnexion du bureau, puisque la file reste côté serveur. En revanche, le retour du résultat est plus fragile : le Graph peut avoir fini, mais la transmission peut échouer. Dans ce cas, le relais doit garder le résultat localement et le renvoyer au cycle suivant.

Le mécanisme observé utilise un outbox local : il ne supprime l'entrée qu'après une réponse positive du serveur. Sans outbox, perdre une transmission laisse parfois l'état bloqué sur running. Avec l'outbox, le résultat finit par être livré au prochain passage. Sur un relais distribué, « persister le résultat avant de le publier » n'est pas un détail : reconstruire un travail terminé est souvent bien plus coûteux que de rejouer la publication.

Quelles règles appliquer pour concevoir ce type d'outil ?

Le cas d'osFoundry montre un principe général pour des agents qui utilisent des ressources locales : le système ne doit pas masquer la réalité opérationnelle. Si la commande est asynchrone, la description doit le dire, nommer l'outil de consultation, et expliquer quoi faire d'un identifiant de commande. Un nom d'outil seul ne suffit pas : il faut que le modèle comprenne que ce n'est pas « un résultat », mais « une demande ».

La sécurité doit aussi être réévaluée au moment où l'action va réellement se produire. Contrôler le partage au moment de la mise en file n'est pas assez si les permissions peuvent changer entre-temps. Le relais doit revalider le projet, la session et la configuration juste avant l'exécution, puis refuser tout ce qui s'écarte.

Et le résultat doit avoir un contrat explicite. Le relais observé publie les informations d'exécution tant que la représentation JSON ne dépasse pas 100 000 caractères. Au-delà, il annonce que la sortie est tronquée plutôt que d'envoyer un fragment ambigu. Les erreurs sont limitées à 2 000 caractères. Le seuil porte sur les caractères, pas sur les octets : du texte japonais peut consommer bien plus d'espace UTF-8 que du texte ASCII pour une longueur « en caractères » comparable.

Enfin, pour un agent, « très long » n'est pas synonyme de « utile ». Un Graph appelé par un modèle doit plutôt finir avec un résumé exploitable et structuré pour la prochaine décision. Le détail peut rester dans l'historique local associé à l'identifiant d'exécution.

Liste de contrĂ´le avant mise en production

  • DĂ©finir qui exĂ©cute le travail et quelles ressources locales sont nĂ©cessaires.
  • Choisir un intervalle de rĂ©cupĂ©ration en arbitrant dĂ©lai, charge et autonomie du poste.
  • Documenter le cycle complet : dĂ©marrage, identifiant, consultation, annulation et Ă©tat final.
  • Exiger une clĂ© d'idempotence stable pour les tentatives liĂ©es Ă  la mĂŞme demande.
  • Revalider les autorisations juste avant l'exĂ©cution, pas seulement Ă  la mise en file.
  • Traiter les commandes en attente, en cours et terminĂ©es comme des Ă©tats distincts.
  • Persister les rĂ©sultats terminĂ©s avant transmission et ne les supprimer qu'après confirmation.
  • Fixer une limite de taille et privilĂ©gier des sorties synthĂ©tiques.
  • Mesurer les appels de suivi et le temps d'attente dans votre propre environnement : une simulation ne remplace pas l'usage rĂ©el.

Conclusion

Claude reçoit un ticket parce que le serveur ne possède pas l'environnement nécessaire pour exécuter le Graph : le travail reste sur le bureau du propriétaire, et le relais se contente de récupérer et de transmettre via une boucle côté sortant. Cette approche protège les ressources locales et marche bien avec des postes derrière un pare-feu, mais elle impose une attente, une capacité de traitement limitée et un retour asynchrone à gérer.

Pour l'utiliser correctement, il faut traiter l'exécution comme un cycle complet : mise en file, vérification de l'état, annulation éventuelle, puis récupération fiable du résultat. Une clé d'idempotence, des permissions revalidées au dernier moment et un outbox durable évitent plusieurs problèmes prévisibles. Et surtout : dimensionnez la fréquence de vérification à partir de vos durées réelles et de votre coût d'appels, au lieu de confondre « plus de sondages » avec « plus de réactivité utile ».

Questions frequentes

Le Graph s’exécute sur le bureau du propriétaire, où se trouvent le moteur, les modèles et les ressources locales. Le serveur met donc la demande en file. Le bureau la récupère ensuite et transmet le résultat, que l’agent lit avec get_graph_run.
Il n’y a pas de fréquence universelle. Une première vérification après environ un intervalle de relais évite les appels prématurés. Ensuite, choisissez une cadence qui équilibre le coût des appels et le délai acceptable. Des vérifications toutes les deux secondes peuvent générer beaucoup d’échanges pour peu de gain.
Elle permet de réutiliser la même demande après une réponse perdue sans créer une nouvelle exécution, si le serveur applique le comportement prévu. Pour un Graph qui produit des effets secondaires, elle réduit le risque d’envoyer deux fois un courriel ou de répéter une opération.
Non, pas tant que le bureau ne peut pas récupérer la commande. La file peut conserver le travail en attente, mais l’exécution nécessite le retour du poste et la validation des permissions. Le délai dépend alors de sa reconnexion.
Non. Une commande en attente peut être annulée avant de démarrer. Une exécution en cours doit d’abord recevoir le signal d’arrêt, et les effets secondaires déjà produits ne sont pas automatiquement annulés. Les Graphs doivent être conçus en conséquence.

Articles similaires