Frameworks

OpenAI Agents SDK: Hello World, Tools and Handoffs

Checked 2026-10-31

Loading poll...

The OpenAI Agents SDK is a small framework for building agents in your own application, in Python or JavaScript. You define an agent with instructions, tools and optional handoffs to other agents, then run it. It is MIT-licensed and free; you pay OpenAI for model use. Checked 31 October 2026.

At a glance

OpenAI Agents SDK

Vendor

OpenAI

Languages

Python (openai-agents) and JavaScript/TypeScript (@openai/agents)

License

MIT (both repositories)

Core ideas

Agent, tools, handoffs, sessions, guardrails, tracing

Where it runs

Inside your application

Cost

The SDK is free; model and hosted-tool usage is billed by OpenAI; GPT-6.1 Sol is $2 and $10 per million input and output tokens

Repo activity

Python: about 30,400 stars, pushed 30 October 2026. JavaScript: about 3,950 stars, pushed 30 October 2026

Related

Agents API (managed), Responses API (lower level), ChatKit (chat UI)

What it is

The SDK is the "control the loop yourself" option in OpenAI's agent stack. OpenAI's own guide splits the stack into four starting points.

You want to

Start with

Run an agent on the Codex harness managed by OpenAI

Agents API

Control the agent loop in your application with reusable agents, tools and handoffs

Agents SDK

Work directly with model responses

Responses API

Add an embedded chat experience

ChatKit

The comparison table in the guide is useful. With the Agents API, OpenAI runs the harness and saves the session; integration effort is low. With the Agents SDK, the SDK runs inside your application; effort is medium, and you own storage, approvals and runtime. With the Responses API you build the agent from scratch; effort is high.

Choose the SDK when you want orchestration in your own code, your own state store and your own deployment. Choose the Agents API when you want long-running tasks managed for you. If you are leaving Agent Builder, see OpenAI Agent Builder, because the SDK is the main code path out of it.

Install

# JavaScript
npm install @openai/agents zod

# Python
pip install openai-agents

export OPENAI_API_KEY=sk-...

The JavaScript package asks for zod because tool parameters are described with Zod schemas.

Hello world

This is the quickstart, with one focused agent and one turn. The SDK makes the model call and returns a result object with the final output and the run history.

import asyncio

from agents import Agent, Runner

agent = Agent(
    name="History tutor",
    instructions="You answer history questions clearly and concisely.",
    model="gpt-6-astra",
)


async def main() -> None:
    result = await Runner.run(agent, "When did the Roman Empire fall?")
    print(result.final_output)


if __name__ == "__main__":
    asyncio.run(main())
import { Agent, run } from "@openai/agents";

const agent = new Agent({
  name: "History tutor",
  instructions: "You answer history questions clearly and concisely.",
  model: "gpt-6-astra",
});

const result = await run(agent, "When did the Roman Empire fall?");
console.log(result.finalOutput);

The model name in the docs' example is gpt-6-astra. Model names change, so check OpenAI's model list before copying it. The docs' advice is to get this loop working first and then add capability step by step, "rather than starting with a large multi-agent design."

Add a tool

The first capability you usually add is a function tool or a hosted OpenAI tool such as web search or file search. A Python function tool is a decorated function:

from agents import Agent, Runner, function_tool


@function_tool
def history_fun_fact() -> str:
    """Return a short history fact."""
    return "Sharks are older than trees."


agent = Agent(
    name="History tutor",
    instructions="Answer history questions clearly. Use history_fun_fact when it helps.",
    tools=[history_fun_fact],
)

In JavaScript you build the tool with tool({ name, description, parameters, execute }), where parameters is a Zod object. The docstring (Python) or description (JavaScript) is what the model reads, so write it for the model, not for yourself.

Add specialist agents with handoffs

A common next step is to split the work into specialists and let a router delegate:

history_tutor = Agent(
    name="History tutor",
    handoff_description="Specialist for history questions.",
    instructions="Answer history questions clearly and concisely.",
)

math_tutor = Agent(
    name="Math tutor",
    handoff_description="Specialist for math questions.",
    instructions="Explain math step by step and include worked examples.",
)

triage_agent = Agent(
    name="Homework triage",
    instructions="Route each homework question to the right specialist.",
    handoffs=[history_tutor, math_tutor],
)

result.last_agent (Python) or result.lastAgent (JavaScript) tells you which specialist ended up answering. After a handoff, reuse that agent for the next turn when the specialist should stay in control. This is the same pattern Agent Builder drew as a graph of agent nodes.

State between turns

The docs give four options for carrying state into the next turn.

If you want

Use

The full history kept in your application

result.to_input_list() in Python, result.history in TypeScript

The SDK to load and save history

A session

OpenAI to manage continuation state

A server-managed continuation ID

To resume a run paused for approval or interruption

result.to_state() in Python, result.state in TypeScript, with interruptions

The last row is how human approval works in SDK code: a run can pause and be resumed after a person decides.

Tracing

The normal server-side path includes tracing. The docs say to open the Traces dashboard as soon as the first run works, to inspect model calls, tool calls, handoffs and guardrails before tuning prompts. Tracing is also what the trace graders in OpenAI's evaluation tooling read. If you send code or prompts you consider sensitive, check what your tracing settings upload. The Python docs say tracing is on by default and give three ways to turn it off: set the environment variable OPENAI_AGENTS_DISABLE_TRACING=1, call set_tracing_disabled(True), or set tracing_disabled on the RunConfig of a single run. Model and function spans can hold sensitive inputs and outputs, and RunConfig.trace_include_sensitive_data controls whether they are captured. One caveat from the docs: disabling tracing stops new traces but does not discard data a processor already buffered.

MCP, tools and guardrails

The agents guide has sections on tools, skills and prompt caching, and the Agents API mentions support for MCP servers. The Agent Builder node reference describes MCP, file search and guardrails as tool nodes, and the SDK is where that functionality lives when you write it in code. The Python docs list four MCP routes, covered in the sections below, and two guardrail kinds plus tool guardrails.

Browse the MCP servers that agents commonly use in our MCP server list.

Models and vendor lock-in

The quickstart uses OpenAI models and OpenAI's hosted tools. The Python models page names two built-in OpenAI model classes, one for the Responses API (recommended) and one for Chat Completions. Whether you can use a non-OpenAI model depends on adapters we did not confirm. Treat it as OpenAI-first. If you need a framework that is model-neutral by design, see LangGraph or CrewAI. If your agent is a coding agent built on Claude, see the Claude Agent SDK.

Connect MCP servers

The Python docs offer four ways to use MCP, and the choice is about who holds the connection.

You want

Use

OpenAI's Responses API to call a publicly reachable MCP server for the model

HostedMCPTool

To connect to a Streamable HTTP server you run or reach yourself

MCPServerStreamableHttp

To launch a local process and talk over stdin and stdout

MCPServerStdio

An older server-sent events transport

MCPServerSse

Hosted tools push the whole round trip into OpenAI's infrastructure, so your code never lists or calls the tools. They currently work with OpenAI models that support hosted MCP in the Responses API. For a server you control, the Streamable HTTP route keeps the connection in your process. This example follows the docs, with the token read from an environment variable and the tool list cached:

import asyncio
import os

from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp


async def main() -> None:
    token = os.environ["MCP_SERVER_TOKEN"]
    async with MCPServerStreamableHttp(
        name="Docs server",
        params={
            "url": "http://localhost:8000/mcp",
            "headers": {"Authorization": f"Bearer {token}"},
            "timeout": 10,
        },
        cache_tools_list=True,
        max_retry_attempts=3,
    ) as server:
        agent = Agent(
            name="Assistant",
            instructions="Use the MCP tools to answer the questions.",
            mcp_servers=[server],
        )
        result = await Runner.run(agent, "Add 7 and 22.")
        print(result.final_output)


asyncio.run(main())

Useful options from the docs: tool_filter exposes only a subset of a server's tools, require_approval adds a human approval policy for local MCP tools, and max_retry_attempts retries tool listing and calls with backoff. Filter and approve before you connect a server with write access, since the model can call anything you expose. The docs also note that the local transports depend on the mcp package, and that a major-version change of that package affects some options, so pin it. To build a server of your own, see how to build an MCP server.

Guardrails

Guardrails check input and output around an agent. The docs describe two kinds: input guardrails run on the initial user input, and output guardrails run on the final agent output. Where they run matters. Input guardrails run only for the first agent in a chain, and output guardrails only for the agent that produces the final answer. If you need a check around every custom function-tool call, including in handoffs, use tool guardrails, which run on each guarded call.

An input guardrail returns a result with a tripwire_triggered flag. When it is true, the SDK raises an exception and the run stops. This sketch follows the docs' pattern, with a simple check in place of a classifier:

from agents import (
    Agent,
    GuardrailFunctionOutput,
    InputGuardrailTripwireTriggered,
    RunContextWrapper,
    Runner,
    TResponseInputItem,
)
from agents.decorators import input_guardrail


@input_guardrail(run_in_parallel=False)
async def no_card_numbers(
    ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
    text = input if isinstance(input, str) else str(input)
    digits = "".join(ch for ch in text if ch.isdigit())
    return GuardrailFunctionOutput(
        output_info={"digits": len(digits)},
        tripwire_triggered=len(digits) >= 13,
    )


agent = Agent(
    name="Support",
    instructions="Answer support questions.",
    input_guardrails=[no_card_numbers],
)


async def main() -> None:
    try:
        await Runner.run(agent, "My card is 4111 1111 1111 1111, please fix billing")
    except InputGuardrailTripwireTriggered:
        print("Blocked before the agent ran")

Input guardrails have two modes. The default runs in parallel with the agent for the best latency, but if the tripwire fires the agent may already have used tokens. With run_in_parallel=False the guardrail finishes first, so a blocked request never reaches the model or any tool. Use blocking mode for checks that protect money or data. A digit counter is a crude rule, and a real guardrail often uses a small model as a classifier. The docs show that pattern, and the threshold you pick should come from labeled examples of your own traffic.

A worked cost at three volumes

The SDK is free, so the bill is model use. OpenAI's API prices from our pricing research are GPT-6.1 Sol at $2 input and $10 output per million tokens, GPT-6.1 Terra at $1 and $5, and GPT-6 Luna at $0.10 and $0.50. These sums use example token counts: one agent run that makes five model calls, reading 60,000 input tokens and writing 3,000 output tokens in total.

Model

One run

100 runs

5,000 runs

50,000 runs

GPT-6.1 Sol

$0.12 + $0.03 = $0.15

$15

$750

$7,500

GPT-6.1 Terra

$0.06 + $0.015 = about $0.075

$7.50

$375

$3,750

GPT-6 Luna

$0.006 + $0.0015 = about $0.0075

$0.75

$37.50

$375

Prompts over 272,000 tokens bill at higher rates, and batch or Flex processing is half price, so check OpenAI API pricing before you plan a large job. The table shows why a router pattern pays: a triage agent on a small model that hands hard cases to a larger one costs far less than sending everything to the biggest. Handoffs are model decisions, though, so measure the routing accuracy on your own questions before you trust the saving.

From prototype to something you can run

  1. Pin the model name in config. Names change, and a code sample is the worst place to hold one.
  2. Put every tool behind a narrow function. Validate arguments in code, as with any tool the model calls.
  3. Decide where history lives before you have users, using the state table above.
  4. Turn on tracing in development and decide for production. Traces are how you debug a bad handoff. Switch off sensitive data capture if prompts contain personal data.
  5. Add approval before side effects. Pausing a run for approval and resuming it is built in.
  6. Keep a small regression set. Ten saved inputs with expected behaviour, run after each prompt change, catch most breakage.
  7. Set a spend limit on the API project, and alert on daily usage.

Limits and gotchas

  • You own the runtime. Storage, approvals, deployment and sandboxing are your job, which is the trade for control.
  • Model names move. Pin them in config, not in code samples.
  • Two libraries. Python and JavaScript are separate repositories with different star counts and release rhythms; check the one you use.
  • Handoffs are model decisions. A router can send a query to the wrong specialist. Test it with ambiguous inputs.
  • Safety. OpenAI's safety guidance for agents applies: keep untrusted text out of developer messages, constrain data flow with structured outputs and put human approval before actions that matter.

SDK, Agents API or Responses API

This is the decision most newcomers get stuck on, so here it is in detail. The three sit at different heights.

Agents API

Agents SDK

Responses API

Use for

Long-running tasks where OpenAI manages the agent and saves its progress

Agents with custom tools and workflows in your application

Calling models directly or building from scratch

Where the agent runs

OpenAI runs a managed Codex harness

Inside your application

Your application, with optional hosted orchestration

State between tasks

Saved session configuration, turns and items

Your storage and SDK sessions, or Responses conversation state

Manual history, response chaining or Conversations

Tool execution

Service-connected tools, application function handlers and an optional sandbox

Tools and integrations you configure

Hosted tools and tools your application runs

Execution environment

OpenAI hosted sandbox, self-hosted sandbox or none

Your runtime and sandbox integrations

Your own

Integration effort

Low

Medium

High

OpenAI says the Agents API includes automatic context compaction, multi-agent orchestration, programmatic tool calling and MCP server support. The SDK "gives your application control over deployment, storage, approvals, and runtime integration," and its runner handles the loop and handoffs.

A way to choose: if the task runs for a long time and you do not want to build storage and a sandbox, look at the Agents API. If you need the logic in your own code and your own cloud, use the SDK. If you want to write the loop yourself, drop to the Responses API.

A sensible project layout

The SDK does not force a structure, so pick one that keeps agents testable. This is our suggestion, not OpenAI's.

File or folder

Holds

agents/

One module per agent: name, instructions, tools, handoffs

tools/

Plain functions with clear names and docstrings

config.py

Model names and the API key lookup, in one place

run.py

The entry point that calls Runner.run and prints or streams the result

evals/

Saved inputs and expected outputs for regression checks

Keep instructions in version control next to the code. When an agent misbehaves, the first thing to check is the prompt, and having it in a diff makes that quick.

Questions people ask

Do I need ChatKit? No. ChatKit is a chat UI you can put in front of an agent. The SDK works from a script, a worker or an API.

Can I use it with a coding agent? The SDK builds your own agent. For a ready-made coding agent, see Codex CLI or the other pages under AI coding agents.

Is it production ready? The repositories are active, with pushes on the day we checked. The docs still tell you to validate runtime configuration, tools, authentication, permissions and deployment yourself, which is a fair summary of what production readiness means with any framework.

Where do I learn more? The guide has pages on agent definitions, tools, running agents and tracing. Start at the quickstart and follow its "next steps".

Who it suits

  • Developers who want a small, readable framework and already use OpenAI models.
  • Teams migrating off Agent Builder who want the closest match in code.
  • Anyone who wants tracing and evaluation tooling next to the framework.

It suits less well if you need many model vendors on equal footing, or a no-code builder. For a visual tool look at n8n or Flowise.

Compared with the other frameworks

Style

Best for

OpenAI Agents SDK

Small agent, tools and handoffs

Staying close to OpenAI's platform

LangGraph

State graph

Long-running, stateful flows

CrewAI

Role-based crews

Teams of agents with roles

Claude Agent SDK

Claude Code's tools as a library

Coding and file-based agents on Claude

See AI agent frameworks and agentic AI frameworks for the whole field.

Our take

This comes from OpenAI's guide, quickstart and the two repositories. We did not build an agent for this page.

The SDK's strength is that it is small. Agent, tool, handoff, run: you can read the whole quickstart in ten minutes and understand the model. That is also what makes it a good landing place for Agent Builder users, since the concepts map across.

The weakness is that it is OpenAI's. The docs, examples and tooling all assume OpenAI models and hosted tools. That is fine if you are committed to OpenAI and a risk if you are not. Keep the model name and the tools behind a thin layer of your own so you can move.

Start with the hello world, add one tool, then add one handoff, and open the trace after each. If that feels like the right amount of framework, stay. If you feel the need for graph state or role teams, compare the others.

Checklist

  • Install the package for your language and set OPENAI_API_KEY
  • Run the hello world with a model you have access to
  • Add one tool and read its trace
  • Add a handoff and test ambiguous questions
  • Decide where history lives: your store, a session or a continuation ID
  • Put approval in front of any action with side effects

Questions

How do I install the OpenAI Agents SDK?

For Python run pip install openai-agents. For JavaScript run npm install @openai/agents zod. Set OPENAI_API_KEY.

Is it open source?

Yes. Both the Python and JavaScript repositories are MIT-licensed.

What is the difference between the Agents SDK and the Agents API?

With the SDK the agent loop runs inside your application. With the Agents API, OpenAI runs a managed Codex harness and saves progress for long-running tasks.

Does the SDK replace Agent Builder?

OpenAI's migration guide offers it as one of two paths for Agent Builder workflows, which are scheduled to shut down on November 30, 2026.

Loading poll...

Sources

  1. github.com/openai/openai-agents-python/blob/main/docs/mcp.md
  2. github.com/openai/openai-agents-python/blob/main/docs/guardrails.md
  3. github.com/openai/openai-agents-python/blob/main/docs/tracing.md
  4. developers.openai.com/api/docs/guides/agents
  5. developers.openai.com/api/docs/guides/agents/quickstart
  6. github.com/openai/openai-agents-python
  7. github.com/openai/openai-agents-js
  8. developers.openai.com/api/docs/guides/agent-builder/migrate-from-agent-builder

Part of the Wbcom Designs family

The all-in-one WordPress community stack

Also ours: wbcomdesigns.comvapvarun.combrndle.com