> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orq.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAI Agents SDK integration

> Connect OpenAI Agents SDK to Orq.ai's AI Router for complete observability, built-in reliability, and access to 300+ LLMs across 20+ providers.

<CardGroup cols={2}>
  <Card title="AI Router" icon="arrow-right-arrow-left" href="#ai-router">
    Route your LLM calls through the AI Router with a single base URL change. Zero vendor lock-in: always run on the best model at the lowest cost for your use case.
  </Card>

  <Card title="Observability" icon="chart-line" href="#observability">
    Instrument your code with OpenTelemetry to capture traces, logs, and metrics for every LLM call, agent step, and tool use.
  </Card>
</CardGroup>

## AI Router

### Overview

OpenAI Agents SDK enables powerful AI-driven automation through structured conversations and tool calling. By connecting the Agents SDK to Orq.ai's AI Router, you transform experimental agents into production-ready systems with enterprise-grade capabilities.

### Key Benefits

Orq.ai's AI Router enhances your OpenAI Agents with:

<CardGroup cols={2}>
  <Card title="Complete Observability" icon="chart-line">
    Track every agent step, tool use, and interaction with detailed traces and analytics
  </Card>

  <Card title="Built-in Reliability" icon="shield-check">
    Automatic fallbacks, retries, and load balancing for production resilience
  </Card>

  <Card title="Cost Optimization" icon="chart-pie">
    Real-time cost tracking and spend management across all your AI operations
  </Card>

  <Card title="Multi-Provider Access" icon="cubes">
    Access 300+ LLMs and 20+ providers through a single, unified integration
  </Card>
</CardGroup>

### Prerequisites

Before integrating OpenAI Agents SDK with Orq.ai, ensure you have:

* An Orq.ai account and [API Key](/docs/administer/api-keys)
* Python 3.8 or higher
* OpenAI Agents SDK installed

<Info>
  To setup your API key, see [API keys & Endpoints](/docs/administer/api-keys).
</Info>

### Installation

Install the OpenAI Agents SDK:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install openai-agents openai
```

### Configuration

Configure OpenAI Agents SDK to use Orq.ai's AI Router by setting a custom AsyncOpenAI client:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from openai import AsyncOpenAI
from agents import set_default_openai_client, set_tracing_disabled
import os

# Configure OpenAI client with Orq.ai AI Router
client = AsyncOpenAI(
    api_key=os.getenv("ORQ_API_KEY"),
    base_url="https://api.orq.ai/v3/router"
)

# Disable the SDK's built-in OpenAI tracing exporter for router-only use
set_tracing_disabled(True)

# Set as default client for all agents
set_default_openai_client(client)
```

> **base\_url**: `https://api.orq.ai/v3/router`

### Built-in OpenAI Tracing

<Warning>
  The OpenAI Agents SDK includes built-in tracing that exports to OpenAI's hosted Traces dashboard by default. When you use Orq.ai's AI Router with `ORQ_API_KEY` and do not configure OpenAI tracing credentials, the SDK can print `No API key provided for OpenAI tracing exporter. Exports will be skipped`.
</Warning>

Do not set `OPENAI_API_KEY` only to silence this warning. That sends SDK traces to OpenAI's dashboard instead of Orq.ai. Choose one of these paths:

**Option A: disable the SDK's built-in OpenAI tracing.** Use this for router-only examples when you do not need agent traces in Orq.ai.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
export OPENAI_AGENTS_DISABLE_TRACING=1
```

Or disable it in code:

```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { setTracingDisabled } from "@openai/agents";

setTracingDisabled(true);
```

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from agents import set_tracing_disabled

set_tracing_disabled(True)
```

**Option B: send agent traces to Orq.ai.** Keep the SDK tracing surface enabled and register an OpenTelemetry exporter to Orq.ai before running agents:

```bash wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install openinference-instrumentation-openai-agents opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
```

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
from opentelemetry import trace as trace_api
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from openinference.instrumentation.openai_agents import OpenAIAgentsInstrumentor

exporter = OTLPSpanExporter(
    endpoint="https://api.orq.ai/v2/otel/v1/traces",
    headers={"Authorization": f"Bearer {os.environ['ORQ_API_KEY']}"},
)
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
trace_api.set_tracer_provider(provider)

OpenAIAgentsInstrumentor().instrument(tracer_provider=provider)
```

The Observability section below uses the same Orq.ai OTLP collector and shows complete examples, including flushing buffered spans in short scripts.

### Basic Agent Example

Here's a complete example of creating and running an OpenAI agent through Orq.ai:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from openai import AsyncOpenAI
from agents import Agent, Runner, set_default_openai_client, set_tracing_disabled
import os

# Configure client with Orq.ai AI Router
client = AsyncOpenAI(
    api_key=os.getenv("ORQ_API_KEY"),
    base_url="https://api.orq.ai/v3/router"
)
set_tracing_disabled(True)
set_default_openai_client(client)

# Create agent
agent = Agent(
    name="Assistant",
    instructions="You are a helpful assistant that explains complex concepts simply."
)

# Run the agent
result = Runner.run_sync(agent, "Explain quantum computing in simple terms")
print(result.final_output)
```

### Agent with Tools

OpenAI Agents can use tools while routing through Orq.ai:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from openai import AsyncOpenAI
from agents import Agent, Runner, set_default_openai_client, set_tracing_disabled, function_tool
import os

# Configure client
client = AsyncOpenAI(
    api_key=os.getenv("ORQ_API_KEY"),
    base_url="https://api.orq.ai/v3/router"
)
set_tracing_disabled(True)
set_default_openai_client(client)

# Define a tool using the @function_tool decorator
@function_tool
def get_weather(location: str) -> str:
    """Get the current weather for a location."""
    return f"The weather in {location} is sunny and 72°F"

# Create agent with tools
agent = Agent(
    name="Weather Assistant",
    instructions="You are a weather assistant. Use the get_weather function to provide weather information.",
    tools=[get_weather]
)

# Run agent with tool access
result = Runner.run_sync(agent, "What's the weather in San Francisco?")
print(result.final_output)
```

### Model Selection

With Orq.ai, you can use any supported model from 20+ providers:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from openai import AsyncOpenAI
from agents import Agent, Runner, set_default_openai_client, set_tracing_disabled
import os

# Configure client
client = AsyncOpenAI(
    api_key=os.getenv("ORQ_API_KEY"),
    base_url="https://api.orq.ai/v3/router"
)
set_tracing_disabled(True)
set_default_openai_client(client)

# Use Claude
claude_agent = Agent(
    name="Claude Assistant",
    model="claude-sonnet-4-5-20250929",
    instructions="You are a helpful assistant."
)

# Use Gemini
gemini_agent = Agent(
    name="Gemini Assistant",
    model="gemini-2.5-flash",
    instructions="You are a helpful assistant."
)

# Use any other model
groq_agent = Agent(
    name="Groq Assistant",
    model="llama-3.3-70b-versatile",
    instructions="You are a helpful assistant."
)

# Run with different models
result = Runner.run_sync(claude_agent, "Explain machine learning")
print(result.final_output)
```

## Observability

### Getting Started

Integrate OpenAI Agents with Orq.ai's observability to gain complete insights into agent performance, token usage, tool utilization, and conversation flows using OpenTelemetry.

### Prerequisites

Before you begin, ensure you have:

* An Orq.ai account and [API Key](/docs/administer/api-keys)
* OpenAI API key and access to the Assistants API
* Python 3.8+

### Install Dependencies

```bash wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install openai-agents orq-ai-sdk opentelemetry-sdk opentelemetry-instrumentation opentelemetry-exporter-otlp-proto-http
```

### Configure Orq.ai

Set up your environment variables to connect to Orq.ai's OpenTelemetry collector:

**Unix/Linux/macOS:**

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.orq.ai/v2/otel"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer $ORQ_API_KEY"
export OTEL_RESOURCE_ATTRIBUTES="service.name=openai-agents-app,service.version=1.0.0"
export OPENAI_API_KEY="<YOUR_OPENAI_API_KEY>"
```

**Windows (PowerShell):**

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://api.orq.ai/v2/otel"
$env:OTEL_EXPORTER_OTLP_HEADERS = "Authorization=Bearer <ORQ_API_KEY>"
$env:OTEL_RESOURCE_ATTRIBUTES = "service.name=openai-agents-app,service.version=1.0.0"
$env:OPENAI_API_KEY = "<YOUR_OPENAI_API_KEY>"
```

**Using .env file:**

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.orq.ai/v2/otel
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer <ORQ_API_KEY>
OTEL_RESOURCE_ATTRIBUTES=service.name=openai-agents-app,service.version=1.0.0
OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
```

### Common Pitfalls

* **Do not set a custom `base_url` when using OTEL.** Pointing the OpenAI client at the **AI Router** while also exporting spans results in duplicate traces: one from the router, one from the OTEL exporter. Use the router when you need multi-provider routing or fallbacks. Use your `OPENAI_API_KEY` directly when you only need observability.
* **Only disable SDK tracing for router-only runs.** `OPENAI_AGENTS_DISABLE_TRACING=1` and `set_tracing_disabled(True)` are correct when you want to silence the OpenAI exporter warning without exporting agent traces. Do not use them with the Observability examples because they prevent agent-level spans from reaching Orq.ai.
* **Wrap runs in `agent_trace(workflow_name=...)`.** Without it the root span is named `"Agent workflow"` for every run, making traces impossible to distinguish.
* **Call `provider.shutdown()` before exit in short scripts.** `BatchSpanProcessor` buffers on a timer and may not flush before the process exits.

### Basic Example

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from orq_ai_sdk.openai_agents_instrumentation import OpenAIAgentsInstrumentor
from agents import Agent, Runner
from agents import trace as agent_trace

os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://api.orq.ai/v2/otel"
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Bearer {os.environ['ORQ_API_KEY']}"

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
OpenAIAgentsInstrumentor().instrument(tracer_provider=provider)

agent = Agent(name="Assistant", instructions="You are a helpful assistant")

with agent_trace(workflow_name="Haiku-Workflow"):
    result = Runner.run_sync(agent, "Write a haiku about recursion in programming.")
    print(result.final_output)

provider.shutdown()  # flush BatchSpanProcessor before exit
```

### Advanced Example with Function Calling

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from orq_ai_sdk.openai_agents_instrumentation import OpenAIAgentsInstrumentor
from agents import Agent, Runner, function_tool
from agents import trace as agent_trace

os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://api.orq.ai/v2/otel"
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Bearer {os.environ['ORQ_API_KEY']}"

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
OpenAIAgentsInstrumentor().instrument(tracer_provider=provider)

@function_tool
def get_weather(location: str) -> str:
    """Mock weather function"""
    return f"The weather in {location} is sunny, 72°F"

agent = Agent(
    name="Weather Assistant",
    instructions="You are a weather assistant. Use the get_weather function to provide weather information.",
    tools=[get_weather]
)

with agent_trace(workflow_name="Weather-Workflow"):
    result = Runner.run_sync(agent, "What's the weather like in Boston?")
    print(result.final_output)

provider.shutdown()
```

### Custom Spans for Agent Operations

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from orq_ai_sdk.openai_agents_instrumentation import OpenAIAgentsInstrumentor
from agents import Agent, Runner
from agents import trace as agent_trace

os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://api.orq.ai/v2/otel"
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Bearer {os.environ['ORQ_API_KEY']}"

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
OpenAIAgentsInstrumentor().instrument(tracer_provider=provider)

tracer = provider.get_tracer(__name__)

agent = Agent(
    name="Research Assistant",
    instructions="You are a research assistant specialized in data analysis.",
)

with agent_trace(workflow_name="Research-Workflow"):
    with tracer.start_as_current_span("agent-execution") as exec_span:
        result = Runner.run_sync(agent, "Analyze the trends in the uploaded dataset")
        exec_span.set_attribute("execution.status", "completed")
    print("Final output:", result.final_output)

provider.shutdown()
```

### View Traces

View your traces in the [AI Studio](/docs/observability/overview) in the **Traces** tab.

<Frame caption="Traces will also display the custom spans created through the observability sdk">
  <img src="https://mintcdn.com/orqai/3I80b9x_G_KAvTRg/images/trace-openai.png?fit=max&auto=format&n=3I80b9x_G_KAvTRg&q=85&s=96e66cda79b01bbc08ea5d8b88bdd99b" alt="Traces will also display the custom spans created through the observability sdk" width="1672" height="945" data-path="images/trace-openai.png" />
</Frame>

<Info>
  Visit your [AI Studio](https://my.orq.ai) to view real-time analytics and traces.
</Info>

### Asset Capture in the Control Tower

When you instrument OpenAI Agents with OpenTelemetry and send traces to Orq.ai, agents, tools, and models are automatically extracted from the spans and registered in [Control Tower](/docs/control-tower/assets).

#### Installation

```bash wrap theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install orq-ai-sdk openai-agents opentelemetry-sdk opentelemetry-instrumentation opentelemetry-exporter-otlp-proto-http
```

#### Configuration

Set the OTLP environment variables and initialise the tracer provider with the `OpenAIAgentsInstrumentor` before running any agents:

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import os
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from orq_ai_sdk.openai_agents_instrumentation import OpenAIAgentsInstrumentor

os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://api.orq.ai/v2/otel"
os.environ["OTEL_EXPORTER_OTLP_HEADERS"]  = "Authorization=Bearer <your-orq-api-key>"

tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))

OpenAIAgentsInstrumentor().instrument(tracer_provider=tracer_provider)
```

#### Examples

**Agent with no tools**: captures `agent/Assistant`, `model/gpt-4o`

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from agents import Agent, Runner

agent = Agent(
    name="Assistant",
    instructions="Be extremely concise.",
    model="gpt-4o",
)

result = Runner.run_sync(agent, "What is the capital of France?")
print(result.final_output)
```

**Agent with a single tool**: captures `agent/Weather Assistant`, `tool/get_weather`, `model/gpt-4o`

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from agents import Agent, Runner, function_tool

@function_tool
def get_weather(location: str) -> str:
    """Get weather for a location."""
    data = {"tokyo": "Sunny, 22°C", "paris": "Cloudy, 15°C", "new york": "Rainy, 18°C"}
    return data.get(location.lower(), f"No data for {location}")

agent = Agent(
    name="Weather Assistant",
    instructions="Use get_weather to answer weather questions.",
    tools=[get_weather],
    model="gpt-4o",
)

result = Runner.run_sync(agent, "What's the weather in Tokyo?")
print(result.final_output)
```

**Multi-agent workflow with handoff**: captures `agent/Assistant`, `agent/Spanish Assistant`, `tool/random_number_tool`, `model/gpt-4o`

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import random
from agents import Agent, Runner, function_tool, handoff, trace as agent_trace
from agents.extensions import handoff_filters
from agents import HandoffInputData

@function_tool
def random_number_tool(max: int) -> int:
    """Return a random integer between 0 and the given maximum."""
    return random.randint(0, max)

def spanish_handoff_message_filter(handoff_message_data: HandoffInputData) -> HandoffInputData:
    handoff_message_data = handoff_filters.remove_all_tools(handoff_message_data)
    history = (
        tuple(handoff_message_data.input_history[2:])
        if isinstance(handoff_message_data.input_history, tuple)
        else handoff_message_data.input_history
    )
    return HandoffInputData(
        input_history=history,
        pre_handoff_items=tuple(handoff_message_data.pre_handoff_items),
        new_items=tuple(handoff_message_data.new_items),
    )

spanish_agent = Agent(
    name="Spanish Assistant",
    instructions="You only speak Spanish and are extremely concise.",
    handoff_description="A Spanish-speaking assistant.",
    model="gpt-4o",
)

first_agent = Agent(
    name="Assistant",
    instructions="Be extremely concise.",
    tools=[random_number_tool],
    model="gpt-4o",
)

second_agent = Agent(
    name="Assistant",
    instructions="Be helpful. If the user speaks Spanish, handoff to the Spanish assistant.",
    handoffs=[handoff(spanish_agent, input_filter=spanish_handoff_message_filter)],
    model="gpt-4o",
)

async def run_workflow():
    with agent_trace(workflow_name="Multi-Agent Workflow"):
        result = await Runner.run(first_agent, input="Hi, my name is Sora.")
        result = await Runner.run(
            first_agent,
            input=result.to_input_list() + [
                {"content": "Generate a random number between 0 and 100.", "role": "user"}
            ],
        )
        result = await Runner.run(
            second_agent,
            input=result.to_input_list() + [
                {"content": "Por favor habla en español. ¿Cuál es mi nombre?", "role": "user"}
            ],
        )
    print(result.final_output)

# In Jupyter notebooks (async supported natively)
await run_workflow()

# In regular Python scripts
import asyncio
asyncio.run(run_workflow())
```

After running your code, open the [Assets page](/docs/control-tower/assets) in Control Tower. Agents, tools, and models from your runs will appear automatically under their respective tabs.

## Evaluations & Experiments

Once your agents are running, use **Evaluatorq** to score outputs across a dataset and **Experiments** to compare configurations side-by-side.

<CardGroup cols={2}>
  <Card title="Run Evaluations with Evaluatorq" icon="flask" href="/docs/evaluators/build#evaluatorq">
    Run parallel evaluations across your agents and compare results.
  </Card>

  <Card title="Run Experiments via the API" icon="flask-vial" href="/docs/experiments/api">
    Compare agent configurations and view results in the AI Studio.
  </Card>
</CardGroup>
