Overview
Laminar is an open-source, OpenTelemetry-native observability platform for AI agents. Trace, debug, and monitor every LangChain chain and LangGraph agent in TypeScript and Python: each graph node, tool call, retriever query, and LLM call is recorded with its inputs, outputs, token usage, and cost. Self-host via Helm or use managed cloud. Your LangChain and LangGraph code stays as it is. Laminar builds the run tree from LangChain’s own callbacks. Calls to OpenAI and Anthropic models are recorded by Laminar’s OpenAI and Anthropic integrations, so each call is one LLM span with the provider’s full request and response.Getting started
- TypeScript
- Python
1
Install Laminar and LangChain
@lmnr-ai/lmnr 0.8.53 or later. Install the model provider’s SDK (openai here, @anthropic-ai/sdk if you use @langchain/anthropic) as a direct dependency, because you pass it to Laminar in step 3.2
Set up your environment variables
.env
node --env-file=.env.3
Initialize Laminar with your LangChain modules
Laminar can’t patch an ES module that your code has already imported, so pass the LangChain modules, and the SDK of each model provider you call, to Then import it first in your entry point, before any LangChain code runs:Each module turns on part of the trace. The LangChain modules go under
instrumentModules. Do it once, in its own file:instrumentation.ts
index.ts
instrumentModules.langchain, and the provider SDKs go at the top level:In a CommonJS app, calling
Laminar.initialize() before LangChain is loaded instruments it without instrumentModules. Passing the modules works in both module systems, so it’s the setup we recommend.4
Use LangChain and LangGraph as usual
A chain:A LangGraph agent with a tool:Agents built with
chain.ts
agent.ts
createAgent from the langchain package run on LangGraph, so they’re traced the same way. await Laminar.shutdown() sends the last spans before a short-lived script exits; a long-running server doesn’t need it.What Laminar records
Each invocation of a chain or graph is one trace:Which integration records each LLM call
- OpenAI (including Azure OpenAI) and Anthropic chat models are recorded by Laminar’s provider integrations, as
openai.chat,openai.response, oranthropic.chatspans. In Python, Google GenAI (langchain-google-genai4 or later) and Groq models are handed off the same way. - Every other chat model (Gemini in TypeScript, Mistral, Amazon Bedrock, Ollama, and so on) is recorded by LangChain as an LLM span named after the model class, such as
ChatGoogleGenerativeAI.chatorChatMistralAI.chat. It carries the same messages, tool calls, model, token usage, and cost. Any provider SDK instrumentation underneath is silenced for that call, so nothing is recorded twice.
Group a LangGraph thread into a session
LangGraph’sthread_id is recorded on the graph and node spans. To see every run of a thread together in Laminar’s sessions view, wrap the call in observe with the thread ID as the session ID:
- TypeScript
- Python
weather_agent span, and the whole trace joins the session.
See what happened in a trace
Open a trace in Laminar and the default view is the transcript: the agent’s auto-extracted input, every LLM turn with a one-line preview of its response, and each tool call with its arguments and result, in the order they ran. You read the conversation instead of clicking through a tree ofexecute_task spans. Switch to tree view for the span-by-span structure, or open the LangGraph view to see which nodes ran.
More on the trace UX: Viewing traces.
Track outcomes with Signals
Traces answer what happened on this run. Signals answer the cross-trace question: how often does the agent answer without calling the tool it needed, when does a graph loop between the same two nodes, which runs end with an apology instead of an answer. A Signal pairs a plain-language instruction 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 LangChain 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 from Claude Code, Cursor, or Codex.
Troubleshooting
I don't see any traces in Laminar (TypeScript)
I don't see any traces in Laminar (TypeScript)
- Pass the LangChain modules to
instrumentModulesas shown in step 3. In an ES module app,Laminar.initialize()without them records nothing from LangChain. - Import your
instrumentationfile before any file that runs LangChain code. - Confirm
LMNR_PROJECT_API_KEYis set in the process that runs LangChain. - Call
await Laminar.shutdown()before a short-lived script exits.
Every OpenAI or Anthropic call shows up twice (TypeScript)
Every OpenAI or Anthropic call shows up twice (TypeScript)
Add
chatModelsModule and llmsModule to instrumentModules.langchain. Without them, LangChain can’t hand the call to the provider integration, so both record it. Laminar logs a warning at startup when chatModelsModule is missing.I see ChatOpenAI.chat instead of an openai.* span (TypeScript)
I see ChatOpenAI.chat instead of an openai.* span (TypeScript)
The OpenAI integration didn’t record the call, so LangChain recorded it instead. Pass
OpenAI from openai to instrumentModules, and check with npm ls openai that @langchain/openai uses the same copy of openai that you import. The same applies to ChatAnthropic.chat and @anthropic-ai/sdk.Self-hosting Laminar
Self-hosting Laminar
Point the SDK at your instance when initializing. For a local OSS deployment:
- TypeScript
- Python
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, user IDs, metadata, and tags.
Related integrations
deepagents
Trace deepagents runs, subagents, and tool calls.
Pydantic AI
Trace Pydantic AI agent runs and typed tool calls.
LiteLLM
One integration for every model LiteLLM routes to.
OpenAI
Trace the OpenAI SDK directly in TypeScript and Python.
Langfuse
Keep Langfuse and send the same spans to Laminar too.
All integrations
Browse every provider, framework, coding agent, and browser integration Laminar supports.