« 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:
- 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 ormax_turns. Everything else hangs off this. - Tools are just typed Python functions.
@function_toolderives the JSON schema from the signature. The model proposes a call; your code executes it (the Phase 00 trust boundary). - 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. - 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 aRunResultwithfinal_output,new_items,last_agent. Guarded bymax_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_handoffcallbacks andinput_filterconversation-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 behindget/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
| Lab | You build | Proves you understand |
|---|---|---|
| 01 — Agent Runner & Tools | Agent, @function_tool (auto-schema), and Runner (the loop) with sync/async/streaming + output_type | the SDK is one loop with good ergonomics; tools are typed functions across a trust boundary |
| 02 — Handoffs | handoffs as transfer_to_<agent> tools that switch the active agent; on_handoff + input_filter; multi-hop | the SDK's multi-agent mechanism, and handoffs-vs-agents-as-tools-vs-graphs |
| 03 — Guardrails & Sessions | input/output guardrails with tripwires + a real sqlite Session | how 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
Runnerloop 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.