Skip to main content

Entity baselines

An entity baseline model scores each entity from aggregate features of its recent history (counts, recencies and summaries of its events) with one calibrated model per label. It is a strong, simple fallback model to compare with the sequence models trained on the same dataset, and to serve when you choose it: for example when a sequence candidate failed promotion gate G1 on quality, or a training study found no competitive candidate. You can train one on any dataset build, evaluate it under the same gates, read what they found and decide whether to serve its scores.

The family is a distinct model with its own operations, report, bundle and ids. The released model, dataset and bundle responses are unchanged, and a family model is 404 on every released model operation.

StepOperationsWhat it does
CreatePOST /entity-baseline-models, GET, :cancel, :archivetrain one calibrated model per label on an existing sequence dataset build
EvaluationGET /entity-baseline-models/{model_id}/eval-reportgates G1–G6 on the dataset's test split, produced automatically after training
BundlesPOST /entity-baseline-models/{model_id}/bundles, GET, GET /entity-baseline-bundles/{bundle_id}the immutable, fingerprinted artifact a slot serves
ServePOST /slots/{slot_id}:activate, POST /slots/{slot}/refreshes, GET /slots/{slot}/entities/{entity_type}/{entity_id}/scoresactivate on a batch slot, refresh, read scores

Create a baseline model​

POST /entity-baseline-models with the dataset build to train on:

{
"dataset_id": "ds_01jb7m2v6q4c8d3x9w0n5t1k2r"
}
  • dataset_id names a succeeded sequence dataset build of the project, in any tokenizer format (v1, descriptions.v1 or semantic.v2). The model reuses its shards, its train-fit encoders, its targets and its splits (a time holdout included).
  • Provenance. Any succeeded build is admitted (the bounds below and an unservable candidate are still refused). Tessera records what it found on the dataset at creation as admitted_by, for context: a completed training study on its fingerprint, or else an evaluated or promoted sequence model on it with a recorded G1 failure (quality, the internal reference check or support). admitted_by is absent when there is neither. The console also shows any sequence model on the same dataset that passed G1, so you can compare before you choose.
  • Candidates (arms). Each label's model is one of a small set of servable fallback candidates. By default every candidate is fitted on the train split and the best validation score wins (selection.basis: validation). Name one per label with arms (a map from label id to candidate name, explicit; the report's family block records each label's chosen candidate, so you can pass the same name back), or pass study_id to take the candidate a study's gate holdout ranked first (study_strongest_on_gate_holdout; that estimate is optimistic by construction, so the validation-chosen candidate is the unbiased alternative). study_id names a completed training study of the project on the same dataset fingerprint, whatever its outcome; a running study, another fingerprint or a study whose winning evaluation report can no longer be read is 400 failed_precondition (study_not_applicable), and a missing or another project's study is 404 not_found.
  • Bounds. Training runs on the cpu-standard class and counts toward concurrent_training_runs. A dataset above the admission bound (100,000 train and validation rows) is refused with entity_baseline_too_large.
  • The request is idempotent: an identical request returns the existing model while it is training, evaluated or promoted.

Binary and multiclass outputs are calibrated on the validation split. A model whose training fails records a typed training.error; :cancel stops a training between two candidate fits and :archive retires a model that no slot serves.

Evaluation and gates​

The evaluation runs on the dataset's test split with the same masked targets a sequence model would have, and writes a report in the standard eval_report.json shape:

GateFor this family
G1beats the previous promoted entity baseline bundle covering the label minus 0.005, else the prevalence predictor
G2expected calibration error at most 0.05 on the served, calibrated scores
G3not_applicable (metrics.reason: no_entity_embedding)
G4input parity: held-out entities rebuilt from the event store and tokenized as the dataset build did must give identical feature rows and identical scores
G5the dataset's audit, as for sequence models: the censor clock and, on a build with a time holdout, the holdout windows and masks (G1 then records the holdout as time_and_entity)
G6the drift baseline for monitoring

G1 and G2 follow your promotion policy, as for every model: under the default warn policy a failure is shown with what it found and needs an acknowledgement with a reason before the model is bundled, and the acknowledgement is recorded in the bundle and the audit log; a strict policy blocks them. G4, G5 and G6 check that the measurement itself is sound and always block. The report's family block records each label's candidate, how it was chosen and the uncalibrated estimate beside the served one.

A baseline model created for a training study must reproduce the candidate the study ranked: on the same compute class its fitted model is byte-identical to the study report's, and otherwise its uncalibrated estimate must equal the report's. A model that does not reproduce it fails arm_reproduction_mismatch, and the study's fallback shows that error.

Bundles​

POST /entity-baseline-models/{model_id}/bundles once the model is evaluated (acknowledge_gates covers a failed G1 or G2 with a reason; a failed G4, G5 or G6 blocks):

{}

A bundle pins every artifact by fingerprint: one fitted model per label, the frozen feature spec, the encoders, the calibration and the report. A bundle of a descriptions.v1 or semantic.v2 build also pins the build's description registry or semantic inputs, so serving tokenizes exactly as the build did. The bundle reads return the bundle without these tokenizer inputs; GET /entity-baseline-bundles/{bundle_id}/tokenizer-inputs returns them, with the bundle fingerprint that covers them. To re-verify such a bundle, add every pins entry of that response to the bundle's pins, and insert each of its artifacts (without position) at its position in the bundle's artifacts, in ascending position order: the result is the stored manifest, and its fingerprint equals fingerprint. The manifest declares runtime.model_family: entity_baseline.

Activate, refresh and read scores​

Activate the bundle on a batch_only slot whose entity type matches the bundle's with POST /slots/{slot_id}:activate, as for any bundle. Realtime slots are refused until realtime scoring of this family ships, and allow_mismatch is refused. Then run a refresh with POST /slots/{slot}/refreshes, as for a sequence slot. The refresh scores each entity at its latest event from its recent window and writes its scores; a refreshed score equals the evaluated score of the same entity at the same event. Read one entity's scores with GET /slots/renewals/entities/account/acct-1042/scores:

{
"entity": {"type": "account", "id": "acct-1042"},
"slot": "renewals",
"model_family": "entity_baseline",
"scores": {"renewed": 0.81},
"freshness": {
"event_cursor": {"timestamp": "2026-10-14T09:12:00Z", "event_id": "evt-77"},
"computed_at": "2026-10-15T02:00:04.000000Z",
"bundle_id": "bnd_01jb7m2v6q4c8d3x9w0n5t1k2r",
"model_fingerprint": "4f1c…"
}
}

An entity without a row (or one that is suppressed or erased) is 404 no_state. The read passes the same purpose gate, suppression filter and metering as GET …/state.

What a baseline slot serves​

ServedRefused (400 model_family_not_supported)
GET …/scores, POST /slots/{slot}/scores:batch (no embedding key)GET …/state (its response requires an embedding)
GET /slots/{slot}/entities:top with by=score or by=deltaby=signal, markers, observation, evidence timeline
GET …/history, GET …/bands and the slot's band bindingstrajectories, feature views, segment rebuilds, similar jobs
POST /slots/{slot}/exports (scores only)warehouse exports and export schedules
destinations, the freshness monitor, alert evaluation of existing rulesnew alert rules, audiences built from a definition

Stored records (refreshes, exports, monitor points, alert episodes and the like) stay readable on a slot of any family. Switching a slot from a sequence bundle to a baseline bundle removes the embedding-based reads; the first refresh replaces every entity's row.