Skip to content

Projects and configs

A project is a calibration namespace. Feedback and calibrators are kept per project, so the same question can be calibrated separately for different data, customers or teams.

d = client.decide(state, questions, project="support")
client.feedback(d.id, "team", "billing")
client.calibration("team", project="support")

Requests without project use "default". The audit log is filtered by project too, and a project can carry its own provider key, so its model calls are billed to it (see Self-hosting).

A config freezes how a decision is made, so answers never change under you when Curva is upgraded. A pin fixes the prompt template and the default mode, debias setting and model.

Config Default model
curva-1.0.0 Ling 3.0 Flash (logprobs)
curva-1.1.0 Nemotron 3 Super (verbal)
curva-1.2.0 Nemotron 3 Super, questions before the state: the repeating part of the prompt comes first, so provider prompt caches and local prefix caches can reuse it. Becomes curva-latest once benchmarked
curva-latest The pin the operator chose with serve --latest-config (currently curva-1.1.0)
client.decide(state, questions, config="curva-1.0.0")

Fields set on the request (such as model or mode) still win over the pin. Every response and audit entry names the config it ran under, and GET /v1/models lists the available pins. Unknown config names get a 422.

model can be:

  • a model id, such as "nvidia/nemotron-3-super-120b-a12b:free";
  • a list tried in order until one answers (a fallback chain): if a model returns 429 or a server error, the next one takes over;
  • a multi-model plan: council, cascade or race.

Without one, the server’s --model (or the pinned config’s model) is used.

privacy: "strict" routes the model call only to providers that neither store nor train on your prompts (provider.data_collection: "deny" on OpenRouter). The default is "standard".

© 2026 Tarkova Private Limited.