Getting started
Set up Blue Guardrails to monitor issues in your AI application
Blue Guardrails detects issues in LLM-powered applications or workflows. Send model inputs and outputs to your workspace to start monitoring.
Prerequisites
- A Blue Guardrails account
- Membership in a workspace with a role of Contributor or higher (see Roles and permissions)
1. Create an API key
Create a workspace key before either coding-agent or manual setup.
- Click Workspaces in the sidebar and open the workspace you want to send traces to.
- Open the Service accounts tab and click Create service account.
- Give the service account a name and pick the Trace writer preset, then click Create.
- In the new row, click Create key, name the key, choose an expiration, and click Create.
Copy the key now. Blue Guardrails only displays it once.
Store it in your application's environment as BLUE_GUARDRAILS_API_KEY. Keep your model provider's key in the environment too:
export BLUE_GUARDRAILS_API_KEY="<YOUR_API_KEY>"
export OPENAI_API_KEY="<YOUR_OPENAI_KEY>"
# Or ANTHROPIC_API_KEY / GOOGLE_API_KEY for those providers.Never hardcode or commit keys. For more permissions and key options, see Create an API key for your workspace.
Set up with your coding agent
Copy this prompt into your coding agent after setting the environment variables above. It includes the Python and TypeScript examples below, so the agent can choose the one for your application. Your API key is not included in the prompt.
View full prompt
Connect this app to Blue Guardrails with the OpenTelemetry SDK. Detect its language and AI framework, then adapt only the matching example below. Keep the app’s existing models and behavior; install only the needed dependencies using its package manager.
Export OTLP/HTTP protobuf traces to https://api.blueguardrails.com/v1/traces. Read BLUE_GUARDRAILS_API_KEY from the environment and send it as an Authorization: Bearer header. Keep model-provider credentials in the environment too; never hardcode or commit secrets.
Capture model inputs and outputs. Initialize tracing once before AI calls, reuse existing tracing when present, and flush on application shutdown—not after each request. Make a test request and verify trace export.
## Python — OpenAI
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http openai opentelemetry-instrumentation-genai-openai
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from openai import OpenAI
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.genai.openai import OpenAIInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
try:
client = OpenAI()
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[
{'role': 'system', 'content': 'Answer the question based on the context.'},
{'role': 'user', 'content': 'Context: Revenue in Q1 was $85 Billion.'},
{'role': 'user', 'content': 'What was the revenue in Q1?'},
],
)
print(response.choices[0].message.content)
finally:
tracer_provider.shutdown()
```
## Python — Anthropic
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http anthropic opentelemetry-instrumentation-genai-anthropic
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from anthropic import Anthropic
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.genai.anthropic import AnthropicInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
AnthropicInstrumentor().instrument(tracer_provider=tracer_provider)
try:
# The GenAI instrumentor captures content; avoid duplicate SDK metadata spans.
client = Anthropic(open_telemetry=False)
response = client.messages.create(
max_tokens=1000,
model='claude-haiku-4-5',
system='Answer the question based on the context.',
messages=[
{'role': 'user', 'content': 'Context: Revenue in Q1 was $85 Billion.'},
{'role': 'user', 'content': 'What was the revenue in Q1?'},
],
)
print(response.content[0].text)
finally:
tracer_provider.shutdown()
```
## Python — Google GenAI
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http google-genai opentelemetry-instrumentation-google-genai
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from google.genai import Client
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
GoogleGenAiSdkInstrumentor().instrument(tracer_provider=tracer_provider)
try:
client = Client()
message = '''Answer the question based on the context.
Context: Revenue in Q1 was $85 Billion.
What was the revenue in Q1?'''
response = client.models.generate_content(model='gemini-2.5-flash', contents=message)
print(response.text)
finally:
tracer_provider.shutdown()
```
## Python — PydanticAI
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http pydantic-ai
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from pydantic_ai import Agent, InstrumentationSettings
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
Agent.instrument_all(InstrumentationSettings(tracer_provider=tracer_provider, include_content=True))
try:
agent = Agent(
'openai:gpt-4o-mini',
instructions='Answer the question based on the context.',
)
result = agent.run_sync(
'Context: Revenue in Q1 was $85 Billion.\nWhat was the revenue in Q1?'
)
print(result.output)
finally:
tracer_provider.shutdown()
```
## Python — Haystack
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http haystack-ai opentelemetry-instrumentation-genai-openai
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.genai.openai import OpenAIInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
try:
messages = [
ChatMessage.from_system('Answer the question based on the context.'),
ChatMessage.from_user(
'Context: Revenue in Q1 was $85 Billion.\nWhat was the revenue in Q1?'
),
]
response = OpenAIChatGenerator(model='gpt-4o-mini').run(messages)
print(response)
finally:
tracer_provider.shutdown()
```
## Python — LangChain
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http langchain langchain-openai opentelemetry-instrumentation-genai-langchain
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from langchain.agents import create_agent
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.genai.langchain import LangChainInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
LangChainInstrumentor().instrument(tracer_provider=tracer_provider)
try:
agent = create_agent(model='openai:gpt-4o-mini', tools=[])
result = agent.invoke({
'messages': [
{'role': 'system', 'content': 'Answer the question based on the context.'},
{
'role': 'user',
'content': 'Context: Revenue in Q1 was $85 Billion.\nWhat was the revenue in Q1?',
},
]
})
print(result['messages'][-1].content)
finally:
tracer_provider.shutdown()
```
## Python — LangGraph
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http langchain langgraph langchain-openai opentelemetry-instrumentation-genai-langchain
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, MessagesState, StateGraph
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.genai.langchain import LangChainInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
LangChainInstrumentor().instrument(tracer_provider=tracer_provider)
try:
model = ChatOpenAI(model='gpt-4o-mini')
def call_model(state: MessagesState) -> dict:
return {'messages': [model.invoke(state['messages'])]}
builder = StateGraph(MessagesState)
builder.add_node('model', call_model)
builder.add_edge(START, 'model')
builder.add_edge('model', END)
graph = builder.compile()
result = graph.invoke({
'messages': [
('system', 'Answer the question based on the context.'),
('user', 'Context: Revenue in Q1 was $85 Billion.\nWhat was the revenue in Q1?'),
]
})
print(result['messages'][-1].content)
finally:
tracer_provider.shutdown()
```
## Python — OpenAI Agents
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http openai-agents opentelemetry-instrumentation-genai-openai opentelemetry-instrumentation-genai-openai-agents
```
```python
import os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from agents import Agent, Runner
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.genai.openai import OpenAIInstrumentor
from opentelemetry.instrumentation.genai.openai_agents import OpenAIAgentsInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
OpenAIAgentsInstrumentor().instrument(
tracer_provider=tracer_provider,
disable_openai_trace_export=True,
)
try:
agent = Agent(
name='Revenue analyst',
instructions='Answer the question based on the context.',
model='gpt-4o-mini',
)
result = Runner.run_sync(
agent,
'Context: Revenue in Q1 was $85 Billion.\nWhat was the revenue in Q1?',
)
print(result.final_output)
finally:
tracer_provider.shutdown()
```
## Python — Claude Agent SDK
```bash
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http claude-agent-sdk "langsmith[otel]"
```
```python
import asyncio
import os
# Set these before importing langsmith or claude_agent_sdk.
os.environ['LANGSMITH_OTEL_ENABLED'] = 'true'
os.environ['LANGSMITH_OTEL_ONLY'] = 'true'
os.environ['LANGSMITH_TRACING'] = 'true'
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
from langsmith.integrations.claude_agent_sdk import configure_claude_agent_sdk
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
configure_claude_agent_sdk()
async def main() -> None:
options = ClaudeAgentOptions(
model='claude-haiku-4-5',
allowed_tools=[],
max_turns=1,
)
async with ClaudeSDKClient(options=options) as client:
await client.query(
'Context: Revenue in Q1 was $85 Billion. What was the revenue in Q1?'
)
async for message in client.receive_response():
if hasattr(message, 'content'):
for block in message.content:
if hasattr(block, 'text'):
print(block.text)
elif hasattr(block, 'name'):
print(f'Tool: {block.name}')
try:
asyncio.run(main())
finally:
tracer_provider.shutdown()
```
## TypeScript (Node.js, server-side) — OpenAI
```bash
npm install openai @arizeai/openinference-instrumentation-openai @opentelemetry/api @opentelemetry/exporter-trace-otlp-proto @opentelemetry/sdk-node
```
```typescript
import { OpenAIInstrumentation } from "@arizeai/openinference-instrumentation-openai";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { NodeSDK } from "@opentelemetry/sdk-node";
import OpenAI from "openai";
const sdk = new NodeSDK({
serviceName: "my-ai-app",
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? "https://api.blueguardrails.com/v1/traces",
headers: { Authorization: `Bearer ${process.env.BLUE_GUARDRAILS_API_KEY}` },
}),
});
sdk.start();
const instrumentation = new OpenAIInstrumentation();
instrumentation.manuallyInstrument(OpenAI);
const client = new OpenAI();
try {
const response = await client.chat.completions.create({
model: "gpt-5-mini",
messages: [
{ role: "system", content: "Answer the question based on the context." },
{ role: "user", content: "Context: Revenue in Q1 was $85 Billion." },
{ role: "user", content: "What was Google's revenue in Q1 2025?" },
],
});
console.log(response.choices[0].message.content);
} finally {
await sdk.shutdown();
}
```
## TypeScript (Node.js, server-side) — OpenAI Responses API
```bash
npm install openai @arizeai/openinference-instrumentation-openai @opentelemetry/api @opentelemetry/exporter-trace-otlp-proto @opentelemetry/sdk-node
```
```typescript
import { OpenAIInstrumentation } from "@arizeai/openinference-instrumentation-openai";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { NodeSDK } from "@opentelemetry/sdk-node";
import OpenAI from "openai";
const sdk = new NodeSDK({
serviceName: "my-ai-app",
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? "https://api.blueguardrails.com/v1/traces",
headers: { Authorization: `Bearer ${process.env.BLUE_GUARDRAILS_API_KEY}` },
}),
});
sdk.start();
const instrumentation = new OpenAIInstrumentation();
instrumentation.manuallyInstrument(OpenAI);
const client = new OpenAI();
try {
const response = await client.responses.create({
model: "gpt-5-mini",
instructions: "Answer the question based on the context.",
input: "Context: Revenue in Q1 was $85 Billion.\nWhat was Google's revenue in Q1 2025?",
});
console.log(response.output_text);
} finally {
await sdk.shutdown();
}
```
## TypeScript (Node.js, server-side) — Anthropic
```bash
npm install @anthropic-ai/sdk @arizeai/openinference-instrumentation-anthropic @opentelemetry/api @opentelemetry/exporter-trace-otlp-proto @opentelemetry/sdk-node
```
```typescript
import Anthropic from "@anthropic-ai/sdk";
import { AnthropicInstrumentation } from "@arizeai/openinference-instrumentation-anthropic";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { NodeSDK } from "@opentelemetry/sdk-node";
const sdk = new NodeSDK({
serviceName: "my-ai-app",
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? "https://api.blueguardrails.com/v1/traces",
headers: { Authorization: `Bearer ${process.env.BLUE_GUARDRAILS_API_KEY}` },
}),
});
sdk.start();
const instrumentation = new AnthropicInstrumentation();
instrumentation.manuallyInstrument(Anthropic);
// OpenInference captures content; avoid duplicate SDK metadata spans.
const client = new Anthropic({ openTelemetry: false });
try {
const response = await client.messages.create({
max_tokens: 1000,
model: "claude-haiku-4-5",
system: "Answer the question based on the context.",
messages: [
{ role: "user", content: "Context: Revenue in Q1 was $85 Billion." },
{ role: "user", content: "What was Google's revenue in Q1 2025?" },
],
});
if (response.content[0].type === "text") {
console.log(response.content[0].text);
}
} finally {
await sdk.shutdown();
}
```
## TypeScript (Node.js, server-side) — LangChain
```bash
npm install langchain @langchain/core @langchain/openai @arizeai/openinference-instrumentation-langchain @opentelemetry/api @opentelemetry/exporter-trace-otlp-proto @opentelemetry/sdk-node
```
```typescript
import { createAgent } from "langchain";
import { LangChainInstrumentation } from "@arizeai/openinference-instrumentation-langchain";
import * as CallbackManagerModule from "@langchain/core/callbacks/manager";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { NodeSDK } from "@opentelemetry/sdk-node";
const sdk = new NodeSDK({
serviceName: "my-ai-app",
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? "https://api.blueguardrails.com/v1/traces",
headers: { Authorization: `Bearer ${process.env.BLUE_GUARDRAILS_API_KEY}` },
}),
});
sdk.start();
// Patch the shared callback manager to capture graph, agent, and model calls.
const instrumentation = new LangChainInstrumentation();
instrumentation.manuallyInstrument(CallbackManagerModule);
// Await tracing callbacks before flushing this short-lived script.
process.env.LANGCHAIN_CALLBACKS_BACKGROUND = "false";
try {
const agent = createAgent({
model: "openai:gpt-4o-mini",
tools: [],
systemPrompt: "Answer the question based on the context.",
});
const result = await agent.invoke({
messages: [{
role: "user",
content: "Context: Revenue in Q1 was $85 Billion.\nWhat was the revenue in Q1?",
}],
});
console.log(result.messages.at(-1)?.content);
} finally {
await sdk.shutdown();
}
```
## TypeScript (Node.js, server-side) — LangGraph
```bash
npm install @langchain/langgraph @langchain/core @langchain/openai @arizeai/openinference-instrumentation-langchain @opentelemetry/api @opentelemetry/exporter-trace-otlp-proto @opentelemetry/sdk-node
```
```typescript
import { ChatOpenAI } from "@langchain/openai";
import { END, START, MessagesValue, StateGraph, StateSchema } from "@langchain/langgraph";
import { LangChainInstrumentation } from "@arizeai/openinference-instrumentation-langchain";
import * as CallbackManagerModule from "@langchain/core/callbacks/manager";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { NodeSDK } from "@opentelemetry/sdk-node";
const sdk = new NodeSDK({
serviceName: "my-ai-app",
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? "https://api.blueguardrails.com/v1/traces",
headers: { Authorization: `Bearer ${process.env.BLUE_GUARDRAILS_API_KEY}` },
}),
});
sdk.start();
// Patch the shared callback manager to capture graph, agent, and model calls.
const instrumentation = new LangChainInstrumentation();
instrumentation.manuallyInstrument(CallbackManagerModule);
// Await tracing callbacks before flushing this short-lived script.
process.env.LANGCHAIN_CALLBACKS_BACKGROUND = "false";
try {
const model = new ChatOpenAI({ model: "gpt-4o-mini" });
const State = new StateSchema({ messages: MessagesValue });
const graph = new StateGraph(State)
.addNode("model", async (state) => ({
messages: [await model.invoke(state.messages)],
}))
.addEdge(START, "model")
.addEdge("model", END)
.compile();
const result = await graph.invoke({
messages: [
{ role: "system", content: "Answer the question based on the context." },
{ role: "user", content: "Context: Revenue in Q1 was $85 Billion.\nWhat was the revenue in Q1?" },
],
});
console.log(result.messages.at(-1)?.content);
} finally {
await sdk.shutdown();
}
```
## TypeScript (Node.js, server-side) — Claude Agent SDK
```bash
npm install @anthropic-ai/claude-agent-sdk @arizeai/openinference-instrumentation-claude-agent-sdk @opentelemetry/api @opentelemetry/exporter-trace-otlp-proto @opentelemetry/sdk-node
```
```typescript
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { NodeSDK } from "@opentelemetry/sdk-node";
import { ClaudeAgentSDKInstrumentation } from "@arizeai/openinference-instrumentation-claude-agent-sdk";
import * as ClaudeAgentSDKModule from "@anthropic-ai/claude-agent-sdk";
// Create mutable copy — ESM namespace objects are frozen
const ClaudeAgentSDK = { ...ClaudeAgentSDKModule };
const instrumentation = new ClaudeAgentSDKInstrumentation();
const sdk = new NodeSDK({
serviceName: "my-ai-app",
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? "https://api.blueguardrails.com/v1/traces",
headers: { Authorization: `Bearer ${process.env.BLUE_GUARDRAILS_API_KEY}` },
}),
instrumentations: [instrumentation],
});
sdk.start();
instrumentation.manuallyInstrument(ClaudeAgentSDK);
const { query } = ClaudeAgentSDK;
try {
for await (const message of query({
prompt: "Context: Revenue in Q1 was $85 Billion. What was the revenue in Q1?",
options: {
model: "claude-haiku-4-5",
allowedTools: [],
maxTurns: 1,
},
})) {
if (message.type === "assistant" && message.message?.content) {
for (const block of message.message.content) {
if ("text" in block) {
console.log(block.text);
} else if ("name" in block) {
console.log(`Tool: ${block.name}`);
}
}
}
}
} finally {
await sdk.shutdown();
}
```Or connect your application manually
2. Pick your language and framework
Choose Python or TypeScript, then your framework. The installation command and code sample below match the examples in the product's onboarding flow.
3. Install dependencies and integrate tracing
Each sample includes its installation command. TypeScript examples run on the server with Node.js, not in the browser.
Initialize tracing once before making AI calls. In a running application, flush traces on shutdown, not after every request. The standalone samples shut down the exporter when they finish.
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http openai opentelemetry-instrumentation-genai-openai
# Or with pip:
pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http openai opentelemetry-instrumentation-genai-openaiimport os
os.environ.setdefault('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', "https://api.blueguardrails.com/v1/traces")
os.environ['OTEL_EXPORTER_OTLP_TRACES_HEADERS'] = (
f"Authorization=Bearer {os.environ['BLUE_GUARDRAILS_API_KEY']}"
)
os.environ['OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT'] = 'SPAN_ONLY'
from openai import OpenAI
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.genai.openai import OpenAIInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(tracer_provider)
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
try:
client = OpenAI()
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[
{'role': 'system', 'content': 'Answer the question based on the context.'},
{'role': 'user', 'content': 'Context: Revenue in Q1 was $85 Billion.'},
{'role': 'user', 'content': 'What was the revenue in Q1?'},
],
)
print(response.choices[0].message.content)
finally:
tracer_provider.shutdown()The Python LangChain example uses create_agent. The LangGraph example builds a StateGraph directly. Both use OpenTelemetry GenAI instrumentation. Install langchain for the LangGraph example too: the instrumentor checks that dependency before enabling tracing.
Verify your traces
Run your application and make an AI request. Traces appear in Blue Guardrails within a few seconds. Open your workspace and click Dashboard to see incoming messages and issue metrics.