自托管后需在 SDK 中正确配置 baseUrl 和端口,UI 默认在 http://localhost:5667;前端 AI 功能(chat-with-trace、SQL-with-AI)需在 .env 中额外配置 LLM provider;自托管默认收集匿名遥测,需设 LAMINAR_TELEMETRY_DISABLED=true 关闭
lmnr
lmnr-aiApache-2.0活跃维护专为 AI Agent 打造的开源可观测性平台,提供链路追踪、评估和数据分析,帮开发者定位 Agent 运行中的问题并持续优化效果。
Laminar - open-source observability platform purpose-built for AI agents. YC S24.
git clone https://github.com/lmnr-ai/lmnr
cd lmnr
docker compose up -dREADME 未说明具体硬件要求;自托管通过 docker compose 启动整套服务,未提及 GPU 或显存需求。
面向 AI Agent 的开源可观测平台,用一行代码接入追踪、信号告警与评测
专为 AI Agent 打造的开源可观测性平台,提供链路追踪、评估和数据分析,帮开发者定位 Agent 运行中的问题并持续优化效果。
核心能力
- 一行代码自动追踪 Vercel AI SDK、LangChain、OpenAI 等调用
- 用自然语言描述 Agent 异常行为,命中后推送 Slack 告警
- 提供可扩展的评测 SDK 与 CLI,支持本地或 CI/CD 运行
- 支持用 SQL 查询 trace、span、指标与事件,并可接入编码 Agent
- Rust 实现,20x trace 压缩与实时 trace 查看引擎
容易踩的坑
- v0.3.4最新正式版2026-11-10 · 2026-11-10 08:54 UTC
What's Changed
- LAM-2433: CLI alert writes via Next.js, alert reads via SQL by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2629
- LAM-2433: dashboards CLI; dashboard writes and chart checks move from app-server to Next.js by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2641
- feat: EE license keys and 30-day trial UI, usage telemetry domains (LAM-2415) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2644
- feat: Laminar Enterprise License (ELv2) policy page + privacy heartbeat wording (LAM-2415) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2645
- feat(agent): run the Laminar Agent on Pi Durable (LAM-2466) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2651
- feat: bump memory by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2654
- feat(agent): store project_id on agent_records and agent_document_revisions by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2655
- LAM-2374: Slack and in-app signal reports use the email report format by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2601
- fix(agent-versioning): mask ids in prompt lines by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2602
- feat(auth): Okta SSO with SCIM-managed workspace membership by @skull8888888 in https://github.com/lmnr-ai/lmnr/pull/2656
- feat(db): mirror agent repo sandbox tables (0126) by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2657
- chore(notifications): "Clusters" section cleanup + colored up/down markers in Slack reports by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2658
- chore(app-server): remove dead LLM streaming and Slack thread code by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2659
- LAM-2474: align sidebar bottom cards with main content by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2660
- fix(email): neutral gray for signal report % change (LAM-2468) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2652
- LAM-2462: trial usage-exhausted email + trial-ended email by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2646
- fix: advertise mcp trace id as a string with regex instead of uuid by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2667
- fix(email): signal event email link chips + severity kicker (OSS port) by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2668
- feat(frontend): unified API error interface — apiHandler, ApiError, internalApiHandler (LAM-2456) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2642
- write trace tags from the API to trace tags, not span tags by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2672
- LAM-2460: audit log storage and write path (1/4) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2661
- LAM-2460: frontend audit wrappers, security events and audit log page (2/4) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2662
- LAM-2460: audit every mutating route and trace reads (3/4) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2663
- LAM-2460: audit SQL queries, the /v1 API, CLI and MCP (4/4) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2664
- feat(notifications): color the Slack report's up/down markers by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2675
- feat(signals): move signal_events to ReplacingMergeTree (LAM-2490) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2674
- fix(audit): don't crash audited routes without dynamic segments by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2677
- lower signal events index granularity by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2678
- fix(audit): never let audit recording break or delay the response by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2679
- LAM-24
- v0.3.32026-11-02 · 2026-11-02 10:30 UTC
查看更新说明
What's Changed
- Drop first tag from blog post header line by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2561
- fix(span-view): render overview input and output in their own formats (LAM-2372) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2562
- feat(dashboards): multiple dashboards per project (LAM-2292) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2426
- Say data access instead of retention in welcome and trial-ending emails by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2558
- Rebuild agent versioning (checkpoints) on top of system-prompt versioning by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2565
- feat(blog): Signals launch-post components with inline cloud trace embeds by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2555
- fix(blog): scroll cost chart sideways on narrow screens by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2567
- fix(trace-view): keep span selection made via span reference links by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2569
- feat(onboarding): drop the plan step, start the Starter trial automatically by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2568
- copy(trial): explain the trial in the sidebar popover by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2571
- feat(blog): compact timeline in embedded trace views by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2572
- feat(signals): public scaffolding for the backfill dispatcher (LAM-2375) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2570
- fix migration to signal versions in place, add lost constraints by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2574
- fix: padding by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2576
- Side-by-side diff dialog for agent versions by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2575
- bump clickhouse-migrations from 1.1.4 to 1.5.0 by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2577
- Normalize tool definitions for agent version identity by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2578
- checkpoints off by default by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2581
- Show agent version tool changes per tool by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2580
- feat: pg engine db in clickhouse pointing to pg by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2441
- Drop redundant severity row and intro line from signal alert email by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2584
- feat(theme): add light theme and theme-aware UI by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2582
- fix(theme): use next-themes so the saved theme applies before first paint by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2585
- fix(theme): polish light-theme surfaces in trace, session, and debugger views by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2586
- feat(checkpoints): string versioning for tool definitions (LAM-2379) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2583
- ci: pin GHCR image release to this repo and tagged commit (LAM-2384) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2588
- LAM-2386: clear membership caches on join; share one 7-day cache between web and CLI by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2590
- feat: cluster details named tuple by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2589
- feat: swap project delete in workspace delete by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2594
- LAM-2389: Agent versioning rebuild by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2592
- LAM-2369: Let workspaces exclude projects from signal reports by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2564
- chore: remove legacy checkpoints agent versioning pipeline by @laminar-coding-agent[bot] in https://gith
- v0.3.22026-10-16 · 2026-10-16 15:30 UTC
查看更新说明
What's Changed
- Fix signal events horizontal scrolling by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2539
- feat: shorten signals step by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2529
- fix: preserve newlines in signal alert emails by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2546
- fix: send onboarding welcome email once across tabs by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2547
- Simplify workspace invitation email styling by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2549
- Remove email banner background image, preserve banners by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2550
- feat(landing): animated grid loop hero and pattern grid footer by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2551
- feat: shared scaffolding for the Cloud signals gateway (LAM-2365) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2552
- feat: starter free trial by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2548
- feat: fix types by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2557
- Pass the telemetry opt-out into self-hosted Compose frontends by @DivyamTalwar in https://github.com/lmnr-ai/lmnr/pull/2438
- LAM-2366: throttle signal-event alert notifications per alert by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2554
- fix(docker): Quickwit healthcheck without curl by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2559
New Contributors
- @DivyamTalwar made their first contribution in https://github.com/lmnr-ai/lmnr/pull/2438
Full Changelog: https://github.com/lmnr-ai/lmnr/compare/v0.3.1...v0.3.2
- v0.3.12026-10-13 · 2026-10-13 08:18 UTC
查看更新说明
What's Changed
- feat: opencode format by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2534
- fix(LAM-2357): persist full column visibility in saved views by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2526
- fix: log clearer warning on consumers with older qw (primarily non docker) by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2535
- feat(notifications): SIGNAL_EMPTY_TRACE email via a Resend template (LAM-2359) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2527
- Bumps dependencies from dependabot reports by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2536
- copy quickwit index definitions to dockerfile by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2537
Full Changelog: https://github.com/lmnr-ai/lmnr/compare/v0.3.0...v0.3.1
- v0.3.02026-10-11 · 2026-10-11 22:01 UTC
查看更新说明
Breaking changes
The primary breaking changes are:
- Default Docker compose files now include Valkey
- Quickwit is now bumped to 0.9. ⚠️ Migration of the postgres schema is irreversible. If you wish to rollback, make a backup ⚠️ For more info see #2528 . See also: https://quickwit.io/docs/main-branch/operating/upgrades#migration-from-08-to-09
- Quickwit now force commits on every doc batch write. This behaviour matches releases < 0.2.5. There are now ways to opt-out / configure. For more info see #2528
- RMCP is bumped to version 3.x and now can communicate in newer MCP versions. This shouldn't break any behaviour, but list_tools responses slightly changed their shape. See more in #2488
What's Changed
- Revert "stop force committing on every ingested doc batch (#2352)" by @dinmukhamedm in https://github.com/lmnr-ai/lmnr/pull/2362
- Add dataset CRUD API by @kolbeyang in https://github.com/lmnr-ai/lmnr/pull/2340
- fix(spans): skip thinking blocks in heuristic preview extraction by @nuthalapativarun in https://github.com/lmnr-ai/lmnr/pull/1865
- LAM-2243: port signal/cluster ClickHouse schema to OSS and rewrite trace-view queries by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2347
- LAM-2248: llm_feature_routes replaces per-feature LLM provider env vars (OSS port of lmnr-private#1048) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2368
- LAM-2248: shared per-scope cache for LLM feature routes, 30-day default entries (OSS mirror) by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2372
- Improve LLM request handling and signal defaults by @cursor[bot] in https://github.com/lmnr-ai/lmnr/pull/2371
- seo: declare the docs sitemap in the root robots.txt by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2374
- feat: logos by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2375
- LAM-2250: show signals and clusters on shared traces by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2366
- strip cc header from system prompt for versioning by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2376
- LAM-2253: support OpenRouter Broadcast traces by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2369
- LAM-2248: one 5-minute TTL for every LLM feature route cache entry by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2373
- LAM-2264: carry AMQP message priority through publish, park and retry by @laminar-coding-agent[bot] in https://github.com/lmnr-ai/lmnr/pull/2381
- Document ClickHouse RowBinary validation constraints by @cursor[bot] in https://github.com/lmnr-ai/lmnr/pull/2385
- pii(1/5): pii-redactor returns canonical text + masks; app-server splices by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2357
- pii(2/5): piiMode setting (off | redact | dual) replaces removePii by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2358
- pii(3/5): ClickHouse mask columns, UDFs, spans_v1/traces_v1, trace_access_policy_dict by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2359
- pii(4/5): actor-derived AccessPolicy baked into spans_v1/traces_v1 reads by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2360
- pii(5/5): dual mode stores canonical text + masks, pii_checked, masked Quickwit indexing by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2361
- pii(6/6): PiiOutcome refactor — SpanVerdict, single index space, mode lookup fails the batch by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2384
- Skip realtime agent_input for dual-mode projects by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2389
- feat: shared trace cleanup by @olzhik11 in https://github.com/lmnr-ai/lmnr/pull/2391
- refactor(processor): split process_span_messages into stage functions by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pull/2390
- pii: API keys and CLI tokens read masked in dual mode by @Rainhunter13 in https://github.com/lmnr-ai/lmnr/pul
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。

Laminar
Laminar is an open-source observability platform purpose-built for AI agents.
- Tracing. Docs
- OpenTelemetry-native powerful tracing SDK - 1 line of code to automatically trace Vercel AI SDK, Browser Use, Stagehand, LangChain, OpenAI, Anthropic, Gemini, and more.
- Signals. Docs
- Describe any behavior of your agent that you want to track in plain English (e.g. "agent is stuck in a loop")
- Laminar reads every agent run and pings you in Slack when it happens.
- Evals. Docs
- Unopinionated, extensible SDK and CLI for running evals locally or in CI/CD pipeline.
- UI for visualizing evals and comparing results.
- MCP / CLI access for your coding agent
- Query traces, spans, metrics, and events with SQL
- Let your coding agent investigate and debug issues based on your traces
- Dashboards. Docs
- Powerful dashboard builder for traces, metrics, and events with support of custom SQL queries.
- Data annotation & Datasets. Docs
- Custom data rendering UI for fast data annotation and dataset creation for evals.
- Extremely high performance.
- Written in Rust 🦀
- 20x trace compression for efficient ingestion and storage. Read more about it here.
- Custom realtime engine for viewing traces as they happen.
- Ultra-fast full-text search over span data.
- gRPC exporter for tracing data.

Documentation
Check out the full documentation here laminar.sh/docs.
Getting started
The fastest and easiest way to get started is with our managed platform -> laminar.sh
Self-hosting with Docker compose
Laminar is very easy to self-host locally. For a quick start, clone the repo and start the services with docker compose:
git clone https://github.com/lmnr-ai/lmnr
cd lmnr
docker compose up -d
This will spin up a lightweight but full-featured version of the stack. This is good for a quickstart or for lightweight usage. You can access the UI at http://localhost:5667 in your browser.
You will also need to properly configure the SDK, with baseUrl and correct ports. See guide on self-hosting.
For production environment, we recommend using our managed platform or docker compose -f docker-compose-full.yml up -d.
Upgrading existing self-hosted installations
The ClickHouse configuration disables internal telemetry logs that are not useful
for a single-node installation and retains query and error logs for three days.
After pulling this change, recreate the ClickHouse container to apply the
configuration. The examples below use docker-compose.yml; pass -f with the
Compose file used by your deployment when it differs:
docker compose up -d --force-recreate clickhouse
Disabling a system log stops new writes but does not clear an existing table. To reclaim its disk space while preserving the table structure, truncate the disabled log tables after ClickHouse restarts:
docker compose exec -T clickhouse clickhouse-client --multiquery <<'SQL'
TRUNCATE TABLE IF EXISTS system.trace_log;
TRUNCATE TABLE IF EXISTS system.text_log;
TRUNCATE TABLE IF EXISTS system.part_log;
TRUNCATE TABLE IF EXISTS system.metric_log;
TRUNCATE TABLE IF EXISTS system.asynchronous_metric_log;
TRUNCATE TABLE IF EXISTS system.background_schedule_pool_log;
TRUNCATE TABLE IF EXISTS system.query_metric_log;
TRUNCATE TABLE IF EXISTS system.query_thread_log;
TRUNCATE TABLE IF EXISTS system.query_views_log;
TRUNCATE TABLE IF EXISTS system.session_log;
TRUNCATE TABLE IF EXISTS system.crash_log;
TRUNCATE TABLE IF EXISTS system.opentelemetry_span_log;
TRUNCATE TABLE IF EXISTS system.zookeeper_log;
TRUNCATE TABLE IF EXISTS system.blob_storage_log;
TRUNCATE TABLE IF EXISTS system.processors_profile_log;
TRUNCATE TABLE IF EXISTS system.asynchronous_insert_log;
SQL
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.
Inspect any suffixed tables before dropping them if you also want to reclaim
their historical data.
Configuring LLM provider (optional)
Frontend AI features (chat-with-trace, SQL-with-AI) and server-side AI workers require an LLM provider. Configure one in your .env file at the repo root.
Pick one of the following provider setups. LLM_MODEL_SMALL|MEDIUM|LARGE are optional — per-provider defaults apply when unset. LLM_DEFAULT_HEADERS_JSON is optional for any provider or gateway that requires static headers.
# Optional for any provider/gateway that requires static headers
# LLM_DEFAULT_HEADERS_JSON='{"X-Gateway-Tenant":"tenant"}'
# Option A: Gemini
LLM_PROVIDER=gemini
LLM_API_KEY=your_gemini_key
# Option B: OpenAI (or any OpenAI-compatible gateway such as LiteLLM, OpenRouter, vLLM)
LLM_PROVIDER=openai
# LLM_BASE_URL=http://localhost:4000 # optional, for OpenAI-compatible gateways
LLM_API_KEY=your_openai_key
# Option C: AWS Bedrock (Anthropic Claude). Uses AWS credentials instead of LLM_API_KEY.
LLM_PROVIDER=bedrock
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=us-east-1
# Option D: Azure AI Foundry. One resource serves three API shapes; pick the one
# matching your deployment. Model ids are deployment names, so set LLM_MODEL_*
# unless your deployments are named after the models.
# azure_chat_completions -> <resource>.services.ai.azure.com/openai/v1/chat/completions
# azure_responses -> <resource>.services.ai.azure.com/openai/v1/responses
# azure_anthropic -> <resource>.services.ai.azure.com/anthropic/v1/messages (Claude)
LLM_PROVIDER=azure_chat_completions
LLM_API_KEY=your_azure_key
AZURE_RESOURCE_ID=your_resource_name # or AZURE_BASE_URL for private endpoints
# AZURE_API_VERSION=preview # optional; only for resources that require it
Custom Postgres schema (optional)
By default Laminar uses the public schema. To target a different schema (e.g.
when deploying alongside other services in a shared Postgres instance), set the
same value for both the frontend and the app-server:
POSTGRES_SCHEMA=laminar
# Set to false if the schema is pre-provisioned or the DB role lacks CREATE.
# POSTGRES_CREATE_SCHEMA=true
The schema is applied as the connection search_path, so all tables, foreign
keys, and migrations target it. When a non-public schema is set, the frontend
also tracks migrations inside that schema (<schema>.__drizzle_migrations)
rather than the shared drizzle schema. Note that running Laminar alongside
another Drizzle-managed service in the same database may still require manual
intervention, since Drizzle's migration journal is versioned per-schema.
SQL access to Postgres entities (optional)
Some SQL tables are read live from Postgres: signals, evaluations and datasets,
plus the signal, evaluation and dataset names on signal_events, evaluation_datapoints
and dataset_datapoints.
ClickHouse reads them through a dedicated read-only role, which is off until you set
both of these in your .env:
CLICKHOUSE_POSTGRES_USER=clickhouse_ro
CLICKHOUSE_POSTGRES_PASSWORD=<choose a strong password>
On boot the frontend creates that role if absent and grants SELECT on only the columns it needs. Use
a dedicated role: the frontend refuses to use the app's own Postgres user or a
privileged role. Without them, those tables and columns return an error. If Postgres
is not the compose postgres service, also set CLICKHOUSE_POSTGRES_HOST /
CLICKHOUSE_POSTGRES_PORT as the ClickHouse server reaches it.
Externally managed Postgres role
The frontend checks whether CLICKHOUSE_POSTGRES_USER already exists. For an
existing dedicated role, it skips role creation, password changes, role settings,
and database CONNECT grants. It still applies schema USAGE, column-level
SELECT grants, and SELECT RLS policies after migrations, and configures
ClickHouse's pg database with the supplied credentials. No additional environment
variable is needed. If the role is absent, the frontend provisions it as before.
To manage the login through Terraform or a database administrator, provision it
before starting the frontend, with LOGIN, CONNECT on the target database,
statement_timeout (normally 15s), and CONNECTION LIMIT (normally 10). The
frontend does not apply CLICKHOUSE_POSTGRES_STATEMENT_TIMEOUT or
CLICKHOUSE_POSTGRES_CONNECTION_LIMIT to existing roles. Do not reuse the app's
login or a role with SUPERUSER, BYPASSRLS, or CREATEROLE. The frontend's
migration login must own, or inherit ownership of, the schema and exposed tables
to apply the schema/table grants and RLS policies.
Verify the credentials, required reads, and connectivity from the ClickHouse
server before enabling the feature, and test a ClickHouse restart in staging.
The PostgreSQL database engine remains a startup dependency of ClickHouse.
After rotating the external password, update CLICKHOUSE_POSTGRES_PASSWORD and
restart the frontend so it recreates pg with the new credentials. For existing
roles, changing this variable does not change the password in Postgres; rotate it
through the system that owns the login. Unset credentials still drop pg.
Anonymous usage telemetry
Self-hosted deployments collect anonymized usage telemetry. To opt out, set LAMINAR_TELEMETRY_DISABLED=true in your .env.
For shipped Docker Compose stacks, set the variable in the repository-root .env and recreate the frontend container. For a manually run frontend or Helm deployment, set it in the frontend process or pod environment.
Contributing
For running and building Laminar locally, or to learn more about docker compose files, follow the guide in Contributing.
TS quickstart
First, create a project and generate a project API key. Then,
npm add @lmnr-ai/lmnr
It will install Laminar TS SDK and all instrumentation packages (OpenAI, Anthropic, LangChain ...)
To start tracing LLM calls just add
import { Laminar } from '@lmnr-ai/lmnr';
Laminar.initialize({ projectApiKey: process.env.LMNR_PROJECT_API_KEY });
To trace inputs / outputs of functions use observe wrapper.
import { OpenAI } from 'openai';
import { observe } from '@lmnr-ai/lmnr';
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const poemWriter = observe({name: 'poemWriter'}, async (topic) => {
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: `write a poem about ${topic}` }],
});
return response.choices[0].message.content;
});
await poemWriter();
Python quickstart
First, create a project and generate a project API key. Then,
pip install --upgrade 'lmnr[all]'
It will install Laminar Python SDK and all instrumentation packages. See list of all instruments here
To start tracing LLM calls just add
from lmnr import Laminar
Laminar.initialize(project_api_key="<LMNR_PROJECT_API_KEY>")
To trace inputs / outputs of functions use @observe() decorator.
import os
from openai import OpenAI
from lmnr import observe, Laminar
Laminar.initialize(project_api_key="<LMNR_PROJECT_API_KEY>")
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
@observe() # annotate all functions you want to trace
def poem_writer(topic):
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "user", "content": f"write a poem about {topic}"},
],
)
poem = response.choices[0].message.content
return poem
if __name__ == "__main__":
print(poem_writer(topic="laminar flow"))
Client libraries
To learn more about instrumenting your code, check out our client libraries: