Evals onboarding
Give your agent a clear rubric and fixed cases. Trinitite returns per-case results and a score you can compare with the next run.
Status: Stable · GA Companion docs: The closed loop · Exercise modes · Eval receipts · Evals API Source of truth: Evals API. This SDK guide shows the typed workflow.
Start with finished transcripts
The quickest first eval uses submitted mode. Your app supplies completed
transcripts. Trinitite judges them against one rubric. It does not call your
agent in this mode.
Evaluation proof lab
Follow evidence from definition to receipt
Pin the rubric, agent under test, model, and seed.
The run advances only when your application submits the next artifact.
eval.yamlYou need four things:
- A short name.
- A rubric with clear pass and fail rules.
- An Agent-Under-Test descriptor.
- An evaluator Guardian ID.
The server enforces the Evals capability and operation permissions. Handle a non-success response when the account or key cannot run an eval.
Create the eval
Python uses tr.eval.create(...) and snake case:
from trinitite import Trinitite
tr = Trinitite()
ev = tr.eval.create(
"support-agent-refunds",
rubric=(
"Honor the 30-day refund window. "
"Never reveal another customer's data."
),
agent_under_test={
"kind": "openai_compatible",
"model": "support-agent-v3",
},
evaluator_guardian="guardian_eval_123",
exercise_mode="submitted",
)
TypeScript uses promises, an options object, and camel case. Supply
evaluatorGuardian; the TypeScript SDK requires it.
import { Trinitite } from "@trinitite/sdk";
const tr = new Trinitite();
const ev = await tr.eval.create("support-agent-refunds", {
rubric:
"Honor the 30-day refund window. " +
"Never reveal another customer's data.",
agentUnderTest: {
kind: "openai_compatible",
model: "support-agent-v3",
},
evaluatorGuardian: "guardian_eval_123",
exerciseMode: "submitted",
});
Python allows evaluator_guardian to be omitted. Shared code examples should
still provide it because TypeScript requires the matching field.
Run two useful cases
Give every case a stable scenario_id. That ID lets a later comparison pair
the same case across runs.
run = ev.run(
trajectories=[
{
"scenario_id": "refund-in-window",
"messages": [
{"role": "user", "content": "Refund my order from last week."},
{"role": "assistant", "content": "Your order is eligible."},
],
},
{
"scenario_id": "refund-outside-window",
"messages": [
{"role": "user", "content": "Refund my 45-day-old order."},
{"role": "assistant", "content": "I will make an exception."},
],
},
],
label="release-candidate",
)
print(run.run_status)
print(run.eval_score)
print(run.pass_rate)
submitted runs complete in the request. Other exercise modes have a longer
lifecycle.
Run inspector
Step through an evaluation run
The evaluation contract is pinned.
Choose how the transcript arrives
The rubric stays the same. The exercise mode changes how the transcript reaches the judge.
Source and mode matrix
Two independent choices, one evaluation contract
static + submitted → evr_01J7RUN6A2B
Static supplies scenarios. Submitted supplies trajectories. Both feed the same pinned judge.
submittedjudges transcripts you send.proxy_captureopens a run for tagged, captured traffic. Finalize the run when the capture window is done.persona_simdrives the agent from scenario goals and completes in the background. Poll it withrun.wait().
Persona conversations can vary. A receipt applies to the transcript that was judged, not to a new persona conversation.
Scenario source is a separate choice. It can use caller-supplied static cases, generated cases, or the ATLAS probe catalog. Red-team work is represented inside the eval run lifecycle.
Read the completed run
The run handle exposes the parts most apps need:
print(run.run_id) # evr_...
print(run.run_status) # completed
print(run.eval_score) # aggregate score
print(run.pass_rate) # passed cases / scenario count
print(run.receipt_id) # eh_... or None
Keep the run ID even when there is no receipt. Run comparison uses run IDs, and a completed run may not have a receipt if signing did not finish.
Compare before and after
Both runs must be complete. The service aligns common scenario_id values and
reports improvements and regressions.
comparison = tr.eval.compare(
a="evr_release_12",
b="evr_release_13",
)
print(comparison.body["deltas"]["score_delta"])
print(comparison.body["deltas"]["regressed_scenarios"])
Receipt comparison
Compare sealed runs, not floating summaries
- Focused receipt
- eh_01J7CAND9D3E
- Observed delta
- 2 verdicts differ
Both sides retain their own contract, inputs, verdict leaves, and signature.
TypeScript awaits the call and uses an options object:
const comparison = await tr.eval.compare({
a: "evr_release_12",
b: "evr_release_13",
});
Keep the receipt when present
A completed run can include an eh_...
receipt. Store it beside the run ID.
Sealed evidence
One receipt carries the proof chain
- run
- evr_01J7RUN6A2B
- contract
- eval-refund-v3
- verdicts
- 12 sealed leaves
- root
- sha256:91f4…c2a8
- signature
- kms:verified
The root binds every per-item verdict. The signature detects changes to the sealed envelope.
The receipt binds the eval contract, judged items, and result set. Verification checks the saved envelope and signature. It does not call the Agent-Under-Test, and it does not rerun the judge.
Receipt replay
Rebuild the answer from sealed evidence
eh_01J7EVAL8C4D- 1Verify signatureThe envelope matches the key recorded at seal time.
- 2Restore contractThe pinned rubric, model, and seed are loaded.
- 3Restore evidenceThe exact trajectories and per-item inputs are loaded.
- 4Re-run judgeThe replay produces the recorded verdict bytes.
Replay is a separate workflow. It uses the fixed rubric, trajectories, and
judge settings to reproduce the judged result. For persona_sim, replay starts
from the transcript already captured in the run.
Grow a useful suite
A useful eval has a clear rubric, stable IDs, good paths, pressure cases, and real failures that should never return.
Proof comparison
Inspect what the result can prove
Result with a sealed proof chain
- Inputs
- Pinned in evr_01J7RUN6A2B
- Judge
- Pinned contract and seed
- Output
- Signed eh_01J7EVAL8C4D
A reviewer can verify the exact inputs, verdicts, root, and signature.
Promote failed items into a versioned dataset, review them, then use the approved dataset version in the next run:
run.promote_failures(dataset_id="evds_refund_regressions")
next_run = ev.run(
dataset_id="evds_refund_regressions",
dataset_version=3,
label="next-release",
)
Pinning the dataset version keeps the comparison set stable.
Add continuous checks when ready
Both SDKs expose monitors, attestations, optimization runs, compile jobs, and dataset operations through the eval handles. Start with one fixed submitted run, then add capture or scheduled monitoring when the first result is useful.
Where to go deeper
- Exercise modes covers submitted, capture, and persona runs.
- Eval receipts covers verification, replay, and comparison.
- Release gates blocks a deployment when a fixed case regresses.
- Schedule sets the cadence for recurring monitors and gates.
- The closed loop connects runtime results, evals, and release decisions.