Technology Apr 28, 2026 · 12 min read

OpenAI Agents SDK Tutorial: Build Multi-Agent AI Systems in Python (2025)

OpenAI Agents SDK: A Practical Guide to Building Multi-Agent Systems in 2025 How to move beyond single-prompt chatbots and create AI workflows that plan, collaborate, and get things done — with working code you can run today. Your chatbot just forgot what you asked it thirty se...

DE
DEV Community
by Akhilesh Pothuri
OpenAI Agents SDK Tutorial: Build Multi-Agent AI Systems in Python (2025)

OpenAI Agents SDK: A Practical Guide to Building Multi-Agent Systems in 2025

How to move beyond single-prompt chatbots and create AI workflows that plan, collaborate, and get things done — with working code you can run today.

Your chatbot just forgot what you asked it thirty seconds ago. You're three prompts deep into what should be a simple task — "research these companies, compare their pricing, and draft an email to the best one" — and you're manually copy-pasting context between messages like it's 2023. The AI is smart enough to write poetry in iambic pentameter, but somehow can't remember step one by the time you reach step three.

This is the wall every developer hits eventually. Single prompts are incredible for isolated tasks, but the moment you need AI to plan, remember, and coordinate — to actually work like a capable assistant rather than a brilliant amnesiac — the cracks show fast.

By the end of this guide, you'll have a working multi-agent system running on your machine — one where specialized AI agents hand off tasks, share context, and use real tools to get things done without you babysitting every step.

Why Single Prompts Aren't Enough Anymore

Picture this: you're chatting with a customer service bot, explaining a billing issue for the third time because it somehow forgot you already gave your account number. Or you ask an AI to "research competitors and draft a summary email" — and it gives you a generic response instead of actually doing the thing.

That's the ceiling of single-prompt AI. One question, one answer, memory wiped, conversation over.

Here's what single prompts can't do: remember that you mentioned your budget constraint five messages ago, realize they need to check your calendar before suggesting meeting times, or break "plan my product launch" into the dozen actual steps required. They're brilliant at answering questions. They're terrible at getting things done.

The Agent Loop: A To-Do List That Checks Itself

Agents work differently. Think of how you actually tackle a complex task — you make a list, start working, realize you need information you don't have, go get it, update your plan, and keep going. That's the agent loop:

  1. Think → What's my goal? What do I know?
  2. Decide → What should I do next? Do I need a tool?
  3. Act → Call that API, search that database, write that code
  4. Observe → What happened? Did it work?
  5. Repeat → Back to thinking, until the job's done

This is why OpenAI's Agents SDK gained rapid traction in the developer community after its release — developers were tired of duct-taping solutions together. OpenAI didn't build this SDK because agents are trendy. They built it because frameworks like LangChain and CrewAI have amassed tens of thousands of GitHub stars, and developers were asking for a production-ready, first-party solution that just works with OpenAI's models.

The single-prompt era is over. The agent era has arrived.

The Building Blocks: Agents, Tools, and Handoffs Explained Simply

Think of an Agent as an employee with a job description and access to specific tools. When you create an agent, you're essentially writing that job description: "You are a customer service specialist who helps with billing questions" or "You are a code reviewer who checks Python for security issues." The agent isn't magic — it's an LLM that knows its role, its boundaries, and what resources it can use.

Tools are where agents stop being fancy chatbots. A regular LLM can describe how to call a weather API. An agent with tools can actually call it and bring back real data. Tools transform "I can explain this concept" into "I can do this thing for you." In the SDK, a tool is just a Python function with a description — the agent reads what the tool does and decides when to use it.

Handoffs solve the "jack of all trades, master of none" problem. Here's the analogy: imagine calling a company's support line. Instead of one overwhelmed person handling billing, technical issues, AND shipping questions, you get transferred to specialists. Handoffs work the same way. A triage agent takes your request, figures out what kind of problem it is, then hands you off to the billing agent, tech support agent, or logistics agent.

Why does this beat one mega-agent? Three reasons:

  • Smaller context windows — each specialist only needs its domain knowledge
  • Better accuracy — focused instructions outperform sprawling ones
  • Easier debugging — when something breaks, you know exactly which agent failed

These three primitives — agents, tools, and handoffs — are all you need to build surprisingly sophisticated pipelines.

How the Agent Loop Actually Works Under the Hood

The agent loop is where the magic happens — and demystifying it kills the "AI is mysterious" vibe that makes debugging impossible.

Every agent runs on a perception → reasoning → action cycle that repeats until the task is complete. Think of it like a chef working through a recipe. Perception: read the next instruction and check what's in front of you. Reasoning: decide what to do — chop the onion? Adjust the heat? Action: actually do it. Then loop back: perceive the new state, reason about the next step, act again.

In the SDK, each loop iteration makes an API call. The agent receives the current context (perception), the model decides what to do next (reasoning), and it either calls a tool, hands off to another agent, or returns a final response (action). This continues until there's nothing left to do.

Context management is where production agents succeed or fail. Every loop iteration consumes tokens — and context windows aren't infinite. The SDK handles this through message truncation and intelligent summarization, but you control what goes in. The rule: give agents exactly what they need, nothing more. A customer service agent doesn't need your entire product catalog — just the relevant order details.

Structured outputs force predictability. Instead of parsing free-text responses and hoping for the best, you define Pydantic models that the agent must conform to:

class TicketResolution(BaseModel):
    resolved: bool
    action_taken: str
    follow_up_required: bool

The model literally cannot return malformed data. This transforms agents from creative writers into reliable system components — exactly what production demands.

OpenAI Agents SDK vs. LangChain and AutoGen: Honest Comparison

Let's cut through the marketing noise. Each framework has legitimate strengths — and pretending otherwise helps no one.

OpenAI Agents SDK shines when simplicity matters. You get native integration with OpenAI models (no adapter layers), minimal dependencies (just openai and pydantic), and a mental model you can explain in five minutes. If your agents exclusively use OpenAI models and you want to ship this week, it's the obvious choice. The tradeoff? You're locked into their ecosystem.

LangChain (specifically LangGraph) wins on flexibility and ecosystem. Need to swap Claude for GPT-4 mid-project? Want pre-built integrations with dozens of vector databases? LangChain's abstraction layer — despite its reputation for complexity — enables this. LangGraph's explicit state machines handle branching workflows that would require custom code in OpenAI's SDK. The community has also built tooling the newer SDK simply lacks.

AutoGen dominates multi-agent conversations. When you need agents that genuinely debate — a researcher agent challenging a writer agent, or a code-reviewer agent pushing back on generated code — AutoGen's conversation patterns are unmatched. It's the research-first framework, battle-tested in academic settings.

Use Case Best Choice Why
Simple tool-calling agent, OpenAI models only OpenAI Agents SDK Minimal setup, native integration
Multi-provider support, complex RAG pipelines LangGraph Ecosystem, model flexibility
Multi-agent debate/collaboration workflows AutoGen Conversation orchestration
Rapid prototyping with swappable components LangChain Abstraction layer
Production system, OpenAI commitment OpenAI Agents SDK First-party support

The honest answer: most teams should prototype in OpenAI's SDK, evaluate LangGraph if they hit its limitations, and consider AutoGen only for research-heavy applications.

Production Essentials: Guardrails, Tracing, and Not Blowing Your Budget

Here's where prototype code goes to die: production. You've built a beautiful 5-agent workflow on your laptop, and now you need to deploy it without bankrupting your company, leaking customer data, or creating an email-sending monster that apologizes to your entire customer base at 3 AM.

Guardrails: Your agents' babysitter

Think of guardrails as the parental controls you wish you'd had on your first computer. The SDK supports both input and output guardrails—validation functions that run before and after every agent turn.

Input guardrails catch prompt injection, off-topic requests, and malicious inputs before they reach your model. Output guardrails filter responses, redact PII, and enforce business rules. The cardinal rule of production agents: never auto-send anything externally. Emails, Slack messages, API calls to third parties—always require human confirmation or a secondary approval agent. One runaway loop can send 10,000 apology emails in minutes.

Tracing: Because "it worked yesterday" isn't debugging

When agent 3 of 5 starts hallucinating, you need observability. The SDK's built-in tracing captures every LLM call, tool invocation, and handoff in a structured format. Export to your existing observability stack (Datadog, Jaeger, or even simple JSON logs), and you'll actually understand why your customer service agent suddenly recommended competitors.

Cost control: The loop that ate my budget

Agents love to think—and thinking costs money. Essential patterns:

  • Cache aggressively: Identical tool calls don't need fresh LLM roundtrips
  • Model tiering: Use GPT-4o for reasoning, GPT-4o-mini for summarization
  • Hard loop limits: Set max_turns religiously. An agent will happily iterate forever if you let it

Code Walkthrough: Building an "Inbox Zero" Email Triage System

Let's build something real: an email triage system that classifies incoming messages, summarizes the important ones, and drafts responses—all without you touching your inbox until the final review.

Setting up your first agent with tools

from agents import Agent, function_tool, Runner
import json

# Define a tool the agent can use
@function_tool
def fetch_emails(limit: int = 10) -> list[dict]:
    """Fetch unread emails from inbox."""
    # Your IMAP/Gmail API logic here
    return [{"id": "1", "from": "boss@company.com", "subject": "Q3 Report", "body": "..."}]

# Your first agent: the Classifier
classifier = Agent(
    name="EmailClassifier",
    model="gpt-4o-mini",  # Fast and cheap for categorization
    instructions="""Categorize emails as: URGENT, NEEDS_RESPONSE, FYI, or SPAM.
    Return structured JSON with email_id and category.""",
    tools=[fetch_emails],
    output_type={"email_id": str, "category": str}  # Structured output parsing
)

The three-agent pipeline with handoffs

summarizer = Agent(
    name="Summarizer",
    model="gpt-4o-mini",
    instructions="Summarize emails marked URGENT or NEEDS_RESPONSE in 2 sentences max."
)

drafter = Agent(
    name="ResponseDrafter", 
    model="gpt-4o",  # Better model for writing
    instructions="Draft professional responses. Match the sender's tone."
)

# Wire them together with handoffs
classifier.handoffs = [summarizer]  # Classifier can hand off to Summarizer
summarizer.handoffs = [drafter]     # Summarizer can hand off to Drafter

Adding guardrails—because auto-sending emails is terrifying

from agents import input_guardrail, output_guardrail, GuardrailFunctionOutput

@input_guardrail
async def check_for_pii(ctx, agent, input_text):
    """Prevent processing emails with sensitive data markers."""
    sensitive_patterns = ["SSN:", "password:", "credit card:"]
    if any(pattern.lower() in input_text.lower() for pattern in sensitive_patterns):
        return GuardrailFunctionOutput(
            output_info={"reason": "Sensitive data detected"},
            tripwire_triggered=True
        )
    return GuardrailFunctionOutput(output_info={}, tripwire_triggered=False)

# Apply guardrail to drafter
drafter.input_guardrails = [check_for_pii]

# Run it
async def main():
    result = await Runner.run(classifier, input="Process my inbox")
    print(result.final_output)

# Every decision logged via built-in tracing

The SDK's tracing automatically captures each agent's reasoning, tool calls, and handoff decisions—your debugging lifeline when the drafter starts being too creative with responses.

When Agents Make Sense (And When They're Overkill)

Not every problem needs an agent. Before you architect a five-agent pipeline, ask yourself: does this task actually require autonomous decision-making?

Where agents shine:

  • Multi-step research — gathering data from APIs, synthesizing findings, iterating on queries
  • Customer routing — triaging tickets, escalating based on context, handing off to specialists
  • Automated review workflows — code review, document analysis, approval chains with human checkpoints

Where agents are overkill (or actively harmful):

  • Simple Q&A — if one prompt gets the job done, an agent adds latency and failure points
  • Latency-critical applications — each agent loop adds 1-3 seconds; real-time chat suffers
  • Tasks requiring perfect accuracy — agents make autonomous decisions; if you need deterministic output, use traditional code

The "start with one agent" rule

Here's the pattern that kills most agent projects: developers decompose problems into seven specialized agents before validating that one agent can't handle it. Each handoff introduces latency, potential errors, and debugging complexity.

Start with a single agent. Give it tools. Only split when you hit a clear wall—like needing fundamentally different models or system prompts for subtasks. The email triage example above uses three agents because classification, summarization, and drafting genuinely benefit from different instructions. But a "research agent" and "writing agent" for blog posts? Usually one agent with a longer prompt works better.

Three key takeaways for your first production agent:

  1. Add human checkpoints early — you'll sleep better knowing irreversible actions require approval
  2. Log everything — traces aren't optional; they're how you debug at 2 AM
  3. Build the simplest version that could work — complexity is always waiting; don't invite it prematurely

The OpenAI Agents SDK represents a genuine shift in how we build autonomous systems—not because it introduces revolutionary concepts, but because it makes proven patterns accessible. Guardrails, handoffs, and tool use aren't new ideas; they've been battle-tested in production systems for years. What's new is having them packaged in a framework that lets you go from prototype to production without rewriting everything. The SDK won't make your agents smarter, but it will make them more predictable, debuggable, and safe. And in production, predictable beats clever every single time.

Key Takeaways

  • The SDK's real value is structure, not magic — guardrails, handoffs, and tracing give you the scaffolding that separates hobby projects from production systems
  • Resist the urge to over-architect — start with one agent and only split when you have concrete evidence that decomposition solves a real problem
  • Human-in-the-loop isn't a crutch, it's a feature — the best agentic systems know when to pause and ask for help

What's been your experience building with the Agents SDK? Drop a comment below—I'm especially curious about edge cases where the handoff patterns broke down.

DE
Source

This article was originally published by DEV Community and written by Akhilesh Pothuri.

Read original article on DEV Community
Back to Discover

Reading List