Une équipe qui choisit son framework d'agents sous contrainte de souveraineté regarde d'abord l'éditeur. C'est le mauvais critère. Le comparatif de 12 frameworks, dont cet article détaille un chapitre, donne le contre-exemple : le seul éditeur européen de la sélection est aussi celui qui collecte le plus par défaut.
Trois choses disent ce qui sort : où partent les traces, quels clients tiers arrivent dans l'arbre de dépendances, et ce que le framework envoie chez lui sans qu'on le lui demande.
Observabilité : qui choisit la destination des traces
Un système d'agents en production pose une question qu'on ne se pose jamais au prototype : six semaines après, pourquoi cette exécution a-t-elle coûté deux euros et rendu une réponse fausse ? Y répondre demande des traces, et les traces doivent atterrir dans l'outil que l'équipe regarde déjà, pas dans un onzième onglet, et pas chez un tiers qu'on n'a pas choisi.
OpenTelemetry est le standard qui permet ça. La question n'est donc pas « le framework trace-t-il », mais qui choisit la destination. Trois postures apparaissent dans les arbres de dépendances, et elles n'ont pas les mêmes conséquences.
| Framework | OpenTelemetry | SDK embarqué | Client de tracing imposé |
|---|---|---|---|
pydantic-ai |
API seule | non | logfire-api (coquille inerte) |
agno |
API seule | non | — |
llama-index-core |
API seule | non | — |
openai-agents |
API seule | non | — |
smolagents |
aucun | non | — |
langchain-core |
aucun | non | langsmith |
langgraph |
aucun | non | langsmith |
haystack-ai |
aucun | non | — |
strands-agents |
oui | oui | — |
google-adk |
oui | oui | — |
semantic-kernel |
oui | oui | — |
crewai |
oui | oui | — |
L'API sans le SDK est la bonne réponse
Quatre frameworks installent l'API OpenTelemetry et s'arrêtent là. C'est contre-intuitif : tel quel, l'agent produit des spans que personne ne collecte. Mais c'est la règle de l'écosystème, et elle est juste : une bibliothèque dépend de l'API, une application choisit le SDK et l'exportateur. Le framework qui s'arrête à l'API te laisse décider de ta version d'OpenTelemetry, de ton exportateur et de ton échantillonnage.
Pydantic AI pousse la logique jusqu'à sa propre plateforme : le paquet installé est logfire-api, une coquille sans effet. Si logfire n'est pas installé et configuré, rien n'est envoyé. L'outil maison de l'éditeur est présent dans l'arbre et inactif par défaut.
4 frameworks embarquent le SDK
Strands, l'ADK de Google, Semantic Kernel et CrewAI installent la machinerie complète. C'est plus confortable au premier lancement, mais le framework impose alors sa version du SDK à ton application. Le jour où ton infrastructure d'observabilité et ton framework d'agents ne veulent pas la même, c'est un conflit de dépendances à arbitrer.
4 frameworks n'ont aucun OpenTelemetry
langchain-core et langgraph n'installent aucun paquet OpenTelemetry, mais ils installent langsmith, le client de tracing commercial de LangChain, en dépendance obligatoire. L'observabilité existe, elle passe par la plateforme de l'éditeur. Ce n'est pas une critique de la qualité de LangSmith. C'est un constat de conception : ici, le chemin par défaut mène chez l'éditeur, pas chez toi.
haystack-ai et crewai n'installent pas non plus d'OpenTelemetry, sans lui substituer de client de tracing. Leur télémétrie propre, sans rapport avec l'observabilité, est traitée dans la section suivante.
Ce que chaque framework envoie sans qu'on le lui demande
Cette télémétrie n'a rien à voir avec les traces OpenTelemetry de la section précédente. Les traces servent TON observabilité, tu choisis où elles vont ; la télémétrie décrite ici informe l'éditeur de ce que tu fais. L'inspection des dépendances ne voit pas la télémétrie écrite en interne. J'ai donc cherché les variables d'environnement reconnues par le code de chaque framework. Un flag de desactivation est un signe qu'il y a quelque chose à éteindre.
Cinq frameworks exposent un flag qui leur appartient : AGNO_TELEMETRY, CREWAI_DISABLE_TELEMETRY (avec un CREWAI_TELEMETRY_BASE_URL), HAYSTACK_TELEMETRY_ENABLED, IS_TELEMETRY_ENABLED et AZURE_TELEMETRY_DISABLED pour Semantic Kernel, et une famille ADK_*_TELEMETRY chez Google. Cette dernière ressemble à de la configuration OpenTelemetry plutôt qu'à un envoi vers l'éditeur, et je ne l'ai pas vérifiée.
haystack-ai et crewai installent posthog, un client d'analytique produit, pas un outil d'observabilité d'agents : de la télémétrie sur toi, pas sur ton système, coupée par le flag cité ci-dessus. Les deux collectent par défaut : un événement anonyme à l'initialisation pour Haystack, des noms d'outils et de rôles d'agents pour CrewAI, d'où son avertissement de ne pas y mettre d'information personnelle. Pour une équipe soumise au RGPD, c'est un traitement à documenter et à couper avant la mise en production. Aucun des deux ne le fait à ta place.
Les autres, Pydantic AI, LangGraph, langchain-core, LlamaIndex, openai-agents, smolagents, Strands, n'exposent que des flags venus de leurs dépendances : HF_HUB_DISABLE_TELEMETRY de Hugging Face, et MISTRAL_SDK_TELEMETRY du SDK officiel de Mistral, présent chez tous ceux qui prennent la route native. La télémétrie du provider voyage avec son SDK, indépendamment du framework.
Cette méthode appelle deux précautions. Un flag ne dit pas ce qui est envoyé, ni si c'est actif par défaut. Et son absence ne prouve rien : elle dit seulement que je n'ai pas trouvé de moyen documenté de couper quoi que ce soit.
Le cas Agno
Ce chapitre n'était pas prévu. Il vient d'une anomalie de mesure, en montant les frameworks dans une application FastAPI pour comparer leur tenue en charge.
Les premiers passages, à vingt requêtes simultanées, donnent 1,07 s, puis 1,89 s, puis 5,92 s. Ce n'est pas du bruit : les 11 autres reproduisent à quelques centièmes près. Une irrégularité pareille a une cause, et elle n'était pas dans le code de l'agent.
Agent accepte un paramètre telemetry, doublé d'une variable AGNO_TELEMETRY. J'ai joué quatre passages de chaque côté :
| Réglage | Passage 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| télémétrie par défaut | 1,66 s | 1,13 s | 0,95 s | 2,34 s |
telemetry=False |
0,41 s | 0,42 s | 0,43 s | 0,41 s |
Agno n'est ni lent ni instable. Il appelle son propre serveur à chaque exécution d'agent. Cet appel réseau a une latence variable, comme tout appel réseau, et c'est elle qui se lit dans le temps de réponse de l'API. Coupé, il devient l'un des plus réguliers du comparatif, à vingt millisecondes près sur quatre passages.
J'en tire deux enseignements. Le premier est actionnable : c'est une ligne à écrire avant la mise en production. Le second explique la méthode de la section précédente : cette télémétrie-là est écrite en interne, donc invisible à l'inspection des dépendances. Sans l'anomalie de latence, je ne l'aurais pas vue.
CrewAI a aussi sa télémétrie, mais ne montre rien de tel : 0,35 à 0,38 s avec ou sans CREWAI_DISABLE_TELEMETRY. Ses points instrumentés, crew_creation, end_crew et flow_creation_span, s'accrochent au cycle de vie d'un Crew, pas à chaque appel de modèle : elle se paie une fois par exécution complète, là où celle d'Agno se paie à chaque tour. Précision honnête : mon montage appelle LLM.call directement, donc il n'exerce pas la couche Crew.
Ce qu'il faut regarder, dans l'ordre
RGPD strict, DORA, données qui ne doivent pas quitter ton infrastructure : quatre choses décident, et aucune n'est le pays de l'éditeur.
La première est une route native vers un provider européen. Sept frameworks parlent à Mistral directement, cinq passent par la gateway LiteLLM. Elle installe au passage les SDK d'OpenAI et d'AWS pour appeler un modèle français, et coûte 150 Mo pour le privilège.
La deuxième est une observabilité qui reste chez toi : OpenTelemetry vers ton collecteur, pas un client d'éditeur en dépendance obligatoire.
La troisième est un historique de conversation dans ta base, sérialisable, sans store imposé par le framework.
La quatrième est l'absence de toute télémétrie active par défaut.
Sur ces quatre-là, Pydantic AI et LlamaIndex sont les seuls à tout tenir : route native, API OpenTelemetry sans SDK ni client d'éditeur, messages nus sérialisables, aucun flag de télémétrie propre au framework.
Sont à écarter dans ce contexte, pour les raisons documentées plus haut :
google-adk, dont leVertexAiSessionServicerange les conversations dans un service géré de Google.crewaiethaystack-ai, qui embarquentposthoget collectent par défaut.langchain-coreetlanggraph, dontlangsmithest une dépendance obligatoire.agno, qui appelle son serveur à chaque exécution tant qu'on n'a pas écrittelemetry=False.
le seul éditeur européen du comparatif est le moins bien placé sur ce critère. Haystack vient de deepset, à Berlin, et c'est précisément lui qui embarque posthog, n'installe aucun OpenTelemetry et n'atteint Mistral que par la gateway.
Le SDK officiel de Mistral porte lui-même un MISTRAL_SDK_TELEMETRY, présent chez tous ceux qui prennent la route native : la télémétrie du provider voyage avec son client, indépendamment du framework. Et ma méthode ne voit que la télémétrie déclarée par une variable d'environnement ou par un paquet tiers : l'épisode Agno a montré qu'on peut en écrire une qui échappe aux deux.
Le reste de la grille est dans le comparatif complet : poids, tenue en charge, gestion des erreurs, persistance, sortie typée.