Build Your First AI Agent in Python: Inside the OpenAI Agents SDK
Most LLM applications are, at heart, elaborate autocomplete. You send a prompt, the model returns text, and the program stops. That works fine for summarization and drafting. It falls apart the moment you want a system that checks the current stable release of Python, calls a function on your behalf, or remembers what you asked two minutes ago.
An AI agent changes that flow. Instead of a single answer, the agent runs a loop: User → Agent → Tool if needed → Agent → Final Response. The model decides whether to act before it speaks, and the developer’s job shifts from orchestrating API calls to defining what the agent is allowed to do. The OpenAI Agents SDK, documented in a recent walkthrough by Abid Ali Awan for KDnuggets, makes that shift unusually concrete. This is a look at how the pieces fit together, and what the SDK’s Runner is actually doing while you watch.
From prompt-response to agentic loop
The distinction matters more than it sounds. A standard LLM application receives a prompt, generates an answer, and stops. It has no mechanism for checking a fact, running a calculation, or retrieving a previous conversation. Every question is answered from whatever the model already knows.
An agent adds tools and an execution loop. Tools are functions the model can request: a web search, a Python function, a memory lookup. The loop is the part that turns a one-shot answer into a process. The model considers the request, decides whether it needs to act first, and if so names the tool and the arguments. The result comes back, the model considers it, and either calls another tool or produces a final response.
This is why agent design is mostly tool design. Give the agent the right tools, let it decide when to use them, and the interesting behavior follows.
Before any of that runs, the walkthrough starts where most should: a clean, isolated Python environment with the dependencies installed. Isolating the environment avoids the version conflicts that make agent debugging miserable before you have written a line of agent code.

Meet the Runner
The piece most tutorials gloss over is who executes the loop. In the Agents SDK, it is the Runner. You hand it an agent and a request. The Runner sends the request to the model, executes any tools the model asks for, passes the results back, and continues until a final answer is produced.
What it abstracts away is worth stating plainly, because it explains what you no longer write. No manual parsing of tool-call payloads. No hand-rolled while loop that re-sends conversation state after each function call. No bespoke logic for deciding when the model is done.
The tradeoff is visibility. When the Runner handles the execution loop, a misbehaving agent can look like a black box. The rest of this article is largely about the levers the SDK gives you to see inside it.
Web search as a hosted tool
The simplest tool to start with is one you do not implement at all. WebSearchTool() is a hosted OpenAI tool, meaning the model decides when it needs current information rather than the developer manually wiring up a search API and deciding when to call it.
That inversion is the point. You do not write code that says “if the question mentions a version number, search the web.” You give the agent a search tool and let it make that call. In the tutorial’s example run, the agent identified Python 3.14.7 as the current stable release (as reported in the KDnuggets walkthrough), a question no model can answer reliably from training data alone.
Hosted tools are also a useful test of whether your agent’s decision-making is working. If the agent answers a time-sensitive question without searching, the problem is usually the instructions, not the tool.
Custom Python tools without JSON schemas
Writing your own tools is where the SDK earns its keep. The Agents SDK automatically builds a tool schema from the function name, its arguments, the type hints, and the docstring. You do not define JSON schemas by hand, and you do not write the tool-calling loop that consumes them.
What you do write matters, though. The docstring is not decoration. It is the description the model reads when deciding which tool to use and when. A vague docstring produces vague tool selection. A precise one, stating what the function returns and the conditions under which it is appropriate, does more for agent reliability than most prompt engineering.
This is also where the fundamentals keep paying off. If you are rusty on the Python that frameworks assume, our breakdown of The Python Basics AI Frameworks Never Replace: Inside KDnuggets’ New Cheat Sheet covers the ground that type hints and clean function signatures depend on.
Conversation memory that survives restarts
A stateless agent forgets everything between requests. Add a session, and the agent becomes conversational: a second request automatically receives the earlier conversation, so references like “the latest version” resolve against what was already discussed.
The tutorial uses a file-backed SQLite database, which has a practical advantage over in-memory state: history persists across program restarts. You can close the terminal, reopen it, and continue the conversation.
For larger applications, the SDK provides session backends for systems including Redis, SQLAlchemy, and MongoDB. The progression is sensible. Start with a file, move to a shared store when you have multiple processes, and only then worry about the operational overhead of a database.
Tracing and debugging on by default
The Agents SDK enables tracing by default, and this is the feature that makes the Runner’s abstraction tolerable. Traces record model calls, tool usage, handoffs, and the other steps in an agent run.
Inspecting a trace in the OpenAI dashboard answers the questions that matter when an agent misbehaves: How did it reach this answer? Which tools did it select, and in what order? Where exactly did the tool-calling go wrong? Reading a trace is often faster than adding print statements, and it shows failures that logging your own code would miss entirely, because the decisions happen inside the model’s turn.
Traces are also a feedback loop for instructions. If the agent consistently picks the wrong tool, the trace shows you the reasoning path that led there, and the fix is usually a sharper tool description or a clearer system prompt.
The assembled agent and next steps
Put the pieces together and you get a genuinely useful assistant: web search for current information, a custom Python tool for your own logic, persistent memory via SQLite, basic error handling, and a continuous chat interface. That combination covers a surprising range of real workflows.
The temptation is to keep adding. The SDK supports APIs, MCP servers, guardrails, handoffs, more specialized tools, and additional agents, and each has a place. If you are heading toward MCP, our write-up on MCP Goes Stateless: Building a Python Server with the v2 SDK explains what changed in the protocol before you wire an agent to one.
But the guidance from the tutorial is the right note to end on: start small, make one workflow useful, and expand only when you actually need more complexity. The Runner will handle the loop. Your job is to give it tools worth using, descriptions worth reading, and traces worth checking.
Build the small one first. The rest is configuration.
Related: agents doing original mathematics.