{"componentChunkName":"component---src-gatsby-theme-chronoblog-templates-note-js","path":"/notes/ai-agents-openai-sdk/","result":{"data":{"mdx":{"parent":{"__typename":"File","fields":{"gitLogLatestDate":"2026-06-12 00:32:37 +0200"}},"id":"eb0e4d32-d69b-51c6-a69d-a67b1295c063","excerpt":"The  OpenAI Agents SDK  ( @openai/agents ) is OpenAI's official framework for agentic apps in TypeScript. It provides a small set of…","frontmatter":{"title":"Building AI agents with OpenAI Agents SDK","date":"2026-06-12 00:01:00 UTC","job_ad":null,"job_ad_id":null,"job_ad_url":null,"tags":["openai","ai","llm","node","agents"],"cover":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAPoAAAD6AG1e1JrAAABb0lEQVQoz22Si47cIAxF5/8/sm12HtrZvGACSTCYUwFNNCPVkhWEzNG9zr3knIGMKjyfga5bsIZa5e5x3+i6F8tLcS5zvXq+v4WwwzQpt9vKPGcaBy7vwKEP/P410fc7KUX2LdL9MXx1Fu8z2wq3m+PnGZAAxij3m8faN2CBlTouVrcz9APTNLUeZyQkVBXVRBQlRa0iypsY8nkufTlgjZeJ0sBHFeX7FjBmxhjDvsm/2VbH/OH0tHwolKBkzedAUeOWlXX1jONA34+Mw4zzjhAE7/YPh5fyPeSewPwJ3LaAiBBCYBpmrHkhUvYo7Kvw7vJDYekC5M1SihnvNoah7dW5rd61dbT5/K6w0dv+KkCUKAFrLYtbSEmrEu8dzi1EiefjCo3HDhv0IzbWJh73hXkK1dK6Bn6eW41TCNSojIMwT6n+jGVRhl5qPv+bw/4ncL2+MLM2takE23P9srhF8S5zrzmUlsNZedxXrNET+Bclsg4Bl1+R0QAAAABJRU5ErkJggg==","aspectRatio":2.0869565217391304,"src":"/static/e18f1ed767f2874b2232f2d00a74e24b/c4ecb/cover.png","srcSet":"/static/e18f1ed767f2874b2232f2d00a74e24b/57ab0/cover.png 192w,\n/static/e18f1ed767f2874b2232f2d00a74e24b/f4739/cover.png 384w,\n/static/e18f1ed767f2874b2232f2d00a74e24b/c4ecb/cover.png 768w","srcWebp":"/static/e18f1ed767f2874b2232f2d00a74e24b/dd090/cover.webp","srcSetWebp":"/static/e18f1ed767f2874b2232f2d00a74e24b/ae504/cover.webp 192w,\n/static/e18f1ed767f2874b2232f2d00a74e24b/fef30/cover.webp 384w,\n/static/e18f1ed767f2874b2232f2d00a74e24b/dd090/cover.webp 768w","sizes":"(max-width: 768px) 100vw, 768px","presentationWidth":768,"presentationHeight":366},"resize":{"src":"/static/e18f1ed767f2874b2232f2d00a74e24b/c4ecb/cover.png"}}}},"fields":{"slug":"/notes/ai-agents-openai-sdk/","readingTime":{"text":"7 min read"}},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Building AI agents with OpenAI Agents SDK\",\n  \"date\": \"2026-06-12 00:01:00 UTC\",\n  \"cover\": \"./cover.png\",\n  \"tags\": [\"openai\", \"ai\", \"llm\", \"node\", \"agents\"],\n  \"canonical_url\": \"https://sevic.dev/notes/ai-agents-openai-sdk/\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"The \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://openai.github.io/openai-agents-js/\"\n  }), \"OpenAI Agents SDK\"), \" (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"@openai/agents\"), \") is OpenAI's official framework for agentic apps in TypeScript. It provides a small set of primitives: \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Agent\"), \", \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"tools\"), \", \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"handoffs\"), \", \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"guardrails\"), \", and a \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"run loop\"), \" managed by \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"run()\"), \".\"), mdx(\"p\", null, \"This post builds the same \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"support triage agent\"), \" as the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/ai-agents-vercel-ai-sdk/\"\n  }), \"Building AI agents with Vercel AI SDK\"), \" post - lookup customers and invoices, search a knowledge base, then create a ticket or escalate - but uses the OpenAI SDK instead of the Vercel tool loop.\"), mdx(\"p\", null, \"For lower-level API access, see the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/llm-integration-openai-responses-api/\"\n  }), \"OpenAI Responses API\"), \" post. For the Vercel AI SDK alternative (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"generateText\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"stopWhen\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"stepCountIs\"), \"), see the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/ai-agents-vercel-ai-sdk/\"\n  }), \"Vercel AI SDK agents post\"), \".\"), mdx(\"h3\", {\n    \"id\": \"prerequisites\"\n  }, \"Prerequisites\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"OpenAI account\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Generated API key\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Enabled billing\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Node.js version 26\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"@openai/agents\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"zod\"), \" installed (\", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"npm i @openai/agents zod\"), \")\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"OPENAI_API_KEY\"), \" set in the environment\")), mdx(\"h3\", {\n    \"id\": \"mental-model---turns-and-the-agent-loop\"\n  }, \"Mental model - turns and the agent loop\"), mdx(\"p\", null, \"A \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"turn\"), \" is one model generation. In that turn the model either:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"returns \", mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"final output\"), \" (the run ends), or\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"returns \", mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"tool calls\"), \" (the SDK executes them and starts another turn with the results), or\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"requests a \", mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"handoff\"), \" to another agent (control switches, history is preserved, loop continues)\")), mdx(\"p\", null, \"Typical flow for the support triage agent: user question \\u2192 model calls lookup tools (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"get_customer\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"get_invoice\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"search_knowledge_base\"), \") \\u2192 model creates a ticket or escalates \\u2192 final answer.\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"maxTurns: 8\"), \" means \\u201Cstop after \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"8 turns\"), \"\\u201D (eight model generations), not eight individual tool calls. A single turn can include multiple parallel tool calls.\"), mdx(\"p\", null, \"When you omit \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"maxTurns\"), \", the SDK defaults to \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"10\"), \" as a safety cap.\"), mdx(\"h3\", {\n    \"id\": \"support-triage-scenario\"\n  }, \"Support triage scenario\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Example prompt:\")), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Customer cus_1042 says they were charged twice for invoice inv_8891. What should we do?\")), mdx(\"p\", null, \"A realistic chain:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"get_customer\"), \" - plan tier, open ticket count\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"get_invoice\"), \" - amount, status, payment IDs\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"search_knowledge_base\"), \" - duplicate-charge and refund policy\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"create_support_ticket\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"escalate_to_human\"), \" - write action or escalation\")), mdx(\"p\", null, \"The demo uses in-memory fixtures (customers, invoices, knowledge-base articles) so scripts run without a database.\"), mdx(\"h3\", {\n    \"id\": \"defining-multiple-tools\"\n  }, \"Defining multiple tools\"), mdx(\"p\", null, \"Register tools with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tool()\"), \" and Zod \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"parameters\"), \". Clear \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"description\"), \" values help the model pick the right tool.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { tool } from '@openai/agents';\\nimport { z } from 'zod';\\n\\nconst getCustomer = tool({\\n  name: 'get_customer',\\n  description: 'Look up a customer account by ID',\\n  parameters: z.object({\\n    customerId: z.string().describe('Customer ID, e.g. cus_1042'),\\n  }),\\n  execute: async ({ customerId }) => {\\n    const customer = customers.find((item) => item.id === customerId);\\n    if (!customer) {\\n      return { found: false, customerId, error: 'Customer not found' };\\n    }\\n    return { found: true, customer };\\n  },\\n});\\n\\nconst getInvoice = tool({\\n  name: 'get_invoice',\\n  description: 'Look up an invoice by ID, including payment IDs and status',\\n  parameters: z.object({\\n    invoiceId: z.string().describe('Invoice ID, e.g. inv_8891'),\\n  }),\\n  execute: async ({ invoiceId }) => {\\n    const invoice = invoices.find((item) => item.id === invoiceId);\\n    if (!invoice) {\\n      return { found: false, invoiceId, error: 'Invoice not found' };\\n    }\\n    return { found: true, invoice };\\n  },\\n});\\n\\nconst searchKnowledgeBase = tool({\\n  name: 'search_knowledge_base',\\n  description: 'Search internal support articles by keyword',\\n  parameters: z.object({\\n    query: z.string().describe('Search terms, e.g. duplicate charge refund'),\\n  }),\\n  execute: async ({ query }) => {\\n    // keyword match against mocked articles\\n    return { query, articles: matches };\\n  },\\n});\\n\")), mdx(\"p\", null, \"Add write tools for outcomes:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const createSupportTicket = tool({\\n  name: 'create_support_ticket',\\n  description: 'Create a support ticket after gathering customer and policy context',\\n  parameters: z.object({\\n    customerId: z.string(),\\n    subject: z.string().min(3),\\n    priority: z.enum(['low', 'medium', 'high']),\\n    summary: z.string().min(10),\\n  }),\\n  execute: async (input) => {\\n    const ticket = createTicket(input);\\n    return { created: true, ticket };\\n  },\\n});\\n\\nconst escalateToHuman = tool({\\n  name: 'escalate_to_human',\\n  description: 'Escalate when policy requires manual review',\\n  parameters: z.object({\\n    customerId: z.string(),\\n    reason: z.string().min(10),\\n    urgency: z.enum(['normal', 'high']),\\n  }),\\n  execute: async (input) => ({\\n    escalated: true,\\n    queue: input.urgency === 'high' ? 'billing-urgent' : 'billing-standard',\\n    ...input,\\n  }),\\n});\\n\")), mdx(\"p\", null, \"Return structured objects from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"execute\"), \". The SDK serializes them as tool results for the next turn. Return explicit errors (for example \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"{ found: false, error: '...' }\"), \") so the model can recover instead of throwing.\"), mdx(\"h3\", {\n    \"id\": \"running-an-agent\"\n  }, \"Running an agent\"), mdx(\"p\", null, \"Define an \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Agent\"), \" with instructions and tools, then call \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"run()\"), \":\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { Agent, run } from '@openai/agents';\\n\\nconst agent = new Agent({\\n  name: 'Support Triage',\\n  model: 'gpt-5.5',\\n  instructions: `You are a billing support triage agent.\\n- Look up customer and invoice before recommending refunds.\\n- Search the knowledge base for policy guidance.\\n- Create a ticket when you can resolve within policy.\\n- Call escalate_to_human when manual review is required.`,\\n  tools: [\\n    getCustomer,\\n    getInvoice,\\n    searchKnowledgeBase,\\n    createSupportTicket,\\n    escalateToHuman,\\n  ],\\n});\\n\\nconst result = await run(\\n  agent,\\n  'Customer cus_1042 says they were charged twice for invoice inv_8891. What should we do?',\\n  { maxTurns: 8 },\\n);\\n\\nconsole.log(result.finalOutput);\\n\")), mdx(\"p\", null, \"Use a model that supports tool calling.\"), mdx(\"h3\", {\n    \"id\": \"maxturns---cap-the-number-of-turns\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"h3\"\n  }, \"maxTurns\"), \" - cap the number of turns\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"maxTurns(n)\"), \" stops once the run reaches \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"n\"), \" turns. Use it on every production agent to prevent runaway loops and unbounded API cost. When the cap is exceeded, the SDK throws \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"MaxTurnsExceededError\"), \".\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Use case\"), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Suggested cap\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Single tool, then answer\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"2\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Chat with occasional tool use\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"3\\u20135\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Task agents (triage, research)\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"8\\u201315\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Long autonomous workflows\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"15\\u201320 (with monitoring)\")))), mdx(\"p\", null, \"Tight vs relaxed cap on the same prompt:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { Agent, run } from '@openai/agents';\\n\\n// Stops after 3 turns even if the model still wants more context\\nconst tight = await run(agent, prompt, { maxTurns: 3 });\\n\\n// Allows a fuller investigation chain\\nconst relaxed = await run(agent, prompt, { maxTurns: 8 });\\n\")), mdx(\"h3\", {\n    \"id\": \"inspecting-runs\"\n  }, \"Inspecting runs\"), mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"newItems\"), \" array on the result contains tool calls, tool outputs, and messages from the run. Use it for debugging:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const result = await run(agent, prompt, { maxTurns: 8 });\\n\\nfor (const item of result.newItems) {\\n  if (item.type === 'tool_call_item') {\\n    console.log('tool:', item.rawItem.name, item.rawItem.arguments);\\n  }\\n  if (item.type === 'tool_call_output_item') {\\n    console.log('output:', item.output);\\n  }\\n}\\n\\nconsole.log('lastAgent:', result.lastAgent.name);\\nconsole.log('answer:', result.finalOutput);\\n\")), mdx(\"p\", null, \"The SDK emits traces automatically. Set \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"workflowName\"), \" on a custom \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Runner\"), \" to group related runs in the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://platform.openai.com/traces\"\n  }), \"OpenAI Traces dashboard\"), \".\"), mdx(\"h3\", {\n    \"id\": \"handoffs\"\n  }, \"Handoffs\"), mdx(\"p\", null, \"For multi-agent workflows, define specialist agents and wire them with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Agent.create()\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"handoffs\"), \". The triage agent in this post stays single-agent, but handoffs are the SDK's way to delegate between agents (similar to routing a case to a billing specialist):\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { Agent } from '@openai/agents';\\n\\nconst billingAgent = new Agent({\\n  name: 'Billing Specialist',\\n  instructions: 'Handle refund and duplicate-charge cases.',\\n  tools: [getInvoice, searchKnowledgeBase, createSupportTicket],\\n});\\n\\nconst triageAgent = Agent.create({\\n  name: 'Triage',\\n  instructions: 'Route billing cases to the billing specialist when needed.',\\n  handoffs: [billingAgent],\\n});\\n\")), mdx(\"p\", null, \"After a run, check \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"result.lastAgent\"), \" to see which agent produced the final output.\"), mdx(\"h3\", {\n    \"id\": \"streaming\"\n  }, \"Streaming\"), mdx(\"p\", null, \"Pass \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"stream: true\"), \" to receive events as the run progresses:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { Agent, run } from '@openai/agents';\\n\\nconst stream = await run(agent, prompt, { maxTurns: 8, stream: true });\\n\\nprocess.stdout.write('Answer: ');\\n\\nfor await (const event of stream) {\\n  if (event.type === 'raw_model_stream_event' && event.data.type === 'output_text_delta') {\\n    process.stdout.write(event.data.delta);\\n  }\\n\\n  if (event.type === 'run_item_stream_event' && event.name === 'tool_called') {\\n    console.error(`\\\\nTool: ${event.item.rawItem.name}`);\\n  }\\n}\\n\\nawait stream.completed;\\nconsole.log('\\\\nDone:', stream.finalOutput);\\n\")), mdx(\"p\", null, \"Text streams incrementally. Tool calls appear as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"run_item_stream_event\"), \" events between text segments.\"), mdx(\"h3\", {\n    \"id\": \"production-notes\"\n  }, \"Production notes\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Always set \", mdx(\"inlineCode\", {\n    parentName: \"strong\"\n  }, \"maxTurns\")), \" - do not rely on the default cap without monitoring\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Cost\"), \" - each turn is another model call; inspect \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"newItems\"), \" or stream events for tool usage\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Tool errors\"), \" - return structured errors from \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"execute\"), \" instead of throwing when the model should retry or escalate\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Instructions\"), \" - keep policy rules in \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"instructions\"), \", not only in the user prompt\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Tracing\"), \" - use the OpenAI Traces dashboard to debug multi-turn runs\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Alternatives\"), \" - hosted tools (web search, code interpreter), MCP servers, and sandbox agents are covered in the \", mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"https://openai.github.io/openai-agents-js/\"\n  }), \"official docs\"))), mdx(\"h3\", {\n    \"id\": \"demo\"\n  }, \"Demo\"), mdx(\"p\", null, \"Runnable scripts for each section live in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"openai-agents-sdk-demo\"), \" folder. Get access via \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/demos\"\n  }), \"code demos\"), \".\"));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"id":"eb0e4d32-d69b-51c6-a69d-a67b1295c063"}},"staticQueryHashes":["1961101537","2542493696"]}