A review is one call with one state and one or more questions. The state is any JSON value describing the situation. Each question is typed and names its own answer space in advance. The model scores every candidate answer independently and returns a probability distribution per question. Nothing is generated: there are no output tokens, and the answer can only be one of the candidates you supplied.
Because each candidate is scored on its own, a question that needs the options compared against each other ("which of these five vendors is cheapest") only works if the comparison is already present in the state.
Question types
Choice: pick one of N
Field
Type
Meaning
type
"choice"
Required in JSON; implicit in Python.
instructions
JSON value
The question. Usually a string; objects are serialized canonically.
criteria
object, 2+ keys
Option key to description. Keys are the labels returned; descriptions are what the model reads.
Choice("Which team should own this?", {"billing": "Payments and refunds", "technical": "Bugs and outages"})
{"type": "choice", "instructions": "Which team should own this?", "criteria": {"billing": "...", "technical": "..."}}
Score: place on an ordered rubric
Field
Type
Meaning
type
"score"
instructions
JSON value
The question.
criteria
array, 2+ items
Ordered levels, lowest first. Index 0 is the first level.
Score("How urgent is this?", ["routine", "time-sensitive", "emergency"])
{"type": "score", "instructions": "How urgent is this?", "criteria": ["routine", "time-sensitive", "emergency"]}
Noul: yes or no, with a probability
Field
Type
Meaning
type
"noul"
"binary" and "boolean" are accepted aliases.
instructions
JSON value
The statement or question to judge.
criteria
object, optional
Optional true and false descriptions. Defaults to "The statement is true." / "The statement is false."
Noul("Is a refund requested?")
Noul("Should the agent proceed?", {"true": "Proceed with the write", "false": "Stop and ask a human"})
{"type": "noul", "instructions": "Is a refund requested?"}
Shared context for every question in the call. Strings pass through; other values are serialized with sorted keys.
questions
object, 1+ keys
Your key to a Choice, Score, Noul, or the equivalent JSON object.
model
string
Echoed in the response. Reserved for routing between checkpoints.
Questions in one call are independent: reordering them or adding an unrelated question does not change another question's probabilities. This is checked in the evaluation suite.
Softmax over the candidates after temperature calibration. Sums to 1 per question.
score
Expected rubric index: the probability-weighted mean of the level indices. 1.62 means "between frustrated and very frustrated, closer to the latter".
legend
Index to level text, so the score is interpretable without the request.
noul
Calibrated probability that the statement is true.
confidence
Normalized entropy concentration in [0, 1]: 1 when all mass is on one option, 0 when uniform. Not a probability of being correct. See below.
usage.input_tokens
Tokens in the state plus each question's instructions, counted once.
usage.output_tokens
Always 0. Nothing is generated.
usage.candidate_token_evaluations
Total tokens scored across all candidate prompts. This is the actual compute cost of the call.
HTTP
The local server exposes the same contract. Body and response are the JSON shapes above.
Route
Meaning
POST /v1/review
Body: {"state": ..., "questions": {...}, "model": "openauditor"}. Returns the response object. Body limit 16 MiB.
GET /health
Returns {"status": "ok", "model": "openauditor"}.
curl -s localhost:8080/v1/review -H 'content-type: application/json' -d '{
"state": {"order_id": "A-1042", "amount": 1250, "customer_tier": "gold", "note": "duplicate charge, please refund"},
"questions": {
"action": {"type": "choice", "instructions": "What should happen next?", "criteria": {"refund": "Issue a refund", "escalate": "Escalate to finance", "close": "Close with no action"}},
"policy": {"type": "noul", "instructions": "Is this within the automatic refund policy?"},
"risk": {"type": "score", "instructions": "Fraud risk", "criteria": ["low", "medium", "high"]}
}}'
Any HTTP client works. In JavaScript: fetch("/v1/review", {method: "POST", headers: {"content-type": "application/json"}, body: JSON.stringify(request)}).
Confidence and calibration
Noul is calibrated. The training loss is a proper score (cross-entropy plus Brier), and a temperature per question type is fitted on a held-out calibration slice that never overlaps test data. On the distribution you trained on, a Noul of 0.83 is meant to be right about 83% of the time. The evidence report publishes reliability bins.
Choice and Score probabilities are calibrated the same way, but confidence is an entropy summary, not an accuracy estimate. Use the probabilities for thresholds; use confidence for sorting or display.
Calibration does not transfer. A new domain needs its own validation data to refit temperatures and choose thresholds. Do not act on a threshold chosen on someone else's data.
Limits
Limit
Value
Prompt length
512 tokens per candidate prompt for the public checkpoint (state + instructions + one candidate). Over-length prompts are rejected, never truncated. The curriculum recipe trains at 4,096.
Candidates per question
No hard cap. Each candidate is one forward pass; 255 candidates measured at about 8.5 s on Apple MPS and 0.4 s on an H100.
Questions per call
No hard cap. Cost is the sum of candidates across questions.
Request body (HTTP)
16 MiB.
Errors
The Python API raises ValueError; the HTTP server returns 422 with {"error": "..."}. Common causes:
Choice with fewer than two criteria, or a criteria value that is not an object.
Score with fewer than two levels, or a criteria value that is not a list.
Noul criteria with keys other than true and false.
Missing instructions, empty questions, or an unknown type.