Inkdown
Start writing

Study

70 filesยท12 subfolders

Shared Workspace

Study
AI eng

02_RUNNER_SYSTEM

Shared from "Study" on Inkdown

Runner System - Comprehensive Deep Dive

Overview

The Runner system is the execution engine of the OpenAI Agents SDK. It's responsible for orchestrating agent runs, managing the lifecycle of agent execution, handling tool execution, coordinating handoffs, managing sessions, and ensuring proper error handling. Think of the Runner as the "director" that brings together all the components (agents, tools, guardrails, etc.) and makes them work together in a coordinated way.

Core Classes

Runner

Runner is the main entry point for executing agents. It provides both async and sync interfaces for running agents.

Location: src/agents/run.py

basic-ques
core
Revision w/ Whiteboard
CN Basics - 1
CN Basics - 2
DNS
Event loop
programming-language-concepts.md
zero-language-explanation.md
DB
Quick
databases-deep-dive.md
01-introduction.md
02-relational-databases.md
03-database-design.md
04-indexing.md
05-transactions-acid.md
06-nosql-databases.md
07-query-optimization.md
08-replication-ha.md
09-sharding-partitioning.md
10-caching-strategies.md
11-cap-theorem.md
12-connection-pooling.md
13-backup-recovery.md
14-monitoring.md
15-database-selection.md
README.md
JS
core topics
Event loop
Merlin Backend
01-Orchestration.md
02-DeepResearch.md
03-Search.md
04-Scraping.md
05-Streaming.md
06-MultiProviderLLM.md
07-MemoryAndContext.md
08-ErrorHandling.md
09-RateLimiting.md
10-TaskQueue.md
11-SecurityAndAuth.md
Orchestration-2nd-draft
Mobile
Build Alternative
Bundling
metro-bundler-deep-dive.md
OpenAI Agents Python
00_OVERVIEW.md
01_AGENT_SYSTEM.md
02_RUNNER_SYSTEM.md
03_TOOL_SYSTEM.md
04_ITEMS_SYSTEM.md
05_GUARDRAILS.md
06_HANDOFFS.md
07_MEMORY_SESSIONS.md
08_MODEL_PROVIDERS.md
09_SANDBOX_SYSTEM.md
10_TRACING.md
11_RUN_STATE.md
12_CONTEXT.md
13_LIFECYCLE_HOOKS.md
14_CONFIGURATION.md
15_ERROR_HANDLING.md
16_STREAMING.md
17_EXTENSIONS.md
18_MCP_INTEGRATION.md
19_BEST_PRACTICES.md
20_ARCHITECTURE_PATTERNS.md
opencode-study
context-handling
core
Python
Alembic
Basics
sqlalchemy - fastapi
SQLAlchemy overview
tweets
system_design_for_agentic_apps.md
Agent Loop

Key Methods:

  • async def run(starting_agent, input, *, context, ...) - Main async method to run an agent
  • def run_sync(starting_agent, input, *, context, ...) - Sync wrapper around run()
  • async def run_streamed(starting_agent, input, *, context, ...) - Run with streaming

Parameters:

  • starting_agent: Agent[TContext] - The agent to start with
  • input: str | list[TResponseInputItem] | RunState - Input to the agent
  • context: TContext | None - User-provided context object
  • max_turns: int - Maximum number of turns (default: 10)
  • hooks: RunHooks | None - Lifecycle hooks for the run
  • run_config: RunConfig | None - Configuration for the run
  • session: Session | None - Session for conversation persistence
  • conversation_id: str | None - ID for server-managed conversations
  • previous_response_id: str | None - ID of previous response for chaining
  • auto_previous_response_id: bool - Enable automatic response chaining
  • error_handlers: RunErrorHandlers | None - Custom error handlers
AgentRunner

AgentRunner is the internal implementation class that does the actual work. The Runner class is a thin wrapper around AgentRunner that provides a simpler public API.

Location: src/agents/run.py

Key Responsibilities:

  • Turn management (tracking which turn we're on)
  • Tool execution coordination
  • Handoff delegation
  • Session persistence
  • Error handling and recovery
  • Streaming event emission
  • Tracing integration

Execution Flow

1. Initialization

When you call Runner.run(), the following initialization happens:

Python

Steps:

  1. Context Wrapper Creation - A RunContextWrapper is created to wrap your context object. This wrapper provides:

    • Approval management (for human-in-the-loop)
    • Usage tracking
    • Tool state management
    • Access to run configuration
  2. Agent Binding - The agent is "bound" to the run. This creates an AgentBindings object that:

    • Resolves the model to use (from agent, run config, or default)
    • Resolves model settings (merged from agent and run config)
    • Prepares the agent for execution
  3. Session Preparation - If a session is provided, the conversation history is loaded and prepared. The session's items are combined with the new input.

  4. Trace Creation - A trace is created for observability. This trace will:

    • Track all events during the run
    • Record timing information
    • Capture inputs and outputs (unless tracing is disabled)
  5. Sandbox Setup - If sandbox configuration is provided, the sandbox session is initialized.

2. Turn Execution

A "turn" is one complete cycle of:

  • Input preparation
  • Model call
  • Tool execution (if needed)
  • Output processing

The Runner manages multiple turns until:

  • The agent produces a final output
  • Max turns is exceeded
  • An error occurs
  • A guardrail tripwire is triggered

Turn Lifecycle:

Python
3. Input Preparation

Input preparation converts the user's input into the format expected by the model:

Input Types:

  1. String input - Simple text input

    Python
  2. List input - Structured input with multiple items

    Python
  3. RunState input - Resume from a paused state

    Python

Session Integration:

If a session is provided, the input preparation:

  1. Loads conversation history from the session
  2. Applies the session's input callback (if configured)
  3. Combines history with new input
  4. Respects session limits (e.g., max items to retrieve)
4. Model Call

The Runner coordinates the model call through the model provider:

Python

Model Resolution:

The model is resolved in this priority order:

  1. RunConfig.model (if set)
  2. Agent.model (if set)
  3. Default model (gpt-4.1)

Settings Merging:

Model settings are merged:

  1. Start with agent.model_settings
  2. Override with run_config.model_settings (if provided)
  3. Apply any provider-specific defaults

Hooks:

Before and after the model call, lifecycle hooks are invoked:

  • on_llm_start - Before the call
  • on_llm_end - After the call
5. Response Processing

The model's response is processed to extract:

  1. Message content - Text output from the model
  2. Tool calls - Requests to call tools
  3. Handoff calls - Requests to hand off to another agent
  4. Reasoning content - Model's reasoning (for reasoning models)
  5. Refusals - Model's refusal to respond

ProcessedResponse Structure:

Python
6. Tool Execution

When the model requests tool calls, the Runner coordinates their execution:

Tool Execution Flow:

Python

Parallel Execution:

If multiple tools are called and they don't depend on each other, they can be executed in parallel for efficiency.

Tool Use Behavior:

Based on the agent's tool_use_behavior setting:

  • "run_llm_again" - Tool results are fed back to the model for another turn
  • "stop_on_first_tool" - First tool result is the final output
  • StopAtTools - Stop if specific tools are called
  • Custom function - Custom logic to determine if tool results are final
7. Handoff Execution

When the model requests a handoff:

Python

Handoff History Management:

Based on nest_handoff_history setting:

  • False (default) - Full conversation history is passed to the next agent
  • True - History is collapsed into a single summary message
  • Custom mapper - Custom function to transform history
8. Output Guardrails

When the agent produces a final output:

Python
9. Session Persistence

After each turn, if a session is configured:

Python

Session Compaction:

For OpenAI Responses API, the SDK supports intelligent compaction:

  • Older items can be collapsed into summaries
  • Reduces token usage while preserving context
  • Configured via SessionSettings
10. Result Return

The Runner returns a RunResult (or RunResultStreaming for streamed runs):

Python

Streaming

Streamed Execution

For real-time updates, use run_streamed:

Python

Streaming Events:

  1. RunItemStreamEvent - Emitted when a new run item is created
  2. AgentUpdatedStreamEvent - Emitted when the current agent changes
  3. RawResponsesStreamEvent - Emitted for raw model stream events

Streaming Flow:

The streaming path mirrors the non-streaming path but yields events as they happen:

  • Model response chunks are yielded as they arrive
  • Tool call events are yielded when tools are called
  • Tool output events are yielded when tools complete
  • Final result is yielded at the end

Error Handling

Error Handlers

The Runner supports custom error handlers:

Python
Error Types
  1. MaxTurnsExceeded - Agent exceeded max turns without producing final output
  2. InputGuardrailTripwireTriggered - Input guardrail blocked execution
  3. OutputGuardrailTripwireTriggered - Output guardrail blocked execution
  4. ToolTimeoutError - Tool execution timed out
  5. ModelBehaviorError - Model behaved unexpectedly
  6. UserError - User configuration error
  7. AgentsException - Base SDK exception
Error Recovery

Some errors can be recovered from:

Python

Run Configuration

RunConfig

RunConfig provides configuration for the entire run:

Python

Key Settings:

  • model - Override model for all agents
  • model_provider - Custom model provider
  • model_settings - Global model settings
  • handoff_input_filter - Global filter for all handoffs
  • nest_handoff_history - Enable nested handoff history
  • input_guardrails - Global input guardrails
  • output_guardrails - Global output guardrails
  • tracing_disabled - Disable tracing
  • workflow_name - Name for tracing
  • trace_id - Custom trace ID
  • group_id - Group ID for linking traces
  • session_settings - Session configuration
  • call_model_input_filter - Filter model input before calling
Configuration Priority

Settings are applied in this priority (highest to lowest):

  1. RunConfig settings
  2. Agent settings
  3. Global defaults

Lifecycle Hooks

Run Hooks

Run hooks allow you to hook into the execution lifecycle:

Python

Server-Managed Conversations

The Runner supports OpenAI's server-managed conversations:

Python

Benefits:

  • Automatic conversation history management on OpenAI servers
  • Reduced local storage needs
  • Better prompt caching
  • Improved performance

How it works:

  1. The Runner uses OpenAIServerConversationTracker to track conversation
  2. Only deltas (new items) are sent to the server
  3. The server maintains full conversation history
  4. Session persistence is disabled when using server-managed conversations

Human-in-the-Loop

Approval Workflow

Tools can require human approval:

Python

Approval Flow:

  1. Tool is called
  2. Runner pauses execution
  3. Returns RunState with interruption
  4. Human reviews and approves/rejects
  5. Run is resumed with approval decision
Python

Tracing Integration

Trace Creation

The Runner automatically creates traces for observability:

Python

Trace Structure:

  • Trace - The entire run trace
  • Span - Individual operations (LLM call, tool execution, etc.)
  • SpanData - Data associated with spans

Trace Configuration:

Python

Usage Tracking

Token Usage

The Runner tracks token usage:

Python

Usage Breakdown:

  • request_tokens - Tokens sent to the model
  • response_tokens - Tokens received from the model
  • total_tokens - Sum of request and response

Per-Turn Usage:

Usage is tracked per turn and aggregated:

Python

Performance Considerations

Async Execution

The Runner is async-first for performance:

Python
Parallel Tool Execution

When tools don't depend on each other, they run in parallel:

Python
Session Compaction

For long conversations, use session compaction:

Python

Best Practices

1. Use Async

Always use the async interface for production:

Python
2. Set Reasonable Max Turns

Prevent infinite loops:

Python
3. Use Sessions for Long Conversations

Maintain conversation state:

Python
4. Enable Tracing for Debugging

Get visibility into execution:

Python
5. Handle Errors Gracefully

Provide good error handling:

Python

Common Patterns

1. Multi-Agent Workflow
Python
2. Streaming Response
Python
3. Resume from State
Python
4. Custom Error Handling
Python

Summary

The Runner system is the execution engine that orchestrates everything. Key takeaways:

  1. Runner is the public API for running agents
  2. AgentRunner is the internal implementation
  3. Turns are cycles of model call โ†’ tool execution โ†’ output
  4. Input preparation converts user input to model format
  5. Model calls are coordinated through model providers
  6. Response processing extracts content, tool calls, handoffs
  7. Tool execution can be parallel for efficiency
  8. Handoffs switch to different agents
  9. Guardrails validate input and output
  10. Sessions maintain conversation history
  11. Streaming provides real-time updates
  12. Error handlers customize error behavior
  13. Lifecycle hooks allow custom logic
  14. Tracing provides observability
  15. Usage tracking monitors token consumption
  16. Human-in-the-loop enables approval workflows
  17. Server-managed conversations offload history to OpenAI

Understanding the Runner system is essential for building robust agent workflows.