All posts
AI AgentsOpenAITutorial

Building AI Agents with the OpenAI Agents SDK: A Practical Guide

OpenAI's Agents SDK is a small, production-minded framework built on four ideas: agents, tools, handoffs, and guardrails. This is the runnable tour — from your first agent to a multi-agent triage system with safety rails.

AS
AgentSwarms Authors
July 10, 2026· 16 min read·
AI AgentsOpenAITutorial

OpenAI's Agents SDK is refreshingly small. Where some frameworks give you fifty concepts, this one gives you four that matter — agents, tools, handoffs, and guardrails — plus sessions and tracing that mostly stay out of your way. It's the production-minded successor to OpenAI's earlier Swarm experiment, and its whole design philosophy is that you shouldn't need to learn a framework to build an agent; you should need to learn agents. This guide is the runnable tour: we'll build a single agent, give it tools, turn it into a multi-agent triage system, and put a safety rail on the front — with code you can paste and run at each step.

Agents

An LLM with instructions, a model, and tools. The core unit you compose everything from.

Six primitives. Everything you build with the SDK is a combination of these.

The whole SDK in six primitives. Learn these and you've learned the framework — tap through them.

Your first agent

An agent is an LLM with instructions and, optionally, tools. A tool is any Python function you decorate with @function_tool — the SDK reads its signature and docstring to build the schema the model sees. And a Runner drives the loop for you: it calls the model, runs any tool the model requests, feeds the result back, and returns the final answer. Here's the whole thing:

# pip install openai-agents
from agents import Agent, Runner, function_tool

@function_tool
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"It's 18°C and clear in {city}."

agent = Agent(
    name="Weather Assistant",
    instructions="You are concise. Use get_weather when asked about the weather.",
    tools=[get_weather],
)

result = Runner.run_sync(agent, "What's the weather in Tokyo?")
print(result.final_output)  # -> "It's 18°C and clear in Tokyo."

That's a complete, tool-using agent in a dozen lines. Runner.run_sync is the synchronous convenience wrapper; in an async app you'd await Runner.run(agent, ...) instead. Either way, result.final_output is your answer. Under the hood, the SDK ran this loop:

Step through one Runner.run call.

The Runner drives the loop for you: it calls tools, feeds results back, and stops at a final answer.

One Runner.run call, stepped. The Runner handles the reason → call tool → observe → answer loop so you don't write it.

Handoffs: multi-agent, the OpenAI way

The SDK's answer to multi-agent systems is the handoff: one agent can delegate the conversation to another. You build specialists as ordinary agents, give each a handoff_description so the router knows what it's for, and list them on a triage agent's handoffs. The routing is the model's decision — you write no dispatch logic.

from agents import Agent, Runner

billing = Agent(
    name="Billing",
    handoff_description="Handles charges, invoices and refunds",
    instructions="Resolve billing questions. Be precise about amounts.",
)
tech = Agent(
    name="Tech",
    handoff_description="Handles bugs, errors and login problems",
    instructions="Help the user troubleshoot technical issues.",
)

triage = Agent(
    name="Triage",
    instructions="Route each request to the right specialist.",
    handoffs=[billing, tech],
)

result = Runner.run_sync(triage, "I was double-charged for my order.")
print(result.final_output)
TriageBillingTechSales
Billing agent replies

I see the duplicate charge and I've issued a refund.

A triage agent with `handoffs=[…]` routes each message to the right specialist — no routing code of your own.

The triage pattern. The triage agent reads each message and hands off to the specialist whose description fits — pick a message to see where it routes.

Guardrails: stop a bad run before it costs you

Guardrails are cheap checks that run alongside your agent and can abort it before it spends money or does harm. An input guardrail inspects the incoming request; if it trips its wire, the run halts immediately. The shape is a decorated function that returns a GuardrailFunctionOutput with tripwire_triggered set:

from agents import Agent, input_guardrail, GuardrailFunctionOutput

@input_guardrail
async def block_injection(ctx, agent, user_input) -> GuardrailFunctionOutput:
    tripped = "ignore your rules" in str(user_input).lower()
    return GuardrailFunctionOutput(output_info={"blocked": tripped}, tripwire_triggered=tripped)

agent = Agent(
    name="Support",
    instructions="Answer support questions from the knowledge base.",
    input_guardrails=[block_injection],
)
input: “what's my order status?”
guardrailtripwire_triggered = False

The guardrail passes and the agent runs normally.

The tripwire. A malicious input trips the guardrail and the run is aborted before the agent ever sees it. Toggle the input.
Cheap guardrail, expensive agent

The point of a guardrail is economics: run a fast, cheap classifier first so your expensive agent never processes input that was always going to be rejected. Output guardrails work the same way on the way out.

Sessions and tracing come for free

Two things you'd normally have to build yourself are built in. Sessions persist conversation history across Runner.run calls, so the agent remembers without you re-sending the transcript. And tracing records every run, tool call, and handoff automatically — which is the difference between debugging an agent and guessing at it. Both are opt-in defaults rather than extra libraries to wire up.

When to reach for the OpenAI Agents SDK

Its sweet spot is exactly its design: you want a small, well-supported framework, you're comfortable in the OpenAI ecosystem, and you value handoffs and built-in tracing over maximal control of the graph. If you need custom control flow — arbitrary loops, branching, human-in-the-loop pauses — a graph-based framework like LangGraph gives you more room, and if you want a role-based team, CrewAI is faster to stand up. Our framework comparison lines them up honestly.

Learn it by running it

Reading the code is one thing; running it is where it sticks. The OpenAI Agents SDK notebook track builds every concept here in the browser, cell by cell — the run loop, handoffs and triage, input and output guardrails, structured output, sessions, and streaming with tracing. And once you've got an agent you like, the Agent Builder lets you ship it — and the 15 agent examples give you working patterns to start from.

The reason this SDK is a good first framework is the reason it's a good last one: it doesn't hide the agent from you. Four primitives, a loop you can see, and the safety and observability you need in production — build one agent with it and you'll understand every other framework faster.


Was this useful?

Comments

Sign in to join the discussion.

Loading comments…