Switch to Curva in 5 minutes
This guide is for teams that already get structured answers from a model: another typed-decision or classification API, or a prompt that asks an LLM to “reply with one of: billing, technical, sales” and parses the text. Curva does the same job and adds the parts that make the answers safe to automate.
Map your concepts
Section titled “Map your concepts”| What you have today | In Curva |
|---|---|
| Pick one label from a list (single choice, classification) | Choice: option key → description; answer is choice + probabilities + confidence |
| A rating or ordered scale (1–5, low/medium/high) | Score: levels, lowest first; answer is the expected level + a probability per level |
| Yes/no, true/false, a flag | Noul: answer is noul = P(yes) |
| Tags, any subset of labels | Multi: each option gets its own probability; selected are those over the threshold |
| “Parse the model’s text and hope it’s valid” | Never needed: every answer is typed and validated |
| A confidence the model wrote in its reply | Probabilities read from the model’s token probabilities, then calibrated on your feedback |
See Questions and answers for every field.
If your client sends criteria
Section titled “If your client sends criteria”Many typed-decision clients send questions in a criteria shape. Curva accepts it as is at
POST /v1/systemone, an alias of /v1/decide:
{ "state": {"ticket": "I was charged twice for order A-104"}, "model": "curva-latest", "questions": { "team": {"type": "choice", "instructions": "Which team?", "criteria": {"billing": "payments, refunds", "technical": "bugs", "sales": null}}, "anger": {"type": "score", "instructions": "How frustrated?", "criteria": ["calm", "annoyed", "angry"]}, "refund": {"type": "noul", "instructions": "Asks for a refund", "criteria": {"true": "explicitly asks for money back", "false": "anything else"}} }}- Choice
criteria: key → description (text,nullor JSON). There is no escape option unless the question sets"escape": true, so answers match what your client expects. - Score
criteria: level descriptions, lowest first. Noulcriteriais optional. model:curva-latestor a pinnedcurva-x.y.zconfig; a name without a provider prefix means the server’s default model; anything else is a model id or a plan.- The response is the
/v1/decideresponse plususageand atypeon every answer. GET /v1/modelslists the config namesmodelaccepts.
The Python SDK has the same shape: client.system_one(...) with
Choice(..., criteria={...}), Score(..., criteria=[...]) and Noul(..., criteria={...})
(reference).
Change the base URL
Section titled “Change the base URL”Run Curva (Getting started or Self-hosting), create a key, and point your client at it:
curva serve # http://127.0.0.1:7777curva keys create --name my-app # prints curva_… once# before: https://<your current provider>/…export BASE_URL=http://127.0.0.1:7777curl -s $BASE_URL/v1/systemone -H "authorization: Bearer $CURVA_API_KEY" \ -H 'content-type: application/json' -d @request.jsonThat’s the whole switch for a criteria client. For a prompt you parse yourself, replace the
prompt with a /v1/decide call: the question list is your label list.
What you gain
Section titled “What you gain”- Calibration on your data. Send the true answer as feedback; from 30 labels per question, Curva calibrates when that helps, so a 0.9 means right about 90% of the time on your traffic.
- Debiasing. Options are asked in both orders and averaged, so an answer doesn’t depend on which label came first (details).
- Abstain. Set
min_confidenceand unsure answers come backabstain: true, for a person or a stronger model. - Audit. Every decision is logged with model, config, answers, cost and a salted hash of the state (never the state itself).
- Self-host. One binary and a SQLite file; your data stays on your machines.
- Any model. Any OpenRouter or OpenAI-compatible model, free ones included, blended with council, cascade or race, or your own fine-tuned model.
Before you switch all traffic
Section titled “Before you switch all traffic”Replay a day of logged traffic with shadow mode to see how often Curva agrees with your current system, and at what confidence it can take over.
Checklist
Section titled “Checklist”- Each question mapped to Choice, Score, Noul or Multi
- Curva running, API key created
- Base URL changed (
/v1/systemoneforcriteriaclients,/v1/decideotherwise) -
modelset (a pinned config for reproducible answers, or a model id) - Shadow run on logged traffic, agreement checked
- Decision ids stored, feedback flowing
-
min_confidenceset where a wrong answer is expensive

