« Track Overview · Warmup · Hitchhiker's · Deep Dive · Principal Deep Dive · Core Contributor · Staff Notes

Phase 21 — Framework Deep-Dive: the OpenAI Agents SDK

Answers these JD lines: Temporal's Staff Software Engineer, AI Foundations role (jd.md) names the OpenAI Agents SDK explicitly — the team builds "plugin systems that connect Temporal's durable execution model with AI frameworks such as Pydantic AI, Vercel AI SDK, Google ADK, and OpenAI Agents SDK." More broadly, this phase answers every "agent orchestration," "LLM orchestration," "tool calling," "guardrails," and "human-in-the-loop validation" line across the JDs — the OpenAI Agents SDK is the reference implementation of the minimal-primitives approach to agents, and being able to rebuild it is the difference between using an agent framework and owning the platform that wraps one.

Why this phase exists

The OpenAI Agents SDK is the counterpoint to LangGraph (Phase 18). Where LangGraph makes you draw an explicit graph of nodes, edges, and persisted state, the Agents SDK gives you a tiny set of primitives — Agents, Handoffs, Guardrails, Sessions — over one built-in loop (the Runner) and gets out of your way. It is Python-first, unopinionated, and small enough to read in an afternoon. That minimalism is exactly why it's worth building from scratch: there is almost no framework to hide behind, so if you understand the SDK you understand the mechanism of agents.

Four ideas do all the work, and this phase makes each of them muscle memory by having you rebuild it deterministically and offline:

  1. The agent loop lives in the Runner. Call the model; if it asked for tools, run them and feed the results back; repeat until a final output or max_turns. Everything else hangs off this.
  2. Tools are just typed Python functions. @function_tool derives the JSON schema from the signature. The model proposes a call; your code executes it (the Phase 00 trust boundary).
  3. Multi-agent = handoffs. A handoff is a transfer_to_<agent> tool that switches the active agent. This is a fundamentally different composition style from LangGraph's explicit supervisor graph or CrewAI's roles — and knowing when to reach for each is a senior signal.
  4. Safety and memory are primitives, not bolt-ons. Guardrails (with tripwires) gate the expensive agent cheaply; Sessions make conversation memory automatic.

Concept map

  • Agent = name + instructions + tools + handoffs + guardrails + output_type + model settings — a declarative bundle of everything one "role" needs.
  • Runner = the loop. Runner.run (async), run_sync, run_streamed; returns a RunResult with final_output, new_items, last_agent. Guarded by max_turns.
  • Function tools = @function_tool → auto-schema from the signature; the model proposes, the Runner dispatches on the trusted side; a tool exception becomes an observation, not a crash.
  • Handoffs = transfer_to_<agent> tools that switch the active agent; on_handoff callbacks and input_filter conversation-reshaping; last_agent = who finished. (Contrast: agents-as-tools, where control returns to the orchestrator.)
  • Guardrails = GuardrailFunctionOutput(output_info, tripwire_triggered); input guardrails halt before the agent, output guardrails block the final answer; run cheap/fast models for them.
  • Sessions = SQLiteSession & friends; automatic cross-run memory behind get/add/pop/clear.
  • Tracing = built-in spans around every run/turn/tool/handoff/guardrail (the observability seam).
  • The durable angle = Temporal wraps the SDK's loop so a long-running agent survives crashes (cross-ref Phase 08).

The labs

LabYou buildProves you understand
01 — Agent Runner & ToolsAgent, @function_tool (auto-schema), and Runner (the loop) with sync/async/streaming + output_typethe SDK is one loop with good ergonomics; tools are typed functions across a trust boundary
02 — Handoffshandoffs as transfer_to_<agent> tools that switch the active agent; on_handoff + input_filter; multi-hopthe SDK's multi-agent mechanism, and handoffs-vs-agents-as-tools-vs-graphs
03 — Guardrails & Sessionsinput/output guardrails with tripwires + a real sqlite Sessionhow the SDK makes safety cheap and memory automatic, both around the same loop

Integrated scenario (how this shows up at work)

You're building a customer-support agent. A triage Agent reads the message and either answers or hands off to a billing or refunds specialist (Lab 02) — result.last_agent tells you who resolved it, which you persist to resume the thread. Each specialist has @function_tools for its systems (Lab 01), and the Runner's max_turns bounds a confused loop. An input guardrail on a tiny fast model rejects abuse and off-topic requests before you pay for the big model; an output guardrail blocks any reply that leaks PII (Lab 03). A SQLiteSession keyed by the customer id gives the whole thing memory across messages for free. When finance asks "can this survive a deploy mid-conversation?", you wrap the Runner in a Temporal workflow (Phase 08) so every turn is a durable, replayable step. That is a production agent, and it is these four primitives plus the durability lens — nothing more.

Deliverables checklist

  • Lab 01 green (20 tests) — the loop, tools, streaming, max_turns, output_type.
  • Lab 02 green (20 tests) — handoffs switch the active agent; last_agent; on_handoff / input_filter; multi-hop; budget across handoffs.
  • Lab 03 green (22 tests) — input/output tripwires; real sqlite sessions; memory across runs.
  • You can whiteboard the Runner loop and say where tools, handoffs, and guardrails plug in.
  • You can contrast the Agents SDK (loop + handoffs) with LangGraph (explicit graph/state) and CrewAI (roles), and say when you'd choose each.
  • You can explain the Temporal integration: why wrapping the loop in a durable workflow buys crash-safety for long-running agents.

Key takeaways

  • The OpenAI Agents SDK is few primitives over one loop; its power is ergonomics and composability, not a novel algorithm. Rebuild the loop and the whole SDK demystifies.
  • Handoffs (switch the active agent) and agents-as-tools (control returns) are two multi-agent styles; the SDK's insight is that a handoff is just a tool, so the loop never changes.
  • Guardrails put safety on the cheap side of the cost curve — a fast model's tripwire gates the smart model. Sessions make memory automatic. Both are decorators/objects around the same loop.
  • Pick the SDK when you want a light, Python-first agent with handoffs and don't want a graph; pick LangGraph when you need explicit state, checkpoints, and complex control flow; reach for Temporal when the agent must be durable and long-running.