Agent Observability
Oodle's Agent Observability helps engineering teams track how large language models are used across their applications - including prompts, responses, token consumption, and estimated costs.
How It Works
Oodle ingests traces and logs that follow the OpenTelemetry Gen AI semantic conventions. When your application instruments LLM calls with these conventions, Oodle automatically:
- Detects the model from
gen_ai.request.modelandgen_ai.response.modelspan attributes - Extracts input and output token counts from
gen_ai.usage.input_tokensandgen_ai.usage.output_tokens - Displays prompt and response content from
gen_ai.input.messages,gen_ai.output.messages, andgen_ai.system_instructionsspan attributes - Calculates estimated costs based on your configured model pricing
All of this is surfaced in the Agent Observability hub at Agent Observability → Overview (ap1, us1).
Exploring Traces
The Agent Observability hub has several tabs for different views of your GenAI data.
Overview
The default tab shows an embedded Grafana dashboard with key metrics: token usage, cost trends, trace counts, and model breakdowns over time.
Traces
The main trace list with columns for timestamp, name, input, output, model, sentiment, turns, latency, and cost.
Search traces by Name, Input, Output, or Input/Output combined using the field dropdown next to the search box.
Click any trace to open the detail view (see Trace Detail below).
Agent Graph
An interactive topology graph showing how agents, tools, and LLM calls connect in your application. Each node displays request count, error rate, and average latency. Click a node to see:
- Decision Paths — outgoing connections split into sub-agents and tool calls with probability, error rate, and latency
- Traces — filtered trace list for that agent
- Insights — AI-generated recommendations specific to that agent (if available)
The Agent Graph has its own sidebar with environment and service filters, plus a node search and visibility toggle.
Observations
A span-level table showing individual LLM calls rather than full traces. Columns include start time, span type, name, input, output, model, sentiment, log level, latency, and cost.
Sessions
Groups traces by session.id into multi-turn
conversations. Each row shows the session ID, trace
count, turns, sentiment, total cost, duration, and
last activity time. Click a session to open a detail
drawer with stats and a cross-trace transcript.
To enable sessions, set session.id as a span
attribute in your instrumentation. Traces sharing
the same session ID are grouped together
automatically.
Users
Aggregates usage by user.id — showing total events,
turns, sentiment, token count, and cost per user.
Click a user to filter the Traces tab to that user's
activity.
Set user.id as a span attribute to enable
per-user tracking.
Insights
Appears when Oodle has generated AI-powered recommendations for your GenAI application. Insights are categorized by type (Quality, Efficiency, Resource, Performance) and severity (High, Medium, Low). Use this tab to identify optimization opportunities and quality issues.
Sidebar Filters
The sidebar on the left lets you filter data across most tabs:
| Filter | Description |
|---|---|
| Time Range | Controls the query window |
| Has Error | Show only traces with errors |
| Environment | Filter by resource::env |
| Service | Filter by resource::service.name |
| Model | Filter by gen_ai.request.model |
| Agent Name | Filter by gen_ai.agent.name |
| Operation Name | Filter by gen_ai.operation.name |
| User ID | Filter by user.id |
| Sentiment | Range slider from −1 to 1 |
| Score | Range slider from 0 to 1 |
| Score Name | Filter by evaluator score name |
You can also add arbitrary label filters using the filter bar above the tab content.
Trace Detail
Clicking on a trace opens the detail view with tabs for Transcript, Trace, Logs, Scores, and Costs.
Transcript
Displays the full conversation — system instructions, user prompts, and assistant responses — alongside the model name and token count.
Use the search bar to find text across all messages. Matches are highlighted and the view scrolls to each result.
For traces with multiple agents (identified by
gen_ai.agent.name), a By Agent toggle groups
the conversation by agent.
Trace
Shows the span waterfall with the full request lifecycle, including nested agent invocations and LLM calls.
By default, non-GenAI infrastructure spans are hidden. Toggle Show all spans to reveal them. GenAI-related spans (GENERATION, AGENT, TOOL) are expanded automatically while infrastructure spans start collapsed.
Each span has sub-tabs for Overview, Gen AI (model/token/cost summary), Transcript, and Errors.
Scores
Shows all evaluator scores attached to the trace. Each row displays the score name, value, source (EVAL, ANNOTATION, or API), data type, model used, and comment.
Costs
Summarizes total cost, tokens, and LLM calls broken down by model. Shows separate breakdowns for model costs and evaluator costs.
Trace Actions
The trace detail toolbar includes several actions:
| Action | Description |
|---|---|
| Analyze with AI | Opens the AI sidebar assistant with the trace as context |
| Open in Playground | Loads the trace conversation into the Playground for iteration |
| Add to Dataset | Adds the trace as a test case to a dataset |
| Open Trace | Opens the trace in the standard trace lookup view |
Getting Started
1. Install OpenTelemetry GenAI instrumentation
The official OpenTelemetry GenAI instrumentation libraries auto-instrument LLM provider SDKs - no manual span creation required. Install the instrumentation package for your LLM provider alongside the core OpenTelemetry SDK and OTLP exporter:
- Google Gemini
- OpenAI
- Pydantic AI
opentelemetry-instrumentation-google-genai>=0.7b1
opentelemetry-exporter-otlp-proto-http>=1.30.0
opentelemetry-sdk>=1.30.0
google-genai>=1.0.0
opentelemetry-instrumentation-openai-v2>=2.0b0
opentelemetry-exporter-otlp-proto-http>=1.30.0
opentelemetry-sdk>=1.30.0
openai>=1.0.0
pydantic-ai
opentelemetry-exporter-otlp-proto-http>=1.30.0
opentelemetry-sdk>=1.30.0
See the OpenTelemetry GenAI instrumentation registry for a full list of supported providers (Anthropic, AWS Bedrock, LangChain, and more).
2. Instrument your application
Initialize the OpenTelemetry SDK with OTLP export, then activate the GenAI instrumentor for your provider:
- Google Gemini
- Pydantic AI
from opentelemetry import _logs as otel_logs
from opentelemetry import trace as otel_trace
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
def setup_opentelemetry():
resource = Resource.create({"service.name": "my-llm-app"})
tracer_provider = TracerProvider(resource=resource)
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
otel_trace.set_tracer_provider(tracer_provider)
logger_provider = LoggerProvider(resource=resource)
logger_provider.add_log_record_processor(
BatchLogRecordProcessor(OTLPLogExporter())
)
otel_logs.set_logger_provider(logger_provider)
setup_opentelemetry()
GoogleGenAiSdkInstrumentor().instrument()
After this, all calls to the Google Gemini SDK (e.g.
client.models.generate_content(...)) are automatically
traced with gen_ai.* attributes.
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.trace import set_tracer_provider
from pydantic_ai import Agent
from pydantic_ai.models.instrumented import InstrumentationSettings
def setup_opentelemetry():
resource = Resource.create({"service.name": "my-llm-app"})
tracer_provider = TracerProvider(resource=resource)
tracer_provider.add_span_processor(
BatchSpanProcessor(OTLPSpanExporter())
)
set_tracer_provider(tracer_provider)
setup_opentelemetry()
Agent.instrument_all(InstrumentationSettings(
use_aggregated_usage_attribute_names=False,
))
Pydantic AI captures prompt and response content by
default. Pass include_content=False to
InstrumentationSettings to disable.
3. Set environment variables
The application needs these environment variables:
| Variable | Description |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP endpoint — points to your OTel Collector (e.g. http://otel-collector:4318) |
OTEL_SEMCONV_STABILITY_OPT_IN | Set to gen_ai_latest_experimental to enable GenAI semantic conventions (not needed for Pydantic AI) |
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT | Set to span_and_event to capture prompt/response content (not needed for Pydantic AI — it captures content by default) |
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT captures full prompt and response text. This may include sensitive data — review your organization's data policies before enabling in production.
4. Configure the OpenTelemetry Collector
Route traces and logs from your application to Oodle
through an OpenTelemetry Collector. The collector
exports to Oodle's OTLP endpoint which supports standard
OTLP paths (/v1/traces, /v1/logs):
receivers:
otlp:
protocols:
http:
endpoint: "0.0.0.0:4318"
processors:
batch:
timeout: 5s
send_batch_size: 512
exporters:
otlphttp/oodle:
endpoint: "https://<OODLE_INSTANCE>-otlp.collector.oodle.ai"
headers:
"X-OODLE-INSTANCE": "<OODLE_INSTANCE>"
"X-API-KEY": "<OODLE_API_KEY>"
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp/oodle]
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp/oodle]
Replace <OODLE_INSTANCE> and <OODLE_API_KEY> with your
credentials from Settings → API Keys in the Oodle UI
(ap1, us1).
See the OpenTelemetry integration guide for full collector and SDK configuration options.