Prediction evidence and peer frames
Behavioral signals say how surprising an entity's recent behavior is. Two options make them explainable and comparable:
- Prediction evidence attaches, to every scored state, the events that
drove the surprise: the top transitions (which event was expected and
which one was observed) and the top attribute values (a never-seen port,
an unusual payment method), each with its own calibrated
surprisal_percentile. - An attribute peer frame calibrates
behavior_surpriseagainst entities that share the value of one contracted categorical attribute (for example, the payment method of their orders) instead of the whole population. Peers with too little test-split support fall back to the population (frame: count_decile_fallback).
{
"signals": {
"behavior_surprise": 0.97,
"frame": "peer:order.placed.payment_method",
"evidence": {
"transitions": [
{
"event_id": "evt_01j9…",
"event_type": "order.paid",
"expected_mass": 0.71,
"observed_type": "order.refunded",
"nll": 4.2,
"surprisal_percentile": 0.99
}
],
"attributes": [
{
"event_id": "evt_01j9…",
"attr_key": "payment_method",
"nll": 6.1,
"surprisal_percentile": 0.98
}
]
}
}
}
Both options are computed at evaluation time (the calibration artifact gains per-transition, per-attribute and per-peer references), so you enable them by evaluating the model with them, then bundling that evaluation.
Enable them
-
Start a signals evaluation of the model:
curl -X POST "$TESSERA_API_BASE/models/$MODEL_ID/signals-evaluations" -H "authorization: Bearer $TESSERA_API_KEY" -H "content-type: application/json" \-d '{"evidence": {"enabled": true}, "peer_frame": {"kind": "attribute", "event_type": "order.placed", "attribute": "payment_method"}}'At least one option is required.
evidence.top_k(1–8, default 8) bounds the transitions and attributes kept per state. The peer attribute must be a contracted categorical feature of an included event type; anything else is400 invalid_argument. The answer is202with the evaluation (status: running) and itsreport_id. Send anIdempotency-Keyheader to make retries of the request safe. -
Poll it until it settles:
curl "$TESSERA_API_BASE/models/$MODEL_ID/signals-evaluations/$REPORT_ID" \-H "authorization: Bearer $TESSERA_API_KEY"statusisrunning,succeeded(withgates_passed) orfailedwith afailure_reason:failure_reasonMeaning job_failedThe evaluation Job failed on every retry. job_deadline_exceededThe Job ran past its 6-hour deadline. report_missingThe Job completed without recording its report. job_missingThe Job never appeared after the launch, or it finished and was cleaned up (finished Jobs are kept 24 hours) before the evaluation was read; a failed Job read within those 24 hours reads job_failed.launch_failedThe Job could not be created. timeoutThe evaluation outlived the evaluation timeout. Re-sending the identical request relaunches a failed evaluation.
-
Create the bundle with signals enabled, then activate it on a slot:
curl -X POST "$TESSERA_API_BASE/models/$MODEL_ID/bundles" -H "authorization: Bearer $TESSERA_API_KEY" \-H "content-type: application/json" -d '{"signals": {"enabled": true}}'The succeeded evaluation is now the model's evaluation of record (
GET /models/{model_id}/eval-reportserves it), so the bundle pins it and copies itssignals.config— includingevidenceandpeer_frame— intoruntime.signals.
What changes, and what does not
- Gates do not move. The signals evaluation is the model's default
evaluation (same seed, baselines and signals) plus these options. G1–G6,
the label metrics and the baselines are identical to the default
evaluation's; only the report's
signalsblock differs (itsconfigand the references in the calibration artifact). - The evaluation of record moves. When the signals evaluation succeeds, it becomes the model's evaluation of record. Bundles you created earlier are immutable: they keep their pinned report, gates and runtime, and a slot serving one keeps serving exactly what it served.
- One at a time. A model runs one signals evaluation at a time; a
second request while one runs is
400 failed_preconditionwith detailreason: evaluation_in_progressand the running evaluation'sreport_id. Re-sending the identical request returns the running evaluation, and makes an already succeeded one the evaluation of record again. - Access. Starting one needs a member role (or an API key with the
adminscope); reading one needsread. - Usage. Like the model's default evaluation, a signals evaluation is not metered separately.