Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openai/openai-cookbook/llms.txt

Use this file to discover all available pages before exploring further.

The OpenAI Agents SDK is a lightweight Python library for building production-ready agents. It handles the agent loop, tool execution, handoffs between agents, and session memory — letting you focus on what your agents should do rather than how to orchestrate them. The SDK is built on the Responses API and integrates directly with OpenAI models, tracing, and evaluation tooling.

Installation

pip install openai-agents
Set your API key as an environment variable:
export OPENAI_API_KEY="sk-..."

Creating your first agent

An Agent takes a name, instructions, and an optional list of tools. The Runner executes the agent loop synchronously or asynchronously.
from agents import Agent, Runner

agent = Agent(
    name="AssistantAgent",
    instructions="You are a helpful assistant. Answer questions clearly and concisely.",
)

result = Runner.run_sync(agent, "What is the capital of Japan?")
print(result.final_output)
# Tokyo
Runner.run_sync is a convenience wrapper for non-async contexts. In production async code, use await Runner.run(agent, input) instead.

Adding tools to an agent

Tools are Python functions decorated with @function_tool. The SDK automatically generates the JSON schema from your function signature and docstring.
from agents import Agent, Runner, function_tool

@function_tool
def get_stock_price(ticker: str) -> str:
    """Return the current stock price for a given ticker symbol."""
    # Replace with a real market data API call
    prices = {"AAPL": "189.42", "GOOG": "175.10", "MSFT": "415.08"}
    return prices.get(ticker.upper(), "Price not found")

agent = Agent(
    name="StockAgent",
    instructions="Help users look up stock prices. Use the get_stock_price tool.",
    tools=[get_stock_price],
)

result = Runner.run_sync(agent, "What's the price of Apple stock?")
print(result.final_output)
The agent will call get_stock_price with the appropriate arguments and incorporate the result into its response automatically.

Agent handoffs

Handoffs let one agent transfer control to a specialized agent when appropriate. The receiving agent inherits the conversation context and continues from there. The dispute management example below shows a triage agent routing to either an acceptance agent or an investigator agent based on order fulfillment status:
from agents import Agent, Runner, handoff

acceptance_agent = Agent(
    name="AcceptanceAgent",
    instructions=(
        "Handle clear-cut dispute cases where the company made an error. "
        "Accept the dispute and provide a concise, professional explanation."
    ),
)

investigator_agent = Agent(
    name="InvestigatorAgent",
    instructions=(
        "Investigate disputes by analyzing order records and communication history. "
        "Collect evidence before recommending any action."
    ),
)

triage_agent = Agent(
    name="TriageAgent",
    instructions=(
        "Determine whether a dispute should be accepted outright or requires investigation. "
        "If the order was not fulfilled, hand off to AcceptanceAgent. "
        "Otherwise hand off to InvestigatorAgent."
    ),
    handoffs=[acceptance_agent, investigator_agent],
)

result = Runner.run_sync(
    triage_agent,
    "Customer claims they never received order #8821."
)
print(result.final_output)
Handoff agents receive the full message history from the previous agent. You don’t need to manually pass context between them.

Parallel agents

When a task has multiple independent subtasks, running specialized agents concurrently reduces total latency. Use asyncio.gather to fan out, then pass all outputs to a meta-agent to produce a final unified result.
import asyncio
from agents import Agent, Runner

# Specialized agents for product review analysis
features_agent = Agent(
    name="FeaturesAgent",
    instructions="Extract the key product features from the review.",
)
pros_cons_agent = Agent(
    name="ProsConsAgent",
    instructions="List the pros and cons mentioned in the review.",
)
sentiment_agent = Agent(
    name="SentimentAgent",
    instructions="Summarize the overall user sentiment from the review.",
)

# Meta-agent combines all outputs into a final summary
meta_agent = Agent(
    name="MetaAgent",
    instructions=(
        "You are given summaries labeled Features, ProsCons, and Sentiment. "
        "Combine them into a concise executive summary with a 1-5 star rating for each area."
    ),
)

async def analyze_review(review_text: str) -> str:
    # Run all specialist agents concurrently
    results = await asyncio.gather(
        Runner.run(features_agent, review_text),
        Runner.run(pros_cons_agent, review_text),
        Runner.run(sentiment_agent, review_text),
    )

    # Combine outputs and pass to the meta-agent
    combined = "\n".join([
        f"### {r.last_agent.name}\n{r.final_output}"
        for r in results
    ])
    final = await Runner.run(meta_agent, combined)
    return final.final_output

review = "Battery life is excellent, but the screen dims too quickly in sunlight."
print(asyncio.run(analyze_review(review)))
This fan-out / fan-in pattern is directly applicable to real-world scenarios like content moderation, customer-support triage, and document analysis.

Session memory

The Session object manages conversation history across multiple turns so you don’t have to manually track previous_response_id or append messages yourself.
from agents import Agent, Runner, Session

agent = Agent(
    name="SupportAgent",
    instructions=(
        "You are a customer support agent. Remember what the user has told you "
        "across the conversation and refer back to it when relevant."
    ),
)

async def multi_turn_conversation():
    session = Session()

    turns = [
        "My order #4412 hasn't arrived yet.",
        "I placed it about two weeks ago.",
        "What are my options for getting a refund?",
    ]

    for user_input in turns:
        result = await Runner.run(agent, user_input, session=session)
        print(f"User: {user_input}")
        print(f"Agent: {result.final_output}\n")

asyncio.run(multi_turn_conversation())

Context management strategies

For long-running conversations, uncurated history can overwhelm the context window. The Agents SDK supports two main strategies:
1

Trimming

Remove older messages from the history when approaching the context limit. The session keeps recent turns and discards earlier ones.
2

Compression

Summarize the conversation so far into a compact representation, replacing the raw message history with a summary. This preserves key facts while reducing token count.
Both strategies are configurable via the Session object and can be combined. See the session memory cookbook for a full walkthrough.

Evaluating agents

The Agents SDK integrates with OpenTelemetry-compatible tracing tools (such as Langfuse) to capture internal traces of every agent run. You can use these traces for:
  • Offline evaluation — batch-test your agent against a labeled dataset and score outputs
  • Online monitoring — watch costs, latency, and tool-call accuracy in real time
  • Debugging — inspect the exact sequence of model calls and tool executions when something goes wrong
from agents import Agent, Runner, set_tracing_export_api_key

# Enable tracing to an OpenTelemetry-compatible backend
set_tracing_export_api_key("your-langfuse-api-key")

agent = Agent(
    name="EvaluatedAgent",
    instructions="Answer questions about OpenAI products.",
)

result = Runner.run_sync(agent, "What models does OpenAI offer?")
print(result.final_output)
# Traces are exported automatically

Next steps

Agents overview

Understand the core concepts — models, tools, instructions, and handoffs.

MCP integration

Connect your agents to external services via Model Context Protocol servers.

Build docs developers (and LLMs) love