Interface
The model reads a request and returns a response. An optional Decision History schema lets the application log decisions and outcomes. All three JSON Schemas ship in the release under schemas/.
Request
One state and one or more typed questions. calibrated applies the optional temperature profile; it is off by default. Use compact structured states for the tested inference path; the encoder processes up to 640 tokens.
{
"workflow": "invoice_processing",
"state": {
"invoice": {
"invoice_number": "INV-2041",
"amount_usd": 1200,
"po_amount_usd": 1000,
"status": "received",
"vendor": "Acme Supplies"
},
"purchase_order": {
"po_number": "PO-7781",
"amount_usd": 1000
}
},
"questions": {
"duplicate": {
"type": "noul",
"instructions": "Is this invoice a duplicate of one already paid?"
},
"disposition": {
"type": "choice",
"instructions": "What should happen to this invoice?",
"criteria": {
"approve": "Approve and pay.",
"hold": "Hold until the discrepancy is resolved.",
"manual_review": "Send to a person for review.",
"reject": "Reject the invoice."
}
},
"discrepancy_severity": {
"type": "score",
"instructions": "How severe is the discrepancy between invoice and purchase order?",
"criteria": [
"No discrepancy.",
"Minor.",
"Material.",
"Severe."
]
}
},
"calibrated": false
}Response
Every answer carries the full distribution, the confidence (largest probability) and one summary: the probability of true, the chosen option, or the expected level. These are the model's actual raw answers to the request.
{
"answers": {
"duplicate": {
"type": "noul",
"probabilities": {
"false": 0.986,
"true": 0.014
},
"confidence": 0.986,
"noul": 0.014
},
"disposition": {
"type": "choice",
"probabilities": {
"approve": 0.002,
"hold": 0.206,
"manual_review": 0.708,
"reject": 0.084
},
"confidence": 0.708,
"choice": "manual_review"
},
"discrepancy_severity": {
"type": "score",
"probabilities": {
"0": 0.043,
"1": 0.041,
"2": 0.118,
"3": 0.798
},
"confidence": 0.798,
"score": 2.672
}
}
}The 20 question schemas
Use one of the following workflow/question-ID pairs. For choice questions, supply a subset of that schema's trained option keys in any order; the runtime validates the schema before inference. All keys are listed in the public model configuration.
- action
- needs_review
- outcome
- risk
- urgency
- action
- category
- churn_risk
- needs_human
- urgency
- discrepancy_severity
- disposition
- duplicate
- matches_order
- urgency
- credential_compromise
- disposition
- severity
- true_positive
- urgency
Decision History
An append-only log of what was asked, what was answered and, later, what turned out to be right. It is the shape for auditing decisions, replaying them against a later model version, and measuring calibration in production. Each record names the model by the sha256 of its ensemble descriptor.
{
"schema_version": "primus-decision-history/1",
"recorded_at": "2026-09-22T10:15:30Z",
"model": {
"model_id": "primus-decision-0.1",
"version": "0.1.0",
"weights_sha256": "368f8eca1186cc8c68cc3bb320cf4fb22b26205b800f22fb8d2e1952b81e120f"
},
"request": {
"workflow": "invoice_processing",
"state_sha256": "…",
"questions": {
"duplicate": {
"type": "noul"
}
}
},
"decisions": [
{
"qid": "duplicate",
"option_keys": [
"false",
"true"
],
"probabilities": [
0.986,
0.014
],
"chosen": "false"
}
],
"outcomes": [
{
"qid": "duplicate",
"gold_label": "false",
"source": "human"
}
]
}Python and the bridge
from primus_decision.ensemble import Ensemble
from primus_decision.predict import request_to_case, answers_from_predictions
model = Ensemble.load("model")
case = request_to_case(state, questions, workflow="invoice_processing")
decisions, predictions = model.predict_cases([case]) # raw probabilities
answers = answers_from_predictions(decisions, predictions) # the response shapeThe release is a folder, not an installed package: save your script in the downloaded primus-decision-0.1 folder and run it there, or add that folder to sys.path and call Ensemble.load("<folder>/model").
python -X utf8 -m primus_decision.serve model-X utf8 keeps the bridge running if a request line is not valid UTF-8: that line gets an error reply instead of stopping the bridge.
Full specification: INTERFACE.md and schemas/ in the release. Download
The life of a decision
A Decision History record follows a decision from its input state to the observed outcome. The application writes these records and retains the original state where replay is needed; a hash identifies that state. The format supports auditing, version comparisons and calibration on application traffic, separately from the model's per-request inference.
- StateWhat the system knew when it asked, recorded by its sha256.
- DecisionThe typed question, the full probability distribution over its answers, and the most likely answer.
- OutcomeThe correct answer and where it came from, recorded later.
- Audit and calibrationReplay against a new model version; measure calibration in production.