Arthur + OpenAI
How does a developer instrument an OpenAI application with Arthur in under 10 minutes? By installing the Arthur Observability SDK with the OpenAI extra, initializing the Arthur client with your credentials, and calling arthur.instrument_openai() — after that, every OpenAI API call is automatically traced and sent to Arthur for observability, evaluation, and debugging. No manual span creation required.
Overview
Arthur's OpenAI integration uses OpenTelemetry-based auto-instrumentation to capture every request and response flowing through the OpenAI Python SDK. Once instrumented, you get full visibility into:
- Prompts and completions — every message sent and received
- Model parameters — model name, temperature, token counts
- Latency and errors — per-call timing and failure tracking
- Session and user context — group traces by conversation or end-user
sequenceDiagram
participant App as Your Application
participant SDK as Arthur SDK
participant OpenAI as OpenAI API
participant Engine as Arthur GenAI Engine
App->>SDK: arthur.instrument_openai()
Note over SDK: Auto-instrumentation enabled
App->>OpenAI: client.chat.completions.create(...)
OpenAI-->>App: Response
SDK->>Engine: Trace (spans, attributes)
Note over Engine: Traces visible in dashboard
Prerequisites:
- Python 3.10+
- An Arthur GenAI Engine instance (cloud or local)
- An Arthur API key — see API Keys to create one
Installation
Install the Arthur Observability SDK with the openai extra:
pip install "arthur-observability-sdk[openai]"This installs the core SDK along with the OpenInference OpenAI instrumentor and all required OpenTelemetry dependencies.
Initialize Arthur
Create an Arthur instance with your credentials and task context.
from arthur_observability_sdk import Arthur
arthur = Arthur(
api_key="your-api-key", # or set ARTHUR_API_KEY env var
base_url="https://your-arthur-engine-instance", # or set ARTHUR_BASE_URL env var
task_id="<your-task-uuid>", # Arthur task UUID
service_name="my-chatbot", # OTel service.name
)| Parameter | Description |
|---|---|
api_key | Your Arthur Engine API key. Falls back to ARTHUR_API_KEY env var. |
base_url | Base URL of your Arthur GenAI Engine. Falls back to ARTHUR_BASE_URL env var, then http://localhost:3030. |
task_id | Arthur task UUID for associating traces with a specific task. |
service_name | OpenTelemetry service.name resource attribute. Used to identify your application in the Arthur dashboard. Creates a new task based on service_name if task_id isn't specified. |
At least one oftask_idorservice_namemust be provided. A new task with theservice_namewill be created iftask_idis not specified.
Use environment variables for secrets. SetARTHUR_API_KEYandARTHUR_BASE_URLas environment variables (e.g., in a.envfile) rather than hardcoding them in your application.
Instrument OpenAI
Call instrument_openai() before making any OpenAI API calls. This patches the OpenAI SDK to automatically emit OpenTelemetry spans for every request.
import openai
from arthur_observability_sdk import Arthur
arthur = Arthur(
api_key="your-api-key", # or set ARTHUR_API_KEY env var
base_url="https://your-arthur-engine-instance", # or set ARTHUR_BASE_URL env var
task_id="<your-task-uuid>", # Arthur task UUID
service_name="my-chatbot", # OTel service.name
)
arthur.instrument_openai()
client = openai.OpenAI()
response = client.chat.completions.create(
model="gpt-5-mini",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)
arthur.shutdown()Key points:
instrument_openai()must be called once, before your first OpenAI call.- All
openai.OpenAI()andopenai.AsyncOpenAI()client instances are automatically instrumented — you don't need to wrap each one. - Call
arthur.shutdown()when your application exits to flush any remaining traces.
Add Session and User Context
Group related OpenAI calls by session or user using the arthur.attributes() context manager. This attaches session_id and user_id to every span created within the block.
with arthur.attributes(session_id="sess-1", user_id="user-99"):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello!"}],
)This is especially useful for:
- Multi-turn conversations — trace an entire chat session end-to-end
- Per-user analytics — understand how individual users interact with your application
- Debugging — filter traces in the Arthur dashboard by session or user
You can also nest context managers or use them across multiple OpenAI calls:
with arthur.attributes(session_id="sess-1", user_id="user-99"):
# First turn
response1 = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "What is Python?"}],
)
# Second turn — same session
response2 = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "What is Python?"},
{"role": "assistant", "content": response1.choices[0].message.content},
{"role": "user", "content": "How does it compare to JavaScript?"},
],
)Verify in Arthur
After running your instrumented application, traces appear in the Arthur GenAI Engine within seconds.

Traces viewed on the Arthur Engine UI
What to look for in the dashboard:
- Trace list — each
chat.completions.createcall appears as a trace with input messages, output completion, model name, and latency - Session grouping — if you used
arthur.attributes(session_id=...), traces are grouped by session - User filtering — filter by
user_idto see a specific user's interactions - Token usage — prompt and completion token counts are captured automatically
You can also query traces programmatically:
curl -X GET "${ARTHUR_BASE_URL}/api/v1/traces?task_ids=${ARTHUR_TASK_ID}" \
-H "Authorization: Bearer ${ARTHUR_API_KEY}"Troubleshooting
| Symptom | Fix |
|---|---|
| No traces appearing | Verify ARTHUR_API_KEY and ARTHUR_BASE_URL are correct and your Arthur Engine is reachable from your application. |
| Missing OpenAI spans | Call arthur.instrument_openai() before creating your first openai.OpenAI() client. |
| Traces delayed | Traces are exported asynchronously via BatchSpanProcessor; allow a few seconds, or call arthur.shutdown() to flush. |
ImportError on instrument | Run pip install "arthur-observability-sdk[openai]" to install the required extra. |
Next Steps
Now that your OpenAI application is instrumented, explore these capabilities:
- Prompt Management — version and manage prompts in Arthur, then fetch them at runtime with
arthur.get_prompt() - Continuous Evaluations — set up automated quality checks that run against your traced inferences
- LangChain Integration — if you're using LangChain with OpenAI, Arthur supports
arthur.instrument_langchain()for deeper chain-level tracing - Read our Best Practices for Building Agents Blog Series — observability and tracing fundamentals for building production agents
- Agentic Experiments — run structured experiments against your AI tasks to evaluate performance at scale
flowchart LR
A[Instrument OpenAI] --> B[View Traces]
B --> C[Add Evaluations]
B --> D[Manage Prompts]
C --> E[Set Up Continuous Evals]
D --> F[A/B Test Prompts]
E --> G[Production Monitoring]
F --> GUpdated about 22 hours ago