Build checks

Trajectory & session grading

Grade the whole agent run, not one call. next

A call-level green says call #3 was well-formed — not that the multi-step agent reached its goal. Declare unit: trajectory (or session / step) on a traces route and EvalGlass groups every call sharing a trace_id into one aggregate and scores its shape. The verdict is informational and cannot gate. Built in the framework; not yet in the version the plugin installs.

The tagline to hold on to: grade the trajectory; an aggregate green is still not proof the agent succeeded. Whole-run grading widens what a Scorecard speaks for — it does not lower the bar for what counts as proof.

A call green is not a run pass

Every individual call can look fine while the run loops, mis-orders its tools, or never reaches the goal. A unit declares which slice a result speaks for. The default call scores one model call at a time; a richer unit grades the run as a whole:

unit:GradesRead it as
callOne model call (the default).A statement about that call only. Absent unit: is byte-identical to this.
stepCalls sharing a trace_id, grouped.Finer-grained inspection of a run’s moves.
trajectoryAll calls sharing a trace_id, as one aggregate.Did the whole ordered run behave?
sessionA whole session, grouped the same way.End-to-end behavior across a task.

Declare it on a traces route

The key is additive and fail-closed. Absent unit:call, so every existing config is unchanged; a present-but-bogus value is a setup error, not a silent fallback.

yaml

traces:
  - path: runs/agent.jsonl
    unit: trajectory        # group each trace_id into one aggregate run

Grading a trajectory wires the built-in trajectory_shape@1 aggregate over the run’s members — one of the six built-ins (see the metrics guide). It reports the fraction of members that produced a non-null output: a shape signal, never a claim the agent succeeded.

Egress is worst-of-members (fail-closed)

Collapsing N calls into one aggregate raises a question the call path never faced: if one member of the trace is forbidden from leaving the machine, is the aggregate? EvalGlass resolves it as the worst of its members — an aggregate is egress-OK iff every member is, so a single forbidden or unknown member blocks the whole trajectory. A forbidden trace can never leak into a replay or judge through an average.

Informational — it cannot gate

Traces carry no validated gold, so an aggregate run inherits proposed dataset status and resolves informational. An approved gating threshold over proposed trace data does not activate a gate — it stays informational, never a laundered pass. Below is one illustrative aggregate row:

json

{
  "unit_id": "trajectory:trace-42",
  "metric": "trajectory_shape",
  "point": 0.67,
  "verdict": "informational",
  "status_counts": { "scored": 1 }
}

Illustrative example, not a measured result. Two of three members produced output, so the shape is 0.67 — a description of the recorded run, not a pass and not proof the agent succeeded.

An empty trajectory is non_evaluable, never 0.0 If no member produced an output, there is no behavior to aggregate. Reporting 0/N = 0.0 would read as “0% complete quality” when the honest state is “no evidence”. trajectory_shape returns non_evaluable (output_all_null) instead — the same never-a-fabricated-zero rule the rest of the framework holds. A call-unit aggregate is non_evaluable too (not_aggregate), never a made-up value.
Built, not yet installed The unit: ladder and config-reachable whole-run grading are next: built in the framework, not yet in the version the plugin installs. The trajectory_shape@1 evaluator existing is not the same as the config-reachable whole-run grading shipping — this page describes the route once it lands, never today’s installed default.

Next steps