← Playbooks

Your first AI agent with the OpenAI Agents SDK in 30 minutes

Build a working Python agent with tools and handoffs using the OpenAI Agents SDK, then inspect it in the trace viewer. Every command checked against the official quickstart.

Who it's for: Developers and technical founders who can run Python and want a real agent, not a chatbot wrapper. Non-coders can follow along but should expect to copy and paste terminal commands.

Time: About 30 minutes · Cost: Free SDK; you pay OpenAI API usage (typically cents for this tutorial)

Tools: OpenAI Agents SDK, ChatGPT, LangSmith, Pydantic AI, LangGraph

Prerequisites:

  • Python 3.10 or newer
  • An OpenAI API key with billing enabled
  • A terminal and a code editor (Cursor, VS Code or similar)

Most “AI agent” tutorials stop at a chatbot. This playbook gets you to the three things that make an agent useful: it can call your code (tools), it can route work to specialists (handoffs), and you can see exactly what happened (traces). We follow the official OpenAI Agents SDK quickstart and extend it into a small but realistic project: a support triage agent for a fictional SaaS product.

What you’ll build

A triage agent that reads a customer message and hands it to either a Billing specialist or a Technical specialist. The technical specialist can call a Python function that looks up a (fake) service status. At the end you’ll have a ~60-line script you can adapt to your own business: swap the fake function for a real API call and you have the bones of a production agent.

Step 1: Create a project and virtual environment

A virtual environment keeps the SDK and its dependencies isolated from the rest of your machine. You only do this once per project:

mkdir triage-agent
cd triage-agent
python -m venv .venv
source .venv/bin/activate      # macOS / Linux
# .venv\Scripts\activate       # Windows

Every time you open a new terminal, re-run the activate line. If your prompt shows (.venv), you’re in.

Step 2: Install the SDK and set your API key

pip install openai-agents
export OPENAI_API_KEY=sk-...          # macOS / Linux
# $env:OPENAI_API_KEY = "sk-..."      # Windows PowerShell

Create the key in the OpenAI platform dashboard under API keys. Note that a ChatGPT subscription is not the same thing as API access: API usage is billed separately, so add a payment method and, ideally, a monthly usage limit before you start experimenting.

Step 3: Define and run a single agent

An agent is a name, instructions, and optional configuration such as a model. Runner.run executes it and returns a result object whose final_output holds the answer. Create main.py:

import asyncio
from agents import Agent, Runner

agent = Agent(
    name="Support Assistant",
    instructions="You answer questions about Acme App clearly and briefly.",
)

async def main():
    result = await Runner.run(agent, "How do I reset my password?")
    print(result.final_output)

if __name__ == "__main__":
    asyncio.run(main())

Run python main.py. You should see a short answer. Congratulations, that’s an agent, though not a very capable one yet. It has no access to real data, so anything it says about “Acme App” is made up. That’s the problem tools solve.

Step 4: Give the agent a tool

Tools are ordinary Python functions the model can choose to call. The SDK reads the function’s name, type hints and docstring to describe it to the model, so write the docstring as if you’re explaining the function to a new teammate. The SDK exposes a function_tool decorator (current docs also show tool from agents.decorators; both are available in version 0.24):

from agents import Agent, Runner, function_tool

@function_tool
def service_status(region: str) -> str:
    """Return the current status of Acme App in a region such as 'us' or 'eu'."""
    fake = {"us": "operational", "eu": "degraded: login latency"}
    return fake.get(region.lower(), "unknown region")

Then pass it to an agent with tools=[service_status]. When a user writes “Login is slow in Europe, is something wrong?”, the model can decide to call service_status("eu") and ground its answer in the result. In real life this function would call your status page API, database or CRM. Keep tools narrow (one job each) and safe (read-only first; add write actions only once you trust the flow).

Step 5: Add specialist agents and handoffs

The SDK documents two multi-agent patterns. Handoffs let a specialist take over the conversation; agents as tools keep an orchestrator in charge. We’ll use handoffs, as the quickstart does. handoff_description tells the routing agent when to delegate:

billing = Agent(
    name="Billing",
    handoff_description="Questions about invoices, refunds, plans and payment methods",
    instructions="You handle billing questions. Never promise refunds; explain the policy and offer to escalate.",
)

technical = Agent(
    name="Technical",
    handoff_description="Bugs, outages, login problems and how-to questions",
    instructions="Diagnose technical issues. Check service_status before blaming the user.",
    tools=[service_status],
)

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

async def main():
    result = await Runner.run(triage, "Login is super slow for our team in Germany today.")
    print(result.final_output)
    print("Answered by:", result.last_agent.name)

result.last_agent.name tells you which specialist finished the job: a cheap but very useful assertion for tests. Try five or six different messages (a refund request, a feature question, an ambiguous one) and check that routing behaves.

Step 6: Inspect traces

Open the Trace viewer in the OpenAI Dashboard. Each run shows the triage call, the handoff, the tool call with its arguments and output, and the final answer. This is where you debug: if the agent routed wrongly, read what the triage agent saw and tighten its instructions or the handoff_description text. If you want vendor-neutral observability across frameworks, tools like LangSmith also ingest agent traces.

Step 7: Add conversation memory

A single Runner.run call is one turn. For a second turn the quickstart lists three options:

  1. Manual: pass result.to_input_list() plus the new user message back into Runner.run. Full control, provider-agnostic.
  2. Sessions: pass session=... and let the SDK load and save history for you.
  3. Server-managed: reuse OpenAI-side state with previous_response_id or conversation_id.

For a prototype, sessions are the least code. For anything where you must control retention (customer data!), the manual approach makes it obvious what you store and where.

Step 8: Harden it before sharing

Before anyone else uses your agent:

Pitfalls

Where to go next

Compare the SDK with LangGraph if you need explicit state machines, or Pydantic AI if structured, validated outputs matter most. If you want to give the agent access to tools other people have already built, read our MCP servers playbook: MCP is supported across many agent frameworks. And when you’re ready to run models privately, see Run local models with Ollama.

FAQ

Is the OpenAI Agents SDK free?

The SDK itself is open source and free to install with pip install openai-agents. You pay for the model calls it makes through your OpenAI API account.

Do I need to use OpenAI models?

The SDK is designed around OpenAI's APIs but its documentation covers using other model providers. Start with OpenAI for the simplest setup, then swap models once your agent works.

What is the difference between handoffs and agents-as-tools?

With a handoff, a specialist agent takes over the conversation for that part of the turn. With agents-as-tools, an orchestrator stays in control and calls specialists like functions. The official quickstart uses handoffs because it is the shortest example.

Where can I see what my agent did?

Runs are traced by default and appear in the Trace viewer in the OpenAI Dashboard, where you can see each model call, tool call and handoff.

How is this different from LangGraph or Pydantic AI?

All three build agents in Python. The Agents SDK is a small set of primitives (agents, tools, handoffs, guardrails, sessions). LangGraph models agents as explicit graphs with state, and Pydantic AI emphasizes typed, validated outputs. Pick the one whose mental model matches your project.

Last checked against official docs: October 2026 (openai-agents 0.24 on PyPI). Prices and UI labels change; confirm on each vendor's site.