Volver al catálogo
Season 6 18 Episodios 1h 13m 2026

OpenAI Agents SDK

v0.13 — Edición 2026. Una guía exhaustiva para construir sistemas multiagente listos para producción con el OpenAI Agents SDK para Python (v0.13 - 2026). Aprende las primitivas fundamentales, patrones de orquestación, tools, handoffs, guardrails, gestión del estado, MCP e integración de voz en tiempo real.

Frameworks de AI/ML Sistemas multiagente
OpenAI Agents SDK
Reproduciendo ahora
Click play to start
0:00
0:00
1
Más allá de Swarm: Las primitivas fundamentales
Descubre los conceptos fundamentales del OpenAI Agents SDK. Este episodio cubre por qué existe el SDK, cómo mejora a Swarm y los principios de diseño principales que priorizan las abstracciones mínimas.
4m 00s
2
Definiendo el Agent y el Run Loop
Aprende a configurar el objeto fundamental Agent. Exploramos las instrucciones, la configuración del modelo y cómo forzar la salida de datos estructurados sin problemas.
3m 26s
3
Equipando Agents con Python Function Tools
Capacita a tus agentes para que pasen a la acción convirtiendo funciones estándar de Python en herramientas ejecutables. Comprende la generación automática de esquemas y la inferencia de tipos.
3m 27s
4
Escalando superficies de herramientas con Hosted Tool Search
Aprende a gestionar bibliotecas de herramientas masivas sin agotar tu presupuesto de tokens. Cubrimos la carga diferida, los namespaces y la ejecución de herramientas alojadas (hosted tools).
4m 08s
5
Delegación descentralizada: El patrón Handoff
Domina el arte de la orquestación multiagente utilizando el patrón Handoff. Descubre cómo crear agentes de triaje que delegan el control total a subagentes especializados sin interrupciones.
3m 38s
6
Orquestación centralizada: Agents as Tools
Mantén el control de la conversación en un solo lugar utilizando el patrón Agents as Tools. Hablamos sobre cómo un agente gestor puede sintetizar las respuestas de múltiples subagentes especialistas.
4m 00s
7
Moldeando el contexto con Handoff Inputs y Filters
Optimiza el uso de tokens en sistemas multiagente modificando los historiales de conversación entre handoffs. Aprende a inyectar metadatos y a aplicar filtros de transcripción.
4m 30s
8
Controlando el estado: to_input_list y Server IDs
Una inmersión profunda en la gestión manual de conversaciones. Comprende los métodos de más bajo nivel para preservar el contexto entre turnos y utilizar los Server IDs de las respuestas.
4m 41s
9
Automatizando la memoria con Sessions integradas
Simplifica tus bucles de chat con el sistema de memoria integrado del SDK. Exploramos SQLiteSession, OpenAIConversationsSession y la persistencia automatizada.
4m 13s
10
Protegiendo flujos de trabajo: Input y Output Guardrails
Asegura tus pipelines de IA interceptando inputs maliciosos antes de que lleguen a modelos costosos. Cubrimos los guardrails a nivel de agente y la ejecución en paralelo frente a la bloqueante.
3m 43s
11
Validando acciones: Tool-Level Guardrails
Evita fugas de datos críticos a nivel de función. Aprende a envolver herramientas específicas con input y output guardrails precisos.
4m 27s
12
Pausando la ejecución: Human-in-the-Loop y RunState
Implementa salvaguardas para acciones irreversibles forzando aprobaciones Human-in-the-Loop. Exploramos el pipeline de serialización de RunState para pausar y reanudar cargas de trabajo.
3m 47s
13
Inyectando dependencias locales con RunContextWrapper
Domina la inyección de dependencias en los flujos de tus agentes. Aprende a pasar de forma segura estados locales y conexiones de bases de datos a las herramientas sin filtrarlos al LLM.
4m 28s
14
El USB-C de la IA: Introducción a MCP
Una introducción al Model Context Protocol (MCP). Descubre cómo este estándar actúa como un conector universal para conectar fácilmente agentes de IA a plataformas SaaS.
4m 00s
15
Conectando servidores MCP locales a través de Stdio y HTTP
Profundiza en MCP ejecutando servidores locales estándar. Aprende a aislar el acceso al sistema de archivos y a las herramientas internas de forma segura con MCPServerStdio.
3m 55s
16
Visualizando flujos de trabajo con Tracing integrado
Elimina la depuración con sentencias print utilizando la observabilidad integrada del SDK. Descubre cómo los spans y traces automáticos enlazan flujos de trabajo complejos en su totalidad.
4m 11s
17
Voz de baja latencia con Realtime Agents
Rompe el paradigma estándar de petición-respuesta. Mira cómo los Realtime Agents mantienen conexiones WebSocket en vivo para gestionar interrupciones y razonamiento multimodal.
4m 32s
18
Construyendo interfaces reactivas con Streaming Events
Ve más allá del streaming de tokens de texto. Utiliza Semantic Streaming Events para construir interfaces frontend ultrarreactivas que reaccionan a las acciones del agente en tiempo real.
4m 28s

Episodios

1

Más allá de Swarm: Las primitivas fundamentales

4m 00s

Descubre los conceptos fundamentales del OpenAI Agents SDK. Este episodio cubre por qué existe el SDK, cómo mejora a Swarm y los principios de diseño principales que priorizan las abstracciones mínimas.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 1 de 18. La mayoría de los frameworks para agentes de IA te obligan a aprender una docena de abstracciones nuevas, sintaxis personalizada y jerarquías de objetos complejas. Pasas más tiempo peleándote con el framework que escribiendo la lógica real de tu aplicación. Hoy vemos Beyond Swarm: The Core Primitives. Cuando los desarrolladores oyen hablar de un nuevo framework para agentes, suelen esperar un ecosistema enorme con una curva de aprendizaje pronunciada. El OpenAI Agents SDK es justo lo contrario. Es una evolución de la librería experimental Swarm. Swarm demostró que podías crear interacciones complejas con conceptos muy simples. El Agents SDK toma esa filosofía y la prepara para producción. Es deliberadamente ligero y es totalmente Python-first. La arquitectura se basa en dos principios de diseño fundamentales: exponer muy pocas primitivas core y mantener la ejecución altamente personalizable. No necesitas un grafo complejo de nodos ni un lenguaje declarativo propietario para crear un agente aquí. El SDK te da un conjunto muy pequeño de bloques de construcción. La pieza fundamental es el objeto Agent. Defines un Agent dándole un nombre y un conjunto de instrucciones. Si quieres crear un tutor de historia sencillo, instancias un Agent, lo llamas HistoryTutor y le pasas un string de texto con las instrucciones para que enseñe eventos históricos de forma clara y precisa. Esa es toda la configuración de tu agente. No hay estado oculto ni una inicialización compleja. Pero un agente por sí solo es solo una estructura de datos estática. No hace nada hasta que se ejecuta. Aquí es donde la cosa se pone interesante. La ejecución la gestiona por completo un componente independiente llamado Runner. El Runner gestiona el loop de interacción completo entre tu código local y la API remota de OpenAI. En una aplicación típica, tendrías que escribir un while-loop a medida para comprobar si el modelo quiere hacer un tool call, parsear la respuesta, ejecutar el tool y devolver el resultado. El Runner abstrae todo eso. Para iniciar el proceso, le pasas tu agente HistoryTutor y el prompt del usuario al método run. El Runner toma el control a partir de ahí. Envía el prompt al modelo. Si el modelo decide que necesita buscar una fecha histórica específica, solicitará un tool call. El Runner se pausa, ejecuta la función local de Python que le pasaste para ese tool, captura el valor de retorno y se lo envía de vuelta al modelo. Repite este ciclo automáticamente. Solo devuelve el control a tu aplicación cuando el modelo determina que la tarea ha finalizado y genera una respuesta de texto final. Esta estricta separación entre la definición estática del Agent y la ejecución activa del Runner es lo que hace que el SDK sea tan personalizable. Como los tools son simplemente funciones estándar de Python con type hints normales, y el agente es un objeto simple, mantienes un control total sobre el flujo de tu aplicación. Puedes inyectar fácilmente logging personalizado, métricas o manejo de errores alrededor del Runner sin sobrescribir clases profundas del framework. Simplemente estás escribiendo Python. El verdadero valor de este SDK no está en lo que añade, sino en lo que quita: se aparta de tu camino y te permite orquestar modelos de lenguaje usando código plano y legible. Si quieres apoyar el programa, puedes buscar DevStoriesEU en Patreon. Eso es todo por este episodio. ¡Nos vemos en el próximo!
2

Definiendo el Agent y el Run Loop

3m 26s

Aprende a configurar el objeto fundamental Agent. Exploramos las instrucciones, la configuración del modelo y cómo forzar la salida de datos estructurados sin problemas.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 2 de 18. ¿Qué pasaría si pudieras obligar a tu modelo de lenguaje a responder siempre con una estructura de datos perfectamente parseada sin escribir ni una sola línea de regex compleja? Hoy veremos cómo definir el Agent y el Run Loop, que es exactamente cómo consigues ese control tan estricto. Un punto de confusión muy común al empezar con este SDK es pensar que un agent es un proceso activo en ejecución. No lo es. En esta arquitectura, el objeto Agent es estrictamente un contenedor de configuración. Envuelve un modelo de lenguaje específico en un contexto predefinido. No se ejecuta por sí mismo ni mantiene ningún estado propio. Simplemente estás construyendo un blueprint. Para definir este blueprint, instancias un Agent. Empiezas por el parámetro instructions. Este es tu system prompt principal, donde defines la persona, los límites y las reglas específicas que el modelo debe seguir. A continuación, proporcionas los model settings. Esto dicta qué modelo subyacente utilizar y configura los detalles estándar de inferencia. En esta etapa, tu agent está completamente definido, pero totalmente inactivo en memoria. Aquí es donde la cosa se pone interesante. Puedes restringir físicamente la forma de la respuesta del agent usando el parámetro output type. Imagina que estás creando una tool para extraer eventos de calendario de hilos de email desordenados. En lugar de escribir instrucciones suplicándole al modelo que formatee las fechas correctamente, defines una estructura de datos concreta en tu código. Defines una clase Calendar Event con campos estrictos para un título, una hora de inicio y una ubicación. Pasas esta clase al parámetro output type de tu Agent. Al configurarlo de esta manera, la API fuerza el schema. El agent no puede devolver una respuesta de texto conversacional. Solo devolverá un objeto Calendar Event validado que el código de tu aplicación puede consumir inmediatamente. Ahora tienes un blueprint de agent estricto y bien configurado. Para que haga el trabajo real, necesitas el Run Loop. Como el agent es solo una definición estática, la ejecución la gestiona completamente un componente Runner independiente. El Runner es el motor. Le pasas la definición de tu agent y el input del usuario al Runner, y este toma el control de la ejecución. Cuando activas el Runner, este entra en un loop de ejecución. Empaqueta las instructions de tu agent, el output schema estricto y el prompt del usuario, y luego los envía al modelo. El Run Loop se encarga de gestionar toda la orquestación de idas y venidas. Si el modelo decide que necesita llamar a una tool externa para obtener datos que faltan, el Runner intercepta esa petición, ejecuta el código local de la tool y le devuelve el resultado al modelo. Gestiona todos estos pasos intermedios automáticamente. El loop solo termina cuando el modelo resuelve el prompt y produce el output final que coincide exactamente con tu output type de calendario. Mantener la configuración estática del agent completamente separada del Run Loop activo es lo que te permite reutilizar de forma segura ese mismo agent de extracción de calendario en miles de ejecuciones simultáneas sin que se mezclen los datos. Gracias por escuchar, ¡happy coding a todos!
3

Equipando Agents con Python Function Tools

3m 27s

Capacita a tus agentes para que pasen a la acción convirtiendo funciones estándar de Python en herramientas ejecutables. Comprende la generación automática de esquemas y la inferencia de tipos.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 3 de 18. Escribir JSON schemas para tools de modelos de lenguaje a mano es tedioso y frágil. Un corchete que falta o un tipo incorrecto, y el modelo no entiende cómo interactuar con tu sistema. En lugar de escribir estas definiciones manualmente, puedes usar Python estándar y dejar que el framework se encargue de la traducción. Esto es exactamente lo que cubrimos hoy: Equipar a los agentes con Python Function Tools. Un error común es pensar que exponer la lógica local a un agente requiere mantener dos fuentes de la verdad. La gente asume que necesita su código Python real, además de un archivo de configuración JSON complejo y separado que describa ese código al modelo de lenguaje. Con el Agents SDK, evitas por completo la escritura manual de JSON. Simplemente escribes una función Python estándar y colocas el decorador de function tool justo encima. Al aplicar ese decorador, el SDK se pone a trabajar por debajo utilizando el módulo inspect integrado de Python y Pydantic. Analiza la firma de tu función. Lee los nombres de los parámetros, extrae los type hints y obtiene el docstring de la función. A partir de esos elementos, genera automáticamente un JSON schema estricto y lo adjunta al agente. Veamos un escenario concreto. Quieres darle a tu agente una función llamada fetch weather. Esta función necesita datos geográficos precisos para funcionar. En lugar de dejar que el modelo adivine qué formato de string usar, tú defines una estructura específica. Creas un tipo personalizado, tal vez un Typed Dictionary llamado Location, que contiene campos de string distintos para la ciudad y el país. Luego, utilizas este tipo Location como el type hint estricto para el parámetro de entrada en tu función fetch weather. Aquí está la clave. Debes añadir un docstring claro a esta función. Podrías escribir una frase sencilla indicando que esta tool obtiene las condiciones meteorológicas actuales para una ciudad y un país específicos. El framework extrae este texto y lo utiliza como la descripción principal de la tool en el prompt. Tu docstring ya no es solo una nota útil para tus compañeros desarrolladores. Es el manual de instrucciones literal que el agente evalúa para decidir si debe ejecutar la tool. Si un usuario pregunta si necesita una chaqueta en Tokio, el agente revisa las tools disponibles. Lee tu docstring, se da cuenta de que la función fetch weather proporciona la respuesta, y estructura una request. Como has usado type hints en la entrada con tu diccionario Location, Pydantic garantiza que el output del agente coincida exactamente con los campos requeridos incluso antes de que se ejecute tu lógica de Python. Si el modelo intenta pasar un solo string de texto en lugar del diccionario, el framework detecta el error y obliga al agente a intentarlo de nuevo con la estructura correcta. El SDK ejecuta la función localmente, captura el valor de retorno y reintroduce el resultado directamente en el bucle de razonamiento del agente. Tus type hints y docstrings estándar de Python ya no son documentación pasiva; forman el contrato de API activo y vinculante en el que se basa tu agente para interactuar con el mundo real. Gracias por pasar unos minutos conmigo. Hasta la próxima, que te vaya bien.
4

Escalando superficies de herramientas con Hosted Tool Search

4m 08s

Aprende a gestionar bibliotecas de herramientas masivas sin agotar tu presupuesto de tokens. Cubrimos la carga diferida, los namespaces y la ejecución de herramientas alojadas (hosted tools).

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 4 de 18. Pasarle cien tools a un modelo de lenguaje destroza el rendimiento y agota tu presupuesto de tokens antes de ejecutar una sola acción. No puedes meter cada schema de una API empresarial en la context window inicial y esperar un buen razonamiento. La solución a esto es escalar las tool surfaces con Hosted Tool Search. Antes de ver cómo escalar, tenemos que definir qué son las hosted tools. Las hosted tools se ejecutan de forma nativa en la infraestructura de OpenAI en lugar de correr en tu máquina local. Algunos ejemplos integrados son la Web Search Tool y la File Search Tool. No tienes que escribir la lógica de ejecución, gestionar el web crawler ni montar el mecanismo de file chunking para ellas. Simplemente se las acoplas a tu agente y el backend de OpenAI se encarga del trabajo real. Pero el concepto de hosted tools se extiende a cómo el modelo descubre tus propias custom tools cuando tienes demasiadas. Imagina un agente de CRM. Podrías tener cincuenta tools distintas para comprobar el estado de los pedidos, sacar el historial de facturación, actualizar direcciones de envío y recuperar logs de soporte. Si le pasas los cincuenta schemas de golpe, saturas el modelo y desperdicias input tokens. Muchos developers creen que tienen que solucionar esto montando un paso de retrieval en el client-side. Asumen que deben interceptar el prompt del usuario, buscar en una base de datos vectorial local los schemas de las tools relevantes, e inyectarlos dinámicamente en el prompt antes de llamar al modelo de lenguaje. No hace falta que hagas eso. El Hosted Tool Search ocurre de forma nativa en los servidores de OpenAI usando la Responses API. El propio modelo es capaz de buscar en la tool surface disponible sin que tu código cliente actúe de intermediario. Esto lo consigues usando dos parámetros: tool namespace y defer loading. Cuando registras tus tools de CRM, agrupas las funciones relacionadas asignándolas a un namespace compartido. Por ejemplo, podrías meter todas tus tools de perfil de cliente en un namespace llamado customer account. Luego, pones el parámetro defer loading a true para esas tools. Esta es la parte que importa. Cuando defer loading está activo, el agente no envía los schemas individuales de las tools al modelo de lenguaje al inicio de la conversación. En su lugar, envía un único schema ligero que representa al propio namespace de customer account. El modelo es consciente de que este namespace existe y sabe cómo consultarlo si lo necesita. Cuando el usuario pide buscar un ID de cliente específico, el modelo se da cuenta de que necesita más información. Ejecuta una búsqueda de forma nativa contra el namespace de customer account. Los servidores de OpenAI encuentran la tool de facturación o soporte relevante, cargan solo el schema de esa tool específica en el context del modelo, y entonces el modelo ejecuta la tool call. Esto desacopla por completo el tamaño de tu librería de tools de tu coste inicial de tokens. Podrías acoplar cientos de tools a un solo agente, y el prompt inicial seguiría siendo minúsculo. El modelo solo incurre en el coste de tokens por los schemas de tools específicos que decide traerse activamente en runtime. Al hacer el defer loading, estás cambiando una enorme carga de contexto estático por un mecanismo de retrieval dinámico y preciso. Eso es todo por este episodio. ¡Nos vemos en el próximo!
5

Delegación descentralizada: El patrón Handoff

3m 38s

Domina el arte de la orquestación multiagente utilizando el patrón Handoff. Descubre cómo crear agentes de triaje que delegan el control total a subagentes especializados sin interrupciones.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 5 de 18. A veces, la mejor manera de que un gestor maneje una tarea compleja es apartarse por completo. Si tu agente de routing principal intenta mediar en cada interacción entre un usuario y tus sistemas backend, tus prompts se inflan y tu ejecución se vuelve poco fiable. Esto es precisamente lo que la delegación descentralizada, y en concreto el Handoff Pattern, está diseñada para solucionar. Un handoff es un mecanismo mediante el cual un agente transfiere el control total de la conversación a otro agente. Un error común es confundir un handoff con el tool calling estándar. Son fundamentalmente diferentes. Cuando un agente llama a una función normal, se pausa, espera a que retornen los datos y luego formula una respuesta para el usuario. Cuando un agente activa un handoff, cede todo el turno de la conversación. El control pasa completamente al nuevo agente. El agente original se aparta por completo. Esto importa porque mantiene tu arquitectura descentralizada. Si un agente de triaje central tiene que procesar el output de cada acción del especialista, su system prompt debe ser enorme. Necesita instrucciones sobre cómo explicar las políticas de reembolso, hacer troubleshooting técnico y eliminar cuentas. Peor aún, el agente de triaje intentará inevitablemente narrarle el trabajo del especialista al usuario. Esto desperdicia tokens, añade latencia e introduce un alto riesgo de alucinación. Los handoffs evitan esto al permitir que el especialista hable directamente con el usuario. Imagina un sistema de atención al cliente. Haces deploy de un agente de triaje general para saludar a los usuarios y categorizar las peticiones. Un cliente escribe pidiendo que se procese un reembolso. También tienes un agente de reembolsos dedicado, que está equipado con tools de facturación específicas e instrucciones estrictas sobre la política de devoluciones de la empresa. Para conectarlos usando el SDK, escribes una función estándar llamada transfer to refund. Pero en lugar de devolver un string o datos en JSON, esta función devuelve tu objeto Agent de reembolsos. Luego, le pasas esta función de transferencia a tu agente de triaje, listándola como cualquier otra tool. Cuando el cliente pide un reembolso, el agente de triaje decide llamar a la función de transferencia. Aquí está la clave. El runner loop subyacente del SDK ejecuta la función y ve que se ha devuelto un objeto Agent en lugar de datos estándar. El runner cambia instantáneamente el agente activo en su memoria. Coge el historial de conversación existente y se lo pasa directamente al agente de reembolsos recién activado. El agente de reembolsos asume el turno activo, procesa la petición del usuario, lanza sus propias tools de facturación y le responde directamente al usuario. También puedes pasar datos durante esta transición. Si el agente de triaje ya le ha pedido al usuario su número de pedido, puede pasar ese número de pedido como argumento a la función de transferencia. La función puede entonces inyectar ese número de pedido en las context variables del nuevo agente antes de devolverlo. El agente de reembolsos se despierta sabiendo ya exactamente qué transacción buscar. Al usar handoffs, mantienes a cada agente pequeño, enfocado y predecible, dejando que la conversación fluya de forma natural de un experto especializado a otro. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
6

Orquestación centralizada: Agents as Tools

4m 00s

Mantén el control de la conversación en un solo lugar utilizando el patrón Agents as Tools. Hablamos sobre cómo un agente gestor puede sintetizar las respuestas de múltiples subagentes especialistas.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 6 de 18. Si tu asistente de IA necesita consultar a tres departamentos diferentes antes de responder a un usuario, rara vez vas a querer que el usuario hable directamente con esos departamentos. Quieres que una única voz coherente gestione la conversación, obteniendo la información de forma silenciosa en segundo plano. Eso es exactamente lo que te permite hacer la orquestación centralizada usando agentes como tools. Puede que confundas esto con los handoffs, donde un agente pasa permanentemente el usuario a otro agente. Con los handoffs, el nuevo agente toma el control total de la conversación. Con la orquestación centralizada, el control nunca se pasa. El agente principal, que suele actuar como manager, mantiene el control absoluto de la conversación. El manager es la única voz que el usuario llega a escuchar. Esto lo consigues cogiendo un agente completamente configurado y convirtiéndolo en una función invocable. Cada objeto agente en el SDK tiene un método llamado as_tool. Cuando llamas a este método, envuelve a todo el agente, incluyendo sus instrucciones específicas y sus propias tools, en un formato de tool estándar. Luego, le pasas este agente envuelto a tu agente manager, exactamente igual que le pasarías una función estándar de Python. Veamos un caso práctico. Estás montando un portal de atención al cliente. Creas un agente especialista en reservas. Su único trabajo es consultar sistemas internos, cruzar fechas y devolver la disponibilidad. Este agente es muy técnico. Sus instrucciones están optimizadas para la precisión de la base de datos, no para tener una conversación educada. No quieres que el usuario interactúe con este especialista. Así que llamas al método as_tool en el especialista de reservas. A continuación, creas tu agente manager. Le das al manager instrucciones estrictas de mantener un tono educado y corporativo, y de gestionar la relación con el usuario. Luego, añades el especialista de reservas envuelto a la lista de tools del manager. Cuando un usuario le pide al manager que compruebe la disponibilidad para el próximo martes, el manager procesa la petición. Reconoce que le faltan los datos reales, pero sabe que tiene una tool que puede encontrarlos. El manager invoca la tool de reservas. Aquí está la clave. Cuando se invoca esa tool, el agente especialista de reservas se despierta, ejecuta sus propios pasos internos aislados y produce una respuesta. Pero no le envía esa respuesta al usuario. Devuelve un resultado en crudo y objetivo directamente al manager. El manager recibe estos datos, los sintetiza, los envuelve en un saludo corporativo educado y, finalmente, le responde al usuario. Este patrón hub-and-spoke resuelve un gran problema en las aplicaciones complejas: el context bloat. El agente manager no necesita conocer el esquema de la base de datos ni las reglas para comprobar las fechas. Mantiene su system prompt limpio, centrándose por completo en enrutar peticiones y formatear respuestas. Mientras tanto, el agente especialista no necesita preocuparse por el historial de la conversación ni por la voz de la marca. Simplemente hace su trabajo específico y devuelve un resultado. Al decidir entre un handoff y una tool, pregúntate quién es el dueño de la respuesta final. Si el agente especializado necesita entrar en un diálogo prolongado de ida y vuelta con el usuario, lo que quieres es un handoff. Pero si el agente especializado es solo un procesador de datos sofisticado que proporciona una respuesta para que la use el asistente principal, envuélvelo como una tool y deja que el manager sea el dueño de la relación. Gracias por pasar unos minutos conmigo. Hasta la próxima, cuídate.
7

Moldeando el contexto con Handoff Inputs y Filters

4m 30s

Optimiza el uso de tokens en sistemas multiagente modificando los historiales de conversación entre handoffs. Aprende a inyectar metadatos y a aplicar filtros de transcripción.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 7 de 18. Cuando transfieres un cliente a un especialista humano, no le obligas a leer una transcripción raw masiva de cada comprobación automatizada del sistema que acaba de ocurrir. Le das una razón clara para la transferencia y un resumen limpio del problema. Sin embargo, cuando los desarrolladores conectan agentes de IA, a menudo vuelcan todo el chat log raw en la context window del siguiente agente. Hoy, solucionamos eso moldeando el contexto con handoff inputs y filters. Cuando un agente cede el control a otro, necesita una forma de comunicar por qué está ocurriendo el handoff. Esto lo haces usando el parámetro input type en tu rutina de handoff. Defines un schema, normalmente un modelo Pydantic, que especifica exactamente qué información requiere el agente receptor. Cuando el agente actual decide ejecutar el handoff, el modelo de lenguaje subyacente genera un payload que coincide con este schema. Aclaremos una confusión común ahora mismo. Es fácil confundir este input type con el state persistente de la aplicación, como un ID de perfil de usuario o una conexión a la base de datos del backend que vive durante toda la sesión. No lo es. El input type es estrictamente para metadatos transitorios generados por el modelo, creados exactamente en el momento del handoff. Por ejemplo, si un agente de triaje pasa un usuario a un especialista de facturación, el input type podría requerir un campo llamado escalation reason. El agente de triaje genera un string corto explicando el error de facturación específico, y el agente de facturación recibe esos datos estructurados inmediatamente al despertarse. Eso cubre el mensaje explícito de handoff. Ahora, debemos gestionar el historial de la conversación. Por defecto, todo el historial de mensajes viaja con el handoff. Cada prompt del usuario, cada respuesta del asistente y cada tool call en segundo plano se pasa al siguiente. Esto quema tokens rápidamente y llena la context window con ruido irrelevante. Controlas esto usando un input filter. Un input filter es una función estándar de Python que intercepta el historial de la conversación justo antes de que el agente receptor lo lea. Toma la lista completa de mensajes anteriores como argumento, los procesa y devuelve una nueva lista de mensajes modificada. Imagina un escenario donde tu agente inicial pasó diez turnos llamando a varias search tools y APIs de bases de datos intentando resolver un problema, antes de finalmente rendirse y enrutar al usuario a un agente general de FAQ. El agente de FAQ solo necesita las preguntas reales del usuario. No necesita para nada los outputs en raw JSON de diez tool calls fallidas. Para solucionar esto, escribes una función de input filter. Dentro de ella, iteras sobre la lista de mensajes entrantes. Compruebas el role de cada mensaje. Si el mensaje es una tool execution o un raw tool result, lo descartas. Si es un mensaje directo del usuario o una respuesta final del asistente, lo añades a tu nueva lista. Luego devuelves esta lista limpia y adjuntas tu función de filter a la definición del handoff. El agente de FAQ ahora recibe un historial optimizado que contiene solo el intercambio de mensajes legible por humanos. Aquí está la clave. Los handoff inputs añaden inteligencia estructurada a la transición, mientras que los input filters cortan el ruido de forma implacable. Juntos, dan forma exactamente a lo que sabe el agente receptor. Ahorras tokens, reduces la latencia y evitas que el nuevo agente alucine basándose en el razonamiento descartado del agente anterior. Controlar el contexto en el límite del handoff es la forma más efectiva de mantener un sistema multiagente rápido y preciso. Si quieres ayudar a que el programa siga adelante, puedes buscar DevStoriesEU en Patreon; tu apoyo significa mucho. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue construyendo!
8

Controlando el estado: to_input_list y Server IDs

4m 41s

Una inmersión profunda en la gestión manual de conversaciones. Comprende los métodos de más bajo nivel para preservar el contexto entre turnos y utilizar los Server IDs de las respuestas.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 8 de 18. Un agente de IA con amnesia es inútil. Pero almacenar su memoria incorrectamente puede duplicar silenciosamente el historial de la conversación y duplicar los costes de tu API. Esto pasa cuando, por accidente, mezclas diferentes métodos para gestionar el historial del chat. Hoy vamos a ver cómo controlar el state: to_input_list y Server IDs. Por defecto, una ejecución básica de un agente es completamente stateless. Envías un string, recibes un string. Si le haces una pregunta de seguimiento, el agente no tiene contexto de lo que acabas de hablar. Tienes que pasarle el historial tú mismo. Aunque el SDK ofrece wrappers de sesión de alto nivel, a veces necesitas la forma de más bajo nivel y más transparente para mantener el historial del chat a lo largo de varios turnos, sin ningún state oculto por arte de magia. Hay dos formas explícitas de gestionar esto. El primer método mantiene la fuente de la verdad en tu máquina usando un método llamado to_input_list. Cuando un agente termina una ejecución, devuelve un objeto result. Este objeto contiene la respuesta final, pero también los pasos ocultos que dio el agente para llegar hasta ahí. Si el agente hizo un tool call a una base de datos, leyó el output y luego formuló una respuesta, todos esos pasos intermedios son parte del state de la conversación. Llamar a to_input_list en el objeto result empaqueta toda esa secuencia. Devuelve un array plano que contiene el prompt original del usuario, las respuestas del agente, los tool calls específicos y los tool outputs. Formatea todo esto exactamente como la API espera recibirlo. Si estás montando un bucle de chat por línea de comandos, la lógica es la siguiente. Defines una variable para guardar el array de la conversación. Al principio, solo contiene el primer prompt del usuario. Le pasas este array al agente. Cuando el agente termina, coges el result y llamas a to_input_list, lo que te da el historial completo y actualizado de ese turno. Cuando el usuario escribe su segunda pregunta, haces un append manual de su nuevo mensaje al final de esa lista, y le vuelves a pasar todo al agente. Tienes el control total del payload. Ahora, la segunda parte de esto. Enviar y recibir un array enorme de mensajes anteriores y tool outputs en JSON por la red en cada turno consume ancho de banda. Si quieres evitar eso, puedes usar Server IDs. Cada respuesta que recibes de la API incluye un identificador único. En lugar de pasarle un array de mensajes anteriores a la siguiente ejecución de tu agente, le pasas un parámetro llamado previous_response_id. Aquí está la clave. Cuando proporcionas un previous_response_id, tu cliente solo envía el nuevo mensaje del usuario. No envías el array del historial. El servidor de OpenAI busca ese ID, recupera el thread de contexto existente por su lado, le adjunta tu nuevo mensaje y genera la siguiente respuesta. Esto nos lleva a una trampa crítica. Puede que te sientas tentado a mezclar estos enfoques. Podrías hacer un append del input del usuario a la lista del lado del cliente, pasarle esa lista completa al agente y, por si acaso, pasarle también el previous_response_id. No hagas esto. Tienes que elegir exactamente una estrategia por conversación. Si proporcionas tanto el array del historial completo como un previous_response_id, el servidor los va a concatenar. Tu agente leerá la conversación entera dos veces, se confundirá con los tool calls duplicados, y pagarás por esos tokens dos veces. La elección entre estos dos métodos se reduce a visibilidad frente a eficiencia. Usa listas del lado del cliente cuando necesites auditar, filtrar o modificar el historial de la conversación entre turnos. Usa Server IDs cuando confíes en el thread en crudo y quieras minimizar tu payload de red. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue programando!
9

Automatizando la memoria con Sessions integradas

4m 13s

Simplifica tus bucles de chat con el sistema de memoria integrado del SDK. Exploramos SQLiteSession, OpenAIConversationsSession y la persistencia automatizada.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 9 de 18. Estás creando un chatbot persistente. Escribes código para recuperar mensajes anteriores de una base de datos, pasárselos a tu agente, extraer la nueva respuesta y guardar la lista actualizada en la base de datos. Es un boilerplate tedioso que has escrito docenas de veces. Hoy vamos a ver cómo automatizar la memoria con sesiones integradas, lo que reemplaza toda esa lógica de lectura y escritura en base de datos por un único objeto. Vamos a aclarar un malentendido muy común desde el principio. Cuando los desarrolladores empiezan a usar sesiones en este SDK, a menudo piensan que todavía necesitan recuperar y pasar manualmente el historial de mensajes al runner del agente junto con la sesión. No es así. Pasarle un objeto de sesión al runner reemplaza por completo la gestión manual del historial. Le entregas las llaves. El runner recupera automáticamente los mensajes anteriores justo antes de que comience el turno de conversación, y hace un append automático de los mensajes nuevos en el momento en que termina el turno. Imagina un bot de Slack persistente que necesita recordar las preferencias del usuario durante varios días. Quieres guardar este estado en disco sin montar una base de datos externa pesada. El SDK incluye una herramienta integrada para esto llamada SQLite Session. Como interactuar con un sistema de archivos requiere operaciones de input output, esta herramienta es totalmente asíncrona. Para usarla, primero instancias un SQLite Session, pasándole un file path para tu base de datos local. Luego, te conectas usando un context manager asíncrono. Imagina que esto es como abrir una conexión segura que garantiza que el archivo de la base de datos se bloquea y desbloquea correctamente. Dentro de ese bloque de conexión, llamas al runner de tu agente. En lugar de pasarle un array de mensajes anteriores al runner, simplemente le pasas el objeto de sesión y un session ID. El session ID es simplemente un string único. Para tu bot de Slack, este ID podría ser el user ID o el channel ID. El runner coge ese ID, busca en el archivo SQLite, carga el historial existente, procesa el prompt del usuario y luego persiste de forma segura el nuevo estado en el archivo. Todo esto ocurre en segundo plano. Aquí está la clave. Un historial de conversación sin límites acabará rompiendo los límites de tu context window. No quieres que un chat sin importancia de hace tres meses infle tu consumo de tokens o rompa tu API call de hoy. Para controlar esto, el SDK incluye Session Settings. Al llamar al runner, puedes incluir un objeto Session Settings junto a la propia sesión. Este objeto de settings acepta un parámetro para el máximo de mensajes anteriores. Si lo pones a diez, el runner trunca automáticamente el historial cargado. Mantiene solo los diez mensajes más recientes en el contexto activo que se envía al modelo, pero todo tu log histórico permanece intacto y seguro en la base de datos SQLite. SQLite Session es ideal para persistencia local o aplicaciones de un solo servidor. Si tu bot de Slack crece y necesitas escalar en múltiples servidores, el SDK lo gestiona sin problemas. Mantienes el código de tu runner exactamente igual, pero cambias el SQLite Session local por una opción distribuida como Redis Session o Dapr Session. La conclusión principal es que las sesiones fuerzan una estricta separation of concerns. Al configurar un objeto de sesión y pasárselo al runner, eliminas el boilerplate frágil de base de datos y garantizas que la memoria de tu agente esté siempre perfectamente sincronizada con su estado de ejecución. Eso es todo por hoy. Gracias por escuchar. Ve a construir algo genial.
10

Protegiendo flujos de trabajo: Input y Output Guardrails

3m 43s

Asegura tus pipelines de IA interceptando inputs maliciosos antes de que lleguen a modelos costosos. Cubrimos los guardrails a nivel de agente y la ejecución en paralelo frente a la bloqueante.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 10 de 18. Tu modelo de razonamiento más potente también es el más caro. Si un usuario intenta engañarlo para que haga sus deberes de matemáticas o infrinja las políticas de seguridad, no querrás enterarte después de que se haya pasado dos minutos y mil tokens pensando en ello. Proteger tus workflows con Input y Output Guardrails es la forma de evitarlo. Los guardrails a nivel de agente actúan como porteros para tus modelos principales. Son funciones independientes, a menudo impulsadas por modelos más pequeños, rápidos y baratos, que validan los datos que entran o salen de tu agente. Al interceptar las requests, mantienen tus modelos caros centrados en el trabajo real y garantizan que tu aplicación siga siendo segura y no se desvíe del tema. Los aplicas en dos sitios: en el input y en el output. Los input guardrails evalúan el prompt del usuario antes de que tu agente principal se ponga a trabajar. Imagina un escenario en el que tienes un modelo pesado y lento que maneja análisis financieros complejos. Puedes configurar un input guardrail usando un modelo rápido y ligero para revisar cada mensaje entrante. Cuando un usuario hace una pregunta, este modelo rápido la intercepta. Comprueba si el usuario intenta que el agente le haga un trabajo de clase, o si tal vez está intentando un ataque de prompt injection. Si el input es marcado como sospechoso, el guardrail lo rechaza inmediatamente y devuelve un mensaje de rechazo estándar. Tu modelo de razonamiento pesado ni siquiera se despierta. Ahorras tiempo y ahorras dinero. Los output guardrails gestionan el otro extremo de la transacción. Hacen una comprobación final antes de que el usuario vea la respuesta. El agente principal ha completado su tarea, pero tienes que asegurarte de que no se filtren datos sensibles, o de que el tono encaje con las directrices de tu empresa. El output guardrail revisa el texto generado. Si detecta una alucinación o una infracción de las políticas, bloquea el mensaje para que no llegue al usuario. Aquí está la clave. Cómo impactan estos guardrails en tu aplicación depende completamente de su modo de ejecución. Puedes ejecutarlos en modo blocking o en modo paralelo. El modo blocking es una secuencia estricta. Un input guardrail debe terminar su evaluación y dar el visto bueno antes de que el agente principal pueda empezar. Un output guardrail debe terminar de comprobar la respuesta final antes de que el usuario reciba una sola palabra. Este es el enfoque más seguro y te garantiza que no vas a tirar el dinero en malas requests, pero añade latencia a la interacción. El modo paralelo sacrifica el control estricto de costes a cambio de velocidad. Un error muy común es pensar que la ejecución en paralelo pausa de alguna forma al agente principal mientras el guardrail se ejecuta a su lado. No es así. En modo paralelo, el input guardrail y el agente principal empiezan exactamente al mismo tiempo. El agente está activamente generando texto y consumiendo tokens mientras el guardrail todavía está evaluando el prompt de input. Si el guardrail decide rechazar la request, cancelará al agente principal a mitad de ejecución. El usuario sigue estando protegido y no verá el output, pero tú sigues pagando por los tokens que el agente principal ha consumido antes de que lo cortaran. Esto lo configuras definiendo una función sencilla que devuelve una decisión de pass o fail, asociándola a tu agente y declarando su modo. Adapta siempre tu modo de ejecución a tus prioridades: usa blocking guardrails para proteger tu cartera de los modelos caros, y parallel guardrails para proteger tu experiencia de usuario de la latencia. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
11

Validando acciones: Tool-Level Guardrails

4m 27s

Evita fugas de datos críticos a nivel de función. Aprende a envolver herramientas específicas con input y output guardrails precisos.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 11 de 18. Incluso la IA más inteligente puede filtrar accidentalmente un secreto de base de datos si mete raw data directamente en su context. Es posible que asumas que tus comprobaciones de seguridad de alto nivel lo pillan todo, pero esas solo se ejecutan justo al principio o al final de una conversación. Si quieres interceptar datos sensibles a mitad del workflow, necesitas Validating Actions, específicamente Tool-Level Guardrails. Una trampa común es asumir que los guardrails a nivel de agente protegen tus sistemas subyacentes. No lo hacen. Los guardrails del agente procesan el prompt inicial del usuario o la respuesta final que se le envía de vuelta. Son ciegos al intercambio interno cuando un agente llama a una base de datos o a una API de terceros. Si un prompt malicioso engaña a tu agente para que llame a una tool interna, los checks a nivel de agente no lo pararán. Para proteger las tools en sí, el OpenAI Agents SDK proporciona tool guardrails. Estos se colocan directamente en la función, actuando como un checkpoint obligatorio justo antes o justo después de que la tool se ejecute. Hay dos tipos que debes conocer. El primero es el tool input guardrail. Aplicas este decorator para validar los argumentos antes de que la tool real se ejecute. Imagina que un agente intenta llamar a una tool que borra una cuenta de usuario. El input guardrail intercepta los argumentos que generó el agente. Comprueba si el user ID proporcionado coincide con un formato válido, o si la sesión actual tiene el nivel de autorización correcto. Si el input no pasa este check, el guardrail impide por completo que la tool se ejecute. En lugar de ejecutar el borrado, devuelve un mensaje de error directamente al agente. Entonces el agente lee ese error y puede intentarlo de nuevo con los inputs corregidos, sin llegar a tocar la base de datos real. Ahora, la segunda parte de esto es el tool output guardrail. Este opera después de que la tool se ejecute con éxito, pero antes de que el resultado se devuelva al agente. Aquí es donde filtras, censuras o validas el payload. Toma como ejemplo una tool de database lookup. El agente pide un perfil de desarrollador, y la tool recupera el registro raw. Sin embargo, da la casualidad de que ese registro contiene una API key activa que empieza con las letras s-k-guion. Si esa key raw vuelve al agente, entra en la context window del modelo de lenguaje. Eso es un riesgo de seguridad enorme. Para arreglar esto, añades un tool output guardrail a esa función de lookup específica. El guardrail coge el resultado raw de la base de datos, escanea el texto en busca de ese patrón s-k-guion, y reemplaza la key real con un string de marcador de posición como redacted. Solo después de este proceso de limpieza, los datos limpios se devuelven al agente. El agente sigue obteniendo la información del perfil que necesita para responder al usuario, pero el secreto nunca sale del límite de ejecución aislado de la tool. Esta es la parte que importa. En workflows multi-agente complejos, diferentes agentes especializados pueden invocar tools en secuencias impredecibles. No puedes depender de hacerle prompting al agente para que se comporte de forma segura. Tampoco puedes esperar que el filtro de output final pille una key filtrada justo antes de que llegue al usuario, porque para entonces, la key ya ha sido expuesta al modelo de lenguaje. Debes blindar la tool en sí. Al adjuntar el guardrail directamente a la función, la lógica de seguridad viaja con la tool. No importa qué agente la llame o cuándo se llame en el workflow. La protección es absoluta. Los tool guardrails tratan tus funciones como límites zero-trust, asegurando que, por muy autónomo que se vuelva tu agente, nunca pueda meter bad data, ni sacar datos sensibles. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue construyendo!
12

Pausando la ejecución: Human-in-the-Loop y RunState

3m 47s

Implementa salvaguardas para acciones irreversibles forzando aprobaciones Human-in-the-Loop. Exploramos el pipeline de serialización de RunState para pausar y reanudar cargas de trabajo.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 12 de 18. No dejarías que un becario nuevo borrara una base de datos en producción sin pedir permiso primero. Tu agente de IA tampoco debería poder hacerlo. Cuando un agente tiene acceso a tools muy destructivos o sensibles, necesitas una forma de pararlo, revisar su trabajo y darle luz verde manualmente. Esto se soluciona pausando la ejecución: con Human-in-the-Loop y RunState. Si necesitas que un humano apruebe una acción, tu primer instinto podría ser pausar el script de Python y esperar un input por teclado. No lo hagas. Mantener un proceso vivo mientras esperas una respuesta por email o un clic en un dashboard desperdicia recursos del servidor. Además, se rompe por completo si el servidor se reinicia o si haces un deploy de código nuevo. El OpenAI Agents SDK gestiona esto limpiamente permitiendo que el proceso de Python termine por completo y se reanude más tarde en un servidor completamente distinto. Todo empieza en la definición del tool. Cuando escribes una función para tu agente, como un tool llamado delete production database, aplicas un flag poniendo needs approval a true. Cuando el agente procesa un prompt y decide que debe llamar a este tool específico, el engine se detiene inmediatamente. El tool no se ejecuta. En su lugar, el runner devuelve el control al código de tu aplicación. Aquí está la clave. Cuando la ejecución se detiene, el runner te da un objeto RunState. Este objeto guarda todo el contexto del run hasta ese milisegundo exacto. Conoce el historial de la conversación, el proceso de pensamiento interno del agente y el tool call específico que quiere ejecutar a continuación. Coges este objeto RunState y lo serializas en un string JSON estándar. Guardas ese payload JSON en tu base de datos, lo metes en una queue, o lo escribes en disco. Una vez que ese estado está guardado de forma segura, tu script de Python termina. Tu aplicación ahora está idle. Pueden pasar horas o incluso días. Finalmente, un engineering manager hace login en un dashboard web, ve el borrado de la base de datos pendiente y hace clic en aprobar. Ese clic dispara una request web totalmente nueva. Tu backend se despierta y lee el payload JSON guardado en la base de datos. Deserializa ese string de vuelta a un objeto RunState válido. Entonces inicias una nueva ejecución del runner. Le pasas la misma instancia del agente, el RunState restaurado y la decisión del humano. Si le pasas una aprobación, el runner ejecuta el tool de borrado de base de datos y el agente sigue respondiendo al usuario. Si el manager hizo clic en rechazar, le pasas un rechazo en su lugar. El runner no ejecuta el tool. Le devuelve el rechazo al agente como un tool error, forzando al agente a adaptar su plan o a decirle al usuario que la acción fue denegada. Al serializar el RunState, conviertes un script síncrono en un workflow asíncrono, permitiendo que humanos y agentes colaboren de forma segura a través de cualquier lapso de tiempo sin dejar ni un solo proceso del servidor colgado. Si quieres ayudar a mantener el programa en marcha, puedes apoyarnos buscando DevStoriesEU en Patreon. Gracias por pasarte por aquí. Espero que hayas aprendido algo nuevo.
13

Inyectando dependencias locales con RunContextWrapper

4m 28s

Domina la inyección de dependencias en los flujos de tus agentes. Aprende a pasar de forma segura estados locales y conexiones de bases de datos a las herramientas sin filtrarlos al LLM.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 13 de 18. ¿Cómo le dices a una función qué usuario está chateando actualmente, sin enseñarle accidentalmente al LLM el ID privado de la base de datos del usuario? Si lo metes en el system prompt, estás exponiendo datos internos y desperdiciando tokens. Para pasar un estado local seguro a tus tools, usas la inyección de dependencias locales con RunContextWrapper. Un error común al crear agentes es tratar al modelo de lenguaje como el intermediario para todo. Los desarrolladores suelen intentar meter connection strings de la base de datos, API keys internas o identificadores privados de usuario directamente en las system instructions. Lo hacen con la esperanza de que el modelo pase obedientemente esas credenciales sensibles de vuelta a las tool calls como parámetros. Esto supone un riesgo de seguridad importante. Además, consume tokens innecesarios de la context window y aumenta la probabilidad de que el modelo alucine parámetros incorrectos. El enfoque correcto es saltarse por completo el modelo de lenguaje para tu estado de ejecución local. El Run Context Wrapper proporciona una capa de transporte segura para inyectar dependencias directamente en tus tools y lifecycle hooks. El atributo context asociado a este wrapper es puramente estado local de Python. El modelo nunca lo ve, nunca lo lee y nunca necesita razonar sobre ello. Imagina un escenario concreto. Un usuario autenticado está chateando con tu agente de atención al cliente y pide ver sus registros de facturación recientes. Tu sistema necesita recuperar estos registros, lo que significa que tu tool de facturación requiere el ID interno de la base de datos del usuario para ejecutar la query de forma segura. Primero, defines tu dependencia local en el código de tu aplicación. Podrías crear una data class estructurada llamada User Info que guarde el ID interno del usuario. A continuación, escribes tu tool function para recuperar el historial de facturación. En la signature de esta tool function, defines un parámetro específicamente tipado para aceptar el objeto context. El SDK entiende este type hint y sabe que no debe exponer este parámetro al modelo de lenguaje. Dentro del cuerpo de la función, accedes al parámetro context, extraes tu dependencia User Info y usas ese ID de usuario privado para hacer una query segura a tu backend. Aquí está la clave. Cuando te preparas para ejecutar el run del agente, no pasas simplemente el mensaje raw del usuario. Creas una instancia del Run Context Wrapper. Adjuntas tu data class User Info ya poblada directamente al wrapper. Luego, le pasas este wrapper al execution runner. El flujo lógico se encarga del resto automáticamente. Cuando el usuario pide su historial de facturación, el modelo de lenguaje decide activar tu tool de facturación. El modelo solo proporciona los argumentos que conoce por la conversación pública, quizás filtrando por un mes específico o un número de factura. No tiene absolutamente ni idea de quién es el usuario en tu backend. Antes de que la función se ejecute realmente, el SDK intercepta la llamada. Inspecciona la tool signature, nota que la tool requiere el context local, e inyecta automáticamente el estado que adjuntaste al Run Context Wrapper. La tool se ejecuta usando el ID de usuario seguro, recupera los registros y devuelve los datos al modelo para formular una respuesta. Este mismo mecanismo de inyección de dependencias funciona para los execution hooks, permitiéndote pasar connection pools de base de datos activos o tracing IDs a tu event logging sin problemas. Al separar el razonamiento externo del modelo de la ejecución interna de tu código, tu infraestructura se mantiene segura y tus prompts se centran exclusivamente en el comportamiento. Mantén tus dependencias de ejecución completamente locales, y obliga a tu arquitectura a depender por completo del estado seguro inyectado en runtime. ¡Gracias por escuchar, que tengáis todos un gran día!
14

El USB-C de la IA: Introducción a MCP

4m 00s

Una introducción al Model Context Protocol (MCP). Descubre cómo este estándar actúa como un conector universal para conectar fácilmente agentes de IA a plataformas SaaS.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 14 de 18. Deja de escribir API wrappers personalizados cada vez que tu agente necesite comunicarse con un nuevo servicio. Si estás cansado de mapear manualmente los REST endpoints a JSON schemas solo para que tu modelo de lenguaje entienda qué hace un servicio, por fin existe un estándar universal. Vamos a ver el Model Context Protocol, o MCP, y cómo usarlo. Piensa en MCP como el puerto USB-C para la IA. Antes del USB-C, cada dispositivo necesitaba un cable de carga específico y propietario. En el mundo de la IA, cada sistema externo requiere glue code personalizado. Si quieres que un agente lea una base de datos o cree un ticket de soporte, escribes un REST client. Luego, escribes un schema complejo que describe ese cliente al modelo. Finalmente, escribes la lógica para capturar la respuesta del modelo y lanzar la HTTP request real. MCP reemplaza ese trabajo manual. Es un estándar abierto que dicta exactamente cómo las tools se describen a sí mismas, sus inputs y sus outputs directamente a un modelo de IA. La gente suele confundir MCP con las REST APIs estándar. Una REST API envía datos entre máquinas, pero espera que sepas exactamente cómo estructurar la request de antemano. MCP estandariza la discovery layer. Un servidor MCP le dice al agente exactamente qué tools contiene y qué parámetros son necesarios, hablando en el formato exacto que necesita el modelo. En el OpenAI Agents SDK, consumes estos servidores MCP externos usando una clase llamada Hosted MCP Tool. Aquí está la clave. No redefines el tool schema en tu código Python para nada. En su lugar, inicializas la Hosted MCP Tool pasándole la URL de un servidor MCP remoto. Esta conexión funciona sobre Server-Sent Events, lo que permite al servidor hacer push de actualizaciones a tu agente de forma segura. Cuando añades esta Hosted MCP Tool al setup de tu agente, se produce un handshake. El agente se conecta al servidor remoto, pregunta qué tools hay disponibles, descarga las descripciones completamente formadas y las registra automáticamente. Vamos a aterrizar esto en un escenario concreto. Quieres darle a tu agente la capacidad de programar reuniones. Sin MCP, te estudiarías la Google Calendar API. Escribirías una función en Python para autenticarte y crear eventos. Luego, escribirías el tool schema para que el agente sepa qué aspecto tiene el título de un evento o un timestamp. Con MCP, haces deploy de un servidor MCP de Google Calendar preconstruido en remoto. En el código de tu aplicación, creas una nueva instancia de Hosted MCP Tool y la apuntas a esa URL remota. Le pasas esa única instancia a tu agente. El servidor remoto le dice al instante al agente que tiene una tool llamada schedule meeting. Cuando el modelo de lenguaje decide programar esa reunión, el SDK actúa como proxy de la llamada. Enruta la request de forma segura a través de la red hacia el servidor remoto, ejecuta la acción y devuelve el resultado. Has escrito cero líneas de lógica de integración de calendario. El verdadero poder de MCP es desacoplar la lógica core de tu agente de las integraciones externas, permitiéndote cambiar o actualizar los backend services con solo cambiar una URL. Gracias por escuchar, ¡happy coding a todos!
15

Conectando servidores MCP locales a través de Stdio y HTTP

3m 55s

Profundiza en MCP ejecutando servidores locales estándar. Aprende a aislar el acceso al sistema de archivos y a las herramientas internas de forma segura con MCPServerStdio.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 15 de 18. Darle a un modelo de lenguaje acceso directo a tu filesystem local suena a una auténtica pesadilla de seguridad. Pero si metes ese acceso en un sandbox estricto mediante un protocolo estandarizado, se convierte en una forma segura y potente de procesar datos locales. Hoy veremos cómo conectar servidores MCP locales a través de stdio y HTTP. El Model Context Protocol define cómo tus agentes se comunican con herramientas y fuentes de datos externas. Cuando quieres ejecutar estos servidores dentro de tu propia infraestructura, el SDK de OpenAI Agents proporciona dos métodos de transporte local. El primero es standard input y output, usando la clase llamada MCPServerStdio. A veces la gente piensa que esto requiere un setup de red local complejo. No es así. Cuando usas el transporte stdio, el SDK simplemente hace un spawn del servidor MCP como un child process local. El agente envía requests escribiendo en el standard input de ese proceso y lee las responses de su standard output. Imagina un escenario en el que quieres que tu agente lea archivos, pero solo desde un directorio local específico. Instancias MCPServerStdio y le pasas el comando a ejecutar. Por ejemplo, podrías pasarle el comando del node package manager npx, seguido de los argumentos para lanzar el servidor oficial del filesystem de MCP, y el path absoluto a tu directorio de destino. Como este servidor se ejecuta como un subproceso, tienes que gestionar su lifecycle. Si tu script de Python termina o crashea, no quieres que quede un proceso de node huérfano en background. El SDK fuerza una gestión limpia del lifecycle requiriendo un context manager asíncrono. Defines un bloque async with para inicializar el servidor stdio. Cuando la ejecución entra en el bloque, el SDK levanta el child process. Cuando la ejecución sale del bloque, destruye el proceso limpiamente. Dentro de ese bloque, conectas el servidor en ejecución a tu agente. Creas un MCP Client, le pasas tu instancia del servidor stdio y, a continuación, le pasas ese client a tu agente. El agente ahora tiene acceso temporal y con scope a tu directorio local. Ahora bien, ¿qué pasa si quieres exponer una API interna privada, o conectarte a un servicio que ya está corriendo? No quieres hacer un spawn de un nuevo subproceso para eso. Esto nos lleva a la segunda opción de transporte, que es MCPServerStreamableHttp. En lugar de pasar un comando ejecutable, le pasas a esta clase la URL de tu servicio existente. Esto es perfecto para conectar de forma segura tu agente a un microservicio interno corriendo en localhost. El agente se comunica haciendo streaming de datos por HTTP. Aquí está la clave. El agente en sí no tiene ni idea de qué transporte has elegido. El código de conexión dentro de tu aplicación es exactamente igual. Sigues usando un context manager, sigues creando un MCP client, y se lo sigues pasando al agente. El SDK abstrae la capa de transporte por completo. La conclusión más útil aquí es que puedes desarrollar una custom tool como un script local por stdio para testing, y más tarde hacer un deploy como un servicio HTTP standalone en producción, sin cambiar ni una sola línea de la lógica de tu agente. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
16

Visualizando flujos de trabajo con Tracing integrado

4m 11s

Elimina la depuración con sentencias print utilizando la observabilidad integrada del SDK. Descubre cómo los spans y traces automáticos enlazan flujos de trabajo complejos en su totalidad.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 16 de 18. Depurar un sistema multiagente con print statements es una pesadilla. Ves pasar los logs, intentando relacionar manualmente un tool execution en la línea cincuenta con la generación de un modelo en la línea doscientos. Por suerte, ya no tendrás que volver a hacerlo. Este episodio trata sobre la visualización de workflows con tracing integrado. Cuando los desarrolladores empiezan a crear workflows de agentes complejos, su primer instinto suele ser escribir wrappers de logging personalizados. Escriben código boilerplate para rastrear exactamente cuándo se inicia un agente, qué argumentos recibe una tool y cuánto tarda el modelo en responder. No hagas esto. El Agents SDK se encarga de ello por ti, totalmente out of the box. Cada vez que ejecutas un agente, solicitas una generación o activas un tool call, el SDK encapsula automáticamente esa acción en un span. Un span es simplemente un registro estructurado y cronometrado de una sola operación. Estos spans capturan los inputs, los outputs y la duración de la tarea. Se envían automáticamente al dashboard de OpenAI. Esto significa que obtienes un timeline visual completo de la ejecución de tu workflow sin escribir ni una sola línea de código de telemetría. Aquí está la clave. Mientras que el SDK gestiona los detalles granulares, tú controlas la agrupación de alto nivel. Imagina un escenario multi-turn donde un agente genera un chiste, un segundo agente lo evalúa y el primero lo refina basándose en el feedback. Por defecto, el SDK registrará cada una de estas generaciones del modelo y tool calls como spans distintos. Pero para un humano que mira un dashboard, todo este intercambio es solo una unidad lógica de trabajo. Puedes agrupar estas acciones usando un bloque trace personalizado. Abres un bloque de contexto usando la función trace y le das un nombre descriptivo, como joke generation loop. Dentro de ese bloque, ejecutas la lógica de tu agente multi-turn. El SDK respeta esta jerarquía. Anidará todos los spans generados automáticamente para los runs, evaluaciones y refinamientos individuales bajo tu trace padre personalizado. Cuando abres el dashboard de OpenAI, ves primero el joke generation loop de nivel superior. Luego puedes expandirlo para investigar la secuencia exacta de llamadas al modelo y tool executions que ocurrieron dentro. Eso cubre la visibilidad, pero ¿qué pasa con la privacidad? Hay veces en las que absolutamente no debes enviar telemetría. Si tu agente maneja historiales médicos confidenciales, datos financieros o requiere un estricto cumplimiento de Zero Data Retention, enviar logs de input y output a un dashboard es una violación de seguridad. Para estas situaciones, el SDK proporciona un bloque de contexto tracing disabled. Cuando envuelves la ejecución de tu agente dentro de este bloque, el SDK deja por completo de generar y enviar spans. La ejecución se realiza localmente, el resultado se devuelve a tu aplicación, pero no aparecerá ningún registro del prompt, los tool calls o la respuesta en el dashboard de OpenAI. Una vez que el código sale de ese bloque deshabilitado, el tracing automático normal se reanuda para el resto de tu aplicación. El tracing en el SDK significa que dejas de escribir logging boilerplate, obtienes depuración visual inmediata y mantienes el control total sobre cuándo tus datos permanecen completamente locales. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
17

Voz de baja latencia con Realtime Agents

4m 32s

Rompe el paradigma estándar de petición-respuesta. Mira cómo los Realtime Agents mantienen conexiones WebSocket en vivo para gestionar interrupciones y razonamiento multimodal.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 17 de 18. La parte más difícil de crear IA de voz no es generar el habla, sino saber cuándo callarse al instante porque el usuario te interrumpe a mitad de frase. Si dependes del ciclo tradicional de request y response, la latencia de red siempre dejará en evidencia al bot. Ese es exactamente el problema que resuelve Low-Latency Voice con Realtime Agents. Muchos desarrolladores confunden esta arquitectura con un pipeline de voz estándar. En un setup tradicional, capturas el audio, lo pasas por un modelo de Speech-to-Text, envías ese texto a un modelo de lenguaje y, finalmente, pasas el texto resultante por un sintetizador de Text-to-Speech. Ese pipeline introduce latencia en cada paso. Los Realtime Agents descartan ese pipeline por completo. Utilizan un único modelo multimodal que razona de forma nativa sobre el audio. El audio entra directamente, y sale directamente como stream. No hace falta ninguna traducción intermedia a texto para que el sistema entienda al usuario. Para lograr esto, tienes que romper con el paradigma estándar de request-response de HTTP. En lugar de enviar un payload y esperar una respuesta completa, el sistema mantiene abierta una conexión persistente. En el SDK, gestionas esto usando dos componentes principales. El primero es el RealtimeAgent. Este objeto contiene tus instrucciones del sistema y cualquier función o tool a la que el modelo necesite acceder. Define la lógica, las capacidades y la personalidad de tu asistente. El segundo componente es el RealtimeRunner. El runner es el motor de ejecución. Gestiona el event loop asíncrono y maneja el stream de red persistente, normalmente a través de una conexión WebSocket o WebRTC. Imagina un bot telefónico de atención al cliente que gestiona una llamada entrante. Conectas a tu proveedor de voz, quizás integrándolo mediante SIP o WebSockets, enrutando el audio continuo hacia tu aplicación en Python. Creas tu RealtimeAgent, equipándolo con una tool para obtener las cuentas de usuario. Luego, le pasas ese agente y tu cliente de conexión de red al RealtimeRunner. Cuando llamas al método run en el runner, este toma el control. Mantiene la conexión viva, escuchando constantemente el stream de audio, mientras gestiona simultáneamente cualquier function call que el agente necesite hacer. Hace push y pull de eventos en ambas direcciones de forma concurrente. El usuario llama y pide el saldo de su cuenta. El agente dispara la tool para consultar la cuenta, obtiene los datos e inmediatamente empieza a hacer streaming de su respuesta hablada hacia el usuario. A mitad de la frase, el usuario de repente habla por encima del bot, diciendo que en realidad quiere reportar una tarjeta perdida. Aquí está la clave. Como la conexión WebSocket está abierta de forma persistente y el modelo ingiere de forma nativa el stream de audio entrante en tiempo real, el servidor detecta la voz humana al instante. Dispara un evento que detiene su propia salida de audio y registra el truncamiento. No tienes que escribir lógica a medida para calcular exactamente qué chunk de audio se estaba reproduciendo cuando el usuario habló. La arquitectura de streaming gestiona la interrupción sin problemas. El modelo absorbe el nuevo contexto de audio de la interrupción e inmediatamente empieza a hacer streaming de la respuesta actualizada sobre la cancelación de la tarjeta perdida. Consigues una dinámica conversacional totalmente natural porque la capa de red y la capa del modelo están construidas para un streaming continuo. El verdadero poder de la Realtime API en el Agents SDK es tratar la voz como un stream continuo de primera clase, en lugar de un batch de texto traducido disfrazado. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue programando!
18

Construyendo interfaces reactivas con Streaming Events

4m 28s

Ve más allá del streaming de tokens de texto. Utiliza Semantic Streaming Events para construir interfaces frontend ultrarreactivas que reaccionan a las acciones del agente en tiempo real.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. OpenAI Agents SDK, episodio 18 de 18. Tus usuarios no solo quieren leer el texto a medida que se escribe en la pantalla. Quieren ver exactamente qué está haciendo la IA en segundo plano. Si intentas crear un loading spinner haciendo parsing de chunks de tokens raw para adivinar cuándo se está ejecutando una search tool, lo estás haciendo por el camino difícil. Construir UIs reactivas con Streaming Events resuelve exactamente este problema. Los desarrolladores a menudo tratan los outputs de la IA como una simple máquina de escribir. Escuchan un stream de texto raw y escriben una lógica de parsing frágil para averiguar si el agente está a punto de llamar a una función. Ese enfoque es frágil. Se rompe si el modelo cambia ligeramente su forma de expresarse, y deja a tu frontend rezagado respecto al estado de ejecución real. El OpenAI Agents SDK ofrece una alternativa estructural. En lugar de esperar strings, lanzas tu agente usando un método llamado run streamed en tu runner. Este método no devuelve texto plano. En su lugar, devuelve una secuencia asíncrona de eventos semánticos, cada uno empaquetado como un objeto Run Item Stream Event. Piensa en un Run Item Stream Event como una notificación precisa sobre el ciclo de vida interno del agente. A medida que el agente procesa una request, emite señales distintas y predecibles. Te dice exactamente cuándo se añade un nuevo mensaje al thread. Te dice cuándo el control se transfiere de un agente de triaje a un agente especializado. Y lo que es crucial para el desarrollo frontend, te dice el milisegundo exacto en el que empieza y termina la invocación de una tool. Apliquemos esto a un escenario concreto. Quieres que tu frontend muestre un spinner que diga Buscando en la base de datos mientras el agente busca el registro de un cliente. Llamas a run streamed e iteras sobre los resultados. Dentro de ese bucle asíncrono, inspeccionas cada evento a medida que llega. Cuando un evento llega por la red, compruebas sus propiedades para ver qué tipo de actualización representa. Cuando un evento indica que ha empezado una tool call, puedes leer el nombre real de la tool directamente desde el payload del evento. No tienes que hacer parsing de ningún lenguaje natural. Si el nombre de la tool coincide con tu función de búsqueda en la base de datos, haces un push inmediato de una actualización de estado a tu frontend para renderizar el spinner. Cuando un evento posterior señala que la ejecución de la tool ha terminado, haces un dispatch de otra actualización para ocultar el spinner. Estos eventos del stream también llevan deltas de mensaje estándar. Si el agente está generando una respuesta de texto larga, el stream emite eventos de chunk que tú añades a la UI. La arquitectura separa el output conversacional raw de las acciones semánticas. Enrutas los chunks de texto a la ventana de chat, y enrutas los eventos del ciclo de vida de la tool y del agente a tu state manager de la UI. Esta separación de responsabilidades te permite construir interfaces que se sienten instantáneamente responsivas y profundamente conectadas a la lógica del agente. Estás reaccionando al path de ejecución real del sistema, no adivinando sus intenciones basándote en palabras. Aquí está la clave. Deja de tratar el output de tu agente como un simple stream de conversación. Trátalo como una state machine orientada a eventos donde cada acción interna es una oportunidad para mantener a tu usuario visualmente informado. Como este es el último episodio de la serie, te animo a que leas la documentación oficial e intentes orquestar estos streams tú mismo. Si tienes ideas sobre lo que deberíamos cubrir en una futura serie, visita devstories dot eu y cuéntanoslo. Eso es todo por este episodio. Nos vemos la próxima.