Skip to content

Changelog

All notable changes to Curva. The format follows Keep a Changelog and versions follow Semantic Versioning. The HTTP API v1 contract is frozen: breaking API changes go to /v2.

First public release: the curva binary (CLI + HTTP server), the curva-ai Python and TypeScript SDKs and the n8n-nodes-curva n8n node, all free to use under the Curva Free License.

  • Core engine: Choice, Score and Noul questions answered through any OpenAI-compatible model, read from logprobs or from a constrained JSON reply (mode: auto | logprobs | verbal), with a label-mass guard, a rate limiter, retries and cost tracking. curva spike and curva bench measure accuracy, ECE and cost on the eval sets.
  • Server and Python SDK: curva serve with POST /v1/decide and GET /health, clear JSON errors, and an LRU decision cache (repeats in 0 ms at $0). Stdlib-only curva-ai SDK with retries and system_one / criteria= aliases.
  • Reliability: order debiasing (on by default), a none_of_these escape option, min_confidence abstain, model fallback chains, a daily budget (CURVA_DAILY_LIMIT) and injection hardening.
  • Calibration: temperature and Platt scaling per question and per project, from POST /v1/feedback, plus bias scaling (a per-answer offset that fixes a model favouring one answer) for Choice and Score; from 30 labels a calibrator is applied only when it clearly beats the raw probabilities on held-out folds in both log-loss and Brier score, moving cautiously with few labels. GET /v1/calibration reports held-out before/after numbers. SQLite store (--db), curva bench --save and curva report.
  • Power features: Multi questions, Council (blended models with agreement), Cascade (escalate only unsure answers), Race, few-shot examples, explain: true attribution, and curva map for large, resumable JSONL jobs.
  • Production: API keys (curva keys, stored hashed) with per-key rate limits and Retry-After on every 429; the server refuses public addresses without keys. Per-project provider keys encrypted with CURVA_MASTER_KEY, an audit log (GET /v1/audit, state hashed, never stored), pinned configs (curva-1.0.0, curva-1.1.0), privacy: "strict", Prometheus /metrics, graceful shutdown, and a distroless Dockerfile.
  • Any model, any provider: @<provider>/<model> ids for OpenAI, Anthropic, Gemini, Groq, Mistral, DeepSeek, Together, Fireworks, xAI and OpenRouter (on when their usual API key is set), local Ollama, LM Studio, vLLM and llama.cpp, and any OpenAI-compatible endpoint (CURVA_PROVIDER_<NAME>_URL). OpenRouter is optional.
  • Own fast model: curva export turns decisions and feedback into fine-tuning data in Curva’s own prompt format; a guide covers fine-tuning and serving a small model.
  • Cache-friendly prompts: pinned config curva-1.2.0 puts the questions before the state, so provider prompt caches and local prefix caches reuse the repeating part.
  • Pro features: conditional questions (when with the rule operators; skipped answers cost nothing), a drift monitor (GET /v1/drift), shadow mode (curva shadow), Curva Tune (curva tune), seven recipe packs (curva recipe: support triage, content moderation, lead qualification, phishing check, LLM output QA, RAG check, RAG rerank), and an MCP server (curva mcp) for AI agents.
  • SDKs: a TypeScript/JavaScript SDK (curva-ai on npm), and in Python an async client (AsyncCurva, decide_many), typed error classes, request ids and level names.
  • Operations: structured request logs (CURVA_LOG=json, CURVA_LOG_LEVEL) with an x-request-id on every response.
  • Docs: a documentation website (MkDocs), a public benchmark page, and a contributor CLA.
  • Packaging: pip install curva-ai ships the curva binary inside platform wheels, and curva.local() starts it on a free localhost port and stops it at exit.
  • Scale and speed: Choice takes up to 255 options (over 20, answered in verbal mode with the top 5 labels), race returns the first valid answer of several models, and a compatible POST /v1/systemone route with criteria requests, plus GET /v1/models.
  • Workflows in one call: depends_on on any question runs a request as a graph, stage by stage (one model call per stage, at most 8), each dependent question seeing its dependencies’ answers; @key fields in when and rules branch on earlier answers. Per-question think: true reasons in its own concurrent call. Answers get stage. Python .depends() / think=, TypeScript dependsOn() / think.
  • Rules: answer a question from the state without a model call (rules: [{"if": ..., "answer": ...}]), with contains, starts_with, gt, gte, lt, lte and exists.
  • Extraction: text, number and integer questions return a typed value with a confidence.
  • Images: images on a request sends https or data: images to vision models.
  • Guaranteed accuracy: coverage returns a conformal prediction set that holds the true answer with the chosen probability, once a question has 30 labels.
  • debias: "auto": stops asking the reversed order once a model shows no position bias.
  • Dashboard and OpenAPI: GET /dashboard and GET /openapi.json.
  • n8n node (integrations/n8n-nodes-curva) and the TypeScript SDK.
  • RAG recipes: rag-check (needs retrieval, answerable, grounded, next step) and rag-rerank (passage relevance as a reranking score).
  • Z.ai (GLM) and Alibaba (Qwen) presets: ZAI_API_KEY, DASHSCOPE_API_KEY.
  • CURVA_PROVIDER_<NAME>_PRICE: input and output price per million tokens for providers that don’t report cost (fine-tuned or self-hosted models).
  • Zero-setup server: curva serve without --model picks a working default from whichever provider key is set, like the Python client.
  • Costs: cost_usd from the provider’s report, OpenAI and Anthropic list prices, or CURVA_PROVIDER_<NAME>_PRICE.
  • Batch parity: curva map, shadow, bench and tune run questions exactly like the API (stages, when, rules, think); bench --per-set and tune take label-balanced samples.
  • Hardening (pre-release audit): at most 64 model calls per request, 60 s provider timeouts, a 120 s request deadline and a 30 s shutdown grace, a hashed decision-cache key scoped to project, privacy and provider key, provider errors kept in the server log (never sent to callers), JSON 413s, a total size limit on question text, reserved control characters in question keys, a case-insensitive prompt fence, a salted audit hash, SQLite busy_timeout, and --locked Docker builds. The server’s provider endpoint variable is CURVA_PROVIDER_URL (the SDK keeps CURVA_BASE_URL for the Curva server).

© 2026 Tarkova Private Limited.