Skip to main content

Overview

Laminar is an open-source, OpenTelemetry-native observability platform for AI agents. Trace, debug, and monitor every Microsoft Agent Framework agent run, model turn, and tool call with a single Laminar.initialize() call. Self-host via Helm or use managed cloud. Microsoft Agent Framework (GitHub) is Microsoft’s open-source framework for building agents and multi-agent workflows, the successor to Semantic Kernel and AutoGen. It emits its own OpenTelemetry GenAI semconv spans for agent runs, model calls, and tool executions. Laminar routes those spans to your project, turns on prompt and response capture, and nests everything your tools do under the right span, so you don’t call configure_otel_providers() or enable_instrumentation() yourself. What Laminar captures:
  • Every agent run, named after the agent, with its model turns and tool calls nested inside.
  • Every chat <model> turn with prompts, responses, tool definitions, token counts, latency, and cost.
  • Every tool call with arguments and return value, and failed tool calls as error spans.
  • Sub-agents called as tools, workflow steps, and MCP tool calls nested under the call that spawned them.

Getting started

1

Install

Ensure you have lmnr version 0.7.66 or higher and agent-framework 1.x:
The agent-framework package installs the core framework plus every provider client. If you only install agent-framework-core, add the client package you use, such as agent-framework-openai.
2

Set environment variables

3

Initialize Laminar

Laminar.initialize() auto-instruments Microsoft Agent Framework when agent-framework-core is installed. Importing agent_framework before or after initialize() both work.
Wrapping your entry point in @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. Sessions, user IDs, and metadata you set with Laminar.set_trace_session_id() and friends apply to the framework’s spans too.
The framework’s chat span already records the model call, so Laminar doesn’t trace the OpenAI or Anthropic SDK call underneath it a second time. Provider SDK calls you make directly, outside an agent run, are still traced as usual.

See what happened in a trace

Each agent run shows up as a span named after the agent, with its model turns and tool calls inside it. Laminar extracts the inputs, LLM outputs, and tool calls into a transcript view, so you read the conversation instead of a span tree. Switch to tree view to see how sub-agents and tools nest. More on the trace UX: Viewing traces.

Multi-agent with agents as tools

A coordinator agent can delegate to specialist agents by passing them as tools with agent.as_tool(). Each delegated run nests under the tool call that started it, so the hierarchy in the trace mirrors the conversation.
The trace for this run nests like this:

Streaming, workflows, and MCP tools

These are traced with no extra setup:
  • Streaming: agent.run(..., stream=True) produces the same spans as a non-streaming run, with the full response recorded on the chat span once the stream finishes.
  • Workflows: orchestrations such as SequentialBuilder emit workflow and executor spans, with each participant agent’s run nested inside its step.
  • MCP tools: tools from MCPStdioTool and the other MCP clients show up as tool calls, with the MCP session’s requests nested underneath.
  • Your own code: functions decorated with @observe, and provider SDK calls made inside a tool, nest under that tool’s span.

Track outcomes with Signals

Traces answer what happened on this run. Signals answer the cross-trace question: how often does the concierge skip a sub-agent, when does a tool get called with a malformed date, how many runs end without a booking. 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.
Every new project ships with a Failure Detector Signal that categorizes issues on any trace over 1000 tokens. Open it from the Signals sidebar to see events as soon as your Microsoft Agent Framework traces arrive.

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

  • Confirm LMNR_PROJECT_API_KEY is set in the same process that runs the agent.
  • agent-framework-core must be installed when Laminar.initialize() runs. The integration requires agent-framework-core 1.x and lmnr >= 0.7.66.
  • If you set ENABLE_INSTRUMENTATION=false or called agent_framework.observability.disable_instrumentation(), the framework emits no spans of its own. Laminar respects that, and only the underlying provider SDK calls are traced.
Laminar turns on the framework’s sensitive-data capture so chat spans carry messages and tool spans carry arguments and results. It leaves the setting alone if you set ENABLE_SENSITIVE_DATA yourself, so check that it isn’t set to false. Set ENABLE_SENSITIVE_DATA=false or LMNR_TRACE_CONTENT=false when you want to keep content out of traces on purpose.
Pass disabled_instruments={Instruments.MICROSOFT_AGENT_FRAMEWORK} to Laminar.initialize(). The framework’s spans are then exported as the framework emits them: no message content unless you enable sensitive data yourself, no nesting of your own spans under tool calls, and provider SDK calls traced as separate LLM spans.
Set base_url and the ports of your instance when initializing. For a local OSS deployment:

What’s next

Viewing traces

Read the transcript view, filter, and search across traces.

Signals

Detect behaviors and failures across every run, then query, cluster, and alert on them.

SQL editor and MCP server

Query traces programmatically from the UI, API, or your IDE.

Tracing structure

Sessions, metadata, and tags for deeper control.

OpenAI

Using the OpenAI SDK directly without an agent framework? Trace it here.

Anthropic

Trace the Anthropic SDK directly in TypeScript and Python.

OpenAI Agents SDK

Trace agent runs, handoffs, and tool calls.

Pydantic AI

Trace Pydantic AI agents, typed tools, and sub-agents.

LangChain / LangGraph

Trace LangChain chains and LangGraph graphs.

All integrations

Browse every provider, framework, coding agent, and browser integration Laminar supports.