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

# OpenAI SDK

> Learn about the Splunk Agent Observability OpenAI integration

The OpenAI wrapper is the simplest way to integrate Splunk Agent Observability logging into your application. By using Splunk Agent Observability's OpenAI wrapper instead of importing the OpenAI library directly, you can automatically log all prompts, responses, and statistics without any additional code changes in an LLM span for every call.

> [!NOTE]
>
> The Python SDK supports both the Chat Completions API and the Responses API.

The wrapper supports both the OpenAI and Azure OpenAI APIs, so will work out of the box with Azure deployments, as well as any LLM that supports the OpenAI SDK.

> **[Python Splunk Agent Observability OpenAI SDK reference](https://agent-observability-docs.splunk.com/sdk-api/python/reference/openai)**
>
> The Python Splunk Agent Observability OpenAI SDK reference.

## Installation

First, make sure you have the Splunk Agent Observability SDK installed. If you are using Python, ensure you install the OpenAI optional dependency.

```bash Pip theme={null}
pip install "splunk-ao[openai]"
```

```bash uv theme={null}
uv pip install "splunk-ao[openai]"
```

```bash Poetry theme={null}
poetry add "splunk-ao[openai]"
```

## Basic usage

If you are using Python, import the `splunk_ao.openai` module, instead of the OpenAI `openai` module and use that to create your client.

```python Python theme={null}
import os
from splunk_ao.openai import openai

# Initialize the Splunk Agent Observability wrapped OpenAI client
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

# Use the Splunk Agent Observability wrapped OpenAI client which logs automatically
# This will create a single span trace with the OpenAI call
chat_completion = client.chat.completions.create(
    messages=[{"role": "user", "content": "Say this is a test"}],
    model="gpt-4o"
)

print(chat_completion.choices[0].message.content)
```

This example will automatically produce a single-span trace in your Agent Stream. The wrapper handles all the logging for you, capturing:

* The input prompt
* The model used
* The response
* Timing information
* Token usage
* Other relevant metadata

## Responses API (Python only)

The Python SDK also supports OpenAI's [Responses API](https://platform.openai.com/docs/api-reference/responses), which provides a simplified interface for single-turn interactions and additional features like built-in tools.

### Responses API basic example

```python Python theme={null}
from splunk_ao.openai import openai

client = openai.OpenAI()

response = client.responses.create(
    model="gpt-4o",
    input="What is the capital of France?"
)

print(response.output_text)
```

### Tool calls

The Responses API supports function calling. Here's an example that demonstrates tool definitions, executing tool calls, and providing results back to the model:

```python Python theme={null}
import json
from splunk_ao.openai import openai

client = openai.OpenAI()

# Define tools
tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get the current weather for a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city and state, e.g. San Francisco, CA",
                },
            },
            "required": ["location"],
        },
    },
    {
        "type": "function",
        "name": "get_stock_price",
        "description": "Get the current stock price for a given ticker symbol",
        "parameters": {
            "type": "object",
            "properties": {
                "symbol": {
                    "type": "string",
                    "description": "The stock ticker symbol, e.g. AAPL",
                },
            },
            "required": ["symbol"],
        },
    },
]

def get_weather(location: str) -> str:
    return json.dumps({"location": location, "temperature": 72, "unit": "fahrenheit"})

def get_stock_price(symbol: str) -> str:
    return json.dumps({"symbol": symbol.upper(), "price": 178.50, "currency": "USD"})

# First call - model decides which tools to use
user_message = "What's the weather in San Francisco and the stock price of Apple?"

response = client.responses.create(
    model="gpt-4o",
    input=user_message,
    tools=tools,
)

# Process tool calls and collect results
input_list = list(response.output)

for item in response.output:
    if item.type == "function_call":
        if item.name == "get_weather":
            result = get_weather(**json.loads(item.arguments))
        elif item.name == "get_stock_price":
            result = get_stock_price(**json.loads(item.arguments))
        else:
            continue

        input_list.append({
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": result,
        })

# Second call - model generates final response with tool results
response = client.responses.create(
    model="gpt-4o",
    input=input_list,
    tools=tools,
)

print(response.output_text)
```

> [!NOTE]
>
> The Responses API also supports advanced features like:
>
> * **Reasoning items** with the `reasoning` parameter for chain-of-thought outputs
> * **Built-in tools** including web search, code interpreter, and file search
> * **Streaming** with `stream=True`
>
> See the [OpenAI Responses API documentation](https://platform.openai.com/docs/api-reference/responses) for more details.

## Sessions and traces

If you use the OpenAI wrapper by itself, it will automatically create a session and start a new trace for you, adding the call as an LLM span. Subsequent calls will be added as an LLM span to a new trace in the same session. The session will have an autogenerated name based off the content.

```python Python theme={null}
import os
from splunk_ao.openai import openai

# Initialize the Splunk Agent Observability wrapped OpenAI client
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

# Use the Splunk Agent Observability wrapped OpenAI client which logs automatically
# This will create a single span trace with the OpenAI call in a new session
first_result = client.chat.completions.create(
    messages=[{"role": "user", "content": "Tell me about the Roman Empire"}],
    model="gpt-4o"
)

# This second call will create a new single span trace inside the same session
second_result = client.chat.completions.create(
    messages=[{
        "role": "user",
        "content": f"Summarize this: {first_result.choices[0].message.content}"
    }],
    model="gpt-4o"
)

print(second_result.choices[0].message.content)
```

![A single session with 2 traces in the Splunk Agent Observability UI](https://mintcdn.com/agent-observability-docs/Y4gaVgpsSUs8MBdT/sdk-api/third-party-integrations/openai/one-session-two-traces.webp?fit=max\&auto=format\&n=Y4gaVgpsSUs8MBdT\&q=85\&s=f5cb3b64e72ede099493d83be1775a51)

If you manually start a session before using the OpenAI wrapper, all calls to the wrapper will be added as new traces to that session.

```python Python theme={null}
import os
from splunk_ao.openai import openai
from splunk_ao import splunk_ao_context

# Get the logger instance
logger = splunk_ao_context.get_logger_instance()

# Start a session
logger.start_session("Chat about the Roman Empire")

# Initialize the Splunk Agent Observability wrapped OpenAI client
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

# Use the Splunk Agent Observability wrapped OpenAI client which logs automatically
# This will create a single span trace in the current session
first_result = client.chat.completions.create(
    messages=[{"role": "user", "content": "Tell me about the Roman Empire"}],
    model="gpt-4o"
)

# This second call will create a new single span trace inside the same session
second_result = client.chat.completions.create(
    messages=[{
        "role": "user",
        "content": f"Summarize this: {first_result.choices[0].message.content}"
    }],
    model="gpt-4o"
)

print(second_result.choices[0].message.content)
```

![A single session called Chat about the Roman Empire with 2 traces in Splunk Agent Observability](https://mintcdn.com/agent-observability-docs/Y4gaVgpsSUs8MBdT/sdk-api/third-party-integrations/openai/manual-session-two-traces.webp?fit=max\&auto=format\&n=Y4gaVgpsSUs8MBdT\&q=85\&s=c1049500bb22e02144a7d1650f244939)

If you create a new trace before using the OpenAI wrapper, all calls will be added as LLM spans to that trace.

```python Python theme={null}
import os
from splunk_ao.openai import openai
from splunk_ao import splunk_ao_context

# Get the logger instance
logger = splunk_ao_context.get_logger_instance()

# Start a session
logger.start_session("Chat about the Roman Empire")

# Start a new trace
logger.start_trace("Summary of the Roman Empire")

# Initialize the Splunk Agent Observability wrapped OpenAI client
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

# Use the Splunk Agent Observability wrapped OpenAI client which logs automatically
# This will create a single span trace in the current session
first_result = client.chat.completions.create(
    messages=[{"role": "user", "content": "Tell me about the Roman Empire"}],
    model="gpt-4o"
)

# This second call will create a new single span trace inside the same session
second_result = client.chat.completions.create(
    messages=[{
        "role": "user",
        "content": f"Summarize this: {first_result.choices[0].message.content}"
    }],
    model="gpt-4o"
)

print(second_result.choices[0].message.content)
```

![A single session called Chat about the Roman Empire with 1 trace in Splunk Agent Observability](https://mintcdn.com/agent-observability-docs/Y4gaVgpsSUs8MBdT/sdk-api/third-party-integrations/openai/manual-session-one-trace.webp?fit=max\&auto=format\&n=Y4gaVgpsSUs8MBdT\&q=85\&s=0943e63b42d624d389e2c19c11adb70c)

## Streaming support

The OpenAI wrapper also supports streaming responses. When streaming, the wrapper will log the response as it streams in:

```python Python theme={null}
import os
from splunk_ao.openai import openai

client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

stream = client.chat.completions.create(
    messages=[{"role": "user", "content": "Say this is a streaming test"}],
    model="gpt-4o",
    stream=True,
)

# This will create a single span trace with the OpenAI call
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")
```

## Combining with the log decorator

You can combine the OpenAI wrapper with the `log` decorator to create more complex traces:

```python Python theme={null}
import os
from splunk_ao import log
from splunk_ao.openai import openai

client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

def call_openai(prompt):
    # This will be automatically logged as a child span
    chat_completion = client.chat.completions.create(
        messages=[{"role": "user", "content": prompt}],
        model="gpt-4o"
    )
    return chat_completion.choices[0].message.content

@log(span_type="workflow", name="Roman Empire Span")
def make_nested_call():
    # This creates a parent workflow span
    first_result = call_openai("Tell me about the Roman Empire")
    second_result = call_openai(f"Summarize this: {first_result}")
    return second_result

# This will create a trace with a workflow span and two nested LLM spans
response = make_nested_call()
print(response)
```

## Benefits of using the OpenAI integration

* **Zero-config logging**: No need to add logging code throughout your application
* **Complete visibility**: All prompts and responses are automatically captured
* **Minimal code changes**: Change your import statement in Python. No other code changes are required.
* **Automatic tracing**: Creates spans and traces without manual setup
* **Streaming support**: Works with both regular and streaming responses

> [!NOTE]
>
> ### Asynchronous OpenAI calls with Splunk Agent Observability
>
> The Splunk Agent Observability OpenAI wrapper currently supports only synchronous calls for both the Chat Completions API and the Responses API. It does not include built-in support for the `AsyncOpenAI` class from the official OpenAI Python library. As a result, asynchronous calls made via the `splunk_ao.openai` wrapper won't automatically generate LLM spans or upload telemetry to Splunk Agent Observability.
>
> You can still track async interactions by manually using the low-level `SplunkAOLogger` API. This requires importing and awaiting the OpenAI `AsyncOpenAI` client, wrapping each call with [a call to add an LLM span](https://agent-observability-docs.splunk.com/sdk-api/logging/splunk-ao-logger.md#llm-spans), and flushing the logger to send your traces.

## Next steps

> **[Splunk Agent Observability logger](https://agent-observability-docs.splunk.com/sdk-api/logging/splunk-ao-logger.md)**
>
> Log with full control over sessions, traces, and spans using the Splunk Agent Observability logger.

> **[Log decorator](https://agent-observability-docs.splunk.com/sdk-api/logging/log-decorator/log-decorator.md)**
>
> Quickly add logging to your code with the log decorator and wrapper.

> **[Splunk Agent Observability context](https://agent-observability-docs.splunk.com/sdk-api/logging/splunk-ao-context.md)**
>
> Manage logging using the Splunk Agent Observability context manager.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.