Curso
El campo de la inteligencia artificial está pasando de sistemas que solo responden a consultas a otros capaces de actuar de forma autónoma. El nuevo SDK de Agents de OpenAI está a la vanguardia de esta tendencia y ofrece a los desarrolladores un marco práctico para crear aplicaciones de IA que toman decisiones y ejecutan acciones por sí mismas. Este conjunto de herramientas marca la siguiente evolución del desarrollo en IA: sistemas que no solo contestan preguntas, sino que resuelven problemas activamente.
El SDK de Agents combina modelos de lenguaje grandes con la capacidad de usar herramientas y coordinar agentes especializados. Desarrollado en Python, logra un equilibrio entre sencillez y potencia con unos pocos conceptos clave: agentes, herramientas, handoffs y guardrails. Este enfoque lo hace accesible para quienes quieren crear sistemas de IA sofisticados sin tener que gestionar la complejidad de las mecánicas internas del comportamiento de los agentes.
En este tutorial, veremos cómo crear aplicaciones prácticas con el SDK de OpenAI Agents. Empezaremos por crear un agente básico y seguiremos con la implementación de herramientas, la coordinación de múltiples agentes y la seguridad mediante guardrails. Con estos conocimientos podrás desarrollar sistemas de IA capaces de abordar distintas tareas, adquiriendo habilidades alineadas con los enfoques actuales de desarrollo en IA.
Si es tu primera vez trabajando con OpenAI, échale un vistazo a nuestro itinerario de aprendizaje OpenAI Fundamentals para ponerte al día. También puedes ver a continuación nuestro tutorial en vídeo sobre el SDK de OpenAI Agents.
Requisitos previos para trabajar con OpenAI Agents SDK
Antes de meterte de lleno en el SDK de OpenAI Agents, es importante comprender varios conceptos fundamentales y configurar bien tu entorno. En esta sección verás todo lo necesario antes de escribir tu primer agente.
Conocimientos necesarios
Para aprovechar al máximo este tutorial, deberías sentirte cómodo con:
- Programación en Python a nivel intermedio: entender funciones, clases, patrones async/await y anotaciones de tipo
- Uso básico de la API de OpenAI: familiaridad con el envío de peticiones a modelos de OpenAI y el manejo de respuestas
- Modelos de lenguaje grandes (LLM): comprensión conceptual de cómo funcionan, sus capacidades y limitaciones
- Pydantic: nociones básicas de validación de datos con Pydantic, ya que el SDK lo usa ampliamente
- Programación asíncrona: familiaridad con los patrones async/await en Python, ya que el SDK se basa en ejecución asíncrona
Si necesitas reforzar alguno de estos temas, DataCamp ofrece varios recursos excelentes:
- Working with the OpenAI API — Aprende los fundamentos para interactuar con los modelos de OpenAI.
- OpenAI Fundamentals Track — Una ruta de aprendizaje completa sobre tecnologías de OpenAI.
- GPT-4.5 overview — Descubre las capacidades más recientes de los modelos GPT.
- Function calling with GPT-4.5 — Contexto esencial para entender el uso de herramientas en agentes.
- Using the GPT-4.5 API — Guía práctica para trabajar con modelos avanzados.
Conceptos clave sobre agentes
Antes de empezar a programar, aclaremos algunos conceptos clave del SDK de Agents:
- Agentes: sistemas de IA que pueden usar herramientas y tomar decisiones para completar tareas
- Herramientas: funciones que los agentes pueden invocar para acciones como buscar en la web o acceder a bases de datos
- Handoffs: mecanismos para transferir el control entre agentes especializados
- Guardrails: medidas de seguridad que validan entradas y salidas para garantizar un comportamiento adecuado
Entender estos conceptos y sus relaciones te ayudará a crear aplicaciones basadas en agentes más eficaces. Puedes conocer más en nuestra guía para entender los agentes de IA.
Configuración del entorno para OpenAI Agents
Vamos a preparar el entorno de desarrollo con todo lo necesario para trabajar con el SDK de OpenAI Agents:
Instalar los paquetes necesarios
Primero, crea y activa un entorno virtual:
# Crea y activa un entorno virtual (ejecútalo en tu terminal)
python -m venv agents-env
source agents-env/bin/activate # En Windows: agents-env\Scripts\activate
Después, instala el SDK de OpenAI Agents y python-dotenv:
pip install openai-agents python-dotenv
Usar python-dotenv para gestionar la clave de API
Cuando trabajes con claves de API, es buena práctica mantenerlas fuera del código. El paquete python-dotenv ofrece una forma segura de gestionar variables de entorno:
- Crea un archivo llamado
.enven el directorio de tu proyecto - Añade tu clave de la API de OpenAI a este archivo:
OPENAI_API_KEY=your-api-key-here
3. Carga y usa las variables de entorno en tu código:
import os
from dotenv import load_dotenv
from agents import Agent, Runner
# Carga las variables de entorno desde el archivo .env
load_dotenv()
# Accede a tu clave de API
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in .env file")
Este enfoque mantiene la información sensible fuera del código, algo especialmente importante si compartes o publicas tu trabajo.
Trabajar con funciones asíncronas
El SDK de OpenAI Agents utiliza programación asíncrona de forma intensiva. Así es como trabajar con funciones async en distintos entornos:
En scripts de Python (archivos .py)
En scripts normales de Python, tendrás que usar asyncio.run() para ejecutar funciones async:
import asyncio
from agents import Agent, Runner
async def main():
agent = Agent(
name="Test Agent",
instructions="You are a helpful assistant that provides concise responses."
)
result = await Runner.run(agent, "Hello! Are you working correctly?")
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main()) # Ejecuta la función async
En cuadernos Jupyter
Los notebooks de Jupyter ya tienen un bucle de eventos en ejecución, por lo que NO debes usar asyncio.run(). En su lugar, puedes esperar a funciones async directamente:
from agents import Agent, Runner
# No hace falta usar asyncio.run() en notebooks
agent = Agent(
name="Test Agent",
instructions="You are a helpful assistant that provides concise responses."
)
result = await Runner.run(agent, "Hello! Are you working correctly?")
print(result.final_output)
Si intentas usar asyncio.run() en un notebook, verás errores como:
RuntimeError: asyncio.run() cannot be called from a running event loop
Este es uno de los ajustes más comunes al copiar código entre scripts y notebooks. A lo largo del tutorial, usaré principalmente la sintaxis compatible con notebooks ya que la mayoría usará Jupyter.
Probar tu instalación
Comprobemos que todo está correctamente configurado:
from agents import Agent, Runner
from dotenv import load_dotenv
load_dotenv()
# Para notebooks Jupyter:
agent = Agent(
name="Test Agent",
instructions="You are a helpful assistant that provides concise responses."
)
result = await Runner.run(agent, "Hello! Are you working correctly?")
print(result.final_output)
# Para scripts de Python, usarías:
# async def test_installation():
# agent = Agent(
# name="Test Agent",
# instructions="You are a helpful assistant that provides concise responses."
# )
# result = await Runner.run(agent, "Hello! Are you working correctly?")
# print(result.final_output)
#
# if __name__ == "__main__":
# asyncio.run(test_installation())
# Hello! Yes, I'm here and ready to help. How can I assist you today?
Con esta configuración lista, ya puedes empezar a crear aplicaciones con el SDK de OpenAI Agents.
Primeros pasos con OpenAI Agents SDK
El núcleo del SDK de OpenAI Agents es la clase Agent, tu interfaz principal para crear sistemas de IA que entienden y ejecutan instrucciones. Veamos cómo crear y configurar agentes para distintos escenarios.
Un agente en este SDK representa un sistema de IA capaz de seguir instrucciones y, opcionalmente, usar herramientas para completar tareas. Crear un agente básico requiere solo unos pocos parámetros esenciales:
from agents import Agent
basic_agent = Agent(
name="My First Agent",
instructions="You are a helpful assistant that provides factual information.",
model="gpt-4o" # Opcional: por defecto es "gpt-4o" si no se especifica
)
Los tres componentes principales de un agente son:
- Nombre: un identificador que ayuda con el registro y la depuración
- Instrucciones: el “system prompt” que define el comportamiento y el propósito del agente
- Modelo: el modelo de lenguaje subyacente que impulsa al agente (por defecto GPT-4o)
Aunque esta configuración básica basta para empezar, la clase Agent ofrece opciones adicionales de configuración del modelo para controlar mejor el comportamiento del LLM:
from agents import ModelSettings
advanced_agent = Agent(
name="Advanced Assistant",
instructions="""You are a professional, concise assistant who always provides
accurate information. When you don't know something, clearly state that.
Focus on giving actionable insights when answering questions.""",
model="gpt-4o",
model_settings=ModelSettings(
temperature=0.3, # Más bajo para salidas más deterministas (0.0-2.0)
max_tokens=1024, # Longitud máxima de la respuesta
),
tools=[] # Veremos las herramientas más adelante
)
Instrucciones y configuración
El parámetro de instrucciones es quizá el aspecto más importante del diseño del agente. Funciona como un “system prompt” que guía su comportamiento, tono y capacidades. Redactar buenas instrucciones es tanto arte como ciencia:
Buenas prácticas para escribir instrucciones
- Sé específico: define con claridad el rol, la personalidad y las limitaciones del agente
- Marca límites: indica explícitamente qué temas o acciones debe evitar
- Define patrones de interacción: explica cómo debería manejar distintos tipos de entrada
- Delimita el conocimiento: aclara qué debe saber y cuándo debe reconocer incertidumbre
Agent también incluye un parámetro description, una descripción legible para humanos que se usa cuando el agente se integra en herramientas/handoffs.
Opciones de configuración
Más allá de las instrucciones, puedes ajustar el comportamiento del agente con varios parámetros de configuración:
- temperature: controla la aleatoriedad de las respuestas (0.0–2.0)
- Valores bajos (0.1–0.4) producen respuestas más deterministas y enfocadas
- Valores altos (0.7–1.0) generan salidas más creativas y variadas
- max_tokens: limita la longitud de las respuestas del agente
- Útil para asegurar respuestas concisas o controlar costes
- El valor por defecto varía según el modelo, pero suele ser suficiente para la mayoría de casos
- model: selecciona el LLM subyacente
- “gpt-4o” ofrece el mejor rendimiento en la mayoría de casos
- “gpt-4o-mini” equilibra rendimiento y coste
- “gpt-3.5-turbo” está disponible para tareas menos complejas donde priman velocidad y coste
Estas opciones dan un marco potente para personalizar el comportamiento del agente según la aplicación. Te animamos a experimentar para ver cómo afectan a las respuestas y encontrar la configuración óptima para tu caso.
Ejemplo de OpenAI Agents SDK: un asistente del tiempo especializado
Ahora, unimos estos conceptos creando un ejemplo práctico: un asistente especializado en información meteorológica. Demuestra cómo definir un agente con conocimientos, capacidades y límites claros:
from agents import Agent, Runner
from dotenv import load_dotenv
# Carga las variables de entorno (clave de API)
load_dotenv()
# Instrucciones detalladas para nuestro asistente del tiempo
weather_instructions = """
You are a weather information assistant who helps users understand weather patterns and phenomena.
YOUR EXPERTISE:
- Explaining weather concepts and terminology
- Describing how different weather systems work
- Answering questions about climate and seasonal patterns
- Explaining the science behind weather events
LIMITATIONS:
- You cannot provide real-time weather forecasts for specific locations
- You don't have access to current weather data
- You should not make predictions about future weather events
STYLE:
- Use clear, accessible language that non-meteorologists can understand
- Include interesting weather facts when relevant
- Be enthusiastic about meteorology and climate science
"""
# Crea nuestro asistente del tiempo especializado
weather_assistant = Agent(
name="WeatherWise",
instructions=weather_instructions,
model="gpt-3.5-turbo",
model_settings=ModelSettings(
temperature=0.5, # Temperatura equilibrada para respuestas naturales pero enfocadas
max_tokens=256, # Longitud máxima de la respuesta
)
)
Ejecutar tu primer agente
Una vez creado el agente, puedes ejecutarlo con la clase Runner, que gestiona la ejecución de tareas y el flujo de la conversación:
# Para notebooks Jupyter:
result = await Runner.run(
weather_assistant, "Can you tell me about the relationship between climate change and extreme weather events?"
)
print(result.final_output)
—--------
Absolutely! Climate change is closely linked to the increase in frequency and intensity of extreme weather events. As the Earth's climate warms due to the buildup of greenhouse gases in the atmosphere, it disrupts the balance of our planet's climate systems.
Here's how climate change influences extreme weather events:
1. **Heatwaves**: Rising global temperatures lead to more frequent and severe heatwaves. These events can have serious impacts on human health, agriculture, and ecosystems.
2. **Intense Storms**: Warmer oceans provide more energy to fuel hurricanes, typhoons, and other tropical storms, leading to stronger and more destructive events.
3. **Heavy Rainfall**: A warmer atmosphere can hold more moisture, resulting in heavier rainfall during storms. This can lead to flooding and landslides.
4. **Droughts**: Climate change can exacerbate drought conditions in certain regions, impacting water resources, agriculture, and ecosystems.
5. **Wildfires**: Higher temperatures and drier conditions increase the likelihood of wildfires, which can be more frequent and intense.
It's important to note that while climate change doesn't directly cause specific weather events, it can increase the likelihood and severity of extreme weather occurrences. Scientists continue to study these connections to better understand and prepare for the impacts of
En scripts de Python, necesitarías el enfoque con asyncio:
# Para scripts de Python:
import asyncio
async def run_agent_example():
result = await Runner.run(weather_assistant, "Can you tell me about the relationship between climate change and extreme weather events?")
print(result.final_output)
if __name__ == "__main__":
asyncio.run(run_agent_example())
En esta sección hemos cubierto los fundamentos para crear y ejecutar agentes con el SDK de OpenAI Agents. En la siguiente, ampliaremos estos conceptos añadiendo herramientas a nuestros agentes para potenciar significativamente sus capacidades.
Trabajar con herramientas
La verdadera potencia del SDK de OpenAI Agents surge cuando equipas a tus agentes con herramientas. Las herramientas permiten interactuar con sistemas externos, acceder a datos y realizar acciones más allá de la simple generación de texto. El SDK admite tres tipos principales: herramientas alojadas, herramientas de función y agentes como herramientas.
Herramientas alojadas
Las herramientas alojadas se ejecutan en los servidores de OpenAI junto a los modelos de lenguaje. Ofrecen capacidades integradas sin que tengas que implementar funcionalidades complejas.
WebSearchTool: creando un asistente de investigación
WebSearchTool da a tu agente la capacidad de buscar en la web información actualizada. Es especialmente útil para tareas que requieren conocimiento reciente más allá de los datos de entrenamiento del modelo.
from agents import Agent, Runner, WebSearchTool
from dotenv import load_dotenv
load_dotenv()
# Crea un asistente de investigación con búsqueda web
research_assistant = Agent(
name="Research Assistant",
instructions="""You are a research assistant that helps users find and summarize information.
When asked about a topic:
1. Search the web for relevant, up-to-date information
2. Synthesize the information into a clear, concise summary
3. Structure your response with headings and bullet points when appropriate
4. Always cite your sources at the end of your response
If the information might be time-sensitive or rapidly changing, mention when the search was performed.
""",
tools=[WebSearchTool()]
)
async def research_topic(topic):
result = await Runner.run(research_assistant, f"Please research and summarize: {topic}. Only return the found links with very minimal text.")
return result.final_output
# Ejemplo de uso (en Jupyter)
summary = await research_topic("Latest developments in personal productivity apps.")
print(summary[:512])
—----------------
Here are some recent developments in personal productivity apps:
- **AI Integration in Productivity Tools**: Startups like Anthropic are developing AI agents capable of performing routine tasks across different applications, aiming to streamline workflows and reduce the need for multiple apps. ([ft.com](https://www.ft.com/content/a0e54dd5-b270-42cc-8c4c-18a0b8b3e6cc?utm_source=openai))
- **Read AI's Expansion**: Read AI, a productivity startup, secured $50 million in funding, valuing the company at $450 m
En este ejemplo, hemos creado un asistente de investigación que puede buscar en la web y sintetizar la información en un resumen coherente. WebSearchTool no requiere parámetros para funcionar, pero puedes personalizar su comportamiento según necesites:
# Herramienta de búsqueda personalizada con contexto de ubicación
location_aware_search = WebSearchTool(
user_location="San Francisco, CA", # Aporta contexto geográfico para consultas locales
search_context_size=3 # Número de resultados a considerar en la respuesta
)
El parámetro user_location es especialmente útil para consultas con componente geográfico, como servicios locales o información regional. search_context_size controla cuántos resultados considera el modelo al formular su respuesta.
Herramientas de función
Las herramientas de función te permiten ampliar tu agente con cualquier función de Python. Aquí es donde brilla la flexibilidad del SDK, facilitando la integración con cualquier API, base de datos o servicio local.
Herramienta de previsión meteorológica
Creemos un ejemplo práctico que integre una API meteorológica de terceros:
import os
import requests
from datetime import datetime
from typing import Optional, List
from dataclasses import dataclass
from agents import Agent, Runner, function_tool
from dotenv import load_dotenv
load_dotenv()
@dataclass
class WeatherInfo:
temperature: float
feels_like: float
humidity: int
description: str
wind_speed: float
pressure: int
location_name: str
rain_1h: Optional[float] = None
visibility: Optional[int] = None
@function_tool
def get_weather(lat: float, lon: float) -> str:
"""Get the current weather for a specified location using OpenWeatherMap API.
Args:
lat: Latitude of the location (-90 to 90)
lon: Longitude of the location (-180 to 180)
"""
# Get API key from environment variables
WEATHER_API_KEY = os.getenv("OPENWEATHERMAP_API_KEY")
# Build URL with parameters
url = f"https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={WEATHER_API_KEY}&units=metric"
try:
response = requests.get(url)
response.raise_for_status()
data = response.json()
# Extract weather data from the response
weather_info = WeatherInfo(
temperature=data["main"]["temp"],
feels_like=data["main"]["feels_like"],
humidity=data["main"]["humidity"],
description=data["weather"][0]["description"],
wind_speed=data["wind"]["speed"],
pressure=data["main"]["pressure"],
location_name=data["name"],
visibility=data.get("visibility"),
rain_1h=data.get("rain", {}).get("1h"),
)
# Build the response string
weather_report = f"""
Weather in {weather_info.location_name}:
- Temperature: {weather_info.temperature}°C (feels like {weather_info.feels_like}°C)
- Conditions: {weather_info.description}
- Humidity: {weather_info.humidity}%
- Wind speed: {weather_info.wind_speed} m/s
- Pressure: {weather_info.pressure} hPa
"""
return weather_report
except requests.exceptions.RequestException as e:
return f"Error fetching weather data: {str(e)}"
Esta herramienta de función actúa como puente entre la API de OpenWeatherMap y nuestro agente. Obtiene datos meteorológicos en tiempo real por coordenadas y los formatea en un informe legible.
El código define una clase de datos WeatherInfo para estructurar la información con tipos (temperatura, humedad, etc.), manteniéndolo organizado y mantenible. El decorador @function_tool transforma nuestra función de Python en una herramienta utilizable por el agente, creando automáticamente un esquema a partir de la firma y la docstring.
Al llamarla, la función recupera de forma segura la clave de API desde variables de entorno, realiza la petición HTTP a OpenWeatherMap y procesa la respuesta JSON.
Gestiona con seguridad campos opcionales como la lluvia y formatea todo en un informe claro, con manejo de errores si falla la petición. Así, el agente puede dar información meteorológica actual en un formato consistente y legible sin conocer los detalles de la API.
# Crea un asistente del tiempo
weather_assistant = Agent(
name="Weather Assistant",
instructions="""You are a weather assistant that can provide current weather information.
When asked about weather, use the get_weather tool to fetch accurate data.
If the user doesn't specify a country code and there might be ambiguity,
ask for clarification (e.g., Paris, France vs. Paris, Texas).
Provide friendly commentary along with the weather data, such as clothing suggestions
or activity recommendations based on the conditions.
""",
tools=[get_weather]
)
Para ejecutar el asistente del tiempo:
async def main():
runner = Runner()
simple_request = await runner.run(weather_assistant, "What are your capabilities?")
request_with_location = await runner.run(weather_assistant, "What's the weather like in Tashkent right now?")
print(simple_request.final_output)
print("-"*70)
print(request_with_location.final_output)
await main()
Output:
I can provide you with the current weather conditions for any location around the world. Just give me the location details, and I'll fetch the weather data for you. I can also offer tips on activities or clothing based on the weather. If you have a specific city in mind, let me know, and I'll get to work!
----------------------------------------------------------------------
The weather in Tashkent is currently lovely with a clear sky. It's around 19.8°C, but it might feel slightly cooler at 18.6°C. The humidity is quite low at 26%, making it a pleasant day to be outdoors. A gentle breeze is blowing at 3.09 m/s, and the air pressure is steady at 1023 hPa.
It's a great time for a picnic in the park or a leisurely walk. Light clothing should be perfect for this weather. Enjoy your day in Tashkent!
La respuesta demuestra que el agente usó correctamente la herramienta de tiempo: identificó la ciudad en el prompt, obtuvo sus coordenadas y las pasó como lat y lon a la herramienta.
Agentes como herramientas
El SDK permite usar los propios agentes como herramientas, habilitando una estructura jerárquica donde agentes especialistas trabajan bajo un coordinador. Es un patrón potente para flujos complejos.
from agents import Agent, Runner
from dotenv import load_dotenv
load_dotenv()
# Agentes especialistas
note_taking_agent = Agent(
name="Note Manager",
instructions="You help users take and organize notes efficiently.",
# En una app real, este agente tendría herramientas de toma de notas
)
task_management_agent = Agent(
name="Task Manager",
instructions="You help users manage tasks, deadlines, and priorities.",
# En una app real, este agente tendría herramientas de gestión de tareas
)
# Agente coordinador que usa especialistas como herramientas
productivity_assistant = Agent(
name="Productivity Assistant",
instructions="""You are a productivity assistant that helps users organize their work and personal life.
For note-taking questions or requests, use the note_taking tool.
For task and deadline management, use the task_management tool.
Help the user decide which tool is appropriate based on their request,
and coordinate between different aspects of productivity.
""",
tools=[
note_taking_agent.as_tool(
tool_name="note_taking",
tool_description="For taking, organizing, and retrieving notes and information"
),
task_management_agent.as_tool(
tool_name="task_management",
tool_description="For managing tasks, setting deadlines, and tracking priorities"
)
]
)
En este ejemplo:
- Creamos dos agentes especialistas, cada uno con un dominio concreto.
- Luego creamos un agente coordinador que puede delegar en ellos.
- Convertimos cada especialista en herramienta con
.as_tool(), indicando:
- Un
tool_namecon el que el coordinador hará referencia a la herramienta. - Un
tool_descriptionque ayuda al coordinador a saber cuándo usarla.
Este patrón permite construir sistemas de agentes complejos manteniendo la separación de responsabilidades. Cada especialista puede tener su propio conjunto de herramientas y conocimientos, mientras el coordinador gestiona la interacción con la persona usuaria y delega en quien corresponda.
Para usar el asistente de productividad:
async def main():
runner = Runner()
result = await runner.run(productivity_assistant, "I need to keep track of my project deadlines")
print(result.final_output)
await main()
Las herramientas transforman a los agentes de simples asistentes conversacionales en sistemas capaces de realizar acciones con impacto en el mundo real. Aunque hemos visto lo básico, esto es solo el principio. Para usos avanzados —incluido el manejo de errores en herramientas de función— consulta la documentación oficial.
Ahora que sabemos equipar a los agentes con herramientas, el siguiente reto es gestionar y estructurar sus salidas. En la próxima sección veremos técnicas para procesar respuestas, desde texto básico hasta datos estructurados complejos, asegurando el formato exacto que necesita tu aplicación.
Entender las salidas de los agentes de OpenAI
Al trabajar con agentes, obtener información estructurada en vez de texto libre hace tus aplicaciones más fiables. El SDK de OpenAI Agents ofrece una forma limpia e integrada de recibir salidas estructuradas directamente desde los agentes.
Salidas estructuradas con modelos Pydantic
El SDK te permite definir exactamente la estructura de datos que quieres que devuelva el agente especificando un parámetro output_type al crearlo:
from pydantic import BaseModel
from typing import List, Optional
from agents import Agent, Runner
from dotenv import load_dotenv
load_dotenv()
True
First, we define our data models using Pydantic:
# Define person data model
class Person(BaseModel):
name: str
role: Optional[str]
contact: Optional[str]
# Define meeting data model
class Meeting(BaseModel):
date: str
time: str
location: Optional[str]
duration: Optional[str]
# Define task data model
class Task(BaseModel):
description: str
assignee: Optional[str]
deadline: Optional[str]
priority: Optional[str]
# Define the complete email data model
class EmailData(BaseModel):
subject: str
sender: Person
recipients: List[Person]
main_points: List[str]
meetings: List[Meeting]
tasks: List[Task]
next_steps: Optional[str]
Estos modelos definen la estructura que queremos para los datos extraídos. Cada clase representa un tipo específico de información a extraer de un correo.
Ahora creamos un agente que devolverá datos en ese formato estructurado configurando el parámetro output_type:
# Crea un agente extractor de emails con salida estructurada
email_extractor = Agent(
name="Email Extractor",
instructions="""You are an assistant that extracts structured information from emails.
When given an email, carefully identify:
- Subject and main points
- People mentioned (names, roles, contact info)
- Meetings (dates, times, locations)
- Tasks or action items (with assignees and deadlines)
- Next steps or follow-ups
Extract this information as structured data. If something is unclear or not mentioned,
leave those fields empty rather than making assumptions.
""",
output_type=EmailData, # Indica al agente que devuelva datos en formato EmailData
)
Al especificar output_type, el agente generará datos estructurados en lugar de texto plano. Esto evita tener que hacer parsing manual de JSON o usar expresiones regulares.
Usemos el extractor con un email de ejemplo:
sample_email = """
From: Alex Johnson <alex.j@techcorp.com>
To: Team Development <team-dev@techcorp.com>
CC: Sarah Wong <sarah.w@techcorp.com>, Miguel Fernandez <miguel.f@techcorp.com>
Subject: Project Phoenix Update and Next Steps
Hi team,
I wanted to follow up on yesterday's discussion about Project Phoenix and outline our next steps.
Key points from our discussion:
- The beta testing phase has shown promising results with 85% positive feedback
- We're still facing some performance issues on mobile devices
- The client has requested additional features for the dashboard
Let's schedule a follow-up meeting this Friday, June 15th at 2:00 PM in Conference Room B. The meeting should last about 1.5 hours, and we'll need to prepare the updated project timeline.
Action items:
1. Sarah to address the mobile performance issues by June 20th (High priority)
2. Miguel to create mock-ups for the new dashboard features by next Monday
3. Everyone to review the beta testing feedback document and add comments by EOD tomorrow
If you have any questions before Friday's meeting, feel free to reach out.
Best regards,
Alex Johnson
Senior Project Manager
(555) 123-4567
"""
Ahora, procesar el email es mucho más sencillo porque el SDK gestiona la conversión:
async def process_email(email_text):
runner = Runner()
result = await runner.run(
email_extractor,
f"Please extract information from this email:\n\n{email_text}"
)
# El resultado ya es un objeto estructurado EmailData
return result
# Procesa el email de ejemplo
result = await process_email(sample_email)
# Muestra la información extraída
result = result.final_output
print(f"Subject: {result.subject}")
print(f"From: {result.sender.name} ({result.sender.role})")
print("\nMain points:")
for point in result.main_points:
print(f"- {point}")
print("\nMeetings:")
for meeting in result.meetings:
print(f"- {meeting.date} at {meeting.time}, Location: {meeting.location}")
print("\nTasks:")
for task in result.tasks:
print(f"- {task.description}")
print(
f" Assignee: {task.assignee}, Deadline: {task.deadline}, Priority: {task.priority}"
)
—----------
Subject: Project Phoenix Update and Next Steps
From: Alex Johnson (Senior Project Manager)
Main points:
- 85% positive feedback from beta testing
- Performance issues on mobile devices
- Client requested additional dashboard features
Meetings:
- June 15th at 2:00 PM, Location: Conference Room B
Tasks:
- Address mobile performance issues
Assignee: Sarah, Deadline: June 20th, Priority: High
- Create mock-ups for new dashboard features
Assignee: Miguel, Deadline: Next Monday, Priority: None
- Review beta testing feedback document and add comments
Assignee: Everyone, Deadline: EOD tomorrow, Priority: None
Este código es mucho más limpio que el enfoque anterior porque:
- No necesitamos extraer ni parsear JSON manualmente.
- El SDK gestiona la conversión de la salida del agente a nuestro modelo Pydantic.
- Podemos acceder directamente a las propiedades estructuradas (como
result.final_output.subject). - La validación de tipos ocurre automáticamente, garantizando que los datos cumplan el modelo.
Trabajar con distintos tipos de salida
El parámetro output_type funciona con cualquier tipo que pueda envolverse en un TypeAdapter de Pydantic:
# Para listas simples
agent_with_list_output = Agent(
name="List Generator",
instructions="Generate lists of items based on the user's request.",
output_type=list[str], # Devuelve una lista de strings
)
# Para diccionarios
agent_with_dict_output = Agent(
name="Dictionary Generator",
instructions="Create key-value pairs based on the input.",
output_type=dict[
str, int
], # Devuelve un diccionario con claves string y valores enteros
)
# Para tipos primitivos
agent_with_bool_output = Agent(
name="Decision Maker",
instructions="Answer yes/no questions with True or False.",
output_type=bool, # Devuelve un booleano
)
Ventajas de las salidas estructuradas
Usar output_type aporta varias ventajas:
- Integración directa: las salidas del agente están disponibles como objetos de Python.
- Seguridad de tipos: el SDK asegura que las salidas cumplan la estructura definida.
- Código más sencillo: sin parsing manual de JSON ni manejo de errores adicional.
- Mejor rendimiento: el SDK realiza la conversión de forma eficiente.
- Soporte del IDE: el autocompletado funciona sobre las propiedades de salida.
Definiendo modelos de datos claros y usando output_type, tus agentes pueden producir exactamente las estructuras que necesita tu aplicación, facilitando la integración y reduciendo la complejidad del código.
En la próxima sección veremos los handoffs entre agentes, lo que permite crear agentes especializados que colaboran en tareas complejas. Estos handoffs pueden usar salidas estructuradas para pasar información entre agentes de forma coherente y con seguridad de tipos.
Handoffs: delegar entre agentes
En aplicaciones complejas, distintas tareas requieren distintas áreas de especialización. El SDK de OpenAI Agents admite “handoffs”, que permiten a un agente delegar el control a otro agente especializado. Esta función es especialmente valiosa al crear sistemas que atienden solicitudes variadas, como atención al cliente donde diferentes agentes gestionan facturación, soporte técnico o gestión de cuentas.
Crear handoffs básicos
En su forma más simple, los handoffs conectan varios agentes para que transfieran el control cuando corresponda. Creemos un sistema sencillo de atención al cliente con un agente de triaje que deriva a especialistas:
from agents import Agent, handoff, Runner
from dotenv import load_dotenv
load_dotenv()
# Agentes especialistas
billing_agent = Agent(
name="Billing Agent",
instructions="""You are a billing specialist who helps customers with payment issues.
Focus on resolving billing inquiries, subscription changes, and refund requests.
If asked about technical problems or account settings, explain that you specialize
in billing and payment matters only.""",
)
technical_agent = Agent(
name="Technical Agent",
instructions="""You are a technical support specialist who helps with product issues.
Assist users with troubleshooting, error messages, and how-to questions.
Focus on resolving technical problems only.""",
)
# Agente de triaje que puede derivar a especialistas
triage_agent = Agent(
name="Customer Service",
instructions="""You are the initial customer service contact who helps direct
customers to the right specialist.
If the customer has billing or payment questions, hand off to the Billing Agent.
If the customer has technical problems or how-to questions, hand off to the Technical Agent.
For general inquiries or questions about products, you can answer directly.
Always be polite and helpful, and ensure a smooth transition when handing off to specialists.""",
handoffs=[billing_agent, technical_agent], # Derivación directa a agentes especialistas
)
En este sistema hemos creado tres agentes:
- Dos especialistas con un enfoque definido
- Un agente de triaje que puede delegar en los especialistas
Observa que solo incluimos los especialistas en el parámetro handoffs del agente de triaje. El SDK crea automáticamente las herramientas de handoff adecuadas para que el agente de triaje las use cuando haga falta.
Veamos el sistema en acción:
async def handle_customer_request(request):
runner = Runner()
result = await runner.run(triage_agent, request)
return result
# Ejemplos de consultas de clientes
billing_inquiry = (
"I was charged twice for my subscription last month. Can I get a refund?"
)
technical_inquiry = (
"The app keeps crashing when I try to upload photos. How can I fix this? Give me the shortest solution possible."
)
general_inquiry = "What are your business hours?"
# Procesamos los distintos tipos de consulta
billing_response = await handle_customer_request(billing_inquiry)
print(f"Billing inquiry response:\n{billing_response.final_output}\n")
technical_response = await handle_customer_request(technical_inquiry)
print(f"Technical inquiry response:\n{technical_response.final_output}\n")
general_response = await handle_customer_request(general_inquiry)
print(f"General inquiry response:\n{general_response.final_output}")
Cuando el agente de triaje recibe una pregunta de facturación, reconoce que el Billing Agent es quien mejor puede gestionarla y activa un handoff. Las preguntas técnicas se derivan al agente técnico. Las preguntas generales se responden directamente. Salida:
Billing inquiry response:
I can help with that. Could you please provide the transaction details or the date of the charges? This will help me locate the duplicate charge and process a refund for you.
Technical inquiry response:
Try these steps:
1. Restart the app.
2. Update to the latest app version.
3. Clear the app cache.
4. Restart your device.
If it persists, reinstall the app.
General inquiry response:
Our business hours are Monday to Friday, 9 AM to 5 PM. If you need assistance outside these hours, feel free to reach out and we'll get back to you as soon as possible. Is there anything else I can help you with?
Personalizar handoffs
Si quieres más control sobre los handoffs, puedes usar la función handoff() en lugar de pasar agentes directamente al parámetro handoffs:
from agents import Agent, handoff, RunContextWrapper
from datetime import datetime
# Agente que gestiona preguntas sobre la cuenta
account_agent = Agent(
name="Account Management",
instructions="""You help customers with account-related issues such as
password resets, account settings, and profile updates.""",
)
# Función de callback personalizada para el handoff
async def log_account_handoff(ctx: RunContextWrapper[None]):
print(
f"[LOG] Account handoff triggered at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
)
# En una app real, podrías registrar esto en una base de datos o avisar a un supervisor
# Agente de triaje con handoffs personalizados
enhanced_triage_agent = Agent(
name="Enhanced Customer Service",
instructions="""You are the initial customer service contact who directs
customers to the right specialist.
If the customer has billing or payment questions, hand off to the Billing Agent.
If the customer has technical problems, hand off to the Technical Agent.
If the customer needs to change account settings, hand off to the Account Management agent.
For general inquiries, you can answer directly.""",
handoffs=[
billing_agent, # Handoff básico
handoff( # Handoff personalizado
agent=account_agent,
on_handoff=log_account_handoff, # Función de callback
tool_name_override="escalate_to_account_team", # Nombre de herramienta personalizado
tool_description_override="Transfer the customer to the account management team for help with account settings, password resets, etc.",
),
technical_agent, # Handoff básico
],
)
result = await Runner.run(
enhanced_triage_agent, "I need to change my password."
)
Salida:
[LOG] Account handoff triggered at 2025-03-16 17:45:48
La función handoff() te permite:
- Especificar un callback personalizado con
on_handoff - Sobrescribir el nombre de herramienta por defecto (normalmente “transfer_to_[agent_name]”)
- Aportar una descripción de herramienta personalizada
- Configurar el manejo de la entrada (más sobre esto abajo)
Pasar datos durante los handoffs
A veces querrás que el primer agente proporcione contexto o metadatos adicionales al derivar a otro. El SDK lo admite mediante el parámetro input_type:
from pydantic import BaseModel
from typing import Optional
from agents import Agent, handoff, RunContextWrapper
# Define la estructura de datos a pasar durante el handoff
class EscalationData(BaseModel):
reason: str
priority: Optional[str]
customer_tier: Optional[str]
# Callback de handoff que procesa los datos de escalado
async def process_escalation(ctx: RunContextWrapper, input_data: EscalationData):
print(f"[ESCALATION] Reason: {input_data.reason}")
print(f"[ESCALATION] Priority: {input_data.priority}")
print(f"[ESCALATION] Customer tier: {input_data.customer_tier}")
# Puedes usar estos datos para priorizar respuestas, alertar a agentes humanos, etc.
# Crea un agente de escalado
escalation_agent = Agent(
name="Escalation Agent",
instructions="""You handle complex or sensitive customer issues that require
special attention. Always address the customer's concerns with extra care and detail.""",
)
# Crea un agente de servicio que pueda escalar con contexto
service_agent = Agent(
name="Service Agent",
instructions="""You are a customer service agent who handles general inquiries.
For complex issues, escalate to the Escalation Agent and provide:
- The reason for escalation
- Priority level (Low, Normal, High, Urgent)
- Customer tier if mentioned (Standard, Premium, VIP)""",
handoffs=[
handoff(
agent=escalation_agent,
on_handoff=process_escalation,
input_type=EscalationData,
)
],
)
Con esta configuración, cuando el agente de servicio decida hacer handoff al agente de escalado, proporcionará datos estructurados sobre el motivo del escalado. El sistema validará estos datos contra el modelo EscalationData antes de pasarlos al callback process_escalation.
Cuándo usar handoffs vs. agente como herramienta
El SDK ofrece dos formas de colaboración entre agentes: handoffs y agentes como herramientas (visto en la sección anterior). Cuándo usar cada enfoque:
Usa handoffs cuando:
- Quieres transferir por completo el control a otro agente
- La conversación debe continuar con una persona especialista
- Estás creando un flujo donde distintos agentes gestionan diferentes etapas
Usa agentes como herramientas cuando:
- El agente principal necesita consultar a un especialista pero mantener el control
- Quieres incorporar la respuesta del especialista como parte de una respuesta mayor
- Estás construyendo un sistema jerárquico donde un coordinador delega subtareas
Ambos enfoques pueden combinarse en sistemas sofisticados, con un agente principal que a veces consulta a especialistas (usándolos como herramientas) y otras veces cede el control por completo cuando corresponde.
Los handoffs son un mecanismo potente para construir sistemas complejos donde la responsabilidad va pasando entre especialistas. Al diseñar tu arquitectura, elige el enfoque que mejor se adapte a tu caso para crear la mejor experiencia de usuario.
Conclusión y próximos pasos
Hemos explorado los componentes clave del SDK de OpenAI Agents: desde crear agentes básicos hasta implementar herramientas de función y gestionar handoffs entre especialistas. Hemos visto cómo las salidas estructuradas con modelos Pydantic hacen las aplicaciones más fiables y mantenibles, y cómo diseñar sistemas de agentes que abordan tareas complejas mediante delegación y especialización.
Aun así, solo hemos arañado la superficie de lo que permite este potente marco. Si quieres llevar tus sistemas de agentes al siguiente nivel, te esperan varios temas avanzados: respuestas en streaming para actualizaciones en tiempo real, trazabilidad y observabilidad para depuración, orquestación multiagente para flujos complejos, gestión del contexto para mantener el estado de la conversación y guardrails para garantizar un comportamiento seguro y adecuado.
A medida que los agentes de IA se vuelven centrales en las aplicaciones modernas, las habilidades que has desarrollado con este tutorial te dan una base sólida para crear sistemas de IA sofisticados. Continúa aprendiendo con recursos como la guía de DataCamp para aprender IA y recuerda que diseñar agentes eficaces es tanto arte como ciencia: requiere iteración, pruebas y un profundo entendimiento de las necesidades de las personas usuarias y de las capacidades de la IA.
Sistemas multiagente con LangGraph
Preguntas frecuentes sobre OpenAI Agents SDK
¿Qué es el OpenAI Agents SDK?
El SDK de OpenAI Agents es un framework en Python que permite a los desarrolladores crear aplicaciones de IA capaces de tomar decisiones y ejecutar acciones. Combina modelos de lenguaje grandes con herramientas y capacidades de coordinación, lo que te permite crear sistemas que resuelven problemas de forma autónoma en lugar de limitarse a responder consultas.
¿Qué tipos de herramientas pueden usar los agentes en el SDK?
El SDK admite tres tipos principales de herramientas: herramientas alojadas (como WebSearchTool, que se ejecutan en los servidores de OpenAI), herramientas de función (funciones de Python personalizadas que amplían las capacidades del agente) y agentes como herramientas (usar agentes especializados como herramientas de otros agentes). Con ellas, los agentes pueden buscar en la web, acceder a APIs o delegar en especialistas.
¿Cómo funcionan las salidas estructuradas en el Agents SDK?
Las salidas estructuradas usan modelos Pydantic para definir exactamente la estructura de datos que quieres recibir del agente. Al establecer el parámetro output_type al crear el agente, obtendrás objetos de datos correctamente formateados en lugar de texto libre. Esto hace que las aplicaciones sean más fiables y elimina la necesidad de parsear manualmente las respuestas.
¿Cuál es la diferencia entre handoffs y agentes como herramientas?
Los handoffs transfieren el control por completo a otro agente, por lo que son ideales cuando la conversación debe continuar con una persona especialista. Los agentes como herramientas permiten que el agente principal consulte a un especialista manteniendo el control e incorporando su respuesta como parte de una contestación mayor. Los handoffs son mejores para transiciones de flujo; los agentes como herramientas funcionan mejor en sistemas jerárquicos.
¿Qué funciones avanzadas ofrece el OpenAI Agents SDK?
Además de la funcionalidad principal, el SDK ofrece streaming para actualizaciones en tiempo real, tracing para depuración y observabilidad, orquestación multiagente para flujos complejos, gestión de contexto para mantener el estado de la conversación y guardrails para garantizar un comportamiento seguro. Estas funciones ayudan a construir sistemas de agentes sofisticados y listos para producción.
Soy creador de contenidos sobre ciencia de datos con más de 2 años de experiencia y uno de los mayores seguimientos en Medium. Me gusta escribir artículos detallados sobre IA y ML con un toque sarcástico, porque hay que darle algo de vidilla al tema. He publicado más de 130 artículos y un curso en DataCamp, y tengo otro en marcha. Mis contenidos han sido vistos por más de 5 millones de personas; 20.000 de ellas se convirtieron en seguidores tanto en Medium como en LinkedIn.




