# Laminar (lmnr-ai/lmnr): self-hosted agent observability with tracing, signals and evals

> Laminar is an Apache-2.0 observability platform for AI agents, written mostly in TypeScript with a Rust core. It bundles OpenTelemetry tracing, plain-English behavioural signals, an eval CLI and a SQL-queryable dashboard builder, and it self-hosts through Docker Compose.

**lmnr-ai/lmnr** — Laminar - open-source observability platform purpose-built for AI agents. YC S24.

- Repository: https://github.com/lmnr-ai/lmnr
- Website: https://laminar.sh
- Stars: 3,291 · Forks: 241
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/lmnr-ai-lmnr

## What Laminar solves and who it is for

Agent failures rarely look like a stack trace. A loop that never terminates, a tool call that returns an empty payload, a prompt that silently drifts after a model swap: none of these raise an exception, and none of them show up in a request-latency dashboard. Laminar is aimed at that gap. The README describes it as an open-source observability platform purpose-built for AI agents, and the feature list splits into tracing, signals, evals, dashboards, datasets and annotation.

The intended user is a team running agents in production or in CI, with enough infrastructure appetite to run ClickHouse, Postgres, Quickwit and an application server. The repository is TypeScript-first, with Rust components and a pii-redactor directory at the top level. If your agents are prototypes on a laptop, the managed platform at laminar.sh is the path the README recommends; self-hosting exists for people who want the data to stay on their own machines.

## How tracing, signals and evals fit together

The tracing layer is OpenTelemetry-native. The README claims one line of code is enough to instrument Vercel AI SDK, Browser Use, Stagehand, LangChain, OpenAI, Anthropic and Gemini, and the exporter for tracing data is gRPC. Spans land in ClickHouse, which the project says gives roughly 20x trace compression for ingestion and storage, and Quickwit backs the full-text search over span data.

Signals sit on top of that stream. You describe a behaviour in plain English, the README's example is "agent is stuck in a loop", and Laminar reads every agent run and pings Slack when the pattern appears. This is a different model from threshold alerting: the condition is expressed in language and evaluated by a model, not compiled into a numeric rule. That makes the alerting layer only as good as the runs it can see, and it means the optional LLM provider configuration is not optional if you want signals at all.

Evals are the third leg. The README calls the SDK and CLI "unopinionated, extensible", usable locally or in a CI/CD pipeline, with a UI for comparing results. Datasets and annotation feed that loop: the custom data rendering UI is where you label runs and turn them into eval sets. The pieces are designed to be used together, and the MCP and CLI access points let a coding agent query traces, spans, metrics and events with SQL, which is the most interesting design decision here. Instead of building a fixed query builder, the project exposes the store to an agent that can write its own queries.

## Installing Laminar with Docker Compose

The README's quickstart clones the repository and starts the lightweight stack. The Compose file is explicit that this version omits RabbitMQ and includes only the frontend, ClickHouse, Postgres and app-server, so it is a quickstart or lightweight-usage configuration rather than the production one.

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

After the containers start, the README says the UI is reachable at http://localhost:5667. Postgres is published on host port 5433 in the Compose file, and Quickwit exposes 7280 for its REST API and UI and 7281 for OTLP/gRPC. The SDK still needs to be pointed at the local server: the README says you must configure baseUrl and the correct ports, and links to the self-hosting guide for the exact values.

For a production deployment the README recommends either the managed platform or the full Compose file, which is a separate invocation:

```bash
docker compose -f docker-compose-full.yml up -d
```

One practical detail before you start: the Compose file reads POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB, CLICKHOUSE_USER and CLICKHOUSE_PASSWORD from the environment, and the repository ships a .env file at the root. The README does not spell out default credentials in the section shown, so check that file rather than guessing.

## Configuring an LLM provider for signals and AI features

Chat-with-trace, SQL-with-AI and the server-side AI workers all need a model provider, configured in the .env file at the repo root. The README lists four options. Gemini and OpenAI are the simple ones; the OpenAI path also accepts an OpenAI-compatible gateway such as LiteLLM, OpenRouter or vLLM through LLM_BASE_URL. Bedrock uses AWS credentials instead of LLM_API_KEY, and Azure AI Foundry has three API shapes selected by the provider value.

```bash
LLM_PROVIDER=openai
# LLM_BASE_URL=http://localhost:4000   # optional, for OpenAI-compatible gateways
LLM_API_KEY=your_openai_key
```

The LLM_MODEL_SMALL, LLM_MODEL_MEDIUM and LLM_MODEL_LARGE variables are optional; per-provider defaults apply when unset. LLM_DEFAULT_HEADERS_JSON is available for gateways that require static headers. The Azure case is the one that needs care: model ids are deployment names, so unless your deployments are named after the models you have to set the LLM_MODEL_* variables yourself. The README also notes that one Azure resource serves three API shapes, so pick azure_chat_completions, azure_responses or azure_anthropic to match your deployment.

## Upgrading a self-hosted install, and the ClickHouse TTL trap

The upgrade path is where the operational cost of this stack becomes visible. The ClickHouse configuration disables internal telemetry logs that the project considers useless for a single-node installation and keeps query and error logs for three days. Applying that change to an existing installation means recreating the ClickHouse container, and the README is explicit that the Compose file you pass with -f may differ from the default:

```bash
docker compose up -d --force-recreate clickhouse
```

Disabling a system log stops new writes but does not clear an existing table. To reclaim disk space while preserving table structure, the README suggests truncating the disabled log tables after ClickHouse restarts, via clickhouse-client with --multiquery. The README also warns that when ClickHouse applies the 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, and that you should inspect any suffixed tables before dropping them if you also want their historical data.

This is the honest picture: Laminar ships a real storage engine, and storage engines need maintenance. The README documents the ClickHouse side of that maintenance but does not document rollback for a failed upgrade, so plan a snapshot before you run the recreate command.

## Where Laminar is the wrong tool

The lightweight Compose file is not the production stack. It omits RabbitMQ, and the README recommends the managed platform or docker-compose-full.yml for production, which means anyone who follows only the quickstart and then points real traffic at it is running a configuration the project does not position as production-grade. The repository also carries several Compose variants, including docker-compose-local-build.yml, docker-compose-local-dev.yml and docker-compose-local-dev-full.yml, so the file you pick is a real decision rather than a default.

Signals depend on an LLM provider. If you self-host without configuring one, you lose chat-with-trace, SQL-with-AI and the server-side workers, and the plain-English alerting that is Laminar's most distinctive feature stops working. A team that wants alerts without an external model call should look elsewhere.

Finally, if your agents are simple request-response LLM calls, the trace volume will not justify a ClickHouse plus Quickwit deployment. The compression and full-text search matter when you have many spans per run and need to search them; a few hundred calls a day does not get there.

## How Laminar differs from Langfuse and Phoenix

Langfuse is the closest comparison in the LLM observability space: it also offers tracing, evals and self-hosting, and it is built around a Postgres-plus-ClickHouse storage model with an SDK that many frameworks already integrate. The difference in approach is the alerting layer. Langfuse's evaluation and scoring model is largely numeric and dataset-driven; Laminar's Signals let you write a condition in plain English and have the platform read every run for it. That is a bet on model-judged alerting, and it carries the failure modes of model-judged anything: false positives, false negatives and a dependency on the provider you configure.

Arize Phoenix takes a different route again, focusing on trace inspection and evaluation within notebooks and a local UI. If your workflow lives inside a notebook and you want to inspect spans interactively, Phoenix is closer to that shape than a full Compose stack with a dashboard builder. Laminar's SQL access through MCP and the CLI is aimed at a different habit: letting a coding agent query the trace store directly rather than clicking through a UI. Choose based on whether you want model-judged alerts and SQL access, or notebook-first inspection.

## Licence, maintenance and what to check before adopting

Laminar is Apache-2.0, which permits commercial use, modification and redistribution, with the usual requirements around notices and the absence of a trademark grant. That is a permissive licence and it removes the source-availability question for teams that cannot use copyleft. It does not answer the operational questions, and it is not legal advice: if you plan to redistribute a modified stack, read LICENSE.md in the repository rather than this summary.

The repository is not archived, and the last push was on 2026-09-10. Releases are frequent and small: v0.2.2 on 2026-08-25, v0.2.3 on 2026-08-30 and v0.2.4 on 2026-09-06. A 0.x version line means the surface can move, and the ClickHouse TTL change described in the README is a concrete example of an upgrade that requires manual container recreation and optional table truncation. Budget for that: every self-hosted upgrade is a Compose operation, not a package bump.

Before adopting, verify three things against your own deployment. First, the SDK configuration for baseUrl and ports, since the README points to the self-hosting guide rather than listing the values inline. Second, which Compose file your environment uses, because the upgrade commands in the README assume you pass the right -f flag. Third, whether you are willing to run an LLM provider for signals, since that determines whether the feature that distinguishes Laminar from a plain trace viewer is available to you at all.

## Conclusion

Adopt Laminar if your agents run in production and you need traces, behavioural alerts and eval runs in one place you control, and if you can operate ClickHouse, Postgres and Quickwit. Skip it if you only need a hosted trace viewer for prototypes, or if you cannot run the full Compose stack and do not want the managed platform. Verify first that your SDK version supports the baseUrl and port configuration the self-hosting guide describes, and confirm which Compose file your deployment actually uses before running any upgrade command.

## FAQ

### What does the Laminar company do?

Laminar builds an open-source observability platform for AI agents, covering tracing, signals, evals, dashboards and datasets. The repository is lmnr-ai/lmnr, licensed Apache-2.0, and the project offers both a managed platform at laminar.sh and a self-hosted Docker Compose stack.

### How do I install and run Laminar locally?

Clone the repository, change into it, and run docker compose up -d. The README states this starts the lightweight stack (frontend, ClickHouse, Postgres and app-server, without RabbitMQ) and that the UI is available at http://localhost:5667.

### Does Laminar need an LLM provider to work?

Tracing works without one, but the README states that frontend AI features such as chat-with-trace and SQL-with-AI, plus server-side AI workers, require an LLM provider configured in the .env file at the repo root. Signals, which read every agent run and notify Slack, depend on that same provider setup.

## Sources

- [License: Apache-2.0](https://github.com/lmnr-ai/lmnr/blob/main/LICENSE)
- [lmnr-ai/lmnr on GitHub](https://github.com/lmnr-ai/lmnr)
- [Project website](https://laminar.sh)
- [README](https://github.com/lmnr-ai/lmnr/blob/main/README.md)
- [Releases](https://github.com/lmnr-ai/lmnr/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lmnr-ai-lmnr
