PythonTypeScriptMedium — primitives with opinions

OpenAI Agents SDK

A small, opinionated agent runtime with handoffs between agents, guardrails, and built-in tracing, tightly integrated with OpenAI models and hosted tools.

Architecture

  • Agent = instructions + tools + optional output_type (Pydantic/Zod) + handoffs; Runner.run executes the loop until a final output.
  • Handoffs are tools that transfer the conversation to another agent; the callee sees the history and becomes the active agent (a swarm-style pattern).
  • Guardrails run as input or output checks (often a cheaper model) in parallel with the main agent and can trip to abort the run.
  • Function tools via @function_tool derive schemas from signatures and docstrings; hosted tools (web search, file search, computer use) are provider-side.
  • Tracing is on by default and exported to the OpenAI dashboard; RunContext carries typed dependencies into tools.

Best use cases

  • Teams committed to OpenAI models who want the vendor's reference loop rather than writing one.
  • Triage/handoff designs (front-desk agent routes to specialists).
  • Rapid experiments with hosted tools such as web search and file search.

Weaknesses

  • Lock-in: other providers work only through the Chat Completions compatibility path; hosted tools and tracing are OpenAI-specific.
  • Handoffs move the *whole* conversation; context growth and confused specialist agents are common, and there is no built-in state pruning.
  • No durable persistence or checkpointing — long-running or approval-paused runs need your own storage (sessions help with history only).
  • Default tracing sends prompts and outputs to OpenAI unless you configure a different processor; check data-handling requirements.
  • Young API; naming and hosting features (Responses API, sessions) still move release to release.

When NOT to use it

  • Multi-provider or on-prem model requirements.
  • Workflows needing resumable checkpoints and explicit state graphs.
  • You want to see and version every system prompt — the handoff prompt prefix is injected for you.

Code example

Illustrative — APIs change between versions.

1from agents import Agent, Runner, function_tool, InputGuardrail, GuardrailFunctionOutput
2from pydantic import BaseModel
3
4class Refund(BaseModel):
5 order_id: str
6 approved: bool
7 reason: str
8
9@function_tool
10def lookup_order(order_id: str) -> dict:
11 """Fetch an order by id."""
12 return orders.get(order_id)
13
14refunds = Agent(name="Refunds", instructions="Decide refunds per policy.",
15 tools=[lookup_order], output_type=Refund)
16billing = Agent(name="Billing", instructions="Answer invoice questions.")
17
18async def no_pii(ctx, agent, user_input): # guardrail runs alongside the agent
19 flagged = contains_card_number(user_input)
20 return GuardrailFunctionOutput(output_info=None, tripwire_triggered=flagged)
21
22triage = Agent(name="Triage", instructions="Route to the right specialist.",
23 handoffs=[refunds, billing], input_guardrails=[InputGuardrail(no_pii)])
24
25result = await Runner.run(triage, "I want a refund for order A-123", max_turns=10)
26print(result.final_output) # Refund(...) if the run ended in the refunds agent

Alternatives

Related lessons