Skip to content
GitHub
Reference

Primitives

This page is the lookup surface for Spectral’s core primitives — the building blocks the rest of the system is built on. Each section is a per-primitive reference: definition, structure, lifecycle, and the relationships that constrain it.

For the conceptual narrative — how the primitives compose into the system, what each one is for, why this shape and not another — see the System Design overview and How Spectral Works.


The top-level customer-identity boundary. An org represents one customer organization across every domain that customer operates in. Tokens, billing, and operator-level access (owner / operations roles) all key on org_id. See ADR-086 D1.

The action-grouping container inside an org. A domain is a coherent subject area whose actions share context vocabulary, configuration, and an authoring authority — ap_operations, underwriting, vendor_risk, etc. Customer-facing roles (admin / contributor / observer) are scoped at the domain level per ADR-086 D2 + D5. Tenancy enforcement keys on domain_id per ADR-086 D6.

Each domain has its own world model, its own action registry, and its own deployed action modules. The customer can run multiple domains under the same org; each is an independent authoring authority.


A versioned artifact scoped to (org_id, domain_id) that holds the entire authoring authority for one domain. Each version declares:

  • A context schema — the typed vocabulary of attributes the domain’s decisions consume (supplied / system_generated / computed).
  • A configuration block — stable values per version that derivations and rule-code generation read (thresholds, business-hour definitions, holiday calendars, regional regulatory parameters).
  • An action registry — the set of registered actions in the domain. Each action carries its own rules and (optionally) an aggregation mode.

The world model lives outside the LLM’s reasoning loop at decision time. Versions are the unit of authority per ADR-026; prior versions remain queryable indefinitely. The unit of publication is the action module (see below), one per (org, domain, action, world_model_version).

The typed declaration of every attribute a domain’s decisions can consume, with each attribute carrying a source that determines where its value comes from at runtime:

  • supplied — caller provides in the request body. Schema validation: missing or mistyped required attribute → YELLOW + gather_evidence_and_retry.
  • system_generated — Spectral captures at request entry (request_time, request_id, authenticated_caller). Cannot fail; caller cannot forge.
  • computed — derivation runs at composition-root entry from supplied + system_generated. Derivation throws → YELLOW + diagnostic in trace.

Rules do not distinguish source — they destructure typed values from the unified DecisionContext. The distinction is operator/authoring-facing.

Configuration is its own primitive at the world-model level — stable values per version that derivations consume at composition-root entry, and that rule code-generation bakes into predicates at authoring time. Configuration is not exposed to predicates at runtime; predicates see only typed context. A configuration change is a world-model version bump that regenerates dependent rule code.

The set of registered actions in a domain. Each action is a first-class entry holding its own rules directly — no separate “rule-set” primitive layered between action and rules. Each action also optionally carries an aggregation_mode per ADR-077 that controls how its rules combine.

Each action carries a persisted input ontology per ADR-107 — one entry per canonical input (name, type, required, enum values, description, and provenance: the contributing rules plus how the name was decided). It is the authority for the action’s published input schema and the source deploy renders input_schema.json from; the union of the deploying rules’ declared inputs is retained only as a deterministic drift check, never a fallback source. The ontology is established at publish by the reconciliation phase, which converges the action’s rules’ divergent input names onto one canonical name per real quantity (an LLM proposes the names and rename map; types and values are derived deterministically), so two rules naming one quantity differently surface as a single input rather than two. A name any published version exposed is conserved across reconciliations (the freeze boundary is the published input, not the enshrined rule); the ontology is snapshotted into the World Model Card so a published version’s input contract is frozen with its action set.


The unit of decision-time routing within a domain. A caller’s request names the action it is about to take (wire_transfer.release, vendor.onboard, ach.release); Spectral routes to the deployed action module for (org, domain, action) and evaluates that action’s rules against the context. A rule associates to one or more actions through the many-to-many action–rule registry (per ADR-104); a rule assigned to no action does not deploy.

A single enforceable expectation, assigned to the action(s) it serves. Each rule is one file inside the action’s module. The file exports:

  • Metadata (static, machine-readable) — id, tier (T1 / T2 / T3), outcome (the status emitted when the rule matches), description, category (optional taxonomy tag), suppresses, dual provenance.
  • applies_when (optional) — a context-only predicate evaluated before the rule’s main predicate. The rule participates in matching only if applies_when returns true.
  • Predicate — pure function, deterministic, no I/O. Takes a typed DecisionContext, returns { matched: bool, reason?: string, trace?: object }.
  • Declared inputs — the typed, documented inputs the predicate consumes; codegen is bound declared == read so the declaration equals the predicate’s actual reads (per ADR-107). Across an action’s rules these declarations are converged at publish onto the action’s canonical input ontology (below), the authority for its published input schema.
  • Behavioral spec + tests — a spec of the inputs the outcome depends on and discriminating case-pairs, extracted from the rule’s natural-language text independently of the predicate; discriminating tests are materialized from it and the predicate is generated to pass them (per ADR-108).

The outcome is static metadata, not predicate output. Rules report whether they matched; the composition root reads metadata.outcome to determine the contributing status. The full lifecycle (candidate → enshrined → retired) is governed by the Evolution Loop.

The severity classification of a rule, used in suppression and aggregation:

  • T1 — unconditional hard-floor override. Any T1 match wins outright regardless of aggregation mode. Preserves the T1-unsuppressible property across all aggregation modes.
  • T2 — standard rules; combine according to the action’s aggregation mode.
  • T3 — soft signal; combine according to the action’s aggregation mode.

Each rule carries two-dimensional provenance — both an authoritative source dimension (statute / regulatory guidance / scholarly publication) and a code dimension (the generated predicate’s lineage to the natural-language rule it was generated from). The authoritative dimension carries through restatement; the code dimension is regenerated when the rule’s natural-language form or its configuration dependencies change.


The deployable artifact per (org, domain, action, world_model_version). Internal structure:

action module
├── composition_root.{py|ts} # deterministic codegen for this action
├── context_schema.{py|ts} # embedded subset of domain context schema
│ # (only attributes this action's rules read)
├── rules/
│ ├── rule_<id>.{py|ts} # metadata + applies_when? + predicate + declared inputs + behavioral tests
│ └── …
├── manifest.{yaml|json} # module version, world-model version,
│ # code-provenance, embedded schema digest, signature
└── (bundled artifact)

The composition root is produced by deterministic codegen from the action’s metadata — not by the LLM. It validates context against the embedded schema, runs applies_when filters, evaluates predicates in severity order, applies suppression chains, falls back to NO_RULE_MATCH, and constructs the work frame. The LLM’s job stays narrowly scoped to per-rule predicate (and applies_when) generation at authoring time.

The content-addressed store keyed by (org, domain, action, version) that holds enshrined action modules. The platform decision-server fetches modules from the store on first request, verifies the content hash and operator-approval marker per ADR-080 D2 + D3, caches the loaded module, and runs it on subsequent requests. The store is the unidirectional handoff from the worlds-side authoring path to the platform-side execution path.

Module bytes are held durably in the database — the same managed-backup and point-in-time-recovery scope as the rest of the system (ADR-040) — with a local-disk cache in front of it for hot reads (ADR-085 D1). A redeployed or recycled compute instance starts with an empty local cache and transparently reloads each module from the durable copy on its first miss; only a database reset clears the modules themselves.

The action-level metadata that controls how an action’s rules combine into a single decision outcome. Today the schema accommodates the field but only one mode is implemented; future modes are deferred-but-shaped.

ModeStatusBehavior
winner_takes_allImplemented (default)All matched rules sort by severity; highest-severity rule’s outcome wins.
vote_of_nReservedGroup of rules with the same outcome must reach a threshold count to fire that outcome.
weighted_sum_thresholdReservedEach matched rule contributes a weight; sum compared against thresholds determines outcome.

T1 rules are an unconditional hard-floor override regardless of aggregation mode. When matched rules share the winning tier but emit different outcomes, the most-restrictive outcome binds (RED > YELLOW > GREEN-SKIP > GREEN). See ADR-106.


The outcome of a single /decide invocation: { status, work_frame, decision_metadata } returned to the caller, plus a structured record written to the audit chain. The response shape is specified by ADR-077 D3. Every decision is deterministic over (world_model_version, supplied_context, system_generated_at_entry).

The audit-grade headline of a decision. Four-state taxonomy:

StatusMeaning
GREENExecute the requested action; it is allowed.
GREEN-SKIPSkip the requested action; the skip itself is allowed (audit-visible no-op).
YELLOWReview path: gather evidence, prepare review packet, or route to a human owner.
REDBlock; the agent must not decide. Escalation required.

The structured contract returned alongside status that bounds the agent’s behavior after receipt. Fields: mode, next_action, allowed_actions, forbidden_actions, required_output, missing_evidence, next_human_owner.

The work frame names explicit anti-patterns by construction: llm_policy_decision: false, forbidden_actions includes "reinterpret_policy" and "override_spectral". The caller’s agent cannot let an LLM talk past Spectral’s decision.

Structured trace returned alongside status + work_frame: which rules matched, suppression chain, aggregation outcome, predicate traces, errored predicates, request ID, request time. Substrate for audit-chain replay and per-decision dashboard inspection.


The internal-only LLM agent that owns the world-model authoring path. Generates predicate code from natural-language rules, materializes tests from a behavioral spec extracted independently of the predicate (not hand-suggested), proposes provenance citations, and runs the implementation-readiness gate. Customer-facing role (per ADR-081 D5) is a post-release explain-this-decision chat affordance. The World Agent never enshrines — enshrinement is the operator’s gate.

One of the gates on the path from draft rule to published module. Enforced at publish (per ADR-108): verifies the generated predicate code is behaviorally complete against an independent behavioral spec — discriminating tests materialized from the rule’s natural-language text, which the predicate is generated to pass — plus a dead-input gate, declared == read codegen binding, and captured code provenance.

The second gate. Verifies the rule against the domain’s authoritative sources (statute, regulatory guidance, scholarly publication).

The mechanism by which world-model versions name what changed and why between versions, extended to three categories: configuration restatement, rule restatement, action restatement. See ADR-026.


The HTTP surface at POST /decide (per ADR-077 D1) and its MCP equivalent per ADR-088. The two surfaces share the same authentication, the same routing, and the same response shape. Action discoverability is exposed via OpenAPI per ADR-089.

The platform pillar’s runtime: api-pod replicas (per ADR-076 D1) that handle the decision API surface, load and cache action modules from the module store, and execute them. The execution layer’s safety contract is specified in ADR-083.

The deployment-scoped record of every decision served, per ADR-076 D3. Each entry captures the full decision trace (request context, matched rules, suppression chain, aggregation outcome, predicate traces, errored predicates, work frame, response). The audit chain backs the System Card and is the substrate for customer-initiated review-request flow (per Customer Dashboard).


The version-scoped methodology disclosure published with each world-model version: scope, sources, decision log, authority basis, two-dimensional provenance summary. Operator-authored, not auto-generated. Per ADR-082 D2 the card is version-scoped and its content covers the authoring path.

The deployment-scoped operational record per ADR-082 D3: per-(org, domain) totals, p50/p95/p99 latency, four-state status distribution, methodology disclosure, version history. The customer-facing view of operational health surfaced through the Customer Dashboard.


The agent-memory primitive — agent reasoning compounded across runs. Observations are append-only, anchored to the agent that produced them, and tiered (interaction / session / persistent) per ADR-058. The records-vs-memory boundary — observations are value-added reasoning about records, not records themselves — is the load-bearing invariant. See Memory System.