OpenAI Agent Stack: A Beginner-Friendly Guide
1. What is an AI Agent?
A traditional language-model application
normally follows a simple pattern:
User asks a question
↓
Model generates an answer
↓
Answer is returned
An AI agent can go further. An agent can:
• Understand a goal• Decide what action is needed
• Call tools
• Use tool results
• Delegate work to another agent
• Apply safety checks
• Repeat steps until the task is complete
• Return a final answer
Definition : An AI agent is a language model configured with instructions, tools, and optional runtime features such as handoffs, guardrails, and structured outputs.
The OpenAI Agents SDK uses the Responses
API by default for OpenAI models and adds higher-level orchestration for tools,
turns, handoffs, guardrails, sessions, and tracing. [openai.github.io]
2. The Four Layers of the OpenAI Agent Stack
A useful way to understand the architecture
is through four layers.
┌─────────────────────────────────────┐
│ 4. Your Application
│ Web app, API, CLI, chatbot
└──────────────────┬──────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 3. OpenAI Agents SDK
│ Agent, Runner, tools, handoffs, guardrails and tracing
│
└──────────────────┬──────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 2. Responses API
│ Model calls, tool calling, state, structured input and output
│
└──────────────────┬──────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 1. OpenAI Models
│ Understanding, reasoning and response generation
│
└─────────────────────────────────────┘
Layer 1: OpenAI Models
The model provides the intelligence.
The model can:
- Understand input
- Follow instructions
- Reason about a task
- Decide whether a tool is required
- Generate text or structured output
- Interpret tool results
A model by itself is not the complete agent
application. The surrounding application supplies tools, control flow, safety
checks, and business logic.
Layer 2: Responses API
The Responses API is the core interface for
interacting with OpenAI models.
It supports capabilities such as:
•
String or structured input
•
Text and structured output
•
Tool calling
•
Conversation chaining
•
Model-driven tool selection
Layer 3: Agents SDK
The Agents SDK sits above model calls and provides agent-oriented orchestration.
Its important building blocks include:
•Agent•
Runner• Tools
• Handoffs
• Guardrails
• Tracing
• Sessions
Layer 4: Your Application
Your application provides the user
experience and business logic.
Examples include:
•
Web application
•
REST API
•
Command-line utility
•
Customer-support chatbot
•
Database migration assistant
•
AWR analysis assistant
•
Cloud-sizing assistant
3. Responses API
The Responses API can be used directly when
the application needs model interaction but does not require the full Agents
SDK abstraction.
Basic Responses API request
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="YOUR_MODEL_NAME",
input="Explain an AI agent in
one paragraph."
)
print(response.output_text)
The application:
1.
Creates a client.
2.
Sends the model name and input.
3.
Receives a response.
4.
Reads the text through response.output_text.
Conversation chaining
One response can be connected to a later
response using the previous response ID.
response1 = client.responses.create(
model="YOUR_MODEL_NAME",
input="My name is Alice and I
work as an engineer."
)
response2 = client.responses.create(
model="YOUR_MODEL_NAME",
input="What is my name and
occupation?",
previous_response_id=response1.id
)
print(response2.output_text)
Conceptually:
First request
↓
Response ID
↓
Second request references the ID
↓
Model receives the connected context
Adding a hosted tool
A supported hosted tool can be included in
a request.
response = client.responses.create(
model="YOUR_MODEL_NAME",
tools=[{"type":
"web_search"}],
input="Find current information
about this topic."
)
print(response.output_text)
The model can decide whether using the
available tool is appropriate.
4. Responses API or Agents SDK?
The choice primarily depends on how much
orchestration the application needs.
Use the Responses API directly when:
•
The operation is simple
•
The application needs one or a
small number of model calls
•
The development team wants to
control the execution loop
•
The application will manage
tool execution and retries
•
Complex agent delegation is
unnecessary
Use the Agents SDK when:
•
The workflow may require
several model turns
•
The model needs to call tools
•
Multiple agents are involved
•
Guardrails are required
•
Handoffs are required
•
Tracing and observability are
important
•
The SDK should manage the agent
loop
The important difference is:
With the Responses API, the application can
own the orchestration loop. With the Agents SDK, Agent and Runner provide a
higher-level runtime for managing the loop.
The Agents SDK documentation describes this
distinction as orchestration: Agent plus Runner can manage turns, tools,
guardrails, handoffs, and sessions, while direct Responses API usage allows the
application to own the loop. [openai.github.io]
5. Core Components of the Agents SDK
A simplified formula is:
Agent = Model + Instructions + Tools +
Runtime behavior
Agent
An Agent
defines:
•
A name
•
Instructions
•
A model
•
Available tools
•
Optional handoffs
•
Optional guardrails
•
Optional output type
Example:
from agents import Agent
agent = Agent(
name="Quick Helper",
instructions="Provide concise
and accurate answers.",
model="YOUR_MODEL_NAME"
)
Runner
The Runner executes the agent workflow.
The three common execution patterns are:
Runner.run() Asynchronous execution
Runner.run_sync() Synchronous
execution
Runner.run_streamed() Streaming
execution
Synchronous execution
from agents import Agent, Runner
agent = Agent(
name="Quick Helper",
instructions="Answer each
question in one sentence.",
model="YOUR_MODEL_NAME"
)
result = Runner.run_sync(
agent,
"What is an AI agent?"
)
print(result.final_output)
Asynchronous execution
import asyncio
from agents import Agent, Runner
agent = Agent(
name="Quick Helper",
instructions="Provide concise
answers.",
model="YOUR_MODEL_NAME"
)
async def main():
result = await Runner.run(
agent,
"What is an AI agent?"
)
print(result.final_output)
asyncio.run(main())
Use:
Runner.run_sync(...)
in a normal synchronous program.
Use:
await Runner.run(...)
inside asynchronous Python code.
6. What the Agent Loop Does
Calling the Runner does not necessarily
produce only one model request. It starts an agent workflow.
User input
↓
Runner sends input to model
↓
Model produces output
↓
Does the output contain a tool call?
├── Yes → Execute tool
│ ↓
│ Return result to model
│ ↓
│ Continue loop
│
└── No → Is the output final?
├── No → Continue
└── Yes → Return final
output
The Runner can:
1.
Invoke the model.
2.
Inspect the model output.
3.
Execute requested tools.
4.
append tool results to the
workflow.
5.
Process a handoff when one is
requested.
6.
Invoke the model again.
7.
Stop when final output is
produced or another stopping condition occurs.
The documented Runner loop processes model
outputs, handoffs, and tool calls until final output is reached or the
configured turn limit is exceeded. [openai.github.io]
7. Tools: Giving Agents Capabilities
Tools allow agents to do more than generate
answers.
Examples of tool actions include:
•
Searching information
•
Reading files
•
Calling an API
•
Running code
•
Querying a database
•
Performing a calculation
•
Calling another specialized
agent
The current Agents SDK documentation
describes hosted tools, locally executed tools, function tools, and agents
exposed as tools. [openai.github.io]
Main tool patterns
1. Hosted tools
Hosted tools are provided and managed by
OpenAI.
Common examples include:
•
Web search
•
File search
•
Code interpreter
•
Image generation
Conceptually:
Agent
↓
Requests hosted tool
↓
Hosted service executes it
↓
Result returns to agent
2. Function tools
Function tools are Python functions exposed
to the model.
Examples:
•
get_weather()
•
search_customer()
•
calculate_database_size()
•
check_migration_status()
3. Agents as tools
A specialized agent can be exposed as a
tool to another agent.
Manager Agent
↓
Calls Specialist Agent as a tool
↓
Specialist returns result
↓
Manager continues orchestration
8. Building a Function Tool
The @function_tool decorator exposes a Python function as an agent tool.
Simple example
from agents import function_tool
@function_tool
def add(a: float, b: float) -> float:
"""Add two numbers
together."""
return a + b
The important elements are:
•
Function name
•
Parameter names
•
Type hints
•
Return type
•
Docstring
The SDK can use Python function definitions
and Pydantic-based validation to generate function-tool schemas. [openai.github.io]
Why the docstring matters
The docstring tells the model when the
function should be used.
Weak description:
"""Performs something with
two values."""
Better description:
"""Add two numbers and
return the result. Use for addition operations."""
A precise description reduces ambiguity
when several similar tools are available.
9. Complete Math Agent Example
The following example creates four
calculation tools.
import math
from agents import Agent, Runner, function_tool
@function_tool
def add(a: float, b: float) -> float:
"""Add two numbers and
return the result."""
return a + b
@function_tool
def multiply(a: float, b: float) -> float:
"""Multiply two
numbers and return the result."""
return a * b
@function_tool
def divide(a: float, b: float) -> float:
"""Divide the first
number by the second number."""
if b == 0:
raise ValueError("Division
by zero is not allowed.")
return a / b
@function_tool
def square_root(number: float) -> float:
"""Calculate the
square root of a non-negative number."""
if number < 0:
raise ValueError("Cannot
calculate the real square root of a negative number.")
return math.sqrt(number)
tools = [
add,
multiply,
divide,
square_root
]
math_agent = Agent(
name="Math Assistant",
instructions=(
"You are a math assistant.
"
"Use the available tools for
calculations. "
"Briefly explain the
calculation."
),
tools=tools,
model="YOUR_MODEL_NAME"
)
result = Runner.run_sync(
math_agent,
"What is 15 multiplied by 8,
then divided by 3?"
)
print(result.final_output)
Conceptual execution
Question:
15 multiplied by 8, then divided by 3
↓
Model selects multiply
↓
multiply(15, 8)
↓
120
↓
Tool result returned to model
↓
Model selects divide
↓
divide(120, 3)
↓
40
↓
Model prepares final response
↓
result.final_output
A simplified answer could be:
15 × 8 = 120, and 120 ÷ 3 = 40.
Important clarification
Two sequential tools do not always imply
exactly two total model calls. The number and shape of model turns depend on:
•
Tool dependencies
•
Runtime configuration
•
Model behavior
•
Whether calls can be
parallelized
•
Whether another model turn is
required to compose the final answer
The main concept is that the Runner manages
the repeated interaction between the model and tools.
10. OpenAI Agents SDK and LangChain
Both technologies can be used to create
agentic applications, but the programming abstractions and ecosystems differ.
Simplified comparison
|
Area |
OpenAI Agents SDK |
LangChain/LangGraph |
|
Agent definition |
|
Agent or graph construction |
|
Function decorator |
|
Commonly |
|
Model configuration |
Can be specified in |
Often initialized separately |
|
Synchronous execution |
|
Framework-specific invoke pattern |
|
Final output |
|
Depends on chain or graph result structure |
|
Main orientation |
Lightweight agent primitives |
Broader LLM application ecosystem |
|
OpenAI integration |
Uses Responses API by default for OpenAI models |
Supports multiple providers and integrations |
This is not a universal “better versus
worse” comparison. Selection should depend on architecture, provider
requirements, existing libraries, orchestration complexity, and operational
standards.
11. Multi-Agent Systems
A multi-agent system uses multiple
specialized agents.
For example:
Triage Agent
├── Math Agent
├── History Agent
└── Science Agent
Two major orchestration patterns are:
1.
Handoffs
2.
Manager or agents-as-tools
12. Pattern One: Handoffs
A handoff transfers control from one agent
to another.
User
↓
Triage Agent
↓
Selects specialist
↓
Handoff
↓
Specialist Agent takes over
↓
Specialist produces response
This is a decentralized orchestration
pattern.
Appropriate use cases
•
Customer-support routing
•
Department-based routing
•
Subject-matter routing
•
Conversation ownership transfer
•
Specialized troubleshooting
Simplified handoff example
from agents import Agent, Runner
math_agent = Agent(
name="Math Tutor",
handoff_description=(
"Use this agent for
mathematics, calculations, and equations."
),
instructions=(
"Explain mathematical
problems step by step "
"using beginner-friendly
language."
)
)
history_agent = Agent(
name="History Tutor",
handoff_description=(
"Use this agent for history
questions and historical events."
),
instructions=(
"Answer history questions
using important facts and context."
)
)
triage_agent = Agent(
name="Triage Agent",
instructions=(
"Route mathematics questions
to the Math Tutor. "
"Route history questions to
the History Tutor."
),
handoffs=[
math_agent,
history_agent
]
)
result = Runner.run_sync(
triage_agent,
"What is 15 percent of
240?"
)
print(result.final_output)
Conceptually:
Question
↓
Triage Agent
↓
Question classified as mathematics
↓
Handoff to Math Tutor
↓
Math Tutor answers
The SDK uses handoffs as a mechanism for
delegating control to another agent. [openai.github.io]
13. Pattern Two: Manager Agent
In the manager pattern, the main agent
retains control.
Specialist agents are exposed as tools.
User
↓
Manager Agent
├── Calls Research Agent
├── Calls Database Agent
└── Calls Report Agent
↓
Manager combines results
↓
Final answer
Conceptual example:
manager_agent = Agent(
name="Manager",
instructions=(
"Coordinate specialist
agents and provide one unified response."
),
tools=[
research_agent.as_tool(
tool_name="research_expert",
tool_description="Research a topic and return findings."
),
database_agent.as_tool(
tool_name="database_expert",
tool_description="Analyze database-related questions."
)
]
)
The Tools documentation describes
agents-as-tools as exposing an agent as a callable tool without performing a
full handoff. [openai.github.io]
14. Handoff vs Agent as a Tool
|
Handoff |
Agent as a tool |
|
Transfers control |
Manager retains control |
|
Receiving agent continues the interaction |
Worker returns a result to the manager |
|
Decentralized orchestration |
Centralized orchestration |
|
Suitable for routing |
Suitable for coordinated workflows |
|
“You handle this request.” |
“Complete this task and report back.” |
Simple analogy
Handoff
Receptionist:
"Please speak directly with the database specialist."
Agent as a tool
Manager:
"I will ask the database specialist and combine the result."
Example for a migration assistant
Handoff design
Triage Agent
├── AWR Analysis Agent
├── Data Pump Agent
├── GoldenGate Agent
└── Azure Sizing Agent
Each specialist becomes responsible for its
part of the conversation.
Manager design
Migration Manager
├── Calls AWR Analysis Agent
├── Calls Compatibility Agent
├── Calls Sizing Agent
└── Produces one migration
recommendation
The manager retains ownership and combines
specialist outputs.
15. Guardrails
Guardrails validate agent input or output.
They are not tools that perform the main
business task. They enforce conditions around the agent workflow.
Input guardrails
Input guardrails evaluate incoming input.
Possible uses include:
•
Rejecting off-topic requests
•
Checking input structure
•
Detecting suspicious
instructions
•
Verifying that required
information is present
•
Preventing unsupported requests
from reaching the main agent
User input
↓
Input guardrail
├── Pass → Main agent
└── Fail → Tripwire or controlled
failure
Output guardrails
Output guardrails evaluate the final
output.
Possible uses include:
•
Required formatting checks
•
Sensitive-data checks
•
Policy checks
•
Brand or tone checks
•
Structured-output validation
Main agent output
↓
Output guardrail
├── Pass → Return to user
└── Fail → Tripwire or controlled
handling
Agents can be configured with input_guardrails and output_guardrails. The Runner
can raise the corresponding tripwire exception when a guardrail triggers. [openai.github.io]
16. Simplified Input Guardrail Example
This example uses a secondary checker agent
to decide whether a question belongs to an allowed topic.
from pydantic import BaseModel
from agents import (
Agent,
Runner,
GuardrailFunctionOutput,
input_guardrail
)
class TopicCheck(BaseModel):
is_on_topic: bool
topic_checker = Agent(
name="Topic Checker",
instructions=(
"Return is_on_topic=true
only when the input "
"is clearly a history
question."
),
output_type=TopicCheck
)
@input_guardrail
async def history_only(context, agent, user_input):
check_result = await Runner.run(
topic_checker,
user_input,
context=context.context
)
return GuardrailFunctionOutput(
output_info=check_result.final_output,
tripwire_triggered=not
check_result.final_output.is_on_topic
)
history_agent = Agent(
name="History Assistant",
instructions="Answer history
questions clearly and accurately.",
input_guardrails=[history_only]
)
Conceptual flow
User asks a question
↓
History-only guardrail runs
↓
Checker returns structured decision
↓
Is the question about history?
├── Yes → Main history agent runs
└── No → Guardrail tripwire triggers
Practical design recommendation
Guardrails should not be treated as the
only security layer. A production system may also require:
•
Authentication
•
Authorization
•
Data-access controls
•
Network restrictions
•
Secret management
•
Tool-level validation
•
Logging and monitoring
•
Human approval for high-impact
actions
This is a practical architectural
recommendation for production systems.
17. Tracing
Tracing provides observability into what
happened during agent execution.
Instead of seeing only:
Question → Final answer
tracing can show the workflow that produced
the answer:
Question
↓
Agent started
↓
Model generation
↓
Tool selected
↓
Tool executed
↓
Tool result returned
↓
Handoff performed
↓
Guardrail evaluated
↓
Final output generated
The Agents SDK includes built-in tracing
for LLM generations, tool calls, handoffs, guardrails, and custom events. [openai.github.io]
What tracing can help inspect
Agent calls
•
Which agent ran
•
The sequence in which agents
ran
•
Which agent became active after
a handoff
Tool usage
•
Which tool was selected
•
Tool arguments
•
Tool results
•
Tool failures
Handoffs
•
Whether a handoff occurred
•
Source and destination agents
•
Where the orchestration path
changed
Guardrail results
•
Which guardrail ran
•
Whether the guardrail passed
•
Whether the tripwire triggered
Model and token information
Tracing can help inspect model-generation
steps and related execution details available in the trace data.
18. Trace and Span
A trace represents an end-to-end workflow
operation.
A span represents one operation inside the
trace.
TRACE: Migration Analysis Workflow
│
├── Runner task span
│
├── Agent span
│
├── Model turn span
│
├── Generation span
│
├── Function-tool span
│
├── Guardrail span
│
├── Handoff span
│
└── Final agent span
The SDK documentation defines traces as
end-to-end workflow operations composed of spans. Spans contain timing and
parent-child information and represent operations such as agent runs, model
generations, function tools, guardrails, and handoffs. [openai.github.io]
19. Is Tracing Always Enabled?
A precise way to describe the default
behavior is:
Tracing is enabled by default, but it can be
disabled globally or for an individual run.
The documentation describes the following
controls:
export OPENAI_AGENTS_DISABLE_TRACING=1
Or in Python:
from agents import set_tracing_disabled
set_tracing_disabled(True)
Tracing can also be disabled for an
individual run through run configuration. The documentation also states that
tracing is unavailable for organizations using the OpenAI API under a Zero Data
Retention policy. [openai.github.io]
20. Complete Agent Execution Architecture
The complete conceptual workflow is:
YOUR APPLICATION
│
▼
Runner.run(...)
│
▼
INPUT GUARDRAIL
│
Pass or tripwire
│
▼
PRIMARY AGENT
┌─────────────┼──────────────┐
│ │ │
▼ ▼ ▼
Hosted Tool Function Tool Agent as Tool
│ │ │
└─────────────┼──────────────┘
│
▼
MODEL
│
Selects next
action
│
┌─────────────┴─────────────┐
│ │
▼ ▼
Tool Call Handoff
│ │
▼ ▼
Tool Result Specialist Agent
│ │
└─────────────┬─────────────┘
│
▼
Model again
│
Repeat if
needed
│
▼
Final model
output
│
▼
OUTPUT GUARDRAIL
│
▼
result.final_output
│
▼
YOUR APPLICATION
Tracing observes the workflow across these stages.
21. Practical Example: Database Migration Agent
The concepts can be applied to an
Oracle-to-cloud migration assistant.
User request
Analyze the source database workload,
review compatibility,
recommend target sizing, and generate a migration approach.
Possible architecture
Migration Manager Agent
│
├── AWR Analysis Agent
│ └── Reads workload metrics
│
├── Compatibility Agent
│ └── Reviews assessment findings
│
├── Sizing Agent
│ └── Recommends target resources
│
├── Data Pump Agent
│ └── Recommends export/import
configuration
│
└── Report Agent
└── Produces the final migration
plan
Supporting tools
File-search tool
Reads AWR and compatibility reports
Function tool
Calculates storage growth
Database metadata tool
Retrieves database characteristics
Sizing-catalog tool
Finds appropriate target
configurations
Report-generation function
Produces structured recommendations
Guardrails
Input guardrail
Rejects requests unrelated to
database migration
Tool-level validation
Prevents destructive commands without
authorization
Output guardrail
Checks for credentials, secrets, and
unsupported claims
Tracing
Trace
├── Migration Manager started
├── AWR Analysis Agent called
├── Workload-analysis tool called
├── Compatibility Agent called
├── Sizing Agent called
├── Guardrail completed
└── Final recommendation returned
22. Final Memory Map
The easiest way to remember the complete
stack is:
OpenAI Model
= Intelligence
Responses API
= Interface to the model
Agent
= Model + instructions + capabilities
Runner
= Executes the agent loop
Hosted Tool
= OpenAI-managed capability
Function Tool
= Application-defined Python
capability
Agent as Tool
= Specialist called by a manager
agent
Handoff
= Transfer control to another agent
Guardrail
= Validate input or output
Tracing
= Observe and debug execution
Your Application
= Delivers business value to the user
One-line summary
The model thinks, the Responses API
communicates, the Agent defines behavior, tools perform actions, the Runner
executes the loop, handoffs delegate, guardrails protect, tracing explains, and
the application delivers the experience.
Comments
Post a Comment