{"id":182,"date":"2026-10-08T16:37:59","date_gmt":"2026-10-08T16:37:59","guid":{"rendered":"https:\/\/devdojo.co.in\/?p=182"},"modified":"2026-10-08T16:38:00","modified_gmt":"2026-10-08T16:38:00","slug":"openai-agents-sdk-python","status":"publish","type":"post","link":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/","title":{"rendered":"OpenAI Agents SDK Tutorial: Build AI Agents in Python"},"content":{"rendered":"\n<div class=\"dd-post\">\n<style>\n.single article:has(.dd-hero) .entry-media{display:none}\n.dd-post{--dd-navy:#0b1020;--dd-blue:#3178c6;--dd-violet:#7c5cff;--dd-ink:#1d2333;--dd-muted:#5b6478;--dd-line:#e3e7f0;font-size:17px;line-height:1.75;color:var(--dd-ink)}\n.dd-post h2{margin:2.2em 0 .6em;font-size:1.6em;line-height:1.3;scroll-margin-top:90px}\n.dd-post h3{margin:1.6em 0 .5em;font-size:1.25em;scroll-margin-top:90px}\n.dd-post a{color:var(--dd-blue)}\n.dd-post .dd-hero{margin:0 0 28px;border-radius:16px;overflow:hidden;box-shadow:0 12px 40px rgba(11,16,32,.35);background:#0b1020}\n.dd-post .dd-hero svg{display:block;width:100%;height:auto}\n.dd-post .dd-hero .node rect{transition:stroke .25s,fill .25s}\n.dd-post .dd-hero .node:hover rect{stroke:#7c5cff;fill:#1e2656}\n.dd-post .dd-hero .node:hover text{fill:#fff}\n.dd-post pre{background:#0f1430;color:#e6e9f5;padding:18px 20px;border-radius:12px;overflow-x:auto;margin:1.2em 0;border:1px solid #232a52;font-size:14.5px !important;line-height:1.6}\n.dd-post pre code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:1em !important;background:none;color:inherit;padding:0;white-space:pre}\n.dd-post :not(pre)>code{background:#eef1fb;color:#3a2fa0;padding:2px 6px;border-radius:5px;font-size:.9em}\n.dd-post .dd-file{display:inline-block;margin:1em 0 -0.9em;background:#232a52;color:#c8cff5;font:600 12.5px\/1 ui-monospace,Menlo,monospace;padding:7px 12px;border-radius:8px 8px 0 0}\n.dd-post .dd-summary{background:linear-gradient(135deg,#eef3ff,#f3efff);border:1px solid #d9def7;border-left:5px solid var(--dd-violet);border-radius:12px;padding:18px 22px;margin:0 0 26px}\n.dd-post .dd-summary strong.dd-label{display:block;font-size:.85em;letter-spacing:.06em;text-transform:uppercase;color:var(--dd-violet);margin-bottom:6px}\n.dd-post .dd-summary ul{margin:0;padding-left:20px}\n.dd-post .dd-toc{background:#f7f8fc;border:1px solid var(--dd-line);border-radius:12px;padding:16px 22px;margin:0 0 28px}\n.dd-post .dd-toc strong{display:block;margin-bottom:6px}\n.dd-post .dd-toc ol{margin:0;padding-left:22px;columns:2;column-gap:32px}\n.dd-post .dd-toc li{break-inside:avoid;margin:2px 0}\n@media (max-width:640px){.dd-post .dd-toc ol{columns:1}}\n.dd-post .dd-tip,.dd-post .dd-note,.dd-post .dd-warn{border-radius:10px;padding:14px 18px;margin:1.2em 0}\n.dd-post .dd-tip{background:#ecfbf3;border-left:5px solid #1fa463}\n.dd-post .dd-note{background:#eef4fe;border-left:5px solid var(--dd-blue)}\n.dd-post .dd-warn{background:#fff6e8;border-left:5px solid #e8930c}\n.dd-post .dd-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:14px;margin:1.2em 0}\n.dd-post .dd-card{border:1px solid var(--dd-line);border-radius:12px;padding:14px 16px;background:#fff;box-shadow:0 2px 8px rgba(20,30,70,.05)}\n.dd-post .dd-card b{display:block;color:var(--dd-violet);margin-bottom:4px}\n.dd-post table{width:100%;border-collapse:collapse;margin:1.2em 0;font-size:.93em;display:block;overflow-x:auto}\n.dd-post th,.dd-post td{border:1px solid var(--dd-line);padding:10px 12px;text-align:left;vertical-align:top}\n.dd-post th{background:#151b3b;color:#fff}\n.dd-post tr:nth-child(even) td{background:#f8f9fd}\n.dd-post figure{margin:1.6em 0;text-align:center}\n.dd-post figure svg{width:100%;height:auto;border-radius:12px}\n.dd-post figcaption{font-size:.88em;color:var(--dd-muted);margin-top:8px}\n.dd-post details{border:1px solid var(--dd-line);border-radius:10px;padding:12px 16px;margin:10px 0;background:#fff}\n.dd-post details summary{cursor:pointer;font-weight:600}\n.dd-post details[open] summary{margin-bottom:8px;color:var(--dd-violet)}\n.dd-post .dd-tabs{margin:1.4em 0;border:1px solid var(--dd-line);border-radius:12px;overflow:hidden;background:#fff}\n.dd-post .dd-tabs input{position:absolute;opacity:0;pointer-events:none}\n.dd-post .dd-tabs .dd-tablist{display:flex;flex-wrap:wrap;background:#151b3b}\n.dd-post .dd-tabs label{padding:11px 16px;color:#b8c0e8;cursor:pointer;font-weight:600;font-size:.92em;border-bottom:3px solid transparent}\n.dd-post .dd-tabs label:hover{color:#fff}\n.dd-post .dd-tabs .dd-panel{display:none;padding:6px 18px 14px}\n.dd-post #dd-t1:checked~.dd-tablist label[for=dd-t1],.dd-post #dd-t2:checked~.dd-tablist label[for=dd-t2],.dd-post #dd-t3:checked~.dd-tablist label[for=dd-t3]{color:#fff;border-bottom-color:#7c5cff;background:#1e2656}\n.dd-post #dd-t1:checked~.dd-p1,.dd-post #dd-t2:checked~.dd-p2,.dd-post #dd-t3:checked~.dd-p3{display:block}\n.dd-post #dd-t1:focus-visible~.dd-tablist label[for=dd-t1],.dd-post #dd-t2:focus-visible~.dd-tablist label[for=dd-t2],.dd-post #dd-t3:focus-visible~.dd-tablist label[for=dd-t3]{outline:2px solid #7c5cff;outline-offset:-2px}\n.dd-post .dd-cta{margin:2em 0 1em;padding:24px 26px;border-radius:14px;background:linear-gradient(135deg,#0b1020,#151b3b);color:#e6e9f5;text-align:center}\n.dd-post .dd-cta h3{color:#fff;margin:0 0 6px}\n.dd-post .dd-cta p{margin:0;color:#c3c9ea}\n.dd-post .dd-cta a{color:#a99bff;font-weight:600}\n.dd-post .dd-check{list-style:none;padding-left:0}\n.dd-post .dd-check li{padding-left:30px;position:relative;margin:6px 0;list-style:none !important}\n.dd-post .dd-check li::marker{content:none}\n.dd-post .dd-check li:before{content:\"\\2713\";position:absolute;left:4px;color:#1fa463;font-weight:700}\n<\/style>\n\n<div class=\"dd-hero\">\n<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 1200 520\" role=\"img\" aria-labelledby=\"ddHeroT ddHeroD\">\n<title id=\"ddHeroT\">OpenAI Agents SDK Tutorial<\/title>\n<desc id=\"ddHeroD\">Animated banner showing a user message flowing into a Python agent, which calls tools and hands off work to a specialist agent.<\/desc>\n<defs>\n<linearGradient id=\"ddBg\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"#0b1020\"\/><stop offset=\"1\" stop-color=\"#151b3b\"\/><\/linearGradient>\n<linearGradient id=\"ddAcc\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\"><stop offset=\"0\" stop-color=\"#3178c6\"\/><stop offset=\"1\" stop-color=\"#7c5cff\"\/><\/linearGradient>\n<radialGradient id=\"ddGlow\" cx=\"0.82\" cy=\"0.2\" r=\"0.6\"><stop offset=\"0\" stop-color=\"#7c5cff\" stop-opacity=\".35\"\/><stop offset=\"1\" stop-color=\"#7c5cff\" stop-opacity=\"0\"\/><\/radialGradient>\n<pattern id=\"ddGrid\" width=\"40\" height=\"40\" patternUnits=\"userSpaceOnUse\"><path d=\"M40 0H0V40\" fill=\"none\" stroke=\"#ffffff\" stroke-opacity=\".04\"\/><\/pattern>\n<\/defs>\n<rect x=\"-10\" y=\"-80\" width=\"1220\" height=\"700\" fill=\"url(#ddBg)\"\/>\n<rect x=\"-10\" y=\"-80\" width=\"1220\" height=\"700\" fill=\"url(#ddGrid)\"\/>\n<rect x=\"-10\" y=\"-80\" width=\"1220\" height=\"700\" fill=\"url(#ddGlow)\"\/>\n<g font-family=\"Segoe UI,Roboto,Helvetica,Arial,sans-serif\">\n<rect x=\"60\" y=\"54\" width=\"170\" height=\"30\" rx=\"15\" fill=\"#3178c6\" fill-opacity=\".18\" stroke=\"#3178c6\"\/>\n<text x=\"145\" y=\"74\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"#8fb8ff\" letter-spacing=\"1.5\">AI \u00b7 PYTHON<\/text>\n<text x=\"60\" y=\"140\" font-size=\"54\" font-weight=\"800\" fill=\"#ffffff\">OpenAI Agents SDK Tutorial<\/text>\n<text x=\"60\" y=\"186\" font-size=\"24\" fill=\"#c3c9ea\">Build AI agents with tools, handoffs, guardrails and memory<\/text>\n<rect x=\"60\" y=\"206\" width=\"120\" height=\"5\" rx=\"2.5\" fill=\"url(#ddAcc)\"\/>\n<path id=\"ddP1\" d=\"M250 380 C 330 320, 420 320, 500 380\" fill=\"none\" stroke=\"#3178c6\" stroke-opacity=\".7\" stroke-width=\"2.5\" stroke-dasharray=\"6 6\"\/>\n<path id=\"ddP2\" d=\"M700 365 C 790 300, 860 290, 950 300\" fill=\"none\" stroke=\"#7c5cff\" stroke-opacity=\".8\" stroke-width=\"2.5\" stroke-dasharray=\"6 6\"\/>\n<path id=\"ddP3\" d=\"M700 395 C 790 450, 860 460, 950 450\" fill=\"none\" stroke=\"#1fa463\" stroke-opacity=\".8\" stroke-width=\"2.5\" stroke-dasharray=\"6 6\"\/>\n<circle r=\"7\" fill=\"#3178c6\"><animateMotion dur=\"2.4s\" repeatCount=\"indefinite\"><mpath href=\"#ddP1\"\/><\/animateMotion><\/circle>\n<circle r=\"5\" fill=\"#8fb8ff\"><animateMotion dur=\"2.4s\" begin=\"1.2s\" repeatCount=\"indefinite\"><mpath href=\"#ddP1\"\/><\/animateMotion><\/circle>\n<circle r=\"6\" fill=\"#7c5cff\"><animateMotion dur=\"1.8s\" repeatCount=\"indefinite\"><mpath href=\"#ddP2\"\/><\/animateMotion><\/circle>\n<circle r=\"6\" fill=\"#3ddc97\"><animateMotion dur=\"2s\" begin=\".6s\" repeatCount=\"indefinite\"><mpath href=\"#ddP3\"\/><\/animateMotion><\/circle>\n<g class=\"node\"><rect x=\"60\" y=\"340\" width=\"190\" height=\"84\" rx=\"14\" fill=\"#141a38\" stroke=\"#2c3566\" stroke-width=\"2\"\/><text x=\"155\" y=\"376\" text-anchor=\"middle\" font-size=\"22\" font-weight=\"700\" fill=\"#dfe4ff\">User<\/text><text x=\"155\" y=\"404\" text-anchor=\"middle\" font-size=\"15\" fill=\"#8d96c4\">&#8220;Where is my order?&#8221;<\/text><\/g>\n<g class=\"node\"><rect x=\"500\" y=\"338\" width=\"200\" height=\"88\" rx=\"14\" fill=\"#1b1f4a\" stroke=\"#7c5cff\" stroke-width=\"2.5\"\/><text x=\"600\" y=\"376\" text-anchor=\"middle\" font-size=\"22\" font-weight=\"700\" fill=\"#ffffff\">Agent<\/text><text x=\"600\" y=\"404\" text-anchor=\"middle\" font-size=\"15\" fill=\"#b9adff\">instructions + model<\/text><\/g>\n<g class=\"node\"><rect x=\"950\" y=\"258\" width=\"200\" height=\"80\" rx=\"14\" fill=\"#141a38\" stroke=\"#7c5cff\" stroke-width=\"2\"\/><text x=\"1050\" y=\"292\" text-anchor=\"middle\" font-size=\"21\" font-weight=\"700\" fill=\"#dfe4ff\">@tool<\/text><text x=\"1050\" y=\"318\" text-anchor=\"middle\" font-size=\"15\" fill=\"#8d96c4\">your Python function<\/text><\/g>\n<g class=\"node\"><rect x=\"950\" y=\"410\" width=\"200\" height=\"80\" rx=\"14\" fill=\"#141a38\" stroke=\"#1fa463\" stroke-width=\"2\"\/><text x=\"1050\" y=\"444\" text-anchor=\"middle\" font-size=\"21\" font-weight=\"700\" fill=\"#dfe4ff\">Handoff<\/text><text x=\"1050\" y=\"470\" text-anchor=\"middle\" font-size=\"15\" fill=\"#8d96c4\">specialist agent<\/text><\/g>\n<g transform=\"translate(900,62)\"><rect width=\"250\" height=\"120\" rx=\"16\" fill=\"#141a38\" stroke=\"#2c3566\"\/><text x=\"125\" y=\"36\" text-anchor=\"middle\" font-size=\"14\" fill=\"#8d96c4\">get started with<\/text><text x=\"125\" y=\"76\" text-anchor=\"middle\" font-size=\"19\" font-weight=\"700\" font-family=\"Menlo,Consolas,monospace\" fill=\"#c9bcff\">pip install<\/text><text x=\"125\" y=\"100\" text-anchor=\"middle\" font-size=\"17\" font-family=\"Menlo,Consolas,monospace\" fill=\"#8fb8ff\">openai-agents<\/text><\/g>\n<\/g>\n<\/svg>\n<\/div>\n<p>Chatbots answer questions. <strong>AI agents<\/strong> get things done: they look up data, call your functions, pass work to a specialist, and keep going until the task is finished. The easiest way to build one in Python today is the <strong>OpenAI Agents SDK<\/strong>, a small open-source library from OpenAI that gives you just a few building blocks (agents, tools, handoffs, guardrails and sessions) and handles the tricky &#8220;loop&#8221; part for you.<\/p>\n<p>In this beginner-friendly tutorial you will build real, runnable examples step by step: a first agent, an agent that calls Python functions, an agent that returns clean typed data, a team of agents that hand work to each other, a safety check (guardrail), and an agent that remembers the conversation. Every example works with the current release of the SDK (version 0.23 at the time of writing) and Python 3.10 or newer.<\/p>\n<div class=\"dd-summary\">\n<strong class=\"dd-label\">Quick Summary<\/strong>\n<ul>\n<li>Install with <code>pip install openai-agents<\/code> and set the <code>OPENAI_API_KEY<\/code> environment variable.<\/li>\n<li>An <strong>Agent<\/strong> is a model plus instructions plus tools. <code>Runner.run()<\/code> runs the agent loop until it has a final answer.<\/li>\n<li>Turn any Python function into a tool with the <code>@tool<\/code> decorator. The docstring and type hints become the tool description.<\/li>\n<li>Use <code>output_type=<\/code> with a Pydantic model to get structured, typed output instead of plain text.<\/li>\n<li><strong>Handoffs<\/strong> let a triage agent pass the conversation to a specialist agent.<\/li>\n<li><strong>Guardrails<\/strong> check input or output and stop the run early. <strong>Sessions<\/strong> (like <code>SQLiteSession<\/code>) give your agent memory.<\/li>\n<\/ul>\n<\/div>\n<nav class=\"dd-toc\" aria-label=\"Table of contents\">\n<strong>Table of contents<\/strong>\n<ol>\n<li><a href=\"#what-is\">What is the OpenAI Agents SDK?<\/a><\/li>\n<li><a href=\"#agent-loop\">How the agent loop works<\/a><\/li>\n<li><a href=\"#setup\">Setup: install and API key<\/a><\/li>\n<li><a href=\"#first-agent\">Your first agent<\/a><\/li>\n<li><a href=\"#tools\">Give your agent tools<\/a><\/li>\n<li><a href=\"#structured-output\">Structured output with Pydantic<\/a><\/li>\n<li><a href=\"#handoffs\">Multi-agent handoffs<\/a><\/li>\n<li><a href=\"#guardrails\">Guardrails: safety checks<\/a><\/li>\n<li><a href=\"#sessions\">Memory with sessions<\/a><\/li>\n<li><a href=\"#streaming\">Streaming and human approval<\/a><\/li>\n<li><a href=\"#patterns\">Which pattern should you pick?<\/a><\/li>\n<li><a href=\"#errors\">Common errors and fixes<\/a><\/li>\n<li><a href=\"#best-practices\">Best practices<\/a><\/li>\n<li><a href=\"#faq\">Frequently asked questions<\/a><\/li>\n<li><a href=\"#conclusion\">Conclusion<\/a><\/li>\n<\/ol>\n<\/nav>\n<\/div>\n\n\n\n<div class=\"dd-post\">\n<h2 id=\"what-is\">What is the OpenAI Agents SDK?<\/h2>\n<p>The <strong>OpenAI Agents SDK<\/strong> is an open-source Python library (there is also a TypeScript version) for building AI agents. It grew out of OpenAI&#8217;s earlier experimental project called Swarm and is now the official, production-ready way to build agents on top of OpenAI models. It is also &#8220;provider-agnostic&#8221;, which means you can plug in other model providers too.<\/p>\n<p>The big idea is simple: instead of learning a huge framework, you learn a handful of building blocks:<\/p>\n<div class=\"dd-cards\">\n<div class=\"dd-card\"><b>Agent<\/b>A model with a name, instructions (a system prompt), and optional tools.<\/div>\n<div class=\"dd-card\"><b>Runner<\/b>Runs the agent loop: call the model, run tools, repeat until done.<\/div>\n<div class=\"dd-card\"><b>Tools<\/b>Normal Python functions the model is allowed to call.<\/div>\n<div class=\"dd-card\"><b>Handoffs<\/b>Let one agent pass the conversation to another, more specialised agent.<\/div>\n<div class=\"dd-card\"><b>Guardrails<\/b>Checks that run on input or output and can stop a run early.<\/div>\n<div class=\"dd-card\"><b>Sessions<\/b>Built-in memory so the agent remembers earlier messages.<\/div>\n<\/div>\n<p>It also comes with <strong>tracing<\/strong> built in. Every run is recorded, and you can open the <a href=\"https:\/\/platform.openai.com\/traces\" rel=\"noopener\" target=\"_blank\">Traces page in the OpenAI dashboard<\/a> to see each model call, tool call and handoff. This is extremely helpful when your agent does something unexpected.<\/p>\n<div class=\"dd-note\"><strong>Agents SDK vs MCP:<\/strong> the Agents SDK is for <em>building the agent<\/em> (the &#8220;brain&#8221; and its loop). The Model Context Protocol (MCP) is a standard way to <em>expose tools and data<\/em> to any agent. They work great together: the SDK can connect to MCP servers. If you want to build the tool side, read our guide on <a href=\"https:\/\/devdojo.co.in\/index.php\/2026\/10\/03\/build-mcp-server-typescript\/\">how to build an MCP server in TypeScript<\/a>.<\/div>\n\n<h2 id=\"agent-loop\">How the agent loop works<\/h2>\n<p>When you call <code>Runner.run(agent, \"some input\")<\/code>, the SDK does not just send one request to the model. It runs a <strong>loop<\/strong>:<\/p>\n<ol>\n<li>Send the instructions, the conversation so far, and the list of tools to the model.<\/li>\n<li>If the model replies with a <strong>final answer<\/strong>, stop and return it.<\/li>\n<li>If the model asks to <strong>call a tool<\/strong>, run your Python function, add the result to the conversation, and go back to step 1.<\/li>\n<li>If the model asks for a <strong>handoff<\/strong>, switch to the other agent and go back to step 1.<\/li>\n<\/ol>\n<p>The loop stops after a maximum number of turns (10 by default, which you can change with <code>max_turns=<\/code>) so that a confused agent cannot run forever.<\/p>\n<figure>\n<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 900 400\" role=\"img\" aria-labelledby=\"ddLoopT ddLoopD\">\n<title id=\"ddLoopT\">The agent loop<\/title>\n<desc id=\"ddLoopD\">Diagram: user input goes to the model; the model either returns a final answer, calls a tool whose result goes back to the model, or hands off to another agent.<\/desc>\n<rect width=\"900\" height=\"400\" fill=\"#0f1430\"\/>\n<g font-family=\"Segoe UI,Roboto,Helvetica,Arial,sans-serif\" text-anchor=\"middle\">\n<defs><marker id=\"ddArr\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto\"><path d=\"M0 0L10 5L0 10z\" fill=\"#8fb8ff\"\/><\/marker><\/defs>\n<rect x=\"30\" y=\"150\" width=\"150\" height=\"70\" rx=\"12\" fill=\"#141a38\" stroke=\"#2c3566\" stroke-width=\"2\"\/>\n<text x=\"105\" y=\"182\" font-size=\"18\" font-weight=\"700\" fill=\"#dfe4ff\">User input<\/text>\n<text x=\"105\" y=\"204\" font-size=\"13\" fill=\"#8d96c4\">Runner.run(&#8230;)<\/text>\n<rect x=\"320\" y=\"140\" width=\"200\" height=\"90\" rx=\"14\" fill=\"#1b1f4a\" stroke=\"#7c5cff\" stroke-width=\"2.5\"\/>\n<text x=\"420\" y=\"178\" font-size=\"20\" font-weight=\"700\" fill=\"#fff\">Model call<\/text>\n<text x=\"420\" y=\"202\" font-size=\"13\" fill=\"#b9adff\">instructions + history + tools<\/text>\n<rect x=\"660\" y=\"40\" width=\"200\" height=\"70\" rx=\"12\" fill=\"#13302a\" stroke=\"#1fa463\" stroke-width=\"2\"\/>\n<text x=\"760\" y=\"72\" font-size=\"18\" font-weight=\"700\" fill=\"#d6ffe9\">Final answer<\/text>\n<text x=\"760\" y=\"94\" font-size=\"13\" fill=\"#8fd6b0\">result.final_output<\/text>\n<rect x=\"660\" y=\"155\" width=\"200\" height=\"70\" rx=\"12\" fill=\"#141a38\" stroke=\"#3178c6\" stroke-width=\"2\"\/>\n<text x=\"760\" y=\"187\" font-size=\"18\" font-weight=\"700\" fill=\"#dfe4ff\">Tool call<\/text>\n<text x=\"760\" y=\"209\" font-size=\"13\" fill=\"#8d96c4\">run your Python function<\/text>\n<rect x=\"660\" y=\"295\" width=\"200\" height=\"70\" rx=\"12\" fill=\"#2a1f44\" stroke=\"#c9bcff\" stroke-width=\"2\"\/>\n<text x=\"760\" y=\"327\" font-size=\"18\" font-weight=\"700\" fill=\"#efeaff\">Handoff<\/text>\n<text x=\"760\" y=\"349\" font-size=\"13\" fill=\"#b9adff\">switch to another agent<\/text>\n<path d=\"M180 185H316\" stroke=\"#8fb8ff\" stroke-width=\"2.5\" fill=\"none\" marker-end=\"url(#ddArr)\"\/>\n<path d=\"M520 165C590 130 600 80 656 76\" stroke=\"#3ddc97\" stroke-width=\"2.5\" fill=\"none\" marker-end=\"url(#ddArr)\"\/>\n<path d=\"M520 182H656\" stroke=\"#8fb8ff\" stroke-width=\"2.5\" fill=\"none\" marker-end=\"url(#ddArr)\"\/>\n<path d=\"M520 210C590 250 600 325 656 329\" stroke=\"#c9bcff\" stroke-width=\"2.5\" fill=\"none\" marker-end=\"url(#ddArr)\"\/>\n<path d=\"M700 225C680 252 560 256 500 234\" stroke=\"#8fb8ff\" stroke-width=\"2\" stroke-dasharray=\"6 5\" fill=\"none\" marker-end=\"url(#ddArr)\"\/>\n<text x=\"790\" y=\"250\" font-size=\"13\" fill=\"#8fb8ff\">tool result goes back<\/text>\n<path d=\"M660 352C520 385 420 320 400 236\" stroke=\"#c9bcff\" stroke-width=\"2\" stroke-dasharray=\"6 5\" fill=\"none\" marker-end=\"url(#ddArr)\"\/>\n<text x=\"360\" y=\"300\" font-size=\"13\" fill=\"#c9bcff\" text-anchor=\"end\">new agent, same loop<\/text>\n<circle r=\"5\" fill=\"#ffd166\"><animateMotion dur=\"3s\" repeatCount=\"indefinite\" path=\"M180 185H320C400 185 470 182 520 182H660H700C680 252 560 256 500 234\"\/><\/circle>\n<\/g>\n<\/svg>\n<figcaption>The agent loop: the Runner keeps calling the model until it gets a final answer. Tool calls and handoffs send the loop round again.<\/figcaption>\n<\/figure>\n\n<h2 id=\"setup\">Setup: install and API key<\/h2>\n<p>You need <strong>Python 3.10 or newer<\/strong> and an OpenAI API key (create one on the OpenAI platform under API keys; API usage is paid per token, so set a small monthly limit while you learn). Create a project folder and a virtual environment:<\/p>\n<pre><code class=\"language-bash\">mkdir agents-demo\ncd agents-demo\npython -m venv .venv\n\n# macOS \/ Linux\nsource .venv\/bin\/activate\n# Windows\n.venv\\Scripts\\activate\n\npip install openai-agents<\/code><\/pre>\n<p>Now set your API key as an environment variable for the current terminal:<\/p>\n<pre><code class=\"language-bash\"># macOS \/ Linux\nexport OPENAI_API_KEY=sk-...\n\n# Windows PowerShell\n$env:OPENAI_API_KEY = \"sk-...\"<\/code><\/pre>\n<div class=\"dd-warn\"><strong>Never hard-code your key<\/strong> in a Python file or push it to GitHub. Use environment variables or a <code>.env<\/code> file that is listed in <code>.gitignore<\/code>.<\/div>\n\n<h2 id=\"first-agent\">Your first agent<\/h2>\n<p>Let&#8217;s create an agent that teaches Python. An agent needs a <code>name<\/code> and <code>instructions<\/code>. If you do not choose a model, the SDK uses its default model, which is a sensible choice for learning.<\/p>\n<span class=\"dd-file\">first_agent.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom agents import Agent, Runner\n\nagent = Agent(\n    name=\"Python Tutor\",\n    instructions=\"You explain Python concepts to beginners in simple words. Keep answers short.\",\n)\n\n\nasync def main():\n    result = await Runner.run(agent, \"What is a list comprehension? Show one example.\")\n    print(result.final_output)\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<p>Run it with <code>python first_agent.py<\/code>. The SDK is <strong>async-first<\/strong>: <code>Runner.run()<\/code> is an <code>async<\/code> function, so we wrap it in <code>asyncio.run()<\/code>. If you just want a quick script and don&#8217;t care about async, use <code>Runner.run_sync()<\/code>:<\/p>\n<span class=\"dd-file\">sync_agent.py<\/span>\n<pre><code class=\"language-python\">from agents import Agent, Runner\n\nagent = Agent(name=\"Assistant\", instructions=\"You are a helpful assistant.\")\n\nresult = Runner.run_sync(agent, \"Give me 3 tips to learn Python faster.\")\nprint(result.final_output)<\/code><\/pre>\n<p>To pick a specific model or tune it, pass <code>model=\"model-name\"<\/code> and <code>model_settings=ModelSettings(...)<\/code> to <code>Agent(...)<\/code>. Check OpenAI&#8217;s models page for the current names.<\/p>\n<\/div>\n\n\n\n<div class=\"dd-post\">\n<h2 id=\"tools\">Give your agent tools<\/h2>\n<p>A model on its own only knows what it learned during training. It does not know your order database, today&#8217;s prices or your company&#8217;s rules. <strong>Tools<\/strong> fix that. In the OpenAI Agents SDK, any Python function can become a tool with the <code>@tool<\/code> decorator (imported from <code>agents.decorators<\/code>).<\/p>\n<p>The SDK reads three things from your function automatically:<\/p>\n<ul>\n<li>The <strong>function name<\/strong> becomes the tool name.<\/li>\n<li>The <strong>docstring<\/strong> becomes the tool description (the model reads this to decide when to call it).<\/li>\n<li>The <strong>type hints<\/strong> and the <code>Args:<\/code> section become a JSON schema for the inputs.<\/li>\n<\/ul>\n<span class=\"dd-file\">tools_agent.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom agents import Agent, Runner\nfrom agents.decorators import tool\n\n# Pretend database. In a real app this would be a SQL query or an API call.\nORDERS = {\n    \"A101\": {\"status\": \"shipped\", \"city\": \"Pune\", \"eta_days\": 2},\n    \"A102\": {\"status\": \"packing\", \"city\": \"Bengaluru\", \"eta_days\": 4},\n}\n\n\n@tool\ndef get_order_status(order_id: str) -&gt; str:\n    \"\"\"Look up the delivery status of an order.\n\n    Args:\n        order_id: The order ID, for example \"A101\".\n    \"\"\"\n    order = ORDERS.get(order_id.upper())\n    if order is None:\n        return f\"No order found with ID {order_id}.\"\n    return (\n        f\"Order {order_id} is {order['status']}, going to {order['city']}, \"\n        f\"expected in {order['eta_days']} days.\"\n    )\n\n\n@tool\ndef convert_currency(amount: float, rate: float) -&gt; float:\n    \"\"\"Convert an amount using an exchange rate.\n\n    Args:\n        amount: The amount of money to convert.\n        rate: How many units of the target currency one unit is worth.\n    \"\"\"\n    return round(amount * rate, 2)\n\n\nsupport_agent = Agent(\n    name=\"Order Support\",\n    instructions=(\n        \"You help customers with their orders. \"\n        \"Always use the tools to check facts. Never guess an order status.\"\n    ),\n    tools=[get_order_status, convert_currency],\n)\n\n\nasync def main():\n    result = await Runner.run(support_agent, \"Hi! Where is my order a101?\")\n    print(result.final_output)\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<p>When you run this, the model sees the message &#8220;Where is my order a101?&#8221;, decides to call <code>get_order_status<\/code> with <code>order_id=\"a101\"<\/code>, gets the result back, and then writes a friendly reply like: <em>&#8220;Your order A101 has shipped and should reach Pune in about 2 days.&#8221;<\/em><\/p>\n<div class=\"dd-tip\"><strong>Tip:<\/strong> Write docstrings for the model, not for yourself. A clear one-line summary and a description of each argument is the single biggest thing that makes tool calling reliable.<\/div>\n<div class=\"dd-note\">Older tutorials use <code>from agents import function_tool<\/code> and <code>@function_tool<\/code>. That still works, but the current docs use the shorter <code>@tool<\/code> from <code>agents.decorators<\/code>, so this guide uses it too. The SDK also offers ready-made &#8220;hosted&#8221; tools such as web search and file search that run on OpenAI&#8217;s servers.<\/div>\n\n<h2 id=\"structured-output\">Structured output with Pydantic<\/h2>\n<p>Plain text is great for chat, but your code usually wants <strong>data<\/strong>: a number, a list, a true\/false. Pass a Pydantic model as <code>output_type<\/code> and the agent&#8217;s final output will be an object of that class, already validated.<\/p>\n<span class=\"dd-file\">structured.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom pydantic import BaseModel, Field\nfrom agents import Agent, Runner\n\n\nclass JobPost(BaseModel):\n    title: str\n    company: str\n    city: str\n    remote: bool\n    skills: list[str] = Field(description=\"Technical skills mentioned in the post\")\n    min_experience_years: int\n\n\nextractor = Agent(\n    name=\"Job Post Extractor\",\n    instructions=\"Extract the job details from the text. If a value is missing, make a sensible guess.\",\n    output_type=JobPost,\n)\n\nTEXT = \"\"\"\nWe're hiring a Backend Developer at DevKart in Hyderabad (hybrid, 3 days office).\nYou should know Python, FastAPI and PostgreSQL. 2+ years of experience needed.\n\"\"\"\n\n\nasync def main():\n    result = await Runner.run(extractor, TEXT)\n    job = result.final_output  # This is a JobPost object, not a string\n    print(job.title, \"|\", job.city, \"| remote:\", job.remote)\n    print(\"Skills:\", \", \".join(job.skills))\n    print(job.model_dump_json(indent=2))\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<p>Now <code>result.final_output<\/code> is a <code>JobPost<\/code> object, so you can save it to a database or return it from a FastAPI endpoint without any string parsing. This pattern is perfect for extracting data from emails, resumes, invoices and support tickets.<\/p>\n\n<h2 id=\"handoffs\">Multi-agent handoffs<\/h2>\n<p>One agent with 30 tools and a giant prompt quickly becomes confused. A better design is a small team: a <strong>triage agent<\/strong> that reads the request and <strong>hands it off<\/strong> to the right specialist. In the SDK, a handoff is just a list of agents on the <code>handoffs=<\/code> parameter. Behind the scenes, each one appears to the model as a special tool named like <code>transfer_to_billing_agent<\/code>.<\/p>\n<figure>\n<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 900 340\" role=\"img\" aria-labelledby=\"ddHoT ddHoD\">\n<title id=\"ddHoT\">Triage agent handing off to specialists<\/title>\n<desc id=\"ddHoD\">Diagram: a customer message goes to the Triage Agent, which hands off billing questions to the Billing Agent and technical problems to the Tech Support Agent.<\/desc>\n<rect width=\"900\" height=\"340\" fill=\"#0f1430\"\/>\n<g font-family=\"Segoe UI,Roboto,Helvetica,Arial,sans-serif\" text-anchor=\"middle\">\n<defs><marker id=\"ddArr2\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto\"><path d=\"M0 0L10 5L0 10z\" fill=\"#c9bcff\"\/><\/marker><\/defs>\n<rect x=\"30\" y=\"135\" width=\"170\" height=\"70\" rx=\"12\" fill=\"#141a38\" stroke=\"#2c3566\" stroke-width=\"2\"\/>\n<text x=\"115\" y=\"166\" font-size=\"17\" font-weight=\"700\" fill=\"#dfe4ff\">Customer<\/text>\n<text x=\"115\" y=\"188\" font-size=\"13\" fill=\"#8d96c4\">&#8220;Charged twice!&#8221;<\/text>\n<rect x=\"320\" y=\"125\" width=\"210\" height=\"90\" rx=\"14\" fill=\"#1b1f4a\" stroke=\"#7c5cff\" stroke-width=\"2.5\"\/>\n<text x=\"425\" y=\"162\" font-size=\"19\" font-weight=\"700\" fill=\"#fff\">Triage Agent<\/text>\n<text x=\"425\" y=\"186\" font-size=\"13\" fill=\"#b9adff\">handoffs=[billing, tech]<\/text>\n<rect x=\"640\" y=\"30\" width=\"240\" height=\"100\" rx=\"12\" fill=\"#13302a\" stroke=\"#1fa463\" stroke-width=\"2\"\/>\n<text x=\"760\" y=\"62\" font-size=\"18\" font-weight=\"700\" fill=\"#d6ffe9\">Billing Agent<\/text>\n<text x=\"760\" y=\"85\" font-size=\"13\" fill=\"#8fd6b0\">refunds, invoices<\/text>\n<text x=\"760\" y=\"112\" font-size=\"12\" font-family=\"Menlo,Consolas,monospace\" fill=\"#6fbf98\">transfer_to_billing_agent<\/text>\n<rect x=\"640\" y=\"210\" width=\"240\" height=\"100\" rx=\"12\" fill=\"#141a38\" stroke=\"#3178c6\" stroke-width=\"2\"\/>\n<text x=\"760\" y=\"242\" font-size=\"18\" font-weight=\"700\" fill=\"#dfe4ff\">Tech Support Agent<\/text>\n<text x=\"760\" y=\"265\" font-size=\"13\" fill=\"#8d96c4\">login, bugs, errors<\/text>\n<text x=\"760\" y=\"292\" font-size=\"12\" font-family=\"Menlo,Consolas,monospace\" fill=\"#8fb8ff\">transfer_to_tech_support_agent<\/text>\n<path id=\"ddH1\" d=\"M200 170H316\" stroke=\"#8fb8ff\" stroke-width=\"2.5\" fill=\"none\" marker-end=\"url(#ddArr2)\"\/>\n<path id=\"ddH2\" d=\"M530 150C580 110 600 82 636 80\" stroke=\"#3ddc97\" stroke-width=\"2.5\" fill=\"none\" marker-end=\"url(#ddArr2)\"\/>\n<path d=\"M530 192C580 230 600 258 636 260\" stroke=\"#3178c6\" stroke-width=\"2.5\" stroke-dasharray=\"6 5\" fill=\"none\" marker-end=\"url(#ddArr2)\"\/>\n<circle r=\"6\" fill=\"#ffd166\"><animateMotion dur=\"2.8s\" repeatCount=\"indefinite\" path=\"M200 170H320C430 170 520 160 530 150C580 110 600 82 636 80\"\/><\/circle>\n<\/g>\n<\/svg>\n<figcaption>Handoffs: the triage agent picks a specialist, and that specialist takes over and writes the final answer.<\/figcaption>\n<\/figure>\n<span class=\"dd-file\">handoffs.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom agents import Agent, Runner\n\nbilling_agent = Agent(\n    name=\"Billing Agent\",\n    handoff_description=\"Handles payments, refunds, invoices and charges.\",\n    instructions=\"You help with billing questions. Be clear and polite.\",\n)\n\ntech_agent = Agent(\n    name=\"Tech Support Agent\",\n    handoff_description=\"Handles login problems, bugs and app errors.\",\n    instructions=\"You solve technical problems step by step.\",\n)\n\ntriage_agent = Agent(\n    name=\"Triage Agent\",\n    instructions=(\n        \"You are the first point of contact. Read the customer's message and \"\n        \"hand it off to the right specialist. Do not answer yourself.\"\n    ),\n    handoffs=[billing_agent, tech_agent],\n)\n\n\nasync def main():\n    questions = [\n        \"I was charged twice for my subscription this month.\",\n        \"The app shows 'Error 500' when I try to log in.\",\n    ]\n    for q in questions:\n        result = await Runner.run(triage_agent, q)\n        print(f\"Q: {q}\")\n        print(f\"Answered by: {result.last_agent.name}\")\n        print(f\"A: {result.final_output}\\n\")\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<p><code>handoff_description<\/code> is what the triage agent reads to decide where to send the request, so keep it short and specific. <code>result.last_agent<\/code> tells you which agent wrote the final answer, which is handy for logging and analytics.<\/p>\n<h3>Agents as tools (the manager pattern)<\/h3>\n<p>Sometimes you don&#8217;t want to <em>give away<\/em> the conversation. You want a manager agent that stays in charge and calls other agents like functions, then combines their answers. Use <code>agent.as_tool()<\/code> for that:<\/p>\n<span class=\"dd-file\">agents_as_tools.py<\/span>\n<pre><code class=\"language-python\">from agents import Agent\n\nhindi_agent = Agent(name=\"Hindi Translator\", instructions=\"Translate the text to Hindi.\")\ntamil_agent = Agent(name=\"Tamil Translator\", instructions=\"Translate the text to Tamil.\")\n\nmanager = Agent(\n    name=\"Translation Manager\",\n    instructions=\"Use your tools to translate. Combine the results into one reply.\",\n    tools=[\n        hindi_agent.as_tool(tool_name=\"to_hindi\", tool_description=\"Translate text to Hindi\"),\n        tamil_agent.as_tool(tool_name=\"to_tamil\", tool_description=\"Translate text to Tamil\"),\n    ],\n)<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"dd-post\">\n<h2 id=\"guardrails\">Guardrails: safety checks for your agent<\/h2>\n<p>A <strong>guardrail<\/strong> is a check that runs next to your agent. An <strong>input guardrail<\/strong> looks at the user&#8217;s message; an <strong>output guardrail<\/strong> looks at the agent&#8217;s final answer. If the check fails, it &#8220;trips a wire&#8221; and the SDK raises an exception, so the expensive main agent never finishes a bad request.<\/p>\n<p>A common trick is to use a small, cheap agent as the checker. Here, a coding-mentor bot refuses anything that is not about programming:<\/p>\n<span class=\"dd-file\">guardrail.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom pydantic import BaseModel\nfrom agents import (\n    Agent,\n    GuardrailFunctionOutput,\n    InputGuardrailTripwireTriggered,\n    RunContextWrapper,\n    Runner,\n    TResponseInputItem,\n)\nfrom agents.decorators import input_guardrail\n\n\nclass TopicCheck(BaseModel):\n    is_off_topic: bool\n    reason: str\n\n\n# A small, fast agent whose only job is to check the input\nchecker_agent = Agent(\n    name=\"Topic Checker\",\n    instructions=(\n        \"Decide if the user's message is about programming or software. \"\n        \"Set is_off_topic to true if it is NOT about programming.\"\n    ),\n    output_type=TopicCheck,\n)\n\n\n@input_guardrail\nasync def programming_only(\n    ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]\n) -&gt; GuardrailFunctionOutput:\n    result = await Runner.run(checker_agent, input, context=ctx.context)\n    return GuardrailFunctionOutput(\n        output_info=result.final_output,\n        tripwire_triggered=result.final_output.is_off_topic,\n    )\n\n\ncoding_agent = Agent(\n    name=\"Coding Mentor\",\n    instructions=\"You help developers with coding questions.\",\n    input_guardrails=[programming_only],\n)\n\n\nasync def main():\n    for message in [\"How do I reverse a string in Python?\", \"Write my history essay on the Mughal empire.\"]:\n        try:\n            result = await Runner.run(coding_agent, message)\n            print(\"Answer:\", result.final_output[:120], \"...\")\n        except InputGuardrailTripwireTriggered:\n            print(\"Blocked by guardrail:\", message)\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<p>The first message gets a normal answer. The second one trips the guardrail and raises <code>InputGuardrailTripwireTriggered<\/code>, which you catch and turn into a polite &#8220;Sorry, I only help with coding&#8221; message in your app. Output guardrails work the same way with <code>@output_guardrail<\/code> and <code>OutputGuardrailTripwireTriggered<\/code>, and are useful for blocking things like leaked secrets or personal data in replies.<\/p>\n<div class=\"dd-tip\"><strong>Good to know:<\/strong> by default input guardrails run at the same time as the main agent (to keep things fast). Guardrails are a safety net, not a replacement for proper permission checks in your tools. A refund tool should still check that the user owns the order.<\/div>\n\n<h2 id=\"sessions\">Memory with sessions<\/h2>\n<p>Each call to <code>Runner.run()<\/code> starts fresh. To build a real chat, the agent must remember earlier messages. You could pass <code>result.to_input_list()<\/code> back in yourself, but the easier way is a <strong>session<\/strong>. The SDK loads the history before each run and saves new messages after it.<\/p>\n<span class=\"dd-file\">sessions.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom agents import Agent, Runner, SQLiteSession\n\nagent = Agent(name=\"Study Buddy\", instructions=\"Reply in 1-2 short sentences.\")\n\n\nasync def main():\n    # Same session ID = same conversation. The file keeps history after restarts.\n    session = SQLiteSession(\"student_42\", \"chat_history.db\")\n\n    r1 = await Runner.run(agent, \"My name is Priya and I am learning FastAPI.\", session=session)\n    print(r1.final_output)\n\n    r2 = await Runner.run(agent, \"What is my name and what am I learning?\", session=session)\n    print(r2.final_output)  # The agent remembers: Priya, FastAPI\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<p><code>SQLiteSession(\"student_42\")<\/code> without a file name keeps history in memory only (lost when the program stops). Passing a file path like <code>\"chat_history.db\"<\/code> stores it on disk. In a web app, use your logged-in user&#8217;s ID or a chat ID as the session ID. The SDK also has other session backends (for example Redis and SQLAlchemy-based ones) for production.<\/p>\n\n<h2 id=\"streaming\">Streaming and human approval<\/h2>\n<h3>Stream the answer word by word<\/h3>\n<p>Users hate staring at a spinner. With <code>Runner.run_streamed()<\/code> you can print tokens as soon as the model produces them, just like ChatGPT does:<\/p>\n<span class=\"dd-file\">streaming.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom openai.types.responses import ResponseTextDeltaEvent\nfrom agents import Agent, Runner\n\nagent = Agent(name=\"Storyteller\", instructions=\"Tell short, fun stories.\")\n\n\nasync def main():\n    result = Runner.run_streamed(agent, input=\"Tell a 5-line story about a bug that became a feature.\")\n    async for event in result.stream_events():\n        if event.type == \"raw_response_event\" and isinstance(event.data, ResponseTextDeltaEvent):\n            print(event.data.delta, end=\"\", flush=True)\n    print()\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<h3>Ask a human before risky actions<\/h3>\n<p>Some tools should never run without a person saying &#8220;yes&#8221;: refunds, deleting data, sending emails. Mark them with <code>needs_approval=True<\/code>. The run then <strong>pauses<\/strong> and returns <code>result.interruptions<\/code>. You approve or reject each one and resume from the saved state:<\/p>\n<span class=\"dd-file\">approval.py<\/span>\n<pre><code class=\"language-python\">import asyncio\nfrom agents import Agent, Runner\nfrom agents.decorators import tool\n\n\n@tool(needs_approval=True)\ndef issue_refund(order_id: str, amount: float) -&gt; str:\n    \"\"\"Refund money for an order.\n\n    Args:\n        order_id: The order to refund.\n        amount: The amount to refund in rupees.\n    \"\"\"\n    return f\"Refund of Rs {amount} issued for order {order_id}.\"\n\n\nagent = Agent(name=\"Refund Agent\", instructions=\"Help with refunds.\", tools=[issue_refund])\n\n\nasync def main():\n    result = await Runner.run(agent, \"Please refund Rs 499 for order A101.\")\n\n    if result.interruptions:  # The run paused and is waiting for a human\n        state = result.to_state()\n        for item in result.interruptions:\n            answer = input(f\"Approve {item.name} with {item.arguments}? (y\/n) \")\n            if answer.lower() == \"y\":\n                state.approve(item)\n            else:\n                state.reject(item)\n        result = await Runner.run(agent, state)\n\n    print(result.final_output)\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())<\/code><\/pre>\n<p>In a real web app you would save <code>state<\/code> (it can be turned into a string with <code>state.to_string()<\/code>), show an &#8220;Approve&#8221; button to a support person, and resume later.<\/p>\n\n<h2 id=\"patterns\">Which pattern should you pick?<\/h2>\n<p>Beginners often ask: &#8220;Do I need one agent or many?&#8221; Click the tabs below to compare the three common designs.<\/p>\n<div class=\"dd-tabs\">\n<input type=\"radio\" name=\"dd-tabs\" id=\"dd-t1\" checked>\n<input type=\"radio\" name=\"dd-tabs\" id=\"dd-t2\">\n<input type=\"radio\" name=\"dd-tabs\" id=\"dd-t3\">\n<div class=\"dd-tablist\">\n<label for=\"dd-t1\">Single agent + tools<\/label>\n<label for=\"dd-t2\">Handoffs<\/label>\n<label for=\"dd-t3\">Agents as tools<\/label>\n<\/div>\n<div class=\"dd-panel dd-p1\">\n<p><strong>Best for:<\/strong> most apps when you are starting out, such as a support bot, a coding helper or a data extractor.<\/p>\n<p><strong>How it works:<\/strong> one agent, clear instructions, 2 to 10 well-described tools.<\/p>\n<p><strong>Watch out:<\/strong> once the prompt grows huge or the agent keeps picking the wrong tool, it is time to split it up.<\/p>\n<\/div>\n<div class=\"dd-panel dd-p2\">\n<p><strong>Best for:<\/strong> customer support and help desks, where different topics need different experts and rules.<\/p>\n<p><strong>How it works:<\/strong> a triage agent routes the conversation; the specialist takes over and talks to the user directly.<\/p>\n<p><strong>Watch out:<\/strong> the triage agent loses control after the handoff. Write clear <code>handoff_description<\/code> text for each specialist.<\/p>\n<\/div>\n<div class=\"dd-panel dd-p3\">\n<p><strong>Best for:<\/strong> research, report writing and translation, where one &#8220;manager&#8221; needs several results and combines them.<\/p>\n<p><strong>How it works:<\/strong> the manager calls sub-agents via <code>agent.as_tool()<\/code> and keeps ownership of the final answer.<\/p>\n<p><strong>Watch out:<\/strong> more model calls means more cost and time. Use smaller, cheaper models for simple sub-agents.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"dd-post\">\n<h2 id=\"errors\">Common errors and fixes<\/h2>\n<table>\n<thead><tr><th>Error or problem<\/th><th>Why it happens<\/th><th>How to fix it<\/th><\/tr><\/thead>\n<tbody>\n<tr><td><code>OpenAIError: Missing credentials<\/code> (older versions say &#8220;The api_key client option must be set&#8221;)<\/td><td>The <code>OPENAI_API_KEY<\/code> environment variable is missing in this terminal.<\/td><td>Run <code>export OPENAI_API_KEY=...<\/code> (or the PowerShell version) in the same terminal, or load a <code>.env<\/code> file before creating agents.<\/td><\/tr>\n<tr><td><code>ModuleNotFoundError: No module named 'agents'<\/code><\/td><td>The package isn&#8217;t installed in the active environment, or you installed the wrong package name.<\/td><td>Activate your virtual environment and run <code>pip install openai-agents<\/code> (the import name is <code>agents<\/code>).<\/td><\/tr>\n<tr><td><code>RuntimeError: asyncio.run() cannot be called from a running event loop<\/code><\/td><td>You are inside Jupyter or another async app that already has an event loop.<\/td><td>Use <code>await Runner.run(...)<\/code> directly in the notebook cell instead of <code>asyncio.run()<\/code>.<\/td><\/tr>\n<tr><td><code>MaxTurnsExceeded<\/code><\/td><td>The agent kept calling tools or handing off without reaching a final answer.<\/td><td>Improve instructions and tool descriptions, return clearer tool results, or raise <code>max_turns=<\/code> on <code>Runner.run()<\/code>.<\/td><\/tr>\n<tr><td><code>InputGuardrailTripwireTriggered<\/code> not caught<\/td><td>A guardrail blocked the input, and the exception crashed your app.<\/td><td>Wrap the run in <code>try\/except<\/code> and show the user a friendly message.<\/td><\/tr>\n<tr><td>Agent ignores your tool<\/td><td>The docstring is vague, or the instructions don&#8217;t tell the agent when to use it.<\/td><td>Write a clear docstring with <code>Args:<\/code>, and add &#8220;Always use the X tool to check&#8230;&#8221; to the instructions.<\/td><\/tr>\n<tr><td>Agent forgets the previous message<\/td><td>Each <code>Runner.run()<\/code> call starts with an empty history.<\/td><td>Pass the same <code>session=<\/code> on every call, or feed back <code>result.to_input_list()<\/code>.<\/td><\/tr>\n<\/tbody>\n<\/table>\n\n<h2 id=\"best-practices\">Best practices for production agents<\/h2>\n<ul class=\"dd-check\">\n<li><strong>Start with one agent.<\/strong> Add handoffs only when a single agent clearly struggles.<\/li>\n<li><strong>Keep tools small and safe.<\/strong> One job per tool, validate inputs, and return short, clear text or JSON.<\/li>\n<li><strong>Use structured output<\/strong> whenever your code (not a human) reads the result.<\/li>\n<li><strong>Put human approval<\/strong> (<code>needs_approval=True<\/code>) on any tool that spends money, deletes data or contacts customers.<\/li>\n<li><strong>Use traces<\/strong> while developing. Turn tracing off with <code>OPENAI_AGENTS_DISABLE_TRACING=1<\/code> if your company policy does not allow sending traces.<\/li>\n<li><strong>Set limits<\/strong>: a sensible <code>max_turns<\/code>, timeouts on slow tools, and a spending limit on your API account.<\/li>\n<li><strong>Test with real examples.<\/strong> Keep a list of 20 to 50 typical user messages and re-run them whenever you change prompts or tools.<\/li>\n<\/ul>\n<p>For everything else (models, context objects, lifecycle hooks, sandbox agents and voice), the <a href=\"https:\/\/openai.github.io\/openai-agents-python\/\" rel=\"noopener\" target=\"_blank\">official OpenAI Agents SDK documentation<\/a> is excellent, and the <a href=\"https:\/\/github.com\/openai\/openai-agents-python\" rel=\"noopener\" target=\"_blank\">GitHub repository<\/a> has many runnable examples.<\/p>\n\n<h2 id=\"faq\">Frequently asked questions<\/h2>\n<details>\n<summary>Is the OpenAI Agents SDK free?<\/summary>\n<p>Yes, the SDK itself is free and open source (MIT license). You only pay for the model API calls your agents make, which are billed per token by OpenAI or whichever provider you use.<\/p>\n<\/details>\n<details>\n<summary>Can I use the Agents SDK with models other than OpenAI?<\/summary>\n<p>Yes. The SDK is provider-agnostic. It supports other providers through integrations such as LiteLLM and any OpenAI-compatible API, so you can try other hosted or local models. Some features (like hosted tools) only work with OpenAI models.<\/p>\n<\/details>\n<details>\n<summary>What is the difference between handoffs and agents as tools?<\/summary>\n<p>With a handoff, the specialist <em>takes over<\/em> the conversation and writes the final answer. With agents as tools, a manager agent <em>stays in control<\/em>, calls the other agent like a function, and writes the final answer itself.<\/p>\n<\/details>\n<details>\n<summary>How is it different from LangChain or LangGraph?<\/summary>\n<p>The Agents SDK is intentionally small: a few building blocks and plain Python. LangChain and LangGraph offer more integrations and fine-grained graph control but have a bigger learning curve. For many beginner and mid-size projects, the Agents SDK is quicker to learn and easier to debug.<\/p>\n<\/details>\n<details>\n<summary>Can I use it inside a FastAPI or Django app?<\/summary>\n<p>Yes. Because <code>Runner.run()<\/code> is async, it fits naturally inside an <code>async def<\/code> FastAPI endpoint. Use a session (keyed by user or chat ID) for memory, and <code>Runner.run_streamed()<\/code> with a streaming response for a live typing effect.<\/p>\n<\/details>\n<details>\n<summary>Which Python version do I need?<\/summary>\n<p>Python 3.10 or newer. Using the latest stable Python is recommended. See what&#8217;s new in our post on <a href=\"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/python-3-15-new-features\/\">Python 3.15 new features<\/a>.<\/p>\n<\/details>\n\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>You now know the core of the <strong>OpenAI Agents SDK<\/strong>: create an <code>Agent<\/code>, run it with <code>Runner<\/code>, give it Python functions as tools, get typed data with <code>output_type<\/code>, split work with handoffs, protect it with guardrails, give it memory with sessions, and keep a human in the loop for risky actions. That is everything you need to build a useful support bot, an internal helper for your team, or an AI feature in your next side project.<\/p>\n<p>A great next step: take the order-support example, connect <code>get_order_status<\/code> to a real database, wrap it in a FastAPI endpoint, and add a session per user. You will have a working AI support agent in an afternoon.<\/p>\n<div class=\"dd-cta\">\n<h3>New posts every day on DevDojo<\/h3>\n<p>Practical, beginner-friendly guides on AI, Python, JavaScript, React and DevOps. <a href=\"https:\/\/devdojo.co.in\/\">Explore more tutorials<\/a> and leave a comment if you get stuck. We read every one!<\/p>\n<\/div>\n<\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.<\/p>\n","protected":false},"author":1,"featured_media":181,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38,9],"tags":[42,44,68,67,66,52],"class_list":["post-182","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-python","tag-ai-agents","tag-llm","tag-multi-agent-systems","tag-openai","tag-openai-agents-sdk","tag-python"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Lokendra\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"DevDojo - Empowering Developers\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"OpenAI Agents SDK Tutorial: Build AI Agents in Python\" \/>\n\t\t<meta property=\"og:description\" content=\"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-08T16:37:59+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-10-08T16:38:00+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"OpenAI Agents SDK Tutorial: Build AI Agents in Python\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#blogposting\",\"name\":\"OpenAI Agents SDK Tutorial: Build AI Agents in Python\",\"headline\":\"OpenAI Agents SDK Tutorial: Build AI Agents in Python\",\"author\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/openai-agents-sdk-python.jpg\",\"width\":1200,\"height\":630,\"caption\":\"OpenAI Agents SDK tutorial banner: a user message flows into a Python agent that calls tools and hands off to a specialist agent\"},\"datePublished\":\"2026-10-08T16:37:59+00:00\",\"dateModified\":\"2026-10-08T16:38:00+00:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#webpage\"},\"articleSection\":\"AI, Python, AI Agents, LLM, Multi-Agent Systems, OpenAI, OpenAI Agents SDK, Python\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/devdojo.co.in\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/#listItem\",\"name\":\"Backend\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/#listItem\",\"position\":2,\"name\":\"Backend\",\"item\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/python\\\/#listItem\",\"name\":\"Python\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/python\\\/#listItem\",\"position\":3,\"name\":\"Python\",\"item\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/python\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#listItem\",\"name\":\"OpenAI Agents SDK Tutorial: Build AI Agents in Python\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/#listItem\",\"name\":\"Backend\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#listItem\",\"position\":4,\"name\":\"OpenAI Agents SDK Tutorial: Build AI Agents in Python\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/backend\\\/python\\\/#listItem\",\"name\":\"Python\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#organization\",\"name\":\"DevDojo\",\"description\":\"Empowering Developers\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/\",\"name\":\"Lokendra\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/99f102f0cc9080237ce54b91304fd1b3b6fa29925cbaeba93cd796872e58b45c?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Lokendra\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#webpage\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/\",\"name\":\"OpenAI Agents SDK Tutorial: Build AI Agents in Python\",\"description\":\"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/openai-agents-sdk-python.jpg\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#mainImage\",\"width\":1200,\"height\":630,\"caption\":\"OpenAI Agents SDK tutorial banner: a user message flows into a Python agent that calls tools and hands off to a specialist agent\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/08\\\/openai-agents-sdk-python\\\/#mainImage\"},\"datePublished\":\"2026-10-08T16:37:59+00:00\",\"dateModified\":\"2026-10-08T16:38:00+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#website\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/\",\"name\":\"DevDojo\",\"description\":\"Empowering Developers\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","description":"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.","canonical_url":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#blogposting","name":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","headline":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","author":{"@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author"},"publisher":{"@id":"https:\/\/devdojo.co.in\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/devdojo.co.in\/wp-content\/uploads\/2026\/10\/openai-agents-sdk-python.jpg","width":1200,"height":630,"caption":"OpenAI Agents SDK tutorial banner: a user message flows into a Python agent that calls tools and hands off to a specialist agent"},"datePublished":"2026-10-08T16:37:59+00:00","dateModified":"2026-10-08T16:38:00+00:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#webpage"},"isPartOf":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#webpage"},"articleSection":"AI, Python, AI Agents, LLM, Multi-Agent Systems, OpenAI, OpenAI Agents SDK, Python"},{"@type":"BreadcrumbList","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/#listItem","position":1,"name":"Home","item":"https:\/\/devdojo.co.in\/","nextItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/#listItem","name":"Backend"}},{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/#listItem","position":2,"name":"Backend","item":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/","nextItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/python\/#listItem","name":"Python"},"previousItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/python\/#listItem","position":3,"name":"Python","item":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/python\/","nextItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#listItem","name":"OpenAI Agents SDK Tutorial: Build AI Agents in Python"},"previousItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/#listItem","name":"Backend"}},{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#listItem","position":4,"name":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","previousItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/python\/#listItem","name":"Python"}}]},{"@type":"Organization","@id":"https:\/\/devdojo.co.in\/#organization","name":"DevDojo","description":"Empowering Developers","url":"https:\/\/devdojo.co.in\/"},{"@type":"Person","@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author","url":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/","name":"Lokendra","image":{"@type":"ImageObject","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/99f102f0cc9080237ce54b91304fd1b3b6fa29925cbaeba93cd796872e58b45c?s=96&d=mm&r=g","width":96,"height":96,"caption":"Lokendra"}},{"@type":"WebPage","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#webpage","url":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/","name":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","description":"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/devdojo.co.in\/#website"},"breadcrumb":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#breadcrumblist"},"author":{"@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author"},"creator":{"@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/devdojo.co.in\/wp-content\/uploads\/2026\/10\/openai-agents-sdk-python.jpg","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#mainImage","width":1200,"height":630,"caption":"OpenAI Agents SDK tutorial banner: a user message flows into a Python agent that calls tools and hands off to a specialist agent"},"primaryImageOfPage":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/#mainImage"},"datePublished":"2026-10-08T16:37:59+00:00","dateModified":"2026-10-08T16:38:00+00:00"},{"@type":"WebSite","@id":"https:\/\/devdojo.co.in\/#website","url":"https:\/\/devdojo.co.in\/","name":"DevDojo","description":"Empowering Developers","inLanguage":"en-US","publisher":{"@id":"https:\/\/devdojo.co.in\/#organization"}}]},"og:locale":"en_US","og:site_name":"DevDojo - Empowering Developers","og:type":"article","og:title":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","og:description":"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.","og:url":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/","article:published_time":"2026-10-08T16:37:59+00:00","article:modified_time":"2026-10-08T16:38:00+00:00","twitter:card":"summary_large_image","twitter:title":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","twitter:description":"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples."},"aioseo_meta_data":{"post_id":"182","title":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","description":"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.","keywords":null,"keyphrases":{"focus":{"keyphrase":"OpenAI Agents SDK","score":80},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","og_description":"Learn the OpenAI Agents SDK in Python step by step: build AI agents with tools, handoffs, guardrails, memory and structured output, plus runnable code examples.","og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"BlogPosting","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":0,"frequency":"default","local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2026-10-08 16:00:01","updated":"2026-10-08 16:38:00","focus_keyword":"OpenAI Agents SDK","additional_keywords":null,"truseo_locale":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/devdojo.co.in\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/devdojo.co.in\/index.php\/category\/backend\/\" title=\"Backend\">Backend<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/devdojo.co.in\/index.php\/category\/backend\/python\/\" title=\"Python\">Python<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tOpenAI Agents SDK Tutorial: Build AI Agents in Python\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/devdojo.co.in\/"},{"label":"Backend","link":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/"},{"label":"Python","link":"https:\/\/devdojo.co.in\/index.php\/category\/backend\/python\/"},{"label":"OpenAI Agents SDK Tutorial: Build AI Agents in Python","link":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/08\/openai-agents-sdk-python\/"}],"_links":{"self":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts\/182","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/comments?post=182"}],"version-history":[{"count":1,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts\/182\/revisions"}],"predecessor-version":[{"id":183,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts\/182\/revisions\/183"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/media\/181"}],"wp:attachment":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/media?parent=182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/categories?post=182"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/tags?post=182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}