Retour au catalogue
Season 6 18 Épisodes 1h 3m 2026

OpenAI Agents SDK

v0.13 — Édition 2026. Un guide complet pour créer des systèmes multi-agents prêts pour la production avec le OpenAI Agents SDK pour Python (v0.13 - 2026). Découvrez les primitives de base, les modèles d'orchestration, les outils, les handoffs, les guardrails, la gestion d'état, le MCP et l'intégration vocale en temps réel.

Frameworks AI/ML Systèmes multi-agents
OpenAI Agents SDK
Lecture en cours
Click play to start
0:00
0:00
1
Au-delà de Swarm : Les primitives de base
Découvrez les concepts fondamentaux du OpenAI Agents SDK. Cet épisode explique la raison d'être du SDK, comment il améliore Swarm, et les principes de conception de base qui privilégient des abstractions minimales.
3m 31s
2
Définir l'Agent et la Run Loop
Apprenez à configurer l'objet fondamental Agent. Nous explorons les instructions, les paramètres du modèle et la manière de forcer des sorties de données structurées en toute transparence.
3m 41s
3
Équiper les Agents avec des outils de fonctions Python
Donnez à vos agents les moyens d'agir en convertissant des fonctions Python standards en outils exécutables. Comprenez la génération automatique de schémas et l'inférence de types.
3m 27s
4
Mettre à l'échelle les surfaces d'outils avec Hosted Tool Search
Apprenez à gérer des bibliothèques d'outils massives sans épuiser votre budget de tokens. Nous abordons le chargement différé, les espaces de noms et l'exécution d'outils hébergés.
3m 18s
5
Délégation décentralisée : Le modèle Handoff
Maîtrisez l'art de l'orchestration multi-agents en utilisant le modèle Handoff. Découvrez comment créer des agents de triage qui délèguent de manière transparente le contrôle total à des sous-agents spécialisés.
3m 31s
6
Orchestration centralisée : Agents as Tools
Gardez le contrôle de la conversation au même endroit en utilisant le modèle Agents as Tools. Nous discutons de la façon dont un agent manager peut synthétiser les réponses de plusieurs sous-agents spécialistes.
3m 28s
7
Façonner le contexte avec les entrées Handoff et les filtres
Optimisez l'utilisation des tokens multi-agents en modifiant les historiques de conversation entre les handoffs. Apprenez à injecter des métadonnées et à appliquer des filtres de transcription.
3m 39s
8
Contrôler l'état : to_input_list et Server IDs
Une plongée approfondie dans la gestion manuelle des conversations. Comprenez les méthodes de plus bas niveau pour préserver le contexte entre les tours et utiliser les Server IDs pour les réponses.
3m 17s
9
Automatiser la mémoire avec les Sessions intégrées
Simplifiez vos boucles de discussion avec le système de mémoire intégré du SDK. Nous explorons SQLiteSession, OpenAIConversationsSession et la persistance automatisée.
3m 33s
10
Protéger les workflows : Input et Output Guardrails
Sécurisez vos pipelines IA en interceptant les entrées malveillantes avant qu'elles n'atteignent des modèles coûteux. Nous couvrons les guardrails au niveau de l'agent et l'exécution parallèle par rapport à l'exécution bloquante.
3m 31s
11
Valider les actions : Tool-Level Guardrails
Empêchez les fuites de données critiques au niveau de la fonction. Apprenez à envelopper des outils spécifiques avec des guardrails d'entrée et de sortie précis.
3m 36s
12
Mettre l'exécution en pause : Human-in-the-Loop et RunState
Mettez en œuvre des garanties pour les actions irréversibles en imposant des approbations Human-in-the-Loop. Nous explorons le pipeline de sérialisation RunState pour mettre en pause et reprendre les charges de travail.
3m 24s
13
Injecter des dépendances locales avec RunContextWrapper
Maîtrisez l'injection de dépendances dans vos flux d'agents. Apprenez à transmettre en toute sécurité des états locaux et des connexions de base de données aux outils sans les divulguer au LLM.
4m 00s
14
L'USB-C pour l'IA : Introduction au MCP
Une introduction au Model Context Protocol (MCP). Découvrez comment ce standard agit comme un connecteur universel pour brancher facilement des agents IA aux plateformes SaaS.
3m 14s
15
Connecter des serveurs MCP locaux via Stdio et HTTP
Plongez plus profondément dans le MCP en exécutant des serveurs locaux standards. Apprenez à isoler l'accès au système de fichiers et aux outils internes en toute sécurité avec MCPServerStdio.
3m 30s
16
Visualiser les workflows avec le Tracing intégré
Éliminez le débogage par instructions print en utilisant l'observabilité intégrée du SDK. Découvrez comment les spans et les traces automatiques relient des workflows complexes entiers.
3m 29s
17
Voix à faible latence avec les Realtime Agents
Brisez le paradigme standard de requête-réponse. Découvrez comment les Realtime Agents maintiennent des connexions WebSocket en direct pour gérer les interruptions et le raisonnement multimodal.
3m 43s
18
Créer des interfaces utilisateur réactives avec les Streaming Events
Allez au-delà du streaming de tokens de texte. Utilisez les Semantic Streaming Events pour créer des interfaces frontend ultra-réactives qui réagissent aux actions de l'agent en temps réel.
3m 34s

Épisodes

1

Au-delà de Swarm : Les primitives de base

3m 31s

Découvrez les concepts fondamentaux du OpenAI Agents SDK. Cet épisode explique la raison d'être du SDK, comment il améliore Swarm, et les principes de conception de base qui privilégient des abstractions minimales.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 1 sur 18. La plupart des frameworks d'agents IA t'obligent à apprendre une douzaine de nouvelles abstractions, une syntaxe custom et des hiérarchies d'objets super lourdes. Tu passes plus de temps à te battre contre le framework qu'à écrire la vraie logique de ton application. Aujourd'hui, on s'intéresse à Beyond Swarm : les primitives de base. Quand les développeurs entendent parler d'un nouveau framework d'agents, ils s'attendent souvent à un écosystème massif avec une courbe d'apprentissage raide. Le SDK OpenAI Agents, c'est exactement l'inverse. C'est une évolution de la library expérimentale Swarm. Swarm a prouvé que tu pouvais créer des interactions complexes avec des concepts très simples. Le SDK Agents reprend cette philosophie et la consolide pour la production. Il est volontairement léger et entièrement Python-first. L'architecture repose sur deux principes de design fondamentaux : exposer très peu de primitives de base, et garder l'exécution hautement customisable. Tu n'as pas besoin d'un graphe de nœuds complexe ou d'un langage déclaratif propriétaire pour créer un agent ici. Le SDK te donne un tout petit ensemble de briques de base. La pièce fondamentale, c'est l'objet Agent. Tu définis un Agent en lui donnant un nom et un set d'instructions. Si tu veux créer un simple tuteur d'histoire, tu instancies un Agent, tu le nommes HistoryTutor, et tu lui passes une string de texte qui lui indique d'enseigner les événements historiques de manière claire et précise. C'est toute la configuration de ton agent. Il n'y a pas de state caché, ni d'initialisation compliquée. Mais un agent en lui-même, c'est juste une structure de données statique. Il ne fait rien tant qu'il n'est pas exécuté. C'est là que ça devient intéressant. L'exécution est entièrement gérée par un composant séparé appelé le Runner. Le Runner gère la boucle d'interaction complète entre ton code local et l'API OpenAI distante. Dans une application classique, tu devrais écrire une boucle while custom pour vérifier si le modèle veut faire un tool call, parser la réponse, exécuter l'outil, et renvoyer le résultat. Le Runner abstrait tout ça. Pour démarrer le process, tu passes ton agent HistoryTutor et le prompt utilisateur à la méthode run. Le Runner prend le relais à partir de là. Il envoie le prompt au modèle. Si le modèle décide qu'il a besoin de chercher une date historique spécifique, il va demander un tool call. Le Runner se met en pause, exécute la fonction Python locale que tu as fournie pour cet outil, capture la valeur de retour, et la renvoie directement au modèle. Il répète ce cycle automatiquement. Il ne rend le contrôle à ton application que quand le modèle détermine que la tâche est terminée et génère une réponse texte finale. Cette séparation stricte entre la définition statique de l'Agent et l'exécution active du Runner, c'est ce qui rend le SDK si customisable. Parce que les outils sont juste des fonctions Python standards avec des type hints classiques, et que l'agent est juste un simple objet, tu gardes un contrôle total sur le flow de ton application. Tu peux facilement injecter du logging custom, des métriques ou de la gestion d'erreurs autour du Runner sans overrider les classes profondes du framework. Tu écris juste du Python. La vraie valeur de ce SDK n'est pas dans ce qu'il ajoute, mais dans ce qu'il enlève — il s'efface pour te laisser orchestrer des modèles de langage avec du code simple et lisible. Si tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour cette fois. À la prochaine !
2

Définir l'Agent et la Run Loop

3m 41s

Apprenez à configurer l'objet fondamental Agent. Nous explorons les instructions, les paramètres du modèle et la manière de forcer des sorties de données structurées en toute transparence.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 2 sur 18. Et si tu pouvais forcer ton modèle de langage à toujours répondre avec une structure de données parfaitement parsée, sans écrire une seule ligne de regex complexe ? Aujourd'hui, on aborde la définition de l'Agent et de la Run Loop, ce qui est exactement la façon dont tu obtiens ce contrôle strict. Une confusion fréquente quand on débute avec ce SDK, c'est de penser qu'un agent est un process actif en cours d'exécution. Ce n'est pas le cas. Dans cette architecture, l'objet Agent est strictement un conteneur de configuration. Il encapsule un modèle de langage spécifique dans un contexte prédéfini. Il ne s'exécute pas lui-même, et il ne conserve aucun state par lui-même. Tu construis simplement un blueprint. Pour définir ce blueprint, tu instancies un Agent. Tu commences par le paramètre instructions. C'est ton system prompt principal, où tu définis le persona, les limites et les règles spécifiques que le modèle doit suivre. Ensuite, tu fournis les settings du modèle. Ça détermine quel modèle sous-jacent utiliser et ça configure les détails d'inférence standards. À ce stade, ton agent est entièrement défini, mais totalement inactif en mémoire. C'est là que ça devient intéressant. Tu peux physiquement contraindre la forme de la réponse de l'agent en utilisant le paramètre output type. Imagine que tu développes un tool pour extraire des événements de calendrier à partir de threads d'emails un peu brouillons. Au lieu d'écrire des instructions qui supplient le modèle de formater correctement les dates, tu définis une structure de données concrète dans ton code. Tu définis une classe Calendar Event avec des champs stricts pour un titre, une heure de début et un lieu. Tu passes cette classe dans le paramètre output type de ton Agent. Configurée comme ça, l'API impose le schéma. L'agent ne peut pas renvoyer une réponse texte conversationnelle. Il renverra uniquement un objet Calendar Event validé que le code de ton application peut ingérer immédiatement. Tu as maintenant un blueprint d'agent strict et bien configuré. Pour qu'il fasse le vrai travail, tu as besoin de la Run Loop. Parce que l'agent est juste une définition statique, l'exécution est entièrement gérée par un composant Runner séparé. Le Runner est le moteur. Tu passes la définition de ton agent et l'input utilisateur dans le Runner, et il prend le relais sur l'exécution. Quand tu déclenches le Runner, il entre dans une boucle d'exécution. Il regroupe les instructions de ton agent, le schéma d'output strict et le prompt utilisateur, puis les envoie au modèle. La Run Loop est responsable de gérer toute l'orchestration des allers-retours. Si le modèle décide qu'il a besoin d'appeler un tool externe pour récupérer des données manquantes, le Runner intercepte cette requête, exécute le code du tool local et renvoie le résultat au modèle. Il gère toutes ces étapes intermédiaires automatiquement. La boucle se termine uniquement quand le modèle résout le prompt et produit l'output final qui correspond exactement à ton output type de calendrier. Garder la configuration statique de l'agent totalement séparée de la Run Loop active, c'est ce qui te permet de réutiliser en toute sécurité ce même agent d'extraction de calendrier sur des milliers d'exécutions simultanées sans aucune fuite de données. Merci d'avoir écouté, happy coding tout le monde !
3

Équiper les Agents avec des outils de fonctions Python

3m 27s

Donnez à vos agents les moyens d'agir en convertissant des fonctions Python standards en outils exécutables. Comprenez la génération automatique de schémas et l'inférence de types.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 3 sur 18. Écrire des JSON schemas à la main pour des language model tools, c'est fastidieux et fragile. Une accolade manquante ou un mauvais type, et le modèle ne comprend plus comment interagir avec ton système. Au lieu d'écrire ces définitions à la main, tu peux juste écrire du Python standard et laisser le framework faire la traduction. C'est exactement ce qu'on aborde aujourd'hui : équiper les agents avec des Python Function Tools. On croit souvent à tort qu'exposer de la logique locale à un agent nécessite de maintenir deux sources de vérité. Les gens pensent qu'ils ont besoin de leur code Python, plus un fichier de configuration JSON séparé et complexe qui décrit ce code au language model. Avec le Agents SDK, tu évites complètement l'écriture manuelle du JSON. Tu écris simplement une fonction Python standard et tu places le décorateur function tool juste au-dessus. Quand tu appliques ce décorateur, le SDK se met au travail en arrière-plan en utilisant le module inspect intégré de Python et Pydantic. Il scanne la signature de ta fonction. Il lit les noms des paramètres, extrait les type hints, et récupère la docstring de la fonction. À partir de ces éléments, il génère automatiquement un JSON schema strict et l'attache à l'agent. Prenons un scénario concret. Tu veux donner à ton agent une fonction appelée fetch weather. Cette fonction a besoin de données géographiques précises pour marcher. Au lieu de laisser le modèle deviner quel format de string utiliser, tu définis une structure spécifique. Tu crées un type personnalisé, peut-être un Typed Dictionary appelé Location, qui contient des champs string distincts pour la ville et le pays. Tu utilises ensuite ce type Location comme type hint strict pour le paramètre d'entrée de ta fonction fetch weather. Voici le point clé. Tu dois ajouter une docstring claire à cette fonction. Tu pourrais écrire une phrase simple indiquant que cet outil récupère les conditions météo actuelles pour une ville et un pays spécifiques. Le framework extrait ce texte et l'utilise comme description principale de l'outil dans le prompt. Ta docstring n'est plus juste une note utile pour tes collègues développeurs. C'est littéralement le manuel d'instructions que l'agent évalue pour décider s'il doit déclencher l'outil. Si un utilisateur demande s'il a besoin d'une veste à Tokyo, l'agent passe en revue les outils disponibles. Il lit ta docstring, se rend compte que la fonction fetch weather fournit la réponse, et structure une requête. Parce que tu as ajouté un type hint sur l'entrée avec ton dictionnaire Location, Pydantic garantit que l'output de l'agent correspond exactement aux champs requis avant même que ta logique Python s'exécute. Si le modèle essaie de passer une simple string de texte au lieu du dictionnaire, le framework attrape l'erreur et force l'agent à réessayer avec la bonne structure. Le SDK exécute la fonction localement, capture la valeur de retour, et réinjecte le résultat directement dans la boucle de raisonnement de l'agent. Tes type hints et docstrings Python standards ne sont plus de la documentation passive ; ils forment le contrat d'API actif et contraignant sur lequel ton agent s'appuie pour interagir avec le monde réel. Merci d'avoir passé quelques minutes avec moi. À la prochaine, à plus.
4

Mettre à l'échelle les surfaces d'outils avec Hosted Tool Search

3m 18s

Apprenez à gérer des bibliothèques d'outils massives sans épuiser votre budget de tokens. Nous abordons le chargement différé, les espaces de noms et l'exécution d'outils hébergés.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 4 sur 18. Passer une centaine de tools à un modèle de langage détruit les performances et crame ton budget de tokens avant même qu'une seule action soit effectuée. Tu ne peux pas bourrer chaque schema d'API d'entreprise dans la context window initiale et espérer un bon raisonnement. La solution à ça, c'est de scaler les tool surfaces avec le Hosted Tool Search. Avant de parler de scaling, on doit définir ce que sont les hosted tools. Les hosted tools s'exécutent nativement sur l'infrastructure d'OpenAI plutôt que de tourner sur ta machine locale. Les exemples intégrés incluent le Web Search Tool et le File Search Tool. Tu n'as pas besoin d'écrire la logique d'exécution, de gérer le web crawler ou de construire le mécanisme de file chunking pour ces tools. Tu les attaches à ton agent, et le backend d'OpenAI gère le vrai travail. Mais le concept de hosted tools s'étend aussi à la façon dont le modèle découvre tes propres custom tools quand tu en as trop. Prends l'exemple d'un agent CRM. Tu pourrais avoir cinquante tools distincts pour vérifier le statut des commandes, récupérer l'historique de facturation, mettre à jour les adresses de livraison et récupérer les logs du support. Si tu passes les cinquante schemas d'un coup, tu surcharges le modèle et tu gaspilles des input tokens. Beaucoup de développeurs pensent qu'ils doivent résoudre ça en construisant une étape de retrieval côté client. Ils supposent qu'ils doivent intercepter le prompt de l'utilisateur, chercher les schemas de tools pertinents dans une vector database locale, et les injecter dynamiquement dans le prompt avant d'appeler le modèle de langage. Tu n'as pas besoin de faire ça. Le Hosted Tool Search se fait nativement sur les serveurs d'OpenAI en utilisant la Responses API. Le modèle lui-même est capable de chercher dans la tool surface disponible sans que ton code client ne serve d'intermédiaire. Tu obtiens ça en utilisant deux paramètres : le tool namespace et le defer loading. Quand tu enregistres tes tools CRM, tu regroupes les fonctions liées en les assignant à un namespace partagé. Par exemple, tu pourrais placer tous tes tools de profil client dans un namespace appelé customer account. Ensuite, tu mets le paramètre defer loading sur true pour ces tools. C'est ça le plus important. Quand le defer loading est actif, l'agent n'envoie pas les schemas de tools individuels au modèle de langage au début de la conversation. À la place, il envoie un seul schema léger qui représente le namespace customer account lui-même. Le modèle est informé que ce namespace existe et sait comment le requêter si besoin. Quand l'utilisateur demande à chercher un customer ID spécifique, le modèle se rend compte qu'il a besoin de plus d'infos. Il exécute une recherche nativement sur le namespace customer account. Les serveurs d'OpenAI trouvent le tool de facturation ou de support pertinent, chargent uniquement ce schema de tool spécifique dans le context du modèle, et ensuite le modèle exécute le tool call. Ça découple complètement la taille de ta tool library de ton coût initial en tokens. Tu pourrais attacher des centaines de tools à un seul agent, et le prompt initial reste minuscule. Le modèle ne génère un coût en tokens que pour les schemas de tools spécifiques qu'il décide activement de récupérer au runtime. En utilisant le defer loading, tu échanges une énorme charge de context statique contre un mécanisme de retrieval dynamique et précis. C'est tout pour cet épisode. À la prochaine !
5

Délégation décentralisée : Le modèle Handoff

3m 31s

Maîtrisez l'art de l'orchestration multi-agents en utilisant le modèle Handoff. Découvrez comment créer des agents de triage qui délèguent de manière transparente le contrôle total à des sous-agents spécialisés.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 5 sur 18. Parfois, la meilleure façon pour un manager de gérer une tâche complexe, c'est de s'effacer complètement. Si ton agent de routing principal essaie de gérer chaque interaction entre un utilisateur et tes systèmes backend, tes prompts deviennent surchargés et ton exécution devient instable. C'est exactement ce que la Decentralized Delegation, et plus particulièrement le Handoff Pattern, est censé résoudre. Un handoff, c'est un mécanisme par lequel un agent cède le contrôle total de la conversation à un autre agent. Une erreur fréquente, c'est de confondre un handoff avec du tool calling standard. Ils sont fondamentalement différents. Quand un agent appelle une fonction normale, il se met en pause, attend le retour des données, puis formule une réponse pour l'utilisateur. Quand un agent déclenche un handoff, il cède entièrement son tour de conversation. Le contrôle passe complètement au nouvel agent. L'agent de départ s'efface complètement. C'est important parce que ça permet de garder ton architecture décentralisée. Si un agent de triage central doit traiter l'output de chaque action d'un spécialiste, son system prompt doit être énorme. Il a besoin d'instructions sur la façon de formuler les politiques de remboursement, le troubleshooting technique et la suppression de compte. Pire encore, l'agent de triage va inévitablement essayer de raconter le travail du spécialiste à l'utilisateur. Ça gaspille des tokens, ajoute de la latence et introduit un gros risque d'hallucination. Les handoffs évitent ça en laissant le spécialiste parler directement à l'utilisateur. Imagine un système de support client. Tu déploies un agent de triage général pour accueillir les utilisateurs et catégoriser les requêtes. Un client écrit pour demander un remboursement. Tu as aussi un agent de remboursement dédié, qui est équipé de tools de facturation spécifiques et d'instructions strictes sur la politique de retour de l'entreprise. Pour les connecter en utilisant le SDK, tu écris une fonction standard appelée transfer to refund. Mais au lieu de retourner une string ou des données JSON, cette fonction retourne ton objet agent de remboursement. Tu passes ensuite cette fonction de transfert à ton agent de triage, en la listant exactement comme n'importe quel autre tool. Quand le client demande un remboursement, l'agent de triage décide d'appeler la fonction de transfert. Voici le point clé. La runner loop sous-jacente du SDK exécute la fonction et voit qu'un objet Agent a été retourné à la place de données standards. Le runner remplace instantanément l'agent actif dans sa mémoire. Il prend l'historique de conversation existant et le passe directement au nouvel agent de remboursement activé. L'agent de remboursement prend le relais sur le tour actif, traite la requête de l'utilisateur, déclenche ses propres tools de facturation, et répond directement à l'utilisateur. Tu peux aussi passer des données pendant cette transition. Si l'agent de triage a déjà demandé à l'utilisateur son numéro de commande, il peut passer ce numéro de commande comme argument dans la fonction de transfert. La fonction peut ensuite injecter ce numéro de commande dans les context variables du nouvel agent avant de le retourner. L'agent de remboursement se réveille en sachant déjà exactement quelle transaction chercher. En utilisant les handoffs, tu gardes chaque agent petit, focus et prévisible, ce qui laisse la conversation couler naturellement d'un expert spécialisé à un autre. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
6

Orchestration centralisée : Agents as Tools

3m 28s

Gardez le contrôle de la conversation au même endroit en utilisant le modèle Agents as Tools. Nous discutons de la façon dont un agent manager peut synthétiser les réponses de plusieurs sous-agents spécialistes.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 6 sur 18. Si ton assistant IA doit consulter trois services différents avant de répondre à un utilisateur, tu as rarement envie que l'utilisateur parle directement à ces services. Tu veux une voix unique et cohérente qui gère la conversation, en récupérant les infos discrètement en arrière-plan. C'est exactement ce que l'orchestration centralisée, en utilisant des agents comme tools, te permet de faire. Tu pourrais confondre ça avec les handoffs, où un agent passe définitivement l'utilisateur à un autre agent. Avec les handoffs, le nouvel agent prend complètement le relais sur la conversation. Avec l'orchestration centralisée, le contrôle n'est jamais transféré. L'agent principal, qui agit généralement comme un manager, garde le contrôle absolu sur la conversation. Le manager est la seule voix que l'utilisateur entend. Tu obtiens ça en prenant un agent complètement configuré et en le transformant en une fonction callable. Chaque objet agent dans le SDK possède une méthode nommée as_tool. Quand tu appelles cette méthode, elle encapsule l'agent entier, y compris ses instructions spécifiques et ses propres tools, dans un format de tool standard. Tu fournis ensuite cet agent encapsulé à ton agent manager, exactement comme tu le ferais pour une fonction Python standard. Regardons un scénario pratique. Tu développes un portail de support client. Tu crées un agent spécialiste des réservations. Son seul boulot est de requêter les systèmes internes, de croiser les dates et de renvoyer les disponibilités. Cet agent est très technique. Ses instructions sont optimisées pour la précision de la base de données, pas pour faire la conversation. Tu ne veux pas que l'utilisateur interagisse avec ce spécialiste. Donc, tu appelles la méthode as_tool sur le spécialiste des réservations. Ensuite, tu crées ton agent manager. Tu donnes au manager des instructions strictes pour garder un ton poli et corporate, et gérer la relation avec l'utilisateur. Tu ajoutes ensuite le spécialiste des réservations encapsulé à la liste de tools du manager. Quand un utilisateur demande au manager de vérifier les disponibilités pour mardi prochain, le manager traite la requête. Il reconnaît qu'il lui manque les données réelles, mais il sait qu'il a un tool qui peut les trouver. Le manager invoque le tool de réservation. Voici le point clé. Quand ce tool est invoqué, l'agent spécialiste des réservations se réveille, exécute ses propres étapes internes isolées, et produit une réponse. Mais il n'envoie pas cette réponse à l'utilisateur. Il renvoie un résultat brut et factuel directement au manager. Le manager reçoit ces données, les synthétise, les enrobe dans une formule de politesse corporate, et répond enfin à l'utilisateur. Ce pattern en étoile résout un problème majeur avec les applications complexes : le context bloat. L'agent manager n'a pas besoin de connaître le schéma de la base de données ou les règles pour vérifier les dates. Il garde son system prompt propre, en se concentrant entièrement sur le routage des requêtes et le formatage des réponses. Pendant ce temps, l'agent spécialiste n'a pas besoin de se soucier de l'historique de conversation ou de la voix de la marque. Il fait juste son boulot très ciblé et renvoie un résultat. Au moment de choisir entre un handoff et un tool, demande-toi à qui appartient la réponse finale. Si l'agent spécialisé doit engager un long dialogue avec l'utilisateur, tu veux un handoff. Mais si l'agent spécialisé est juste un processeur de données sophistiqué qui fournit une réponse que l'assistant principal va utiliser, encapsule-le comme un tool et laisse le manager gérer la relation. Merci d'avoir passé quelques minutes avec moi. À la prochaine, porte-toi bien.
7

Façonner le contexte avec les entrées Handoff et les filtres

3m 39s

Optimisez l'utilisation des tokens multi-agents en modifiant les historiques de conversation entre les handoffs. Apprenez à injecter des métadonnées et à appliquer des filtres de transcription.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 7 sur 18. Quand tu transfères un client à un spécialiste humain, tu ne l'obliges pas à lire une énorme transcription brute de chaque vérification automatisée du système qui vient d'avoir lieu. Tu lui donnes une raison claire pour le transfert et un résumé propre du problème. Pourtant, quand les développeurs connectent des agents IA, ils balancent souvent tout le chat log brut dans la context window de l'agent suivant. Aujourd'hui, on règle ça en modelant le contexte avec les handoff inputs et les input filters. Quand un agent passe le contrôle à un autre, il a besoin d'un moyen de communiquer pourquoi le handoff a lieu. Tu fais ça en utilisant le paramètre input type sur ta routine de handoff. Tu définis un schema, généralement un modèle Pydantic, qui spécifie exactement de quelles informations l'agent récepteur a besoin. Quand l'agent actuel décide d'exécuter le handoff, le modèle de langage sous-jacent génère un payload qui correspond à ce schema. Dissipons tout de suite une confusion courante. C'est facile de confondre cet input type avec un state d'application persistant, comme un ID de profil utilisateur ou une connexion à une base de données backend qui vit pendant toute la session. Ce n'est pas le cas. L'input type sert strictement aux métadonnées transitoires générées par le modèle, créées exactement au moment du handoff. Par exemple, si un agent de triage fait un handoff d'un utilisateur vers un spécialiste de la facturation, l'input type pourrait exiger un champ appelé escalation reason. L'agent de triage génère une courte string qui explique l'erreur de facturation spécifique, et l'agent de facturation reçoit ces données structurées immédiatement à son réveil. Ça, c'est pour le message de handoff explicite. Maintenant, on doit gérer l'historique de la conversation. Par défaut, tout l'historique des messages voyage avec le handoff. Chaque prompt utilisateur, chaque réponse de l'assistant et chaque tool call en arrière-plan est transmis. Ça consomme des tokens rapidement et ça remplit la context window avec du bruit inutile. Tu contrôles ça en utilisant un input filter. Un input filter est une fonction Python standard qui intercepte l'historique de la conversation juste avant que l'agent récepteur ne le lise. Elle prend la liste complète des messages précédents comme argument, les traite, et retourne une nouvelle liste de messages modifiée. Imagine un scénario où ton agent initial a passé dix tours à appeler différents search tools et APIs de base de données pour essayer de résoudre un problème, avant de finalement laisser tomber et de router l'utilisateur vers un agent FAQ général. L'agent FAQ a seulement besoin des vraies questions de l'utilisateur. Il n'a absolument pas besoin des outputs JSON bruts de dix tool calls qui ont échoué. Pour résoudre ça, tu écris une fonction d'input filter. Dedans, tu itères sur la liste des messages entrants. Tu vérifies le rôle de chaque message. Si le message est une exécution d'outil ou un tool result brut, tu le supprimes. Si c'est un message direct de l'utilisateur ou une réponse finale de l'assistant, tu l'ajoutes à ta nouvelle liste. Tu retournes ensuite cette liste propre et tu attaches ta fonction de filter à la définition du handoff. L'agent FAQ reçoit maintenant un historique épuré qui contient uniquement les allers-retours lisibles par un humain. Voici l'idée clé. Les handoff inputs ajoutent une intelligence structurée à la transition, pendant que les input filters coupent impitoyablement le bruit. Ensemble, ils modèlent exactement ce que l'agent récepteur sait. Tu économises des tokens, tu réduis la latence, et tu empêches le nouvel agent d'halluciner en se basant sur le raisonnement écarté de l'agent précédent. Contrôler le contexte à la frontière du handoff est le moyen le plus efficace de garder un système multi-agents rapide et précis. Si tu veux aider à faire vivre l'émission, tu peux chercher DevStoriesEU sur Patreon — ton soutien compte beaucoup. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
8

Contrôler l'état : to_input_list et Server IDs

3m 17s

Une plongée approfondie dans la gestion manuelle des conversations. Comprenez les méthodes de plus bas niveau pour préserver le contexte entre les tours et utiliser les Server IDs pour les réponses.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 8 sur 18. Un agent IA amnésique est inutilisable. Mais mal stocker sa mémoire peut dupliquer silencieusement l'historique des conversations et doubler tes coûts d'API. Ça arrive quand tu mélanges accidentellement différentes méthodes de suivi de l'historique du chat. Aujourd'hui, on s'intéresse au Controlling State : to_input_list et les Server IDs. Par défaut, un run d'agent basique est complètement stateless. Tu envoies une string, tu reçois une string. Si tu poses une question de suivi, l'agent n'a aucun contexte sur ce dont tu viens de parler. Tu dois fournir l'historique toi-même. Bien que le SDK propose des wrappers de session de haut niveau, tu as parfois besoin de la méthode la plus bas niveau et la plus transparente pour maintenir l'historique du chat sur plusieurs turns, sans aucun state caché par magie. Il y a deux façons explicites de gérer ça. La première méthode garde la source de vérité sur ta machine en utilisant une méthode appelée to_input_list. Quand un agent termine un run, il renvoie un objet result. Cet objet contient la réponse finale, mais il contient aussi les étapes cachées que l'agent a suivies pour y arriver. Si l'agent a appelé un tool de base de données, a lu l'output, puis a formulé une réponse, toutes ces étapes intermédiaires font partie du state de la conversation. Appeler to_input_list sur l'objet result package toute cette séquence. Ça renvoie un array plat qui contient le prompt utilisateur original, les réponses de l'agent, les tool calls spécifiques et les tool outputs. Ça formate tout ça exactement comme l'API s'attend à le recevoir. Si tu développes une chat loop en ligne de commande, la logique est la suivante. Tu définis une variable pour stocker l'array de la conversation. Au début, elle contient juste le premier prompt utilisateur. Tu passes cet array à l'agent. Quand l'agent a terminé, tu prends le result et tu appelles to_input_list, ce qui te donne l'historique complet et mis à jour de ce turn. Quand l'utilisateur tape sa deuxième question, tu ajoutes manuellement son nouveau message à la fin de cette liste, et tu repasses le tout à l'agent. Tu as le contrôle total du payload. Maintenant, la deuxième partie. Faire transiter un array massif de messages précédents et de tool outputs JSON sur le réseau à chaque turn, ça utilise de la bande passante. Si tu veux éviter ça, tu peux utiliser des Server IDs. Chaque réponse que tu reçois de l'API inclut un identifiant unique. Au lieu de passer un array d'anciens messages dans ton prochain run d'agent, tu passes un paramètre appelé previous response ID. Voici le point clé. Quand tu fournis un previous response ID, ton client envoie uniquement le tout nouveau message utilisateur. Tu n'envoies pas l'array d'historique. Le serveur OpenAI cherche cet ID, récupère le thread de contexte existant de son côté, y attache ton nouveau message, et génère la réponse suivante. Ça nous amène à un piège critique. Tu pourrais être tenté de mélanger ces approches. Tu pourrais ajouter l'input utilisateur à la liste côté client, passer cette liste complète à l'agent, et aussi passer le previous response ID juste pour être sûr. Ne fais pas ça. Tu dois choisir exactement une seule stratégie par conversation. Si tu fournis à la fois l'array d'historique complet et un previous response ID, le serveur va les concaténer. Ton agent lira la conversation entière deux fois, sera confus par les tool calls en double, et tu paieras ces tokens deux fois. Le choix entre ces deux méthodes se résume à la visibilité contre l'efficacité. Utilise les listes côté client quand tu as besoin d'auditer, de filtrer ou de modifier l'historique de conversation entre les turns. Utilise les Server IDs quand tu fais confiance au thread brut et que tu veux minimiser ton payload réseau. C'est tout pour cet épisode. Merci de ton écoute, et continue à développer !
9

Automatiser la mémoire avec les Sessions intégrées

3m 33s

Simplifiez vos boucles de discussion avec le système de mémoire intégré du SDK. Nous explorons SQLiteSession, OpenAIConversationsSession et la persistance automatisée.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 9 sur 18. Tu développes un chat bot persistant. Tu écris du code pour récupérer les messages précédents depuis une base de données, les passer à ton agent, extraire la nouvelle réponse, et écrire la liste mise à jour dans la base de données. C'est du boilerplate fastidieux que tu as écrit des dizaines de fois. Aujourd'hui, on s'intéresse à l'automatisation de la mémoire avec les sessions intégrées, qui remplace toute cette logique de lecture et d'écriture en base de données par un seul objet. Levons tout de suite un malentendu fréquent. Quand les développeurs commencent à utiliser les sessions dans ce SDK, ils pensent souvent qu'ils doivent toujours récupérer et passer manuellement l'historique des messages à l'agent runner avec la session. Ce n'est pas le cas. Fournir un objet session au runner remplace complètement la gestion manuelle de l'historique. Tu lui confies les clés. Le runner récupère automatiquement les messages passés juste avant que le tour de conversation ne commence, et il append automatiquement les nouveaux messages au moment où le tour se termine. Prends l'exemple d'un bot Slack persistant qui doit mémoriser les préférences de l'utilisateur sur plusieurs jours. Tu veux stocker ce state sur disque sans configurer une lourde base de données externe. Le SDK fournit un outil intégré pour ça, appelé SQLite Session. Comme l’interaction avec un file system nécessite des opérations d’I/O, cet outil est entièrement asynchrone. Pour l’utiliser, tu instancies d'abord une SQLite Session, en fournissant un chemin de fichier pour ta base de données locale. Ensuite, tu t'y connectes en utilisant un async context manager. Vois ça comme l'ouverture d'une connexion sécurisée qui garantit que le fichier de base de données est correctement verrouillé et déverrouillé. À l’intérieur de ce bloc de connexion, tu appelles ton agent runner. Au lieu de passer un array de messages précédents au runner, tu passes simplement l’objet session et un session ID. Le session ID est juste une string unique. Pour ton bot Slack, cet ID pourrait être le user ID ou le channel ID. Le runner prend cet ID, cherche dans le fichier SQLite, charge l’historique existant, traite le user prompt, puis persiste le nouveau state de manière sécurisée dans le fichier. Tout cela se passe en arrière-plan. Voici le point clé. Un historique de conversation illimité finira par dépasser les limites de ta context window. Tu ne veux pas qu'un petit chat d'il y a trois mois gonfle ton usage de tokens ou fasse crasher ton call API aujourd'hui. Pour contrôler ça, le SDK propose les Session Settings. Quand tu appelles le runner, tu peux inclure un objet Session Settings en plus de la session elle-même. Cet objet de settings accepte un paramètre pour le maximum de messages passés. Si tu le mets à dix, le runner tronque automatiquement l'historique chargé. Il ne garde que les dix messages les plus récents dans l'active context envoyé au modèle, mais ton log historique complet reste intact et en sécurité dans la base de données SQLite. SQLite Session est idéal pour la persistance locale ou les applications single server. Si ton bot Slack grandit et que tu as besoin de scale sur plusieurs serveurs, le SDK gère ça de manière transparente. Tu gardes ton code de runner exactement pareil, mais tu remplaces la SQLite Session locale par une option distribuée comme une Redis Session ou une Dapr Session. Ce qu'il faut retenir, c'est que les sessions imposent une stricte separation of concerns. En configurant un objet session et en le passant au runner, tu élimines le boilerplate de base de données fragile et tu garantis que la memory de ton agent est toujours parfaitement synchronisée avec son execution state. C'est tout pour aujourd'hui. Merci d'avoir écouté — va construire un truc cool.
10

Protéger les workflows : Input et Output Guardrails

3m 31s

Sécurisez vos pipelines IA en interceptant les entrées malveillantes avant qu'elles n'atteignent des modèles coûteux. Nous couvrons les guardrails au niveau de l'agent et l'exécution parallèle par rapport à l'exécution bloquante.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 10 sur 18. Ton modèle de raisonnement le plus puissant est aussi le plus cher. Si un utilisateur essaie de le piéger pour qu'il fasse ses devoirs de maths ou qu'il enfreigne les règles de sécurité, tu n'as pas envie de le découvrir après qu'il ait passé deux minutes et mille tokens à y réfléchir. Protéger tes workflows avec des input et output guardrails, c'est comme ça que tu évites ça. Les guardrails au niveau de l'agent agissent comme des videurs pour tes modèles principaux. Ce sont des fonctions séparées, souvent propulsées par des modèles plus petits, plus rapides et moins chers, qui valident les données qui entrent ou qui sortent de ton agent. En interceptant les requêtes, ils permettent à tes modèles qui coûtent cher de rester concentrés sur le vrai travail, et ils s'assurent que ton application reste sûre et dans le sujet. Tu les appliques à deux endroits : à l'input, et à l'output. Les input guardrails évaluent le prompt de l'utilisateur avant que ton agent principal ne se mette au travail. Imagine un scénario où tu as un modèle lourd et lent qui gère des analyses financières complexes. Tu peux configurer un input guardrail en utilisant un modèle rapide et léger pour examiner chaque message entrant. Quand un utilisateur pose une question, ce modèle rapide l'intercepte. Il vérifie si l'utilisateur essaie de faire faire un devoir scolaire à l'agent, ou s'il tente peut-être une attaque par prompt injection. Si l'input est signalé, le guardrail le rejette immédiatement et renvoie un message de refus standard. Ton modèle de raisonnement lourd ne se réveille même pas. Tu gagnes du temps, et tu économises de l'argent. Les output guardrails gèrent l'autre bout de la transaction. Ils font une dernière vérification avant que l'utilisateur ne voie la réponse. L'agent principal a terminé sa tâche, mais tu dois t'assurer qu'aucune donnée sensible ne fuite, ou que le ton correspond aux règles de ton entreprise. L'output guardrail examine le texte généré. S'il détecte une hallucination ou une violation des règles, il empêche le message d'arriver jusqu'à l'utilisateur. Voici le point clé. La façon dont ces guardrails impactent ton application dépend entièrement de leur mode d'exécution. Tu peux les faire tourner en mode bloquant, ou en mode parallèle. Le mode bloquant est une séquence stricte. Un input guardrail doit terminer son évaluation et donner son feu vert avant que l'agent principal ne soit autorisé à démarrer. Un output guardrail doit finir de vérifier la réponse finale avant que l'utilisateur ne reçoive le moindre mot. C'est l'approche la plus sûre et ça te garantit que tu ne vas pas gaspiller d'argent sur de mauvaises requêtes, mais ça ajoute de la latence à l'interaction. Le mode parallèle sacrifie le contrôle strict des coûts pour la vitesse. Une idée reçue très courante, c'est que l'exécution en parallèle met l'agent principal en pause pendant que le guardrail tourne à côté. Ce n'est pas le cas. En mode parallèle, l'input guardrail et l'agent principal démarrent exactement en même temps. L'agent génère activement du texte et consomme des tokens pendant que le guardrail est encore en train d'évaluer le prompt en input. Si le guardrail décide de rejeter la requête, il va annuler l'agent principal en plein vol. L'utilisateur est toujours protégé et ne verra pas l'output, mais tu paies quand même pour les tokens que l'agent principal a consommés avant d'être coupé. Tu configures ça en définissant une fonction simple qui renvoie une décision de succès ou d'échec, en l'attachant à ton agent, et en déclarant son mode. Adapte toujours ton mode d'exécution à tes priorités : utilise des guardrails bloquants pour protéger ton portefeuille des modèles qui coûtent cher, et des guardrails parallèles pour protéger ton expérience utilisateur de la latence. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
11

Valider les actions : Tool-Level Guardrails

3m 36s

Empêchez les fuites de données critiques au niveau de la fonction. Apprenez à envelopper des outils spécifiques avec des guardrails d'entrée et de sortie précis.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 11 sur 18. Même l'IA la plus intelligente peut accidentellement faire fuiter un secret de base de données si elle tire des données brutes directement dans son context. Tu pourrais penser que tes contrôles de sécurité de haut niveau détectent tout, mais ils ne s'exécutent qu'au tout début ou à la toute fin d'une conversation. Si tu veux intercepter des données sensibles au beau milieu de ton workflow, tu as besoin de Validating Actions, et plus précisément de Tool-Level Guardrails. Un piège classique, c'est de croire que les guardrails au niveau de l'agent protègent tes systèmes sous-jacents. Ce n'est pas le cas. Les guardrails de l'agent traitent le prompt initial de l'utilisateur ou la réponse finale qui lui est renvoyée. Ils sont aveugles aux allers-retours internes quand un agent appelle une base de données ou une API tierce. Si un prompt malveillant piège ton agent et le pousse à appeler un outil interne, les contrôles au niveau de l'agent ne l'arrêteront pas. Pour protéger les outils eux-mêmes, le OpenAI Agents SDK fournit des tool guardrails. Ils se placent directement sur la fonction, agissant comme un point de contrôle obligatoire juste avant ou juste après l'exécution de l'outil. Il y a deux types que tu dois connaître. Le premier, c'est le tool input guardrail. Tu appliques ce decorator pour valider les arguments avant que l'outil ne s'exécute réellement. Disons qu'un agent essaie d'appeler un outil qui supprime un compte utilisateur. L'input guardrail intercepte les arguments que l'agent a générés. Il vérifie si l'ID utilisateur fourni correspond à un format valide, ou si la session en cours a le bon niveau d'autorisation. Si l'input échoue à cette vérification, le guardrail empêche complètement l'outil de s'exécuter. Au lieu d'exécuter la suppression, il renvoie un message d'erreur directement à l'agent. L'agent lit alors cette erreur et peut réessayer avec des inputs corrigés, sans jamais toucher à la base de données réelle. Maintenant, la deuxième partie de tout ça, c'est le tool output guardrail. Il intervient après que l'outil s'est exécuté avec succès, mais avant que le résultat ne soit renvoyé à l'agent. C'est là que tu filtres, que tu masques ou que tu valides le payload. Prends l'exemple d'un outil de lookup dans une base de données. L'agent demande un profil de développeur, et l'outil récupère l'enregistrement brut. Sauf que cet enregistrement se trouve contenir une clé API active qui commence par les lettres s-k-tiret. Si cette clé brute retourne à l'agent, elle entre dans la context window du modèle de langage. C'est un risque de sécurité énorme. Pour corriger ça, tu ajoutes un tool output guardrail à cette fonction de lookup spécifique. Le guardrail prend le résultat brut de la base de données, scanne le texte à la recherche de ce pattern s-k-tiret, et remplace la vraie clé par une string de substitution comme redacted. Ce n'est qu'après ce processus de nettoyage que les données propres sont renvoyées à l'agent. L'agent obtient toujours les informations de profil dont il a besoin pour répondre à l'utilisateur, mais le secret ne quitte jamais la boundary d'exécution isolée de l'outil. C'est ça la partie importante. Dans des workflows multi-agents complexes, différents agents spécialisés peuvent invoquer des outils dans des séquences imprévisibles. Tu ne peux pas compter sur le prompting de l'agent pour qu'il se comporte de manière sécurisée. Tu ne peux pas non plus espérer que le filtre d'output final attrape une fuite de clé juste avant qu'elle n'aille à l'utilisateur, parce qu'à ce moment-là, la clé a déjà été exposée au modèle de langage. Tu dois verrouiller l'outil lui-même. En attachant le guardrail directement à la fonction, la logique de sécurité voyage avec l'outil. Peu importe quel agent l'appelle ou quand il est appelé dans le workflow. La protection est absolue. Les tool guardrails traitent tes fonctions comme des boundaries zero-trust, garantissant que, peu importe à quel point ton agent devient autonome, il ne pourra jamais faire entrer de mauvaises données, ni extraire des données sensibles. C'est tout pour cet épisode. Merci d'avoir écouté, et continue à développer !
12

Mettre l'exécution en pause : Human-in-the-Loop et RunState

3m 24s

Mettez en œuvre des garanties pour les actions irréversibles en imposant des approbations Human-in-the-Loop. Nous explorons le pipeline de sérialisation RunState pour mettre en pause et reprendre les charges de travail.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 12 sur 18. Tu ne laisserais pas un nouveau stagiaire drop une base de données de production sans demander la permission d'abord. Ton agent IA ne devrait pas pouvoir le faire non plus. Quand un agent a accès à des tools très destructeurs ou sensibles, tu as besoin d'un moyen de l'arrêter, de vérifier son travail et de donner un feu vert manuel. C'est ce que résout la mise en pause de l'exécution : le Human-in-the-Loop et le RunState. Si tu as besoin qu'un humain approuve une action, ton premier réflexe pourrait être de mettre le script Python en pause et d'attendre un input clavier. Ne fais surtout pas ça. Garder un process en vie en attendant une réponse par e-mail ou un clic sur un dashboard gaspille les ressources du serveur. Ça plante aussi complètement si le serveur redémarre ou si tu fais un deploy de nouveau code. Le OpenAI Agents SDK gère ça proprement en permettant au process Python de s'arrêter complètement et de reprendre plus tard sur un serveur complètement différent. Tout commence au niveau de la définition du tool. Quand tu écris une fonction pour ton agent, comme un tool appelé delete production database, tu appliques un flag qui met needs approval à true. Quand l'agent traite un prompt et décide qu'il doit faire ce tool call spécifique, le moteur s'arrête immédiatement. Le tool ne s'exécute pas. À la place, le runner rend le contrôle à ton code applicatif. Voici l'élément clé. Quand l'exécution s'arrête, le runner te donne un objet RunState. Cet objet contient tout le contexte du run jusqu'à cette milliseconde précise. Il connaît l'historique de la conversation, le processus de réflexion interne de l'agent, et le tool call spécifique qu'il veut exécuter ensuite. Tu prends cet objet RunState et tu le sérialises en une string JSON standard. Tu sauvegardes ce payload JSON dans ta base de données, tu le pousses dans une queue, ou tu l'écris sur le disque. Une fois que cet état est stocké en toute sécurité, ton script Python se termine. Ton application est maintenant idle. Des heures, voire des jours, peuvent s'écouler. Finalement, un engineering manager se connecte à un dashboard web, voit la suppression de la base de données en attente, et clique sur approve. Ce clic déclenche une toute nouvelle web request. Ton backend se réveille et lit le payload JSON sauvegardé depuis la base de données. Il désérialise cette string pour recréer un objet RunState valide. Tu lances ensuite une nouvelle exécution du runner. Tu lui passes la même instance de l'agent, le RunState restauré, et la décision de l'humain. Si tu passes une approbation, le runner exécute le tool de suppression de la base de données et l'agent continue de répondre à l'utilisateur. Si le manager a cliqué sur reject, tu passes un rejet à la place. Le runner n'exécute pas le tool. Il renvoie le rejet à l'agent sous forme de tool error, forçant l'agent à adapter son plan ou à dire à l'utilisateur que l'action a été refusée. En sérialisant le RunState, tu transformes un script synchrone en un workflow asynchrone, ce qui permet aux humains et aux agents de collaborer en toute sécurité, peu importe le délai, sans laisser un seul process serveur en plan. Si tu veux aider à faire vivre l'émission, tu peux nous soutenir en cherchant DevStoriesEU sur Patreon. Merci d'avoir passé ce moment avec nous. J'espère que tu as appris quelque chose de nouveau.
13

Injecter des dépendances locales avec RunContextWrapper

4m 00s

Maîtrisez l'injection de dépendances dans vos flux d'agents. Apprenez à transmettre en toute sécurité des états locaux et des connexions de base de données aux outils sans les divulguer au LLM.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 13 sur 18. Comment tu dis à une fonction quel utilisateur est en train de chatter, sans apprendre par erreur au LLM l'ID de base de données privé de l'utilisateur ? Si tu le mets dans le system prompt, tu exposes des données internes et tu gaspilles des tokens. Pour passer un state local sécurisé à tes tools, tu utilises l'injection de dépendances locales avec RunContextWrapper. Une erreur courante quand tu crées des agents, c'est de traiter le modèle de langage comme l'intermédiaire pour tout. Les développeurs essaient souvent d'embarquer des connection strings de base de données, des clés d'API internes ou des ID utilisateurs privés directement dans les instructions système. Ils font ça en espérant que le modèle va gentiment repasser ces credentials sensibles dans les tool calls comme paramètres. C'est un risque de sécurité important. Ça consomme aussi des tokens de context window pour rien et ça augmente le risque que le modèle hallucine des paramètres incorrects. La bonne approche, c'est de bypasser complètement le modèle de langage pour ton state d'exécution local. Le Run Context Wrapper fournit une couche de transport sécurisée pour injecter des dépendances directement dans tes tools et tes lifecycle hooks. L'attribut context attaché à ce wrapper est purement du state Python local. Le modèle ne le voit jamais, ne le lit jamais, et n'a jamais besoin de raisonner dessus. Prends un scénario concret. Un utilisateur authentifié discute avec ton agent de support client et demande à voir ses récents relevés de facturation. Ton système doit récupérer ces relevés, ce qui veut dire que ton tool de facturation a besoin de l'ID de base de données interne de l'utilisateur pour exécuter la query en toute sécurité. D'abord, tu définis ta dépendance locale dans le code de ton application. Tu pourrais créer une data class structurée appelée User Info qui contient l'ID utilisateur interne. Ensuite, tu écris la fonction de ton tool pour récupérer l'historique de facturation. Dans la signature de cette fonction, tu définis un paramètre spécifiquement typé pour accepter l'objet context. Le SDK comprend ce type hint et sait qu'il ne faut pas exposer ce paramètre au modèle de langage. Dans le corps de la fonction, tu accèdes au paramètre context, tu extrais ta dépendance User Info, et tu utilises cet ID utilisateur privé pour requêter ton backend en toute sécurité. Voici le point clé. Quand tu prépares l'exécution du run de l'agent, tu ne passes pas juste le message utilisateur brut. Tu crées une instance du Run Context Wrapper. Tu attaches ta data class User Info peuplée directement au wrapper. Ensuite, tu passes ce wrapper au runner d'exécution. Le flux logique gère le reste automatiquement. Quand l'utilisateur demande son historique de facturation, le modèle de langage décide de déclencher ton tool de facturation. Le modèle fournit uniquement les arguments qu'il connaît depuis la conversation publique, peut-être en filtrant par un mois spécifique ou un numéro de facture. Il n'a absolument aucune idée de qui est l'utilisateur sur ton backend. Avant que la fonction ne s'exécute vraiment, le SDK intercepte l'appel. Il inspecte la signature du tool, remarque que le tool a besoin du context local, et injecte automatiquement le state que tu as attaché au Run Context Wrapper. Le tool s'exécute en utilisant l'ID utilisateur sécurisé, récupère les enregistrements, et retourne les données au modèle pour formuler une réponse. Ce même mécanisme d'injection de dépendances fonctionne pour les execution hooks, ce qui te permet de passer des pools de connexion de base de données actifs ou des tracing IDs dans ton event logging de façon transparente. En séparant le raisonnement externe du modèle de l'exécution interne de ton code, ton infrastructure reste sécurisée et tes prompts restent entièrement concentrés sur le comportement. Garde tes dépendances d'exécution complètement locales, et force ton architecture à reposer entièrement sur le state sécurisé injecté au runtime. Merci de m'avoir écouté, bonne journée tout le monde !
14

L'USB-C pour l'IA : Introduction au MCP

3m 14s

Une introduction au Model Context Protocol (MCP). Découvrez comment ce standard agit comme un connecteur universel pour brancher facilement des agents IA aux plateformes SaaS.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 14 sur 18. Arrête d'écrire des wrappers d'API custom à chaque fois que ton agent doit parler à un nouveau service. Si tu en as marre de mapper manuellement des endpoints REST à des schémas JSON juste pour que ton modèle de langage comprenne ce que fait un service, il existe enfin un standard universel. On va s'intéresser au Model Context Protocol, ou MCP, et à la façon de l'utiliser. Imagine le MCP comme le port USB-C de l'IA. Avant l'USB-C, chaque appareil avait besoin d'un câble de charge propriétaire spécifique. Dans le monde de l'IA, chaque système externe demande du glue code custom. Si tu veux qu'un agent lise une base de données ou crée un ticket de support, tu écris un client REST. Ensuite, tu écris un schéma complexe pour décrire ce client au modèle. Enfin, tu écris la logique pour attraper la réponse du modèle et déclencher la vraie requête HTTP. MCP remplace tout ce travail manuel. C'est un standard ouvert qui dicte exactement comment les tools se décrivent, avec leurs inputs et leurs outputs, directement à un modèle d'IA. On confond souvent MCP avec les API REST standards. Une API REST envoie des données entre les machines, mais elle s'attend à ce que tu saches exactement comment structurer la requête à l'avance. MCP standardise la couche de discovery. Un serveur MCP dit exactement à l'agent quels tools il contient et quels paramètres sont requis, en parlant le format exact dont le modèle a besoin. Dans le SDK OpenAI Agents, tu consommes ces serveurs MCP externes en utilisant une classe appelée Hosted MCP Tool. Voici le point clé. Tu ne redéfinis pas du tout le tool schema dans ton code Python. À la place, tu initialises le Hosted MCP Tool en lui donnant l'URL d'un serveur MCP distant. Cette connexion fonctionne via des Server-Sent Events, ce qui permet au serveur de push des mises à jour vers ton agent de manière sécurisée. Quand tu attaches ce Hosted MCP Tool au setup de ton agent, un handshake se produit. L'agent contacte le serveur distant, demande quels tools sont disponibles, récupère les descriptions complètes et les enregistre automatiquement. Prenons un scénario concret. Tu veux donner à ton agent la capacité de planifier des réunions. Sans MCP, tu devrais étudier l'API Google Calendar. Tu écrirais une fonction Python pour t'authentifier et créer des événements. Ensuite, tu écrirais le tool schema pour que l'agent sache à quoi ressemble un titre d'événement ou un timestamp. Avec MCP, tu déploies à distance un serveur MCP Google Calendar préconfiguré. Dans le code de ton application, tu crées une nouvelle instance de Hosted MCP Tool et tu la pointes vers cette URL distante. Tu passes cette instance unique à ton agent. Le serveur distant dit instantanément à l'agent qu'il a un tool appelé schedule meeting. Quand le modèle de langage décide de planifier cette réunion, le SDK sert de proxy pour l'appel. Il route la requête de manière sécurisée sur le réseau vers le serveur distant, exécute l'action et renvoie le résultat. Tu as écrit zéro ligne de logique d'intégration de calendrier. La vraie puissance de MCP, c'est de découpler la logique core de ton agent des intégrations externes, te permettant de remplacer ou de mettre à jour des services backend juste en changeant une URL. Merci pour ton écoute, et bon code à tous !
15

Connecter des serveurs MCP locaux via Stdio et HTTP

3m 30s

Plongez plus profondément dans le MCP en exécutant des serveurs locaux standards. Apprenez à isoler l'accès au système de fichiers et aux outils internes en toute sécurité avec MCPServerStdio.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 15 sur 18. Donner à un language model un accès direct à ton filesystem local, ça ressemble à un vrai cauchemar de sécurité. Mais si tu sandboxes strictement cet accès via un protocole standardisé, ça devient un moyen sûr et puissant de traiter des données locales. Aujourd'hui, on va voir comment connecter des serveurs MCP locaux via stdio et HTTP. Le Model Context Protocol définit comment tes agents communiquent avec des tools externes et des sources de données. Quand tu veux run ces serveurs dans ta propre infrastructure, le OpenAI Agents SDK fournit deux méthodes de transport locales. La première, c'est le standard input et output, en utilisant la classe qui s'appelle MCPServerStdio. On pense parfois que ça demande un setup réseau local complexe. Pas du tout. Quand tu utilises le transport stdio, le SDK va simplement spawn le serveur MCP comme un child process local. L'agent envoie des requests en écrivant sur le standard input de ce process, et lit les responses depuis son standard output. Imagine un scénario où tu veux que ton agent lise des fichiers, mais uniquement depuis un directory local spécifique. Tu instancies MCPServerStdio et tu lui passes la commande à run. Par exemple, tu pourrais passer la commande du node package manager npx, suivie des arguments pour lancer le serveur filesystem MCP officiel, et le chemin absolu vers ton directory cible. Comme ce serveur run en tant que subprocess, tu dois gérer son lifecycle. Si ton script Python se termine ou plante, tu ne veux pas qu'un process Node orphelin reste en arrière-plan. Le SDK impose une gestion propre du lifecycle en exigeant un context manager asynchrone. Tu définis un bloc async with pour initialiser le serveur stdio. Quand l'exécution entre dans le bloc, le SDK spin up le child process. Quand l'exécution sort du bloc, il tear down proprement le process. À l'intérieur de ce bloc, tu connectes le serveur qui run à ton agent. Tu crées un MCP Client, tu lui passes ton instance de serveur stdio, et ensuite tu fournis ce client à ton agent. L'agent a maintenant un accès scopé et temporaire à ton directory local. Maintenant, que faire si tu veux exposer une API interne privée, ou te connecter à un service qui run déjà ? Tu ne veux pas spawn un nouveau subprocess pour ça. Ça nous amène à la deuxième option de transport, qui est MCPServerStreamableHttp. Au lieu de passer une commande exécutable, tu fournis à cette classe l'URL de ton service existant. C'est parfait pour connecter ton agent en toute sécurité à un microservice interne qui run sur localhost. L'agent communique en streamant des données via HTTP. Voici le point clé. L'agent lui-même n'a aucune idée du transport que tu as choisi. Le code de connexion dans ton application est exactement le même. Tu utilises toujours un context manager, tu crées toujours un MCP client, et tu le passes toujours à l'agent. Le SDK abstrait complètement la transport layer. Ce qu'il faut vraiment retenir ici, c'est que tu peux développer un custom tool sous forme de script stdio local pour les tests, et plus tard le deploy comme un service HTTP autonome en production, sans changer une seule ligne de la logique de ton agent. C'est tout pour cet épisode. Merci pour ton écoute, et continue à build !
16

Visualiser les workflows avec le Tracing intégré

3m 29s

Éliminez le débogage par instructions print en utilisant l'observabilité intégrée du SDK. Découvrez comment les spans et les traces automatiques relient des workflows complexes entiers.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 16 sur 18. Debugger un système multi-agents avec des print statements est un véritable cauchemar. Tu regardes les logs défiler, en essayant de faire correspondre manuellement une tool execution à la ligne cinquante avec une model generation à la ligne deux cents. Heureusement, tu n'auras plus jamais à faire ça. Cet épisode parle de la visualisation des workflows avec le tracing intégré. Quand les développeurs commencent à créer des workflows d'agents complexes, leur premier réflexe est souvent d'écrire des logging wrappers personnalisés. Ils écrivent du boilerplate pour tracker exactement quand un agent démarre, quels arguments un tool reçoit, et combien de temps le modèle met pour répondre. Ne build pas ça. Le SDK Agents s'en charge pour toi, complètement out of the box. À chaque fois que tu exécutes un agent, que tu demandes une génération ou que tu déclenches un tool call, le SDK wrap automatiquement cette action dans un span. Un span est simplement un enregistrement structuré et minuté d'une seule opération. Ces spans capturent les inputs, les outputs et la durée de la tâche. Ils sont automatiquement envoyés au dashboard OpenAI. Ça veut dire que tu obtiens une timeline visuelle complète de l'exécution de ton workflow sans écrire une seule ligne de code de télémétrie. Voici l'idée clé. Même si le SDK gère les détails granulaires, c'est toi qui contrôles le regroupement haut niveau. Disons que tu as un scénario multi-turn où un agent génère une blague, un deuxième agent l'évalue, et le premier agent l'affine en fonction du feedback. Par défaut, le SDK va tracker chacune de ces model generations et de ces tool calls comme des spans distincts. Mais pour un humain qui regarde un dashboard, tout cet aller-retour n'est qu'une seule unité logique de travail. Tu peux regrouper ces actions en utilisant un trace block custom. Tu ouvres un context block avec la fonction trace et tu lui donnes un nom descriptif, comme joke generation loop. À l'intérieur de ce bloc, tu exécutes ta logique d'agent multi-turn. Le SDK respecte cette hiérarchie. Il va imbriquer tous les spans générés automatiquement pour les runs, les évaluations et les affinages individuels sous ta trace parente custom. Quand tu ouvres le dashboard OpenAI, tu vois d'abord la joke generation loop de top-level. Tu peux ensuite l'étendre pour examiner la séquence exacte des model calls et des tool executions qui se sont passés à l'intérieur. Ça couvre la visibilité, mais qu'en est-il de la confidentialité ? Il y a des moments où tu ne dois absolument pas envoyer de télémétrie. Si ton agent manipule des dossiers médicaux sensibles, des données financières, ou nécessite une stricte conformité Zero Data Retention, envoyer des logs d'input et d'output à un dashboard est une violation de sécurité. Pour ces situations, le SDK fournit un context block avec tracing désactivé. Quand tu wrap l'exécution de ton agent à l'intérieur de ce bloc, le SDK arrête complètement de générer et d'envoyer des spans. L'exécution tourne en local, le résultat est renvoyé à ton application, mais aucune trace du prompt, des tool calls ou de la réponse n'apparaîtra sur le dashboard OpenAI. Une fois que le code sort de ce bloc désactivé, le tracing automatique normal reprend pour le reste de ton application. Le tracing dans le SDK signifie que tu arrêtes d'écrire du boilerplate de logging, que tu obtiens un debugging visuel immédiat, et que tu gardes un contrôle total sur le moment où tes données restent entièrement en local. C'est tout pour cet épisode. Merci pour ton écoute, et continue de build !
17

Voix à faible latence avec les Realtime Agents

3m 43s

Brisez le paradigme standard de requête-réponse. Découvrez comment les Realtime Agents maintiennent des connexions WebSocket en direct pour gérer les interruptions et le raisonnement multimodal.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 17 sur 18. Le plus dur quand tu crées une IA vocale, ce n'est pas de générer la parole. C'est de savoir quand se taire instantanément parce que l'appelant humain t'a interrompu au milieu d'une phrase. Si tu te bases sur le cycle request-response traditionnel, la latence du réseau finira toujours par trahir le bot. C'est exactement le problème que résout la Low-Latency Voice avec les Realtime Agents. Beaucoup de développeurs confondent cette architecture avec un pipeline vocal standard. Dans une configuration classique, tu captures l'audio, tu le passes dans un modèle Speech-to-Text, tu envoies ce texte à un language model, et enfin tu pousses l'output texte dans un synthétiseur Text-to-Speech. Ce pipeline introduit de la latence à chaque étape. Les Realtime Agents abandonnent complètement ce pipeline. Ils utilisent un seul modèle multimodal qui raisonne nativement sur l'audio. L'audio entre directement, et ressort directement en stream. Aucune traduction intermédiaire en texte n'est requise pour que le système comprenne l'utilisateur. Pour y arriver, tu dois casser le paradigme standard request-response HTTP. Au lieu d'envoyer un payload et d'attendre une réponse complète, le système garde une connexion persistante ouverte. Dans le SDK, tu gères ça avec deux composants principaux. Le premier, c'est le RealtimeAgent. Cet objet contient tes system instructions et toutes les fonctions ou tools auxquels le modèle doit avoir accès. Il définit la logique, les capacités et la personnalité de ton assistant. Le deuxième composant, c'est le RealtimeRunner. Le runner est le moteur d'exécution. Il gère l'event loop asynchrone et s'occupe du stream réseau persistant, généralement via une connexion WebSocket ou WebRTC. Prends l'exemple d'un bot de service client téléphonique qui gère un appel entrant. Tu fais le pont avec ton voice provider, peut-être en l'intégrant via SIP ou WebSockets, et tu routes l'audio en continu vers ton application Python. Tu crées ton RealtimeAgent, en l'équipant d'un tool pour récupérer les comptes utilisateurs. Ensuite, tu passes cet agent et ton client de connexion réseau au RealtimeRunner. Quand tu appelles la méthode run sur le runner, il prend le relais. Il garde la connexion ouverte, en écoutant constamment le stream audio, tout en gérant simultanément les function calls que l'agent doit faire. Il push et pull des events dans les deux sens en même temps. L'utilisateur appelle et demande le solde de son compte. L'agent déclenche le tool pour récupérer le compte, récupère les données, et commence immédiatement à streamer sa réponse vocale à l'appelant. Au milieu de la phrase, l'utilisateur parle soudainement par-dessus le bot, en disant qu'il veut en fait signaler une carte perdue. Voici le point clé. Parce que la connexion WebSocket reste ouverte en permanence et que le modèle ingère nativement le stream audio entrant en temps réel, le serveur détecte la voix humaine instantanément. Il déclenche un event qui coupe son propre output audio et enregistre la truncation. Tu n'as pas besoin d'écrire une logique custom pour calculer exactement quel chunk audio était en train d'être lu quand l'utilisateur a parlé. L'architecture de streaming gère l'interruption de manière transparente. Le modèle absorbe le nouveau contexte audio de l'interruption et commence immédiatement à streamer la réponse mise à jour sur l'annulation de la carte perdue. Tu obtiens une dynamique conversationnelle naturelle uniquement parce que la couche réseau et la couche modèle sont construites pour le streaming continu. La vraie puissance de la Realtime API dans le Agents SDK, c'est de traiter la voix comme un stream continu de premier plan, plutôt que comme un batch de texte traduit déguisé. C'est tout pour cet épisode. Merci d'avoir écouté, et continue à développer !
18

Créer des interfaces utilisateur réactives avec les Streaming Events

3m 34s

Allez au-delà du streaming de tokens de texte. Utilisez les Semantic Streaming Events pour créer des interfaces frontend ultra-réactives qui réagissent aux actions de l'agent en temps réel.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. OpenAI Agents SDK, épisode 18 sur 18. Tes utilisateurs ne veulent pas juste lire du texte qui s'affiche à l'écran. Ils veulent voir exactement ce que fait l'IA en coulisses. Si tu essaies de créer un loading spinner en parsant des chunks de tokens bruts pour deviner quand un search tool tourne, tu te compliques la vie. Créer des UIs réactives avec des streaming events résout exactement ce problème. Les développeurs traitent souvent les outputs de l'IA comme une simple machine à écrire. Ils écoutent un stream de texte brut et écrivent une logique de parsing fragile pour savoir si l'agent est sur le point de faire un function call. Cette approche est fragile. Elle casse si le modèle change légèrement sa formulation, et elle laisse ton frontend à la traîne par rapport à l'état d'exécution réel. Le OpenAI Agents SDK offre une alternative structurelle. Au lieu d'attendre des strings, tu déclenches ton agent avec une méthode appelée run streamed sur ton runner. Cette méthode ne renvoie pas du texte brut. À la place, elle renvoie une séquence asynchrone d'événements sémantiques, chacun encapsulé dans un objet Run Item Stream Event. Vois un Run Item Stream Event comme une notification précise sur le lifecycle interne de l'agent. Pendant que l'agent traite une requête, il émet des signaux distincts et prévisibles. Il te dit exactement quand un nouveau message est ajouté au thread. Il te dit quand le contrôle passe d'un agent de triage à un agent spécialisé. Point crucial pour le développement frontend, il t'indique la milliseconde exacte où un tool call commence et se termine. Appliquons ça à un scénario concret. Tu veux que ton frontend affiche un spinner qui dit Recherche dans la base de données pendant que l'agent cherche une fiche client. Tu appelles run streamed et tu boucles sur les résultats. Dans cette boucle asynchrone, tu inspectes chaque événement quand il arrive. Quand un événement arrive sur le réseau, tu vérifies ses propriétés pour voir quel genre d'update il représente. Quand un événement indique qu'un tool call a commencé, tu peux lire le nom exact du tool directement depuis le payload de l'événement. Tu n'as pas besoin de parser du langage naturel. Si le nom du tool correspond à ta fonction de recherche dans la base de données, tu pousses immédiatement un state update vers ton frontend pour afficher le spinner. Quand un événement suivant signale que l'exécution du tool est terminée, tu dispatches un autre update pour cacher le spinner. Ces stream events transportent aussi des message deltas standards. Si l'agent génère une longue réponse textuelle, le stream émet des chunk events que tu ajoutes à l'UI. L'architecture sépare l'output conversationnel brut des actions sémantiques. Tu routes les chunks de texte vers la fenêtre de chat, et tu routes les événements de lifecycle du tool et de l'agent vers ton UI state manager. Cette séparation des responsabilités te permet de créer des interfaces qui semblent instantanément réactives et profondément connectées à la logique de l'agent. Tu réagis au chemin d'exécution réel du système, au lieu de deviner ses intentions en te basant sur des mots. Voici l'idée clé. Arrête de traiter l'output de ton agent comme un simple stream de conversation. Traite-le comme une state machine event-driven où chaque action interne est une opportunité de garder ton utilisateur visuellement informé. Puisque c'est le dernier épisode de la série, je t'encourage à lire la documentation officielle et à essayer d'orchestrer ces streams toi-même. Si tu as des idées de ce qu'on devrait couvrir dans une future série, visite devstories dot eu et fais-le-nous savoir. C'est tout pour aujourd'hui. À la prochaine !