session_id form a session - pass it to the tracer,
or let framework integrations set it:
When does a conversation get judged?
Conversations have no end event - the engine can’t know a user won’t come back. Session evaluation answers this the way trace/group-scoped online scoring tools converged on: judge once the session has been quiet. A background sweep (every 60s) finds sessions idle longer than the evaluator’sidle_seconds (default 120) and judges the full transcript. If the
conversation later resumes, the next sweep re-judges it automatically - a session whose latest
score is newer than its last activity is never judged twice.
Bounds that keep this safe to leave on:
- Only sessions with 2+ turns qualify - single-trace sessions are already covered by per-trace scoring, and judging them again at conversation prices would double the bill.
- Each sweep tick spends at most a budget of 5 judge calls (shared across all projects on the instance, round-robin) - the budget bounds calls, not sessions, so a session-scoped scorer group with N judge members consumes N units for one session. Anything left over is picked up next tick.
- The sweep looks back 24h for candidates by default.
AGENTX_SESSION_SWEEP_WINDOW_HOURSwidens that (values are bucketed: up to 24 means 24h, up to 168 means 7d, above that 30d) - useful after downtime, or for traffic that arrives in delayed batches. sample_rate(builder default 0.1) is a true per-conversation fraction: the keep-or-skip decision is hashed once per (conversation, scorer) and stays stable across sweep ticks, so a sampled-out conversation stays out permanently instead of being re-rolled every minute until it eventually gets judged.AGENTX_SESSION_SWEEP=falsedisables the sweep entirely.
When a session does not get scored
- A scorer that fails on a session (judge model breaking the schema, every group member deleted) backs off for about 10 minutes before that (session, scorer) pair is retried, so a few stuck sessions can’t starve the healthy ones out of the tick budget.
- A judge that returns no usable verdict (empty or unparseable, even after the automatic
retry) stores no score row - the session stays retryable on a later tick instead of
being marked fresh - and the failure is recorded as an
online_eval_judge_failureevent, excluded from ratings and calibration. - With multiple engine replicas sharing one database, one replica wins the sweep lease per tick and does the judging; the others skip. A crashed holder’s lease times out on its own.
The built-in: Session Baseline Judge
Every project ships with one built-in session evaluator: the Session Baseline Judge. Like every scorer it is created paused - switch it on from the Scorers page. It scores whole-conversation consistency - context retention, self-contradiction, goal drift, non-repetition - and points at the first span where the conversation broke. Its rubric is an ordinary judge-scorer rubric, so Tune judge improves it from calibration evidence like any other evaluator; the row itself can be paused but not deleted. Alongside the 0-10 score, every session judgment returns structured findings: up to six per-step citations, each with a short category tag, rendered as the judge rail in the session’s detail view with the cited turns flagged inline.Your own session criteria
Create a session-scoped evaluator exactly like a per-trace one - the only difference isscope="session":
alert_threshold raises a signal in the normal
triage queue, deduped like every other signal source, and pages the
agent’s webhook alert channels (the channels list on its monitor profile) - the same
fan-out a below-threshold trace verdict gets. Verdicts also appear on the session’s detail view and in the Session score
column of Observe → Sessions.
Need more than one opinion per conversation? A scorer group can be
session-scoped too (online: {"scope": "session", ...}): several judges, patterns, and code
scorers read the same transcript and blend into one 0-10 verdict on the same idle trigger,
with must-pass gates - e.g. an apology tripwire that zeroes the conversation’s score.
On demand from the SDK
The sweep is the automatic path; both checks also run on demand - the same judging, same score shape, and an explicit call ignores the evaluator’s paused state (a human asking for a score should get one):Closing the loop
A failing conversation is the best kind of regression test - multi-turn, real, and specific. Add to dataset from the session view converts the whole conversation into a dataset case (follow-up turns included, provenance kept), so the fix gets guarded by offline runs and CI gates. Simulated conversations from the Playground are recorded as real sessions too, so the same judging and the same loop apply to rehearsals before any real user is involved. The full runnable flow - weak prompt, scripted multi-turn session, per-turn and session-level judging, then prompt/tool improvement proposals from the evidence - isselfhost_demo/10_session_coherence_and_tool_improvement.py.
