The producing side, step by step
- Turn end. Your loop (or a framework adapter) calls
on_turn_endwith the session id and turn payload. This returns immediately — nothing on this path blocks your agent. - Admission gates. Cheap producer-side controls run first: a hard per-process eval budget, per-session turn sampling, and a per-session rate limit. A newer turn supersedes the session’s in-flight evaluation.
- Detached evaluation. A background task checks platform health (once, memoized), then runs one batched session evaluation under a global concurrency cap and polls it to completion. See Evaluation & detection.
- Trend detection. Every resolved score feeds a local dual-EWMA detector, so a slow decline is caught even when no absolute threshold is crossed.
- Validation cadence. Every handled report — healthy or not — feeds the candidate-rule validation engine: forward trials get their denominator, and a single-flight task evaluates open candidates. See Rule validation.
- Notice gate. Identical conditions are de-duplicated per session, recoveries are journaled, and a circuit breaker escalates notice storms to a single
needs_human. - Persistence. A surviving condition becomes a
DiagnosticNoticeinmailbox/pending/, a verbose dump undertraces/, a journal event — and, when capture is enabled, a replayable eval case.
The consuming side
harness.system_context() returns one block to prepend to your system prompt:
- The rendered rules — validated rules first, then candidates under a clearly-labeled “Provisional rules (under evaluation)” section. With retrieval on, only the rules relevant to the current situation render.
- The standing protocol — instructions to check the mailbox each turn and, for each pending notice: read → inspect traces → consult memory → record a rule → acknowledge.
- The banner — a count and max severity when notices are pending; nothing otherwise.
pandaprobe-harness-agent companion CLI.
The workspace on disk
Everything the harness knows lives under one directory — inspectable, greppable, and durable across process restarts:Journal event types
The journal is the harness’s cross-run memory. Every notable event is one JSON line:One healing cycle, end to end
A concrete run (this is exactly whatexamples/closed_loop_self_heal.py prints):
- Turn 1 repeats an identical payment call;
agent_reliabilityscores0.30→ notice posted, the session captured as a replayable failure case. - Turn 2: the agent pulls the notice, inspects the flagged trace, records “Never call the payment tool twice without verifying the transaction status” → a candidate rule.
- The harness replays the captured failure with the candidate in force; the replayed session scores
0.92→ the candidate is promoted (rule_promote, validatorreplay). - The validated rule re-enters the system context; subsequent turns score healthy (recovery).
- A regression run replays the corpus against the current rules: the old failure is
improved, the protected winunchanged— CLEAN.

