Rna Agent
Rna SDK

Decision kernel

Transport, thresholds, cache and ledger for JEV judgments, and where question templates belong.

The decision kernel is Rna’s only path to JEV. The code lives in four places:

LocationContents
packages/sdk/src/decision-kernel.mjsTransport, cache, ledger
packages/sdk/src/decision-templates.mjsThresholds, question templates, functions that turn probabilities into verdicts
packages/sdk/src/decision-state.mjsState builders
prototypes/control-center/decision-service.mjsHost call sites

Modes and backends

  • Modes: off, shadow (record only, no behavior change), active.
  • Backends: typesafe (JEV) or llm (a language model acting as judge).
  • Each result names its source: judge for a judgment, fallback for the rule used when no judge is available, and rule for a deterministic rule of the host.
  • In the Rna app all decision points are built in and active by default, with only a few off or shadow; mode and backend can only be overridden for diagnosis with the environment variables RNA_JEV_MODE, RNA_JEV_MODES and RNA_JEV_BACKEND. The backend is chosen automatically: the JEV key first, then the fast model, and with the fast model (llm) every threshold is raised by 0.1.

Thresholds

Thresholds are tiered by consequence; the constant is DECISION_THRESHOLDS in decision-templates.mjs. A yes/no question’s confidence is max(p, 1 - p):

TierThreshold
low0.60
medium0.75
high0.85

The constants also hold a floor of 0.5, the fast-model offset llmOffset of 0.1, and numeric thresholds set per decision point (some points use two, {act, ask}). Look at the real distribution on a labelled set before choosing a tier for each question. Never copy one from another question or type.

Adding a decision point

  1. Write the question template and its combining function in decision-templates.mjs. Phrase questions as literal, observable situations, one judgment each.
  2. Register the template with every question ID in TEMPLATE_SPECS. Missing entries make the kernel reject the whole plan as invalid_assessment_plan; packages/sdk/test/decision-templates-valid.test.mjs guards this.
  3. Register the point in the host's decision-service.mjs (title, risk tier, effect) so it appears in the settings Judgment records.
  4. Build the state in decision-state.mjs: only the text the judgment needs, with lengths, counts and dates computed in code and bucketed.
  5. Run a labelled set through the probe, record the distribution next to the study, then choose thresholds.

Probe

POST /api/v2/decision-kernel/probe
Content-Type: application/json

{ "state": "…", "questions": { "…": { "type": "noul", "instructions": "…", "criteria": "…" } } }

The probe sends one raw call with the app’s configured key, bypassing thresholds, cache and ledger. The reusable harness is prototypes/control-center/benchmark/jev-capability-probe.mjs; set RNA_STATE to the main checkout’s .state/state.json to read real rule bodies.

On this page