Skip to main content
This quickstart gets a first agent evaluation suite running with lmnr-cli eval run. The fastest path is to let your coding agent build it with the Laminar skill. If you’d rather see every file, follow Get started manually below.

Set up with your coding agent

You need Docker, uv, and Node.js. From the repo root, link the directory to a Laminar project:
setup signs you in, writes LMNR_PROJECT_API_KEY to .env, and installs the Laminar agent skill, which knows the evals folder layout. In Claude Code, Cursor, or Codex, ask for the suite directly:
Set up agent evaluations for the refund flow with lmnr-cli eval run. Use our real Postgres and seed each case from a production trace.
The skill follows the same guidance as these docs: it finds the entry point, builds one image, seeds per-case data, writes the verifier, and runs the suite locally. Review what it wrote against Build a production harness, then open the run in Laminar.

Get started manually

This walkthrough evaluates a small support-ticket triage function: it sends a ticket to Claude and returns a category. You’ll package it into an image, add a case, and run it. The same layout scales to an app with a database and several services; Build a production harness covers that. The app is one module, instrumented with Laminar:
app/triage.py
with anthropic and lmnr in requirements.txt.
1

Install the prerequisites and link the project

You need Docker, uv, and Node.js for lmnr-cli. lmnr-cli eval run runs a pinned Harbor version with the Laminar plugin through uvx, so you don’t install Harbor yourself.From the repo root, link the directory to a Laminar project. Skip this if you already ran it above:
setup signs you in and writes LMNR_PROJECT_API_KEY to .env. See Laminar CLI for details.
2

Lay out the evals folder

Create this structure next to your code:
3

Describe the image

lmnr.yaml names the image and how to build it. Paths are relative to evals/, and context: .. makes the repo root the build context, so the image is built from your live source:
evals/lmnr.yaml
evals/image/Dockerfile
The driver imports the production function unchanged, runs it on this case’s data, and writes the outcome to /logs/agent/result.json:
evals/image/shared/run_case.py
4

Write the suite config and the agent

harbor.yaml is a Harbor job config. Secrets are ${VAR} placeholders, never literal values:
evals/support/harbor.yaml
The agent runs the driver inside the container. Everything it needs is already in the image, so install() does nothing. It passes self.model_name on so --model can override the model for a run:
evals/support/agent/agent.py
5

Add a case

The task points at the image by name and says where its environment/ files go:
evals/support/tasks/refund-double-charge/task.toml
evals/support/tasks/refund-double-charge/instruction.md
evals/support/tasks/refund-double-charge/environment/case.json
The reference answer and the verifier live in tests/, which Harbor uploads only when the verifier runs, so the app never sees them:
evals/support/tasks/refund-double-charge/tests/expected.json
evals/support/tasks/refund-double-charge/tests/test.sh
Make the verifier executable with chmod +x. A second case is a copy of this directory with a different case.json and expected.json.
6

Add secrets

Put ANTHROPIC_API_KEY in .env at the repo root, next to the LMNR_PROJECT_API_KEY that setup wrote. lmnr-cli fills every ${VAR} from your shell, then .env.local / .env, and stops before anything starts if one is missing.Keep secrets and Harbor’s job output out of git:
.gitignore
7

Run the evals

From the repo root:
lmnr-cli builds triage-evals with your Docker, runs every task in every suite, and prints a link to the results. The support suite becomes an evaluation group in your project, and this run is a new evaluation in it.
8

Read the results

Open the evaluation. Each trial is a datapoint with its reward as the score. Because the app calls Laminar.initialize(), the trial’s trace shows the Claude call under the agent span as a transcript, so a 0 takes one click to explain.Locally, Harbor’s raw output is in evals/support/jobs/<timestamp>/: each trial has agent/ (your result.json and logs) and verifier/ (reward.txt, test-stdout.txt).

Next steps

Run evals with lmnr-cli

Filter suites and tasks, run trials in Laminar sandboxes, and wire it into CI.

The evals folder

Reference for lmnr.yaml, harbor.yaml, task.toml, and secrets.

Build a production harness

Grow this single function into a full stack with services and seeded data.

Read a failing trial

Open a low-scoring datapoint and read the app’s run as a transcript.