Overview
Laminar is an open-source, OpenTelemetry-native observability platform for AI agents built with Google ADK (Agent Development Kit). Trace, debug, and monitor every agent invocation, model call, and tool execution with a singleLaminar.initialize() call. Self-host via Helm or use managed cloud.
ADK is Google’s Python framework for building agents: you define an Agent with a model, an instruction, and tools, then drive it with a Runner. ADK emits its own OpenTelemetry spans for agent invocations, LLM calls, and tool calls. Laminar routes those spans into your project and enriches them so they read as a conversation.
What Laminar captures:
- An
invocationspan for eachrunner.run_async()call. - An agent span named after the agent (for example
travel_assistant), with the ADK session ID and user ID attached as Laminar’s session and user ID. - A
call_llmspan for every model turn, with the model, token counts, latency, and cost. - A tool span named after the tool (for example
get_weather) with the tool’s arguments and return value.
Getting started
Install
lmnr version 0.7.67 or higher and google-adk version 2.0.0 or higher:Set environment variables
Initialize Laminar
Laminar.initialize() auto-instruments ADK when google-adk is installed. No ADK telemetry configuration or OTLP exporter setup is needed.@observe() is optional but recommended: it creates a root span that captures inputs and outputs and makes the trace easy to find in the UI.See what happened in a trace
Open the trace in Laminar. The transcript view extracts the user message, each model turn, and every tool call with its arguments and result, so you read the conversation instead of a span tree. Switch to tree view to see how ADK nestscall_llm and tool spans under the agent span for each invocation.

Transcript of the travel-assistant run. The first Gemini turn calls get_weather and get_local_time in parallel, the second turn answers. The selected call_llm span shows the system instruction, the user message, and the model's tool calls, and the session and user ID from ADK sit in the trace header.
Sessions and users
ADK sessions map to Laminar sessions automatically. Thesession_id and user_id you pass to runner.run_async() are attached to each agent span, so every turn of one ADK conversation is grouped under the same session and filterable by user ID.
Message content and privacy
Laminar reads model and tool content from the attributes ADK itself records, so ADK’s content toggle applies to Laminar too. SetADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS=false to keep prompts, responses, and tool payloads out of the trace while still recording span timing, model names, and token counts.
Track outcomes with Signals
Traces answer what happened on this run. Signals answer the cross-trace question: how often does the agent call the wrong tool, when does it answer without calling a tool at all, how many runs end without a final response. A Signal pairs a plain-language prompt with a JSON output schema. Laminar runs it live on new traces (Triggers) or backfills it across history (Jobs) and records a structured event every time it matches. From there you query, cluster, and alert on events across every trace.Query across traces
- SQL editor for ad-hoc queries across traces, spans, signals, and evals.
- SQL API for programmatic access from scripts and pipelines.
- CLI (
lmnr-cli sql query) for terminal-driven queries and piping JSON into shell tools or coding agents. - MCP server to query Laminar directly from Claude Code, Cursor, or Codex.
Troubleshooting
I don't see any traces in Laminar
I don't see any traces in Laminar
- Confirm
LMNR_PROJECT_API_KEYis set in the same process that runs the agent. google-adkmust be installed whenLaminar.initialize()runs.- The integration requires
lmnr >= 0.7.62andgoogle-adk >= 2.0.0, < 3.0.0.google-adk2.10 and later needlmnr >= 0.7.67for full prompt and response capture.
LLM spans have no messages, only model, tokens, and cost
LLM spans have no messages, only model, tokens, and cost
pip show lmnr google-adk. With google-adk 2.10 or later, lmnr before 0.7.67 doesn’t attach the prompt and response to call_llm spans: upgrade with pip install -U lmnr. If your versions are fine, check ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS (see below).Tool spans have no input or output
Tool spans have no input or output
ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS is set to false. With content capture off, ADK records tool and model payloads as empty, and Laminar keeps them empty.I want to disable the Google ADK integration
I want to disable the Google ADK integration
disabled_instruments={Instruments.GOOGLE_ADK} to Laminar.initialize(). The Google Gen AI SDK instrumentation is then enabled again, so Gemini calls are still traced as plain LLM spans.Self-hosting Laminar
Self-hosting Laminar
base_url and the ports of your instance when initializing. For a local OSS deployment:What’s next
Viewing traces
Signals
SQL editor and MCP server
Tracing structure
Related integrations
Gemini
Pydantic AI
OpenAI Agents SDK
LangChain / LangGraph
LiteLLM
LiteLlm? See how LiteLLM calls are traced.