> ## Documentation Index
> Fetch the complete documentation index at: https://laminar.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Capture Agent Trajectories in Every Evaluation Trial

The trajectory is what your app did during a trial: its LLM calls and tool calls. Laminar shows it under the trial's trace, next to the verifier's score, so a failing [agent evaluation](https://laminar.sh/docs/agent-evaluations/introduction.md) case takes one click to explain.

The trace is only as rich as what the app reports: without a trajectory you see the reward but not the calls behind it. How you capture it depends on whether the app is instrumented with Laminar.

## Instrumented apps

**If the app is instrumented with Laminar** (it calls `Laminar.initialize()`), there's nothing to convert. During a run, the plugin sets `LMNR_TRAJECTORY_PATH=/logs/agent/trajectory.json` in the agent env. With it set, the SDK writes the app's spans to that file instead of sending them to Laminar, and the plugin attaches them to the trial's trace: every LLM call with tokens and cost, and tool calls as `TOOL` spans. The app needs no Laminar API key and no network access to Laminar. This works with the Python SDK (`lmnr` 0.8.4 and later); TypeScript SDK support is in progress. Make sure the app process actually receives `LMNR_TRAJECTORY_PATH`, especially if the start script uses `env -i`.

If the app isn't instrumented yet, adding Laminar is a small production change that also gives you production traces. See [Tracing](https://laminar.sh/docs/tracing/introduction.md).

## Apps without instrumentation

**If it isn't instrumented, reconstruct the trajectory from the app's own history.** Most products already store the conversation for their UI, for audit, or as agent memory: message tables, run and step tables, LangGraph checkpointers, JSONL transcripts. After the driver finishes, including on `failed` and `timeout` since partial trajectories are the most useful, run an exporter that reads this case's history and writes `/logs/agent/trajectory.json` in Harbor's [ATIF](https://docs.harborframework.com/agents/atif) format:

* Each message is a step with a sequential `step_id` (1, 2, 3…), a `source` (`system`, `user`, or `agent`), a `message`, and an ISO 8601 `timestamp`.
* `model_name`, `tool_calls`, and `metrics` are only allowed on `agent` steps. Tool results go in that step's `observation.results`, paired by `source_call_id`.
* History seeded from `case.json` gets `is_copied_context: true`, so it's shown but not mistaken for the agent's work.
* Leave `metrics` unset rather than estimating: stored history usually lacks token counts, costs, and the exact prompt of each call. Say where the trajectory came from in `notes`.

Don't write a reconstructed trajectory for an instrumented app, or the agent's steps show up twice.

## Next steps

> [card] [Write the agent and verifier](https://laminar.sh/docs/agent-evaluations/agent-and-verifier.md)
>
> Drive the entry point, wait for a terminal state, and grade the result.

> [card] [Read a failing trial](https://laminar.sh/docs/platform/viewing-traces.md)
>
> Open a low-scoring datapoint and read the app's run as a transcript.

> [card] [Track failures with Signals](https://laminar.sh/docs/signals/introduction.md)
>
> Detect a failure in production traces, then turn the flagged traces into cases.

> [card] [Troubleshooting](https://laminar.sh/docs/agent-evaluations/troubleshooting.md)
>
> Fixes for stale images, missing env vars, and empty traces.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.