Text size
Dark mode
RecallRunGuides & benchmarks
Learn to build real systemsGuides•Benchmarks•Experiments•Community
Search the site/Free checklist

Guides/OpenAI SDK

OpenAI SDK: The OpenAI Agents SDK

In part 07 you wrote the tool loop by hand. The Agents SDK ( pip install openai-agents ) packages that loop with a few primitives: an Agent (instructions + tools…

In this post

What this post covers
  1. 1. An agent with tools
  2. 2. Handoffs: a team of specialists
  3. 3. Guardrails
  4. 4. Sessions and tracing
  5. 5. When to use an agent framework
  6. Recap

In part 07 you wrote the tool loop by hand. The Agents SDK (pip install openai-agents) packages that loop with a few primitives: an Agent (instructions + tools + model), a Runner that runs the loop, handoffs between specialised agents, guardrails that validate input and output, sessions for memory, and built-in tracing. It is deliberately small, and still plain Python.

Not executed here

The examples follow the Agents SDK documentation as of September 2026 (from agents import Agent, Runner, function_tool). The package is not installed in this guide's build environment, so these blocks were not run. The concepts map directly onto the hand-written loop from part 07, which was.

1. An agent with tools

from agents import Agent, Runner, function_tool

@function_tool
def get_order(order_id: str) -> dict:
    """Look up one order by id. Returns status, delivery date and amount."""
    return {"order_id": order_id, "status": "DELIVERED", "delivered_on": "2025-10-12"}

support = Agent(
    name="Support",
    instructions="You help customers with orders. Look orders up; never guess.",
    model="gpt-5.6-luna",
    tools=[get_order],                   # schema generated from the type hints and docstring
)

result = Runner.run_sync(support, "Where is order 1042?")
print(result.final_output)

@function_tool builds the JSON schema from the signature and docstring, so type hints and docstrings become the prompt. The Runner calls the model, executes requested tools, sends results back, and stops when the agent produces a final output or a turn limit is reached. That is the same loop as part 07.

2. Handoffs: a team of specialists

Triage agent no tools; decides who helps Orders agent tools: get_order, track_parcel Billing agent tools: get_invoice, request_refund each agent: short, focused instructions and only the tools it needs (least privilege)
orders = Agent(name="Orders", instructions="Answer order and delivery questions.", tools=[get_order])
billing = Agent(name="Billing", instructions="Handle invoices and refunds. Refunds need confirmation.",
                tools=[get_invoice, request_refund])
triage = Agent(name="Triage",
               instructions="Route the customer to Orders or Billing. Do not answer yourself.",
               handoffs=[orders, billing])

result = Runner.run_sync(triage, "I was charged twice for order 1042")
print(result.last_agent.name, "→", result.final_output)

3. Guardrails

from pydantic import BaseModel
from agents import Agent, GuardrailFunctionOutput, InputGuardrailTripwireTriggered, Runner, input_guardrail

class Relevance(BaseModel):
    is_about_our_shop: bool

checker = Agent(name="Relevance check", instructions="Is this about our shop's orders or billing?",
                output_type=Relevance, model="gpt-5.6-luna")

@input_guardrail
async def only_shop_questions(ctx, agent, user_input):
    verdict = (await Runner.run(checker, user_input, context=ctx.context)).final_output
    return GuardrailFunctionOutput(output_info=verdict, tripwire_triggered=not verdict.is_about_our_shop)

support = Agent(name="Support", instructions="...", tools=[get_order],
                input_guardrails=[only_shop_questions])
try:
    Runner.run_sync(support, "Write my homework essay on the French revolution")
except InputGuardrailTripwireTriggered:
    print("Sorry, I can only help with orders and billing.")

A guardrail runs a cheap check (often a small model with a structured output) alongside the main agent, and aborts the run when its tripwire fires. Output guardrails check the final answer before it reaches the user. As part 16 said, guardrails complement least-privilege tools. They do not replace them.

4. Sessions and tracing

from agents import SQLiteSession

session = SQLiteSession("customer-u123", "conversations.db")    # memory persisted per conversation id
Runner.run_sync(support, "Hi, I'm Asha. Order 1042 please.", session=session)
Runner.run_sync(support, "And when was it delivered?", session=session)   # remembers the order

Every run is traced by default: model calls, tool calls, handoffs and guardrails appear as spans you can inspect in the OpenAI dashboard’s Traces view, or export to your own observability stack. The AI Engineering guide’s parts on OpenTelemetry and Langfuse explain what to do with those traces.

5. When to use an agent framework

Use it when…

You have several tools, multi-step tasks, specialist roles, or you want sessions, guardrails and tracing without writing them yourself.

Skip it when…

One call with structured output solves the problem, or a fixed sequence of steps (a workflow) is enough. Deterministic code is cheaper, faster and easier to test than an autonomous loop.

Recap

  • Agent = instructions + tools + model; Runner runs the tool loop until a final output.
  • @function_tool turns type hints and docstrings into tool schemas.
  • Handoffs build specialist teams; guardrails validate input and output; sessions remember.
  • Tracing is built in; prefer plain workflows when an agent is not needed.

Get the free RAG production checklist

25 checks to run before real users see your RAG feature: exact-match misses, invented citations, prompt injection through documents, quality that slips after a prompt change. Confirm your email and the PDF comes with the welcome email, plus each new experiment.

One email to confirm. Unsubscribe any time. What's in it · Privacy

Want the production version of this? See ShipRAG: A production RAG + MCP starter kit for FastAPI: hybrid search, validated citations, evals in CI, Docker, 32 tests.

Written by

Alby Tomy

Python/FastAPI Engineer | Data Engineer | AI Engineer building RAG and MCP systems.

X · GitHub · Contact & enquiries