Documentation/Guides/Evals & Monitoring

STEP 7 OF 10

Evals & Monitoring

Two separate pages cover "is this agent/workflow actually working": Evals (/evals) for offline quality measurement, and Monitoring (/monitoring) for live activity.

Evals

/evals has five tabs: Datasets, Runs, Improve, Playground, Annotation Queue.

An eval run dispatches each dataset item through the same real execution path as a manual run — agent_execution_service, through the actual data-plane runtime — not a bare LLM call. Every EvalItemResult links to a real AgentExecution you can open on /runs/{id} and read step by step; cost and latency come from that execution, not an estimate.

Datasets is where you author eval sets — cases don't have to come from a fixture file:

# Create a dataset, add cases by hand
curl -X POST https://your-control-plane-host/api/v1/evals/datasets \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Matter triage accuracy", "skill": "matter_triage"}'
curl -X POST https://your-control-plane-host/api/v1/evals/datasets/{dataset_id}/items \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"input_payload": {"content": "..."}, "expected_output": "...", "grading_rubric": {"method": "llm_judge"}}'

# Or draft cases from your own knowledge graph
curl -X POST https://your-control-plane-host/api/v1/evals/datasets/{dataset_id}/generate-from-kg \
  -H "Authorization: Bearer $TOKEN"

Generated cases land with source: generated, reviewed: false and are excluded from real eval runs until a human reviews them — POST /datasets/{dataset_id}/items/{item_id}/review. A run's pass rate is never inflated by cases nobody has actually checked.

A completed real run can also become a regression-test case directly:

curl -X POST "https://your-control-plane-host/api/v1/executions/{execution_id}/save-as-eval-case" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"dataset_id": "<dataset_id>"}'

Runs lists eval executions against a dataset, with pass rate and groundedness. The page computes regression detection client-side: if the latest run's pass rate drops 15 points or more below the trailing baseline (last 5 runs), it's flagged as a regression.

# Kick off a new eval run
curl -X POST https://your-control-plane-host/api/v1/evals/runs \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"dataset_id": "<dataset_id>", "agent_id": "<agent_id>"}'

# List / inspect runs
curl "https://your-control-plane-host/api/v1/evals/runs" -H "Authorization: Bearer $TOKEN"
curl "https://your-control-plane-host/api/v1/evals/runs/{run_id}" -H "Authorization: Bearer $TOKEN"

# Trend data for the pass-rate/groundedness charts
curl "https://your-control-plane-host/api/v1/evals/trends" -H "Authorization: Bearer $TOKEN"

Improve is prompt optimization scored against that same real-execution path — this is what used to be the standalone /optimization page (now a redirect here) — run it against an agent and a dataset, and a deployed improvement bumps that agent's spec_hash so the runtime reloads it.

Playground (POST /api/v1/evals/playground) is a one-off: run a single prompt against a chosen agent/model outside of a formal dataset, to sanity-check a change quickly.

Annotation Queue is where a human labels eval outputs the automated grader wasn't confident about:

curl "https://your-control-plane-host/api/v1/evals/annotation-queue" \
  -H "Authorization: Bearer $TOKEN"

curl -X POST https://your-control-plane-host/api/v1/evals/annotation-queue/{item_result_id}/label \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"label": "pass", "note": "Correct, grader missed the citation format."}'

Eval regressions are also checked automatically on a schedule — see the drift-sweep Celery beat task in app/tasks/eval_monitoring.py.

Monitoring

/monitoring has three tabs: Overview, Traces, Threads. Overview polls GET /api/v1/monitoring/overview every 10 seconds for a live fleet-wide view (tile per agent, eval health summary alongside it).

# Fleet-wide overview (polled every 10s in the UI)
curl "https://your-control-plane-host/api/v1/monitoring/overview" -H "Authorization: Bearer $TOKEN"

# One agent's monitoring detail
curl "https://your-control-plane-host/api/v1/monitoring/agents/{agent_id}" -H "Authorization: Bearer $TOKEN"
curl "https://your-control-plane-host/api/v1/monitoring/agents/{agent_id}/actions" -H "Authorization: Bearer $TOKEN"

# Traces -- individual execution traces (LLM calls, tool calls, timing)
curl "https://your-control-plane-host/api/v1/monitoring/traces" -H "Authorization: Bearer $TOKEN"
curl "https://your-control-plane-host/api/v1/monitoring/traces/{trace_id}" -H "Authorization: Bearer $TOKEN"

# Threads -- full conversations, grouped
curl "https://your-control-plane-host/api/v1/monitoring/threads" -H "Authorization: Bearer $TOKEN"
curl "https://your-control-plane-host/api/v1/monitoring/threads/{conversation_id}" -H "Authorization: Bearer $TOKEN"

Per-agent detail lives on that agent's own workspace at /agents/{id} — Run/Runs for execution history and a live timeline, Cost for spend, and the real per-run trace on /runs/{id}. There is no separate /agents/{id}/monitor route; that page's content (approval stats, chat) was folded into the Runs and Cost tabs once runs became a real, persisted AgentExecution record — see Step 8 — Runs & Boundaries.

What's next

Step 8 — Runs & Boundaries: the unified execution record behind every run, with a full step-by-step timeline and per-agent enforcement boundaries.