Use when building AI agents with OpenAI's Agents SDK. Triggers include creating agents, implementing tools, multi-agent handoffs, guardrails, MCP integration, tracing. Also for using LiteLLM to run agents on free/alternative models (Anthropic, Gemini). NOT for general OpenAI API usage (use openai-python SDK docs instead).
Scanned 6/2/2026
Install to Claude Code
npx -y skills add majiayu000/claude-skill-registry --skill building-with-openai-agents --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Building With Openai Agents?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/majiayu000-building-with-openai-agents)More formats (shields.io, HTML) on the badges page.
---
name: building-with-openai-agents
description: Use when building AI agents with OpenAI's Agents SDK. Triggers include creating agents, implementing tools, multi-agent handoffs, guardrails, MCP integration, tracing. Also for using LiteLLM to run agents on free/alternative models (Anthropic, Gemini). NOT for general OpenAI API usage (use openai-python SDK docs instead).
---
# Building with OpenAI Agents SDK
Production-ready agent framework with minimal abstractions, released March 2025.
## Persona
You are an OpenAI Agents SDK expert with production experience. You understand:
- Official SDK patterns from openai-agents-python
- LiteLLM integration for alternative model providers
- MCP (Model Context Protocol) integration patterns
- Multi-agent orchestration with handoffs
- Production guardrails and safety patterns
## Quick Start
### Installation
```bash
pip install openai-agents
export OPENAI_API_KEY=sk-...
```
For alternative models (free/low-cost):
```bash
pip install "openai-agents[litellm]"
```
### Hello World
```python
from agents import Agent, Runner
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant."
)
result = Runner.run_sync(agent, "Hello!")
print(result.final_output)
```
### With LiteLLM (Free Models)
```python
from agents import Agent, Runner
from agents.extensions.models.litellm_model import LitellmModel
# Use any of 100+ models via LiteLLM
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
model=LitellmModel(
model="anthropic/claude-3-5-sonnet-20240620",
api_key="your-anthropic-key"
)
)
result = await Runner.run(agent, "Hello!")
```
Supported prefixes: `anthropic/`, `gemini/`, `bedrock/`, `azure/`, `mistral/`
## Core Primitives
| Primitive | Purpose |
|-----------|---------|
| **Agent** | LLM with instructions, tools, handoffs |
| **Tool** | Python function the agent can call |
| **Handoff** | Transfer control to another agent |
| **Guardrail** | Validate input/output before processing |
| **Session** | Automatic conversation history |
| **Runner** | Executes the agent loop |
## Creating Agents
```python
from agents import Agent
agent = Agent(
name="Customer Support",
instructions="You help customers with their orders.",
model="gpt-4o", # or use LitellmModel
tools=[get_order_status, create_refund],
handoffs=[billing_agent, shipping_agent],
output_type=OrderResponse, # Structured output
)
```
### Dynamic Instructions
```python
def dynamic_instructions(context, agent):
user = context.context.user_name
return f"You are helping {user} with their account."
agent = Agent(
name="Support",
instructions=dynamic_instructions
)
```
## Function Tools
### Basic Tool
```python
from agents import function_tool
@function_tool
def get_weather(city: str) -> str:
"""Get weather for a city.
Args:
city: The city name.
"""
return f"Weather in {city}: Sunny, 72F"
```
### Async Tool
```python
@function_tool
async def fetch_order(order_id: str) -> dict:
"""Fetch order details from database."""
order = await db.orders.get(order_id)
return order.dict()
```
### Tool with Pydantic
```python
from pydantic import BaseModel
class Location(BaseModel):
city: str
country: str = "USA"
@function_tool
def search_restaurants(location: Location, cuisine: str) -> list:
"""Search restaurants by location and cuisine."""
return [...]
```
### Tool Error Handling
```python
def custom_error(e: Exception) -> str:
return f"Tool failed: {str(e)}. Try a different approach."
@function_tool(failure_error_function=custom_error)
def risky_operation(data: str) -> str:
"""Perform risky operation."""
...
```
## Multi-Agent Handoffs
### Basic Handoff
```python
from agents import Agent, handoff
billing_agent = Agent(
name="Billing Agent",
instructions="Handle billing questions."
)
support_agent = Agent(
name="Support Agent",
instructions="Handle general support.",
handoffs=[billing_agent] # Can hand off to billing
)
```
### Handoff with Callback
```python
from pydantic import BaseModel
from agents import handoff, RunContextWrapper
class EscalationData(BaseModel):
reason: str
priority: str
async def on_escalate(ctx: RunContextWrapper, data: EscalationData):
await log_escalation(data.reason, data.priority)
escalation_handoff = handoff(
agent=escalation_agent,
on_handoff=on_escalate,
input_type=EscalationData,
tool_name_override="escalate_to_human"
)
```
### Two Multi-Agent Patterns
**Pattern 1: Manager (Agents as Tools)**
- Central orchestrator invokes sub-agents as tools
- Orchestrator retains control
- Best for: predictable workflows, classification
```python
# Sub-agent as tool
research_agent = Agent(name="Researcher", ...)
writer_agent = Agent(name="Writer", ...)
manager = Agent(
name="Manager",
tools=[
research_agent.as_tool(
tool_name="do_research",
tool_description="Research a topic"
),
writer_agent.as_tool(
tool_name="write_content",
tool_description="Write content"
)
]
)
```
**Pattern 2: Handoffs (Peer Agents)**
- Specialized agents hand off to each other
- Receiving agent takes full control
- Best for: customer support flows, expert routing
```python
triage_agent = Agent(
name="Triage",
instructions="Route to appropriate specialist.",
handoffs=[billing_agent, technical_agent, sales_agent]
)
```
## Guardrails
### Input Guardrail
```python
from agents import Agent, input_guardrail, GuardrailFunctionOutput
@input_guardrail
async def check_no_pii(ctx, agent, input: str) -> GuardrailFunctionOutput:
has_pii = detect_pii(input)
return GuardrailFunctionOutput(
output_info={"has_pii": has_pii},
tripwire_triggered=has_pii
)
agent = Agent(
name="Support",
input_guardrails=[check_no_pii]
)
```
### Output Guardrail
```python
from agents import output_guardrail
@output_guardrail
async def check_no_secrets(ctx, agent, output: str) -> GuardrailFunctionOutput:
has_secrets = scan_for_secrets(output)
return GuardrailFunctionOutput(
output_info={"scanned": True},
tripwire_triggered=has_secrets
)
agent = Agent(
name="CodeHelper",
output_guardrails=[check_no_secrets]
)
```
### Handle Guardrail Failures
```python
from agents import InputGuardrailTripwireTriggered
try:
result = await Runner.run(agent, user_input)
except InputGuardrailTripwireTriggered as e:
print(f"Blocked: {e.guardrail_result.output_info}")
```
## MCP Integration
### Stdio Server (Local Process)
```python
from agents import Agent
from agents.mcp import MCPServerStdio
async with MCPServerStdio(
name="Filesystem",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
}
) as mcp_server:
agent = Agent(
name="FileHelper",
mcp_servers=[mcp_server]
)
result = await Runner.run(agent, "List files in /path")
```
### HTTP Server (Remote)
```python
from agents.mcp import MCPServerStreamableHttp
async with MCPServerStreamableHttp(
name="Remote Tools",
params={
"url": "https://mcp.example.com/mcp",
"headers": {"Authorization": f"Bearer {token}"}
}
) as server:
agent = Agent(mcp_servers=[server])
```
### Tool Filtering
```python
from agents.mcp import MCPServerStdio, create_static_tool_filter
server = MCPServerStdio(
params={...},
tool_filter=create_static_tool_filter(
allowed_tool_names=["read_file", "list_directory"]
)
)
```
## Sessions (Conversation Memory)
### SQLite (Simple)
```python
from agents import SQLiteSession
# In-memory (lost on restart)
session = SQLiteSession("user_123")
# File-based (persistent)
session = SQLiteSession("user_123", "conversations.db")
result = await Runner.run(agent, "Hello", session=session)
# Next run automatically includes history
result = await Runner.run(agent, "What did I say?", session=session)
```
### SQLAlchemy (Production)
```python
from agents import SQLAlchemySession
session = SQLAlchemySession.from_url(
"user_123",
url="postgresql+asyncpg://user:pass@localhost/db",
create_tables=True
)
```
## Streaming
```python
result = await Runner.run_streamed(agent, "Tell me a story")
async for event in result.stream_events():
if event.type == "raw_response_event":
print(event.data, end="", flush=True)
```
## Structured Outputs
```python
from pydantic import BaseModel
class OrderAnalysis(BaseModel):
sentiment: str
urgency: int
action_required: bool
agent = Agent(
name="Analyzer",
instructions="Analyze customer orders.",
output_type=OrderAnalysis
)
result = await Runner.run(agent, "My order is late!")
analysis: OrderAnalysis = result.final_output
print(f"Urgency: {analysis.urgency}")
```
## Tracing
Tracing is enabled by default. View in OpenAI Dashboard.
### Custom Spans
```python
from agents import trace
with trace("Customer Support Flow"):
result1 = await Runner.run(triage, query)
result2 = await Runner.run(specialist, query)
```
### Disable Tracing (for non-OpenAI models)
```python
from agents import set_tracing_disabled
set_tracing_disabled(True)
```
## Decision Logic
| Situation | Pattern |
|-----------|---------|
| Single agent, simple task | Basic Agent |
| Need conversation history | Add Session |
| Multiple specialized tasks | Handoffs between agents |
| Predictable routing | Manager with agents-as-tools |
| User-facing validation | Input guardrails |
| Output safety checks | Output guardrails |
| External tool ecosystem | MCP integration |
| Non-OpenAI models | LiteLLM |
## TaskManager Example
Complete example building a task management agent:
```python
from agents import Agent, Runner, function_tool
from pydantic import BaseModel
from typing import Optional
# Task model
class Task(BaseModel):
id: str
title: str
completed: bool = False
# In-memory storage
tasks: dict[str, Task] = {}
@function_tool
def add_task(title: str) -> str:
"""Add a new task."""
task_id = f"task_{len(tasks) + 1}"
tasks[task_id] = Task(id=task_id, title=title)
return f"Created task {task_id}: {title}"
@function_tool
def list_tasks() -> str:
"""List all tasks."""
if not tasks:
return "No tasks yet."
return "\n".join(
f"[{'x' if t.completed else ' '}] {t.id}: {t.title}"
for t in tasks.values()
)
@function_tool
def complete_task(task_id: str) -> str:
"""Mark a task as completed."""
if task_id not in tasks:
return f"Task {task_id} not found."
tasks[task_id].completed = True
return f"Completed: {tasks[task_id].title}"
# Create agent
task_agent = Agent(
name="TaskManager",
instructions="""You help users manage their tasks.
Use add_task to create tasks, list_tasks to show them,
and complete_task to mark them done.""",
tools=[add_task, list_tasks, complete_task]
)
# Run
async def main():
result = await Runner.run(
task_agent,
"Add a task to buy groceries, then list all tasks"
)
print(result.final_output)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
```
## Safety
### NEVER
- Expose API keys in code or logs
- Skip error handling for API calls
- Trust user input without validation
- Ignore rate limits
### ALWAYS
- Use environment variables for secrets
- Wrap API calls in try/except
- Implement input guardrails for user-facing agents
- Use output guardrails for sensitive content
- Test with tracing enabled
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `MaxTurnsExceeded` | Agent loops too long | Increase `max_turns` in RunConfig |
| `ModelBehaviorError` | Invalid LLM output | Check model compatibility |
| `InputGuardrailTripwireTriggered` | Input blocked | Handle exception, provide feedback |
## References
- [Official Docs](https://openai.github.io/openai-agents-python/)
- [GitHub Repo](https://github.com/openai/openai-agents-python)
- [LiteLLM Providers](https://docs.litellm.ai/docs/providers)
- [Customer Service Demo](https://github.com/openai/openai-cs-agents-demo)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!