A live graph of a company's records: contacts, tickets, accounts, invoices and orders, linked to each other and to the systems they sync from. Every few seconds one record changes, the records its judgment reads light up, and it gets a new answer.

NEWStarter judgments for churn, triage and moderation v1

Run System One models on your live data

Vainona runs System One models like Jev across your data, and reruns them when it changes. We handle dependency tracking, drift detection and audit trails.

Start building

TypeScript and Python SDKs · Priced per judgment · Free quickstart namespace

01How it works

Ask a question about your records. Vainona keeps it answered.

You keep your records in sync and say what you want to know about them. Everything between a change to your data and an answer you can act on is a system of its own. Here is each one, on one account.

Animated walkthrough of the seven parts of the system, one at a time: the records you keep in sync; the question with its recipe, version and settings; change tracking, which decides what each write affects; the compiled context and its size class; the engine, batched, priced against a budget and probed for changes; the answer on the record with its freshness, provenance, queries and subscriptions; and over time, calibration from outcomes, the evaluation log and shadow runs for new versions.

outcomes from your writes
rules · labelling queue · implicit negatives
3 KB each, forever
every evaluation, with the context the engine saw

It learns, keeps everything, and changes safely. Outcomes arrive from writes you already make; a nightly fit is used only if it beats the raw numbers. Every evaluation is kept with its context. A new version is judged in shadow before you confirm it.

One account, one question. The same runs for every record in the namespace, every time something a recipe reads changes.

Start from a starter. Point it at your records, adjust the recipe.

Is this ticket urgent?

ticket_triage.urgencybool

subject, first message, latest 3 replies, the plan

Which team should take it?

ticket_triage.routingchoice

the same ticket, in the same engine request

Does this post break a rule?

moderation.breaks_rulebool

title and text · likes and replies re-run nothing

Will this account cancel within 30 days?

churn_risk.at_riskbool

its latest 8 tickets and 180 days of invoices

How good is this lead, 1 to 5?

lead_quality.scorescore

company, role, what they wrote, size and source

Does a person need to look at this?

review_queue.needs_reviewbool

the item, its summary and category

dry_run shows the definition and its cost before anything is created

02Why a judgment layer

The first version is always the same: when a row changes, call a model and save what it said. It works until the answer depends on other records, until the model quietly changes, and until someone asks how often it's right. Vainona is that first version, finished.

The same month of writes. Two ways to run it.

One question about 120 accounts: will this account cancel in the next 30 days? Below, a month of activity plays in about half a minute. On the left, the usual shortcut: call a model every time an account row changes. On the right, Vainona.

Animated comparison. The same stream of events plays on two grids of 120 accounts. On the left, a model is called whenever an account row changes: a new ticket or a paid invoice never touches the row, so the saved answer goes out of date; a login heartbeat and a burst of notes each cost model calls; a cancellation teaches nothing; a model change goes unnoticed. On the right, Vainona knows the answer depends on the account, its tickets and its invoices: the ticket gets the account answered again, the heartbeat is skipped, the burst is answered once, the cancellation is recorded as an outcome, and the model change is detected and recorded.

Same events, same 120 accounts. Vainona knows what each answer depends on, so it runs only when that changes, and it learns from what happens next.

03Guarantees

Nothing changes behind your back.

Six rules the system is built around. Each one is a field you can read, not a promise in a footnote, and each card below is the rule running.

01

No silent staleness

Every answer says how current it is, and why when it isn't. Filter to fresh answers only, or have a write wait for its answer.

freshness: "stale" · stale_reason
02

No silent model swaps

When the model behind Jev changes, a new epoch starts and every answer records it. A pinned version never moves, and a retired one fails by name.

engine_version: "current+2026-09-28.1"
03

No rewritten numbers

Calibration sits beside the engine's probability, never over it. Thresholds and ranking read the raw number, so a refit never flips a decision on its own.

p: 0.87 · calibrated.p: 0.81
04

No lost history

Every computation is kept as an evaluation, with the exact context the engine read. Nothing is overwritten, so any answer can be explained later.

evaluation_id: "ev_01JB7KQ2"
05

No surprise bills

A backfill shows its cost and duration before you confirm. Every engine request is priced before it's sent, and judging pauses at your budget instead of passing it.

estimate.cost_usd · budget_paused
churn_risk · v3 → v4
mean p
0.31 → 0.34
at_risk flips
+38 in · 3 out
recompute all
48,210 judgments · $12.05

awaiting your confirm · v3 still answering

06

No untested changes

Question versions are immutable. A new one is judged on a sample beside the old one, at no charge, and reports what it would move before you switch.

threshold_flips: { to_true: 38, to_false: 3 }
How the system behaves, and what it gives up

04The SDK

You write the question. We compile what the engine sees.

A judgment is a question and a recipe: the fields and related records the engine reads. The recipe decides what an answer costs, how accurate it is and when it's judged again. Turn the knobs and watch both.

judgments/churn.ts
tickets
per ticket
invoices
await ns.judgments.create({  name: "churn_risk",  type: "bool",  question: "Will this account cancel within the next 30 days?",  applies_to: { "attributes.kind": "account" },  context: {    fields: ["state.name", "attributes.plan"],    related: {      tickets: {        match: { "attributes.kind": "ticket" },        join: { theirs: "attributes.account_id", mine: "id" },        last_n: 8,        fields: ["created_at", "state.subject", "state.status"],      },      invoices: {        match: { "attributes.kind": "invoice" },        join: { theirs: "attributes.account_id", mine: "id" },        window: "180d",        aggregate: { count: true, latest: ["state.status"] },      },    },  },  horizon: "30d",  engine: { name: "jev", version: "current" },  freshness: { policy: "on_change" },});
npm install vainona
What the engine seesacct/brightline · rev 14
{  "state.name": "Brightline",  "attributes.plan": "enterprise",  "related.invoices": { "count": 6, "latest(state.status)": "paid" },  "related.tickets": [    { "created_at": "2026-09-28T14:02:11Z", "state.subject": "Third outage this week", "state.status": "open" },    { "created_at": "2026-09-21T09:40:52Z", "state.subject": "Export keeps timing out", "state.status": "open" },    { "created_at": "2026-09-02T16:11:07Z", "state.subject": "SSO login loop", "state.status": "solved" },    { "created_at": "2026-08-19T11:03:44Z", "state.subject": "Invite link expired", "state.status": "solved" },    { "created_at": "2026-08-04T08:27:19Z", "state.subject": "Webhook retries", "state.status": "solved" },    { "created_at": "2026-07-22T15:48:03Z", "state.subject": "Add a seat", "state.status": "solved" },    { "created_at": "2026-07-09T10:12:31Z", "state.subject": "Dashboard slow on Mondays", "state.status": "solved" },    { "created_at": "2026-06-30T13:55:20Z", "state.subject": "API key rotation", "state.status": "solved" }  ]}
tokens
412, with the question
size class
standard · up to 2,000 tokens
counts as
1 judgment
at the first tier
$0.00025

A write to the account, a ticket or an invoice is checked against this. If what the engine would see is unchanged, the answer is reused without calling it.

  • ns.write({ upsert })Keep documents in sync. Answers follow in seconds.
  • ns.query({ rank_by })Filter and rank on answers like any column.
  • ns.subscriptions.create()Entered and exited events, by webhook or feed.
  • ns.outcomes.append()What actually happened. Calibration learns from it.
Read the quickstartTypeScript: Node 20.19+ or any runtime with fetch · Python 3.9+

05Calibration

An engine's 0.9 isn't 90%. Yours will be.

An engine's probability is its own confidence, and confidence isn't being right. Outcomes, what actually happened, measure it on your data and correct it, so you can say how often an action above a threshold will be wrong.

churn_risk@v3 · reliability1,240 outcomes
000.50.5110.9 means 90%what the answer sayshow often it came true

On outcomes the fit didn't see

rawcalibrated
calibration error0.1590.008
log loss0.4410.344
accuracy80.1%83.7%

Calibration cut this judgment's error by 22% since it started, on 1,240 outcomes.

Pick a threshold

Thresholds read the raw number. Calibration tells you what it means, and the recommender picks one from a target.

at_risk · p ≥ 0.60

The engine says 0.60. On your accounts that comes true 47% of the time.

194 of 1,240 accounts are flagged. 63% of them go on to churn.

46% of the accounts that churn are flagged.

recommendThreshold(“precision:0.7”) → 0.74 · precision 70% · recall 30%
held-out error, per nightly fitrawwhat answers read

current+2026-09-28.1 · fitted from replay

A new epoch starts its own headline. The chart keeps the old one beside it.

  • From 100 outcomeswith 20 of each kind, every answer carries a calibrated p beside the raw one.
  • Only when it helpsa fit is used only if it beats the raw numbers on outcomes it wasn't fitted on.
  • No labelling pipelineoutcome rules read cancellations and closures from writes you already make.
  • Survives model changesa new epoch is re-fitted by replaying your labelled answers, not by waiting for new ones.

06Numbers

Measured, not promised.

Every figure here comes from a run we can name. Latency was measured on staging on 28 and 29 September 2026, so it's a small deployment's number, not a guarantee. Engine quality is re-checked every day against a suite built to be hard.

Answer fresh after a write

1.6s

p90, one write at a time, on a one-field recipe. p50 was 1.3 s and the slowest of 200 was 2.4 s.

Jev current · yes/no accuracy

82.6%

On a golden set built to be hard: 40% easy, 40% medium, 20% hard. Calibration error 0.017 before any outcomes. Re-run daily and after every change we detect.

Model probes a day

2,880

Every 30 seconds we ask Jev the same questions and compare 10-minute averages. A change starts a new epoch, recorded on every answer from then on.

07Pricing

Pay per judgment. A record that sits still is free.

A judgment is one answer over its compiled context, counted by size. An unchanged record isn't judged again, a reused answer isn't billed, failed evaluations aren't billed, and every plan has the whole product. Plans set a monthly minimum and what else they include.

5.1Manswers

= 5,100,000 judgments · $1,275 of usage at the graduated tiers

Size class
≤ 2,000 tokens · ×1
Per 1,000 judgments, graduated like tax brackets
  1. First 100M$0.255,100,000
  2. To 1B$0.14
  3. To 10B$0.07
  4. Above$0.035

Developer

For one product, paid from prepaid credit.

$19/ month minimum

$1,275 of usage, above the $19.00 minimum. The invoice is $1,275.

Start on Developer
  • Everything: judgments, recipes, related records, shadow reports, budgets, webhooks
  • Calibration from the outcomes you post
  • The learning loop, previewed in the dashboard
  • 25 tenant namespaces, 2 webhook endpoints

TeamYour range

For teams that act on the answers, paid as usage grows.

$499/ month minimum

$1,275 of usage, above the $499 minimum. The invoice is $1,275.

Start on Team
  • Outcome rules: outcomes from writes you already make
  • Labelling queue, threshold recommender, recipe tuning
  • Templates: one judgment across every tenant
  • 25 tenant namespaces, 20 webhook endpoints

Scale

For platforms and regulated teams.

$2,500/ month minimum

$1,275 of usage. The invoice is the minimum, $2,500.

Talk to us
  • Each tenant grows its own calibration from the pool
  • Audit and evaluation history export
  • SSO, SLA and support response times
  • 100 tenant namespaces, an annual commitment priced for your workload
Storage, history included: $0.03 per GiB-month. Writes $0.10 per GiB. Queries $0.01 per GiB scanned.The same price on every engine. Prices in USD.

08Start

Ask once.Stay answered.

An API key, one starter judgment and three writes. Your first answers land in the free quickstart namespace a couple of minutes from now. Nothing to deploy.

zsh — ~/code/support
~/code/support $ npm install vainona
added 1 package in 1.2s
~/code/support $ npx tsx quickstart.ts
namespace default/quickstart (free)
✓ judgment urgent · from ticket_triage.urgency · on_change
✓ wrote 3 tickets · wait_for: urgent
t_1 p 0.94 urgent fresh “Cancel my account”
t_3 p 0.71 urgent fresh “Invoice”
t_2 p 0.06 — fresh “Dark mode?”
3 judgments · 3 evaluations kept · quickstart is never billed
~/code/support $