Model or dataset
lmnr-ai/lmnr avatar
lmnr-ai/lmnr

Laminar: self-hosted tracing, signals and evals for AI agents

Laminar - open-source observability platform purpose-built for AI agents. YC S24.

3,258 stars239 forksTypeScriptApache-2.0

At a glance

What is it?
Laminar is an Apache-2.0 observability platform for agent workloads, written in Rust with a TypeScript SDK layer. Its differentiator is Signals, which turns a plain-English description of bad agent behaviour into a Slack alert, but the self-hosted path has real operational weight in ClickHouse.
Who is it for?
Adopt Laminar if you are running multi-step agents with tool calls and you want one place for traces, datasets and eval runs, and you have someone who can own a ClickHouse-backed Compose deployment. Do not adopt it if you only need request-level latency and error tracking for a single LLM call: OpenTelemetry plus Grafana covers that with less to operate.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Laminar targets: agent runs are not request logs

A single agent turn can fan out into a dozen model calls, tool invocations, retrievals and retries. Standard application monitoring sees one HTTP request and one latency number. What you actually need to know is which step chose the wrong tool, where a loop started, and whether the final answer was any good. Laminar is built for that second question set, and the README frames the audience narrowly: teams shipping AI agents, not teams shipping a chatbot wrapper around one completion.

The feature list maps onto that audience. Tracing captures the run structure. Signals watches every run for a described behaviour. Evals and Datasets close the loop by turning interesting runs into test cases. The README's own example of a signal is "agent is stuck in a loop", which is the kind of failure that never shows up as a 500 and never shows up in a latency percentile.

If your product makes one model call per user action, this is more machinery than the problem deserves. The interesting parts of Laminar only pay off once a run has enough internal structure to be worth inspecting.

OpenTelemetry in, compressed columnar storage out

The tracing SDK is described as OpenTelemetry-native, and the README claims one line of code is enough to instrument Vercel AI SDK, Browser Use, Stagehand, LangChain, OpenAI, Anthropic and Gemini. That matters more than it sounds. Because the wire format is OTel, you are not adopting a proprietary agent format; you are pointing an existing exporter at a different backend.

On the storage side the README states the backend is written in Rust, that trace payloads are compressed roughly 20x for ingestion and storage, and that a gRPC exporter is available alongside the HTTP path. There is also a custom realtime engine for watching traces as they happen, and full-text search over span data. The repository topics list both rust and typescript, which lines up with a split architecture: a compiled ingestion and query core, and TypeScript packages for the SDK and eval tooling.

One thing the README does not spell out is the exact boundary between the Rust services and the TypeScript packages, or which services the lightweight Compose file starts versus the full one. If you are evaluating this for a security review, that gap matters and you will need to read the Compose files and the docs rather than the README.

Signals is the part with no obvious equivalent elsewhere. You describe a behaviour in plain English, and according to the README Laminar reads every agent run and notifies you in Slack when it occurs. That implies an LLM-based classifier running over incoming traces, which in turn implies a cost and a false-positive rate that the README does not quantify. Treat Signals as a triage aid, not a paging system, until you have measured its precision on your own traffic.

Getting a local stack running with docker compose

The documented quickstart is three commands. Clone the repository, change into it, and bring the stack up:

git clone https://github.com/lmnr-ai/lmnr cd lmnr docker compose up -d

The README says this starts a lightweight but full-featured version of the stack, reachable at http://localhost:5667. It also warns that you must configure the SDK with the correct baseUrl and ports, and links to a self-hosting guide for that step. That warning is worth taking literally: the default SDK configuration points at the managed platform, so a local stack without an explicit baseUrl will silently send nothing to your instance.

For anything beyond a quickstart, the README points at docker compose -f docker-compose-full.yml up -d, and states that the managed platform is the recommendation for production. That is an honest framing, and it tells you the lightweight Compose file is not a production topology.

LLM provider configuration is optional but gates several features. Frontend AI features (chat-with-trace, SQL-with-AI) and server-side AI workers need a provider set in a .env file at the repository root. Four options are documented: gemini, openai (including any OpenAI-compatible gateway such as LiteLLM, OpenRouter or vLLM via LLM_BASE_URL), bedrock using AWS credentials instead of an API key, and Azure AI Foundry with three selectable API shapes. LLM_MODEL_SMALL, LLM_MODEL_MEDIUM and LLM_MODEL_LARGE are optional and fall back to per-provider defaults. There is also LLM_DEFAULT_HEADERS_JSON for gateways requiring static headers.

The Azure option carries a detail worth reading twice: model ids are deployment names, so unless your deployments are named after the models you must set the LLM_MODEL_* variables yourself. That is a common source of a stack that starts cleanly and then fails only when someone opens the chat-with-trace panel.

Upgrades are not just a container restart

The README devotes real space to upgrading existing self-hosted installations, and the detail is a fair signal of the maintenance burden. The ClickHouse configuration disables internal telemetry logs that are not useful for a single-node install and keeps query and error logs for three days. Applying that change requires recreating the container:

docker compose up -d --force-recreate clickhouse

Disabling a system log stops new writes but does not clear an existing table, so the README provides a truncate script for roughly seventeen system tables (trace_log, text_log, part_log, metric_log, query_log relatives, zookeeper_log and others) to reclaim disk space while keeping the table structure. That is a manual, multi-statement operation against your observability database.

There is a second wrinkle. When ClickHouse applies a new TTL to an existing query_log or error_log, it may rename the previous table with a numeric suffix such as query_log_0. The README advises inspecting any suffixed tables before dropping them. In other words, an upgrade can leave orphaned historical tables that quietly hold disk. Plan for a person who understands ClickHouse to perform upgrades, or accept that your observability store will grow without bound.

The release cadence visible in the supplied material is roughly weekly (v0.2.2, v0.2.3, v0.2.4 across August and September 2026), and the version numbers are still in the 0.2.x range. Expect to read release notes before each upgrade rather than assuming a patch bump is inert.

Where Laminar is the wrong tool

The clearest failure mode is scope mismatch. If your system is a retrieval-augmented question answerer with one model call and one vector lookup, Laminar's tracing, signals, datasets and eval UI are all solving problems you do not have, and you are taking on a ClickHouse deployment to get them.

The second is operational. The production recommendation in the README is the managed platform or the full Compose file. The lightweight Compose file is explicitly described as good for a quickstart or lightweight usage. Teams that run the lightweight file in production because it was the first command in the README will hit the limits of a single-node ClickHouse configuration without much warning.

The third is provider lock-in on the AI-assisted features. Chat-with-trace, SQL-with-AI and the server-side AI workers all require an LLM provider to be configured. If your organisation forbids sending trace data to a third-party model API, those features are off the table unless you run an OpenAI-compatible gateway such as vLLM or LiteLLM internally. The README does document that path, but it is an extra component you now operate.

Finally, be sceptical of Signals until you measure it. The README does not state how signal evaluation is billed, how often it runs, or what its false-positive behaviour looks like. A plain-English condition like "agent is stuck in a loop" is easy to write and hard to evaluate precisely.

How this differs from Langfuse and from plain OpenTelemetry

The most direct comparison in this space is Langfuse, another open-source LLM observability platform. The architectural difference visible from the README is the storage and query core: Laminar is written in Rust and states roughly 20x trace compression with a gRPC exporter and a custom realtime engine. Langfuse's public description centres on a Postgres and ClickHouse stack with a Python and TypeScript SDK surface. If your constraint is ingestion volume per node, that difference is the one to test. If your constraint is the breadth of framework integrations and community tooling, the two projects make different trade-offs and you should compare their integration lists directly rather than trusting either README.

The comparison against plain OpenTelemetry plus a general backend is simpler and more useful. OTel gives you spans, a collector and a vendor-neutral export path. It does not give you datasets, an eval runner, or a UI for annotating runs. Laminar's eval story is a CLI and SDK for running evaluations locally or in CI, plus a UI for comparing results. If you already have a CI pipeline and you want eval results to gate merges, that CLI is the piece OTel cannot supply.

The honest framing is that Laminar is an OTel consumer with an opinionated layer on top. You can keep the OTel instrumentation and change the backend later, which lowers the cost of trying it.

Licence, maintenance and who should adopt it

Laminar is Apache-2.0, which permits commercial use, modification and redistribution, and includes an explicit patent grant. It does not carry the source-available restrictions that some observability vendors attach to their open core. This is a description of the licence text, not legal advice; if you plan to redistribute a modified version or embed it in a product, have counsel review the NOTICE and attribution requirements.

Maintenance cost is dominated by the data layer, not the application code. ClickHouse configuration changes, TTL application, and the possibility of suffixed orphan tables after an upgrade are the recurring work. The truncate script in the README is a one-time cleanup, but the pattern it represents (system tables you must manage by hand) will recur.

Adopt Laminar if you have multi-step agents, you want traces, datasets and eval runs in one place, and you have someone comfortable with ClickHouse. Do not adopt it if you need only request-level metrics, or if you cannot run an LLM provider for the AI-assisted features and those features are the reason you were interested.

Before you commit, verify three things against your own environment. Confirm the SDK baseUrl and port configuration against your self-hosted instance, because the default targets the managed platform. Confirm that your span volume fits the single-node ClickHouse configuration produced by the quickstart, since the README recommends the full Compose file or the managed platform for production. And confirm your provider appears among the documented .env options, remembering that Azure deployments require explicit LLM_MODEL_* values when deployment names differ from model names.

Editorial conclusion

Adopt Laminar if you are running multi-step agents with tool calls and you want one place for traces, datasets and eval runs, and you have someone who can own a ClickHouse-backed Compose deployment. Do not adopt it if you only need request-level latency and error tracking for a single LLM call: OpenTelemetry plus Grafana covers that with less to operate. Before committing, verify three things in your own environment: that the SDK's baseUrl and port settings match your self-hosted stack, that your existing span volume fits the single-node ClickHouse configuration the quickstart produces, and that your LLM provider is one of the four documented in the .env options, since the frontend AI features and server-side workers depend on it.

Official sources

  1. License: Apache-2.0
  2. lmnr-ai/lmnr on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes