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 Tracevell skill. If you would 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 Tracevell project:
setup signs you in, writes LMNR_PROJECT_API_KEY to .env, and installs the Tracevell agent skill, which knows the evals folder layout. Then prompt your coding agent. For example:
Set up agent evaluations for the refund flow with lmnr-cli eval run. Use our real database and seed each case from a production trace.
If you don’t have production traces yet, describe in plain words what you want to evaluate. 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 Tracevell.

Get started manually

This walkthrough evaluates a support agent that handles billing tickets. It looks up a customer’s charges in a SQLite database and can refund one. Each case starts with its own copy of the database, and the verifier checks two things: whether the right refund is in the database, and whether the reply to the customer is any good. An LLM judge grades the reply. The complete project is examples/agent-evals in the lmnr-python repo. Clone it to follow along, or copy the files into your own repo as you go. The agent is a single module, app/support_agent.py. It runs an Anthropic tool loop over two tools, list_charges and refund_charge. It calls Laminar.initialize() and wraps the tools in observe, so each trial’s trace shows the model calls and the tool calls. Trimmed to the parts the harness relies on:
app/support_agent.py
The driver imports DB_PATH and handle_ticket, and the Harbor agent sets AGENT_MODEL. The app’s dependencies, anthropic and lmnr, are in the project’s pyproject.toml and uv.lock, which the image installs.
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 version of Harbor with the Tracevell plugin through uvx, so you don’t install Harbor yourself.From the repo root, link the directory to a Tracevell project. Skip this if you already ran it above:
setup signs you in and writes LMNR_PROJECT_API_KEY to .env. See Tracevell 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 says 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
The Dockerfile starts from uv’s official image, which already has uv and Python 3.14 on Debian trixie. It installs the locked dependencies first, so they stay cached when only the app code changes:
evals/image/Dockerfile
The driver creates this case’s database from seed.json, imports the production function unchanged, calls it with the ticket, 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. It refers to the API key as a ${VAR} placeholder that lmnr-cli fills in when the run starts, so the key itself does not end up in a file you commit:
evals/support/harbor.yaml
The Harbor agent runs the driver inside the container. Everything it needs is already in the image, so install() has nothing to do. It passes self.model_name on to the app, which lets --model override the model for a run:
evals/support/agent/agent.py
5

Add a case

The task points at the image by name. Harbor copies everything in the task’s environment/ folder into workdir (here /case) when the container starts:
evals/support/tasks/duplicate-charge/task.toml
The [verifier.env] block gives the verifier the key it needs to call the LLM judge.
evals/support/tasks/duplicate-charge/instruction.md
evals/support/tasks/duplicate-charge/environment/case.json
evals/support/tasks/duplicate-charge/environment/seed.json
The agent can read everything in environment/, so the reference answer must not go there. Put it in tests/, which Harbor only uploads when the verifier runs.
evals/support/tasks/duplicate-charge/tests/expected.json
The verifier first checks the database, which is the hard evidence of what the agent did. It then asks an LLM judge whether the reply is acceptable. It writes one reward per check, and each becomes its own score in Tracevell. If the agent run itself failed, both rewards are 0 and the judge is skipped:
evals/support/tasks/duplicate-charge/tests/test.sh
evals/support/tasks/duplicate-charge/tests/verify.py
Make test.sh executable with chmod +x.To add another case, copy the duplicate-charge directory, then change case.json and seed.json to describe a different ticket and account, and change expected.json to match. For example, a customer asking for a refund on a charge that should be declined expects "refund_count": 0.
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} placeholder from your shell first, then from .env.local and .env. If one is missing, it stops before anything starts.Keep secrets and Harbor’s job output out of git:
.gitignore
7

Run the evals

From the repo root:
lmnr-cli builds refund-agent-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 a refund score and a reply score. Because the app calls Laminar.initialize(), the trial’s trace shows the model calls and the list_charges / refund_charge tool calls 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.json and test-stdout.txt, which includes the judge’s reasoning).

Next steps

Run evals with lmnr-cli

Filter suites and tasks, run trials in Tracevell 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 module 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.