Skip to content
CurvaCurva

Typed decisions with calibrated probabilities, from any LLM.

You give Curva some data and typed questions. It returns typed answers with probabilities, and never free text.

Curva means “curve”: the calibration curve is what keeps its probabilities honest. Once calibrated on your data, when Curva says 90%, it is right about 90% of the time.

Curva is a small Rust server with Python and TypeScript SDKs. It works with any OpenRouter or OpenAI-compatible model, free ones included, using your own key. Curva is free to use and runs on your own servers.

Terminal window
pip install curva-ai
export OPENROUTER_API_KEY=sk-or-v1-... # any OpenRouter key; free models work
import curva
from curva import Choice, Score, Noul
client = curva.local() # starts a private server for this process
d = client.decide(
state={"ticket": "I was charged twice for order A-104. Please refund the duplicate!"},
questions={
"team": Choice("Which team should handle this?",
{"billing": "payments, refunds", "technical": "bugs", "sales": "pricing"}),
"frustration": Score("How frustrated is the customer?", ["calm", "annoyed", "angry"]),
"refund": Noul("The customer explicitly asks for a refund"),
},
)
print(d["team"].choice, d["team"].confidence) # billing 0.9999
print(d["frustration"].score) # 0.65 (expected level, 0 = calm)
print(d["refund"].noul) # 0.999 (P(yes))
What comes back
teamChoice
billing0.9999
frustrationScore
between calm and annoyed0.65
refundNoul
yes0.999

Every answer is one of the labels you declared, with a probability for each label. There is no reply text to parse.

  1. Make a first decisionInstall with pip and get typed answers in three lines. There is no server or config to set up.Getting started
  2. Run it for a teamOne binary with embedded SQLite. Docker, API keys, HTTPS, the audit log and Prometheus metrics.Self-hosting
  3. Call it from any stackThe full v1 HTTP contract, the Python and TypeScript SDKs, the CLI and the OpenAPI spec.HTTP API reference

How a Curva decision flows. Your app sends a state and typed questions. The server checks rules, then the cache, builds a prompt with the state fenced as data, asks the model with the options in both orders, reads the probabilities and calibrates them. Typed answers go back to your app, and feedback you send is stored and used to fit calibrators.

  1. Rules answer the cases you already know, with no model call. See Instant decisions with rules.
  2. The cache returns identical requests in about 0 ms at $0.
  3. The prompt wraps your state in a fenced block and tells the model it is data, not instructions.
  4. Both option orders are asked concurrently and averaged, which cancels position bias. See Debiasing, escape and abstain.
  5. Probabilities are read from logprobs when the model has them, and asked for otherwise.
  6. Calibration adjusts them once a question has 30 labels, whenever that makes them more accurate. See Probabilities and calibration.

Probabilities you can trust

Send the true answer whenever you learn it. From 30 labels per question, Curva calibrates the answers when that helps, so a 0.9 means right about 90% of the time on your data. Calibration →

Never free text

Every answer is a typed Choice, Score, Noul (yes/no) or Multi, mapped only onto the labels you declared and validated before it reaches you. Questions →

Any model

Any OpenRouter or OpenAI-compatible model, free or paid, with your own key. Curva reads probabilities from logprobs when the model has them, and asks for them otherwise.

Stable and consistent

Options are asked in both orders and averaged, which cancels position bias. An escape option means the model is never forced into a wrong pick. Trust →

Fast and cheap on repeats

Repeat decisions come from the cache in about 0 ms at $0. All questions for one state go in a single request.

More than one model

Blend models in a council, escalate only unsure answers in a cascade, or race models for the fastest valid answer. Multi-model →

Yours to run

API keys, an audit log that never stores your data, privacy: strict, Prometheus metrics and a small Docker image. Self-hosting →

  • Getting started: install, first decision, and a shared server.
  • Concepts: the four question types and what the probabilities mean.
  • HTTP API: the full v1 contract, for any language.
  • Benchmarks: what has been measured so far, with honest sample sizes.

Looking for Crowkis? Its documentation lives at crowkis.com/docs.

© 2026 Tarkova Private Limited.