The OpenAI Agents SDK is a lightweight Python framework for building multi-agent AI applications with minimal abstractions. Released as the production-ready successor to Swarm, it gives you agents, tools, handoffs, and guardrails — all in a package you can learn in an afternoon. If your team orchestrates AI agents across workflows, platforms like cowork.ink can help you manage them at scale.
This guide covers everything from installation to building a multi-agent pipeline with real code examples.
Install with pip install openai-agents, set your OPENAI_API_KEY, and you can have a working agent in under 10 lines of Python.
What You Need Before Starting
Before writing your first agent, make sure you have:
- Python 3.10 or newer installed on your machine
- An OpenAI API key — grab one from platform.openai.com
- Basic Python knowledge — the SDK uses async/await and type hints
No other dependencies are required. The SDK deliberately avoids heavy abstractions, so if you know Python, you already know most of what you need.
Step 1: Install the OpenAI Agents SDK
Create a project directory, set up a virtual environment, and install the package:
mkdir my-agent-project && cd my-agent-project
python -m venv .venv
source .venv/bin/activate
pip install openai-agents
Then export your API key:
export OPENAI_API_KEY=sk-your-key-here
Never hardcode API keys in source files. Use environment variables or a .env file with python-dotenv.
Step 2: Build Your First Agent
An Agent is the core primitive — an LLM equipped with instructions and optional tools. Here is the simplest possible agent:
from agents import Agent, Runner
import asyncio
agent = Agent(
name="History Tutor",
instructions="You answer history questions clearly and concisely.",
)
async def main():
result = await Runner.run(agent, "When did the Roman Empire fall?")
print(result.final_output)
asyncio.run(main())
That is it. The Runner handles the entire agent loop — sending the prompt, processing tool calls, and returning the final output. For quick scripts, you can also use Runner.run_sync() to skip the async boilerplate.
Step 3: Add Tools to Your Agent
Tools let agents take actions beyond generating text. The SDK supports four types:
| Tool Type | Runs Where | Example |
|---|---|---|
| Function tools | Your machine | Custom Python functions |
| Hosted tools | OpenAI servers | WebSearchTool, FileSearchTool, CodeInterpreterTool |
| Agents as tools | Your machine | Delegate to a specialist agent |
| MCP tools | External servers | Any MCP-compatible service |
For deeper context on how tool calling works across frameworks, see our guide to AI agent tool calling.
Function Tools
Wrap any Python function with the @function_tool decorator. The SDK auto-generates the JSON schema from type hints and docstrings:
from agents import Agent, Runner, function_tool
import asyncio
@function_tool
def get_weather(city: str) -> str:
"""Fetch the current weather for a city."""
# In production, call a real weather API here
return f"It's 22°C and sunny in {city}."
agent = Agent(
name="Weather Bot",
instructions="Help users check the weather.",
tools=[get_weather],
)
async def main():
result = await Runner.run(agent, "What's the weather in Berlin?")
print(result.final_output)
asyncio.run(main())
Hosted Tools
OpenAI provides tools that run on their infrastructure, so you don't need to manage APIs yourself:
from agents import Agent, WebSearchTool
agent = Agent(
name="Researcher",
instructions="Answer questions using web search.",
tools=[WebSearchTool()],
)
Other hosted tools include FileSearchTool for vector store retrieval, CodeInterpreterTool for sandboxed code execution, and ImageGenerationTool for creating images.
Step 4: Connect Agents with Handoffs
Handoffs are what make the SDK a true multi-agent framework. A handoff transfers control from one agent to a specialist when the model decides a different agent is better suited.
from agents import Agent, Runner
import asyncio
history_agent = Agent(
name="History Tutor",
instructions="You answer history questions. If asked about math, hand off.",
handoffs=[] # will be set below
)
math_agent = Agent(
name="Math Tutor",
instructions="You answer math questions. If asked about history, hand off.",
handoffs=[]
)
# Wire up cross-handoffs
history_agent.handoffs = [math_agent]
math_agent.handoffs = [history_agent]
triage_agent = Agent(
name="Triage Agent",
instructions="Route each question to the right tutor.",
handoffs=[history_agent, math_agent],
)
async def main():
result = await Runner.run(triage_agent, "What is 15% of 280?")
print(result.final_output)
asyncio.run(main())
The triage agent inspects the user's question and hands off to the math tutor — no if/else routing in your code. The model handles the decision. For more patterns like this, read our AI agent orchestration guide.
Step 5: Add Guardrails for Safety
Guardrails validate inputs and outputs in parallel with agent execution, so you can catch unsafe or off-topic content early. For a comprehensive look at safety patterns, check our AI agent guardrails guide.
Input Guardrails
Run a check on the user's message before (or alongside) the main agent:
from agents import Agent, Runner, input_guardrail, GuardrailFunctionOutput
from pydantic import BaseModel
class SafetyCheck(BaseModel):
is_unsafe: bool
reasoning: str
safety_agent = Agent(
name="Safety Check",
instructions="Determine if the input contains harmful requests.",
output_type=SafetyCheck,
)
@input_guardrail
async def safety_guardrail(ctx, agent, input):
result = await Runner.run(safety_agent, input, context=ctx.context)
return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=result.final_output.is_unsafe,
)
main_agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
input_guardrails=[safety_guardrail],
)
When the guardrail's tripwire_triggered returns True, the SDK raises an exception and stops the agent — no unsafe output reaches the user.
Output Guardrails
Same pattern, but applied to the agent's response after generation. Useful for catching hallucinations, PII leaks, or off-topic answers.
Step 6: Enable Tracing and Debugging
The SDK includes built-in tracing that records every LLM call, tool invocation, handoff, and guardrail check. Traces are viewable in the OpenAI Traces dashboard.
Tracing is on by default. To wrap multiple runner calls into a single trace:
from agents import Agent, Runner, trace
async def main():
agent = Agent(name="Joke Bot", instructions="Tell jokes.")
with trace("Joke Workflow"):
joke = await Runner.run(agent, "Tell me a joke")
rating = await Runner.run(agent, f"Rate this joke: {joke.final_output}")
print(rating.final_output)
To disable tracing, set the environment variable OPENAI_AGENTS_DISABLE_TRACING=1 or use set_tracing_disabled(True) in code.
Over 20 observability platforms integrate with the SDK's tracing — including Langfuse, Weights & Biases, and Pydantic Logfire. For more on monitoring agent systems, see our AI agent monitoring guide.
Practical Example: Research Agent Pipeline
Here is a more complete example that combines tools, handoffs, and structured output into a mini research pipeline:
from agents import Agent, Runner, function_tool, WebSearchTool
from pydantic import BaseModel
import asyncio
class ResearchReport(BaseModel):
title: str
summary: str
key_findings: list[str]
sources: list[str]
@function_tool
def save_report(report_json: str) -> str:
"""Save the research report to a file."""
with open("report.json", "w") as f:
f.write(report_json)
return "Report saved successfully."
researcher = Agent(
name="Researcher",
instructions="""Search the web for information on the given topic.
Compile findings into a structured report.""",
tools=[WebSearchTool()],
output_type=ResearchReport,
)
writer = Agent(
name="Writer",
instructions="""Take the research report and write a polished summary.
Save it using the save_report tool.""",
tools=[save_report],
)
orchestrator = Agent(
name="Orchestrator",
instructions="""You manage a research workflow:
1. Hand off to Researcher for data gathering.
2. Hand off to Writer for polishing and saving.""",
handoffs=[researcher, writer],
)
async def main():
result = await Runner.run(
orchestrator,
"Research the current state of AI agent frameworks in 2026."
)
print(result.final_output)
asyncio.run(main())
This pattern — triage agent delegates to specialists who have their own tools — scales naturally. You can add more agents without rewriting orchestration logic.
OpenAI Agents SDK vs Other Frameworks
How does the Agents SDK compare to other popular frameworks? Here is a quick overview based on our full framework comparison:
| Feature | OpenAI Agents SDK | LangGraph | CrewAI |
|---|---|---|---|
| Learning curve | Lowest (~1 day) | Steepest (~1-2 weeks) | Moderate (~3-5 days) |
| Core abstraction | Agents + Handoffs | State graphs | Role-based crews |
| Built-in tracing | Yes (OpenAI dashboard) | Via LangSmith | Via third-party |
| Guardrails | Native | Manual | Manual |
| Model support | OpenAI-first, any via LiteLLM | Model-agnostic | Model-agnostic |
| Best for | Fast prototyping, OpenAI stack | Complex stateful workflows | Role-based multi-agent teams |
| GitHub stars | 18K+ | 12K+ | 44K+ |
The Agents SDK is the fastest path from zero to a working agent if you are already in the OpenAI ecosystem. For complex state management, LangGraph gives more control. For role-based collaboration, CrewAI has the most intuitive API.
Tips for Production Deployments
Once your prototype works, keep these best practices in mind:
- Use structured outputs. Define Pydantic models as
output_typeon agents to guarantee response shape and enable downstream validation. - Set timeouts on tools. Use
@function_tool(timeout=5.0)to prevent a single slow API call from blocking your pipeline. - Handle guardrail failures gracefully. Catch
InputGuardrailTripwireTriggeredandOutputGuardrailTripwireTriggeredexceptions and return user-friendly error messages. - Manage memory with sessions. The SDK offers three approaches — manual history via
result.to_input_list(), session-based persistence, or server-managed state withconversation_id. - Monitor costs. Each agent turn costs API tokens. Use built-in tracing to track per-agent token usage and identify expensive steps.
- Run guardrails in blocking mode for sensitive apps. Set
run_in_parallel=Falseon input guardrails to ensure the agent never executes before the safety check passes.
Get Started
The OpenAI Agents SDK strips away the complexity that other frameworks pile on. You get agents, tools, handoffs, and guardrails — nothing more, nothing less.
Start with the official quickstart, build a single agent, then add tools and handoffs as your use case grows. When you need to coordinate multiple agents across your team, cowork.ink gives your entire engineering org a shared workspace for managing AI agents — no prompt gymnastics required.