ModelRig Docs Leaderboard Console ↗ GitHub Sign up

Review gates that earn autonomy

(needs modelrig 0.13.0 or newer) Your automations draft emails, quotes and purchase-order replies that an employee checks before they go out. A review gate answers one question for your own code, per draft: does this still need a human? — review, sample or auto, with a receipt that says why. Every approval your employees record teaches the task's grader; once that grader is calibrated against them, an earned gate keeps only a deterministic sample in front of a person.

ModelRig never sends, holds or approves anything. The gate only answers; your code decides what review, sample and auto mean.

1. Set up

You need a ModelRig API key in the environment of the process that asks the gate and records approvals:

Mint a key in the org you want the data in. Sign in at https://app.modelrig.ai, check the organization name in the header badge, and create a key on the API keys page. The rig_sk_ secret is shown once. One key = one org: every row the key exports lands in the organization it was minted in, whichever organization you happen to be viewing in the console. Set it on every service, worker and cron that creates a rig; your provider keys stay where they are.


# Wherever your app reads configuration: .env.local, your platform's env vars, a secret manager. Never in code.
MODELRIG_API_KEY=rig_sk_…

The task is the step or route whose drafts are reviewed (for example po-followup-draft). It needs a grading guide before approvals can calibrate its grader — see Set up a grader.

2. The decision table

The policy lives on the task (review_gate; off until you set it):


{ "mode": "earned", "sample_rate": 0.1, "floor": "none" }
The task grader's ladder statemode: alwaysmode: earned
UNGRADED, TEACHINGreviewreview
CALIBRATEDreviewsample for a deterministic sample_rate share of drafts, auto for the rest
JUDGE_LEDreviewsample at ½ sample_rate, auto for the rest
DRIFT_CHECKreviewreview (demoted, with the reason)
any, with a high_risk floorreviewreview
no policy, or ModelRig unreachablereviewreview

sample_rate is between 0.02 and 1. The sample is a hash of your own key for the draft, so the same draft always gets the same answer. auto is only ever possible at CALIBRATED or JUDGE_LED, with mode: earned and no floor.

Every answer is a ReviewDecision — the receipt:


{
  decision: "review" | "sample" | "auto",
  reason: { code: "calibrated_sampled", message: "The grader is calibrated and this draft falls in …" },
  ladder_state: "CALIBRATED", agreement: 0.92, ci: [0.84, 0.96], n: 61, policy_version: 1,
}

3. Ask the gate


const decision = await rig.reviewDecision({ task: "po-followup-draft", subjectKey: po.id });

if (decision.decision === "review" || decision.decision === "sample") {
  await queueForApproval(draft, decision); // your own dashboard
} else {
  await sendDraft(draft); // your code acts; ModelRig never does
}

grade:
  pass_threshold: 0.7
  review_floor: high_risk

4. Record approvals from your own dashboard

When an employee approves, edits or rejects a draft in your dashboard, record it:


rig.approval({
  task: "po-followup-draft",
  subject: { artifact: draftArtifact.id }, // or { inference: result.inferenceId }
  verdict: "edited",                       // "approved" | "edited" | "rejected"
  edited: sentText,                        // only with verdict "edited"
  reviewer: employee.id,                   // an opaque id from your system
});

The ModelRig grade queue is optional — approvals from your own UI are enough.

5. Turn on auto-grading for the task so drift is caught

Agreement needs judge grades on the same drafts your employees approved. Turn on auto-grading for the task (the Calibration tab of its grader, or set_task_settings with grade_auto), so drafts sent as sample or auto keep being graded by the judge. If the judge drifts from your employees, the grader drops to DRIFT_CHECK and the gate demotes itself to review on its own.

6. Set the policy

7. Deploy order

Apply control-plane migration 00090 (tasks.review_gate) → deploy the server → upgrade the SDK. Until the server sees the column (it re-checks about once a minute; no restart), a review_gate PATCH answers 503 with a teaching message and every decision is review.

8. What the gate never does