All articles
October 18, 2025 7 min read

The OpenAI Agents SDK: a small, production-ready way to build agents

OpenAI's Agents SDK is a lightweight, Python-first framework built on a handful of primitives — agents, tools, handoffs, guardrails, and sessions. Here's what each does and when to reach for it.

Written forEngineering
OpenAIAgent FrameworksSDK

In the agent-framework-landscape post I split the field into lightweight, code-first SDKs and heavier orchestration frameworks. The OpenAI Agents SDK is the cleanest example of the first camp: a small, production-ready library — the successor to OpenAI's experimental Swarm — that hands you the agent loop and a few primitives, then gets out of the way. It's Python-first (with a TypeScript version too) and deliberately minimal.

GoalLLM — reason + decideTool call?yesRun toolresultdoneAnswer
The SDK's Runner drives this loop: call the model, run any tools or handoffs it asks for, feed the results back, and repeat until the agent produces a final output.

The philosophy: few primitives

The SDK's whole design is to be small enough to learn in an afternoon. There are really just a handful of concepts — agents, tools, handoffs, guardrails, and sessions — plus a Runner to execute them and built-in tracing to see what happened. You write mostly ordinary Python; the SDK is a thin layer, not a world you move into.

Agents and tools

An Agent is an LLM bundled with its instructions, its tools, its model, and optionally its guardrails. Tools are the interesting part: decorate a plain Python function with @function_tool and the SDK infers the schema from its type hints and docstring, so the model can call it. (It also offers hosted tools like web and file search, and lets you expose one agent as a tool to another.)

An agent with a tool
from agents import Agent, Runner, function_tool

@function_tool
def get_weather(city: str) -> str:
    """Return the current weather for a city."""
    return lookup_weather(city)

agent = Agent(
    name='Assistant',
    instructions='You are a concise, helpful assistant.',
    tools=[get_weather],
)

result = Runner.run_sync(agent, "What's the weather in Paris?")
print(result.final_output)

Handoffs: multi-agent, the lightweight way

Handoffs are the SDK's answer to multi-agent systems. An agent can delegate the conversation to another agent — the classic pattern is a triage agent that routes each request to a specialist. It's the same idea as the routing workflow, but expressed as agents passing control to each other rather than a graph you wire by hand.

A triage agent that hands off
spanish = Agent(name='Spanish', instructions='Respond only in Spanish.')
english = Agent(name='English', instructions='Respond only in English.')

triage = Agent(
    name='Triage',
    instructions='Hand off to the agent for the language the user writes in.',
    handoffs=[spanish, english],
)

Runner.run_sync(triage, 'Hola, ¿qué tiempo hace?')   # → handed to the Spanish agent

Guardrails and sessions

Guardrails run alongside the agent to validate inputs and outputs, and can trip a wire that halts the run before a bad request or response gets through — the input/output safety layer from the guardrails post, built in. Sessions handle conversation memory: pass a session and the SDK stores and replays history across runs automatically, so you're not threading the transcript through every call by hand (the memory-and-state problem, solved for you).

The Runner and tracing

The Runner is what actually executes the agent loop — Runner.run for async, Runner.run_sync for scripts — calling the model, running the tools and handoffs it requests, and looping until there's a final output (with a configurable cap so it can't spin forever). And because debugging agents means seeing every step, the SDK ships tracing out of the box: each run is captured as a trace you can inspect, which is the single most useful thing when something goes wrong.

When to reach for it

  • You want a lean agent and you'll own the orchestration in your own code — this is the least-ceremony way to get there.
  • You're comfortable close to OpenAI's stack (though it works with other models through a Chat Completions-compatible interface, so it's not strictly OpenAI-only).
  • Your multi-agent needs are handoffs and routing, not a complex, durable, stateful graph — if it's the latter, LangGraph is the better fit (see that post).
The OpenAI Agents SDK's strength is what it leaves out. Five primitives, a Runner, and tracing — enough to ship an agent, little enough to still understand it.
Building something with LLMs?
I help teams ship GenAI that’s reliable and cost-efficient.
Let’s talk