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(...)

Agent or graph construction

Function decorator

@function_tool

Commonly @tool

Model configuration

Can be specified in Agent(...)

Often initialized separately

Synchronous execution

Runner.run_sync(...)

Framework-specific invoke pattern

Final output

result.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

Popular posts from this blog

Oracle GoldenGate Deployment Types

Oracle Database@Azure: The Future of Enterprise Database Modernization

Oracle GoldenGate Microservices Deployment: Connectivity, Configuration, and Best Practices