The OpenAI Agents SDK
Use the OpenAI Agents SDK to streamline model interactions, tool execution, and agent orchestration while maintaining application-level control over authorization and conversation history. Distinguish the SDK’s responsibilities for managing model turns, tool invocation, guardrails, and tracing from the application’s responsibilities for user identity, access permissions, and data security. Implement guardrails to validate inputs, outputs, and sensitive operations without treating them as substitutes for authorization controls. Establish a session registry that verifies conversation ownership and prevents unauthorized access to sensitive information. Maintain secure conversation state across multiple turns, monitor agent execution through tracing, and enforce access controls before retrieving session data or executing protected actions. Apply this architecture to coordinate agents efficiently, support reliable multi-turn interactions, and ensure secure, traceable, and maintainable production workflows.
Northstar’s operator B opened the assistant, asked about their own ticket, and got an answer that leaned on operator A’s ticket evidence. Every read tool enforced authorization correctly. The leak came through conversation history, which the SDK loaded before any tool ran.
“Why use the Agents SDK when you already have a working tool loop?” is a fair interview question, and “less code” is only half the answer. The OpenAI Agents SDK takes over the repetitive work of running model turns, invoking tools, and feeding results back. It doesn’t decide who the caller is, what they may read, or whether an answer is good enough to accept. This lesson moves Northstar’s hand-written loop onto the SDK and keeps those decisions in application code.
What does the SDK take over, and what stays ours?
Decide who owns each responsibility before writing code. Each card below is tagged with its owner.
The SDK splits the previous lesson’s loop into two pieces. An Agent holds instructions, a model and its settings, a list of tools, and an optional typed output. The Runner is the loop: Runner.run calls the model, runs any tool calls and appends their results, follows any handoff to another agent, and stops when the model produces a final output with no tool calls.
That draws a clear line. The SDK orchestrates model turns, tool invocation, result plumbing, and run completion or interruption. The application keeps authenticated identity, authorization of every read, access to conversation history, resource budgets, and business acceptance. Northstar still exposes only get_ticket, and moving to the SDK adds no permission to update a ticket or make a callback.
How do we set up the project?
Keep northstar.py, patch.py, and the existing tests unchanged; the exercise adds three new files. Use Python 3.11 or newer, and create a virtual environment if one isn’t already active:
python -m venv .venv
On macOS or Linux, activate it with source .venv/bin/activate. In Windows PowerShell, use .\.venv\Scripts\Activate.ps1, or call .venv\Scripts\python.exe directly. Then install the packages and record exactly what was installed:
python -m pip install --upgrade openai-agents openai pydanticpython -m pip show openai-agents openai pydanticpython -m pip freeze > requirements.lock.txt
The package is openai-agents, but you import it as agents. Later, python sdk_demo.py --inspect prints the installed versions and SDK signatures. For a live run, set credentials only in your terminal session. On macOS or Linux:
export OPENAI_API_KEY='{{OPENAI_API_KEY}}'export OPENAI_MODEL='{{OPENAI_MODEL}}'
In Windows PowerShell:
$env:OPENAI_API_KEY='{{OPENAI_API_KEY}}'$env:OPENAI_MODEL='{{OPENAI_MODEL}}'
Replace both placeholders locally, choosing a model available to your account that supports the features used here.
What happens during one tool call?
The SDK tool wraps the authorized dispatcher you already built:
@function_tool(failure_error_function=None)async def get_ticket(ctx: RunContextWrapper[LocalContext], ticket_id: str) -> str:return json.dumps(ctx.context.read(ticket_id))
Line 1:
@function_toolbuilds the tool schema from the ...