Eagle // Logic
Product Showcase Pricing Support

API Reference

The PRIOR engine is a single native Rust server. It exposes an OpenAI-compatible inference endpoint with the Tri-State WHEN gate + golden-layer steering applied in-process, plus a governance surface under /admin, plus system endpoints. Default port 8089 (PRIOR_PORT).

One request path for proprietary controls. All PRIOR-specific per-request options ride a single prior_options object on POST /v1/chat/completions. A vanilla OpenAI client that never sends prior_options is unaffected (the gate still applies).

Base URL: http://<host>:8089 Auth: Authorization: Bearer <api-key>. /v1 user-auth is off by default and toggleable live (PATCH /admin/runtime or PRIOR_REQUIRE_AUTH); /admin always requires an Operator/Admin key.


Inference

POST /v1/chat/completions

OpenAI-compatible chat completion. messages are chat-templated server-side using the model's own template. The WHEN gate routes on the combined system+user intent (so a jailbreak in the system prompt is gated too), and steering is applied per the routing decision.

Request. Standard OpenAI fields plus the optional prior_options extension:

{
  "model": "prior",
  "messages": [
    {"role": "system", "content": "You are our support assistant."},
    {"role": "user", "content": "What port does our SSH service listen on?"}
  ],
  "max_tokens": 256,
  "stream": false,
  "prior_options": {
    "ephemeral_memory": {
      "target": "6022",
      "pin_phrase": "Our SSH service listens on port 6022"
    }
  }
}
Field Type Notes
model string? Tolerated/ignored; one model per container.
messages array {role, content} where role is system / user / assistant.
max_tokens integer Default 256.
temperature number? Accepted for compatibility; decoding is greedy/deterministic.
stream bool? SSE (chat.completion.chunk) when true.
prior_options object? PRIOR controls (see below).

Response. A standard OpenAI chat.completion object (or an SSE stream when stream: true). PRIOR telemetry is returned in response headers (additive; OpenAI clients ignore them).

On a YELLOW route the pack's confirm notice is also prepended to the message content (unless PRIOR_YELLOW_MODE=header), so header-blind UIs still surface it.


prior_options

Field Type Effect
ephemeral_memory {target, pin_phrase} Stateless fact injection. Steers the golden-layer residual toward target while teacher-forcing pin_phrase, so the model recalls a fact it otherwise wouldn't know. The client owns RAG / user state, so re-send each turn. Injected only on a GREEN route; any YELLOW/RED flag suppresses it (safety > memory).
signals {name: float} Scores from your own detectors. A pack declaring external_signal: "<name>" is scored from this map instead of from an embedding, then composes through the ordinary precedence lattice — so an in-house or third-party classifier drives PRIOR's enforcement, not just a label. See Bring your own detector.
engage_override bool? true = force a refusal even on GREEN/YELLOW; false = suppress steering (vanilla passthrough even on RED); omit / null = use the gate decision.
steer object? Explicit low-level steering override (gate bypassed). For calibration / efficacy harnesses. Licensed-only. Fields below.

steer object (advanced; you rarely need this, since the gate does it for you):

Field Meaning
engage apply steering this request
target steering target token/phrase (e.g. "cannot")
alpha steering strength
golden golden-layer index override
onset_n number of onset tokens hard-pinned
tau maintenance threshold
recompute_every re-projection cadence (0 = onset-only)
pin_n, pin_phrase teacher-forced pin length + phrase
reactive_repin, repin_markers reactive re-pin on marker tokens
logits_only force the backward-free steering path for this request (see below)

steer.logits_only is one-way. A request may opt into logits-only, but it can never opt out of it: if the engine selected logits-only for this model (because the architecture has no usable backward pass, or VRAM is tight), a request asking for L2LM is ignored rather than crashing. Set it globally with PRIOR_LOGITS_ONLY=1 or live via PATCH /admin/runtime.

Bring your own detector

PRIOR's cosine gate is a reference detector, not the product. If you have a classifier that knows your traffic better — an in-house model trained on your own data, a commercial safety classifier, a regex, a deny-list — you can drive PRIOR's enforcement from it directly.

Declare a pack with external_signal, then pass that detector's score on each request:

// the pack
{ "pack": "house_classifier", "external_signal": "house", "on_missing": "red",
  "tristate": { "t_low": 0.55, "t_high": 0.80 }, "enforcement": "hard", … }
// the request — you score first, then call
{ "model": "prior", "messages": [ … ],
  "prior_options": { "signals": { "house": 0.87 } } }

Three properties worth knowing:

  • PRIOR never calls out. You score first and pass the result inline. There is no round-trip in the serving path, no second service to keep up, and no new failure mode between the request and the answer.
  • The score is on your scale. A foreign score is not a zone. Calibrate the consuming pack's t_low/t_high against your detector's benign distribution, exactly as a cosine pack is calibrated against ours. PRIOR stores and enforces what you declare; it will not re-derive your thresholds, because re-deriving them from exemplars the pack does not have would replace your policy with a meaningless number.
  • It composes. An external pack sits in the same precedence lattice as a cosine pack, so a classifier verdict and a membership boundary can both be live, and the more restrictive one wins.

on_missing decides what happens when the named signal is absent from a request — "red" fails closed, which is what you want if the detector going down should stop traffic rather than open the door.

Trust model: the /v1 caller is the operator's authenticated application, not the end user. A signals value is a statement by your backend, so treat the endpoint accordingly (PRIOR_REQUIRE_AUTH=1 whenever it is reachable beyond localhost).


Response headers (x-prior-*)

Emitted on /v1/chat/completions:

Header Meaning
x-prior-zone GREEN / YELLOW / RED; the WHEN-gate decision.
x-prior-pack The winning policy pack.
x-prior-injections Golden-layer steering steps applied (0 = bit-for-bit vanilla).
x-prior-steering enabled / disabled (the license gate).
x-prior-decision-id Correlation id; matches the row in the durable safety audit.
x-prior-memory injected / suppressed / preempted / disabled; set only when ephemeral_memory was sent. suppressed means the call succeeded and the answer does not contain the fact you supplied — branch on it if your application depends on that fact being present.

The response exposes the decision (zone, winning pack, whether steering engaged) but not the underlying match scores. Raw scores are deliberately kept off the caller-facing surface: exposing them would let a caller probe the exact boundary and map the detection and steering. Scores are retained only in the admin-gated safety audit, for operators tuning their own policies.

POST /v1/completions

Legacy (non-chat) OpenAI completion endpoint, kept for compatibility. New integrations should use /v1/chat/completions.


System

Method · Path Purpose
GET /health Liveness (answers immediately; the model loads lazily).
GET /v1/models The loaded model id.
GET /metrics Prometheus exposition: zone distribution, refusal counts, latency / token / injection histograms.

Governance: /admin/*

All /admin routes require an Operator or Admin key (an Observer key gets 403). See Authentication & roles.

Packs & policy

Method · Path Purpose
GET /admin/packs/native List loaded native arbiter packs, reporting name, encoder, tier, priority, thresholds, exemplar count, enabled. (Exemplars themselves are never served.)
POST /admin/packs/reload Hot-swap all packs from disk, with no restart.
PATCH /admin/packs/{pack}/enabled Mute / unmute a pack instantly (body: {"enabled": bool}).
PATCH /admin/packs/{pack}/priority Set a pack's arbitration priority (which pack wins when several match).
POST /admin/packs/ingest Prose → calibrated pack. Submit a governance document; PRIOR extracts intents, generates exemplars, calibrates thresholds, and hot-reloads. See Policy & Packs.
POST /admin/packs/import Load a pre-built arbiter pack verbatim, skipping ingest and calibration. For packs you built elsewhere or version-control yourself.
GET /admin/packs List on-disk packs (metadata only).

Pack authoring (1.1.0)

Author and refine a pack against real evidence instead of guessing at thresholds. These are the API behind the WebUI's pack editor.

Method · Path Purpose
GET / PUT /admin/packs/{pack} Read a pack's editable definition (goal, rules, transitions, thresholds) and write it back.
GET /admin/packs/{pack}/coverage Coverage drill-down. Per-probe results: which positives the pack missed and which negatives it fired on — the two lists you actually iterate against. Reports per-rule coverage where rules are defined.
POST /admin/packs/{pack}/rules/{rule_id}/expand Expand one rule into additional exemplars, to lift that rule's coverage without disturbing the others.
GET / POST /admin/packs/{pack}/examples Read and add the pack's exemplars.
GET / POST /admin/packs/{pack}/dataset Manage the pack's test dataset and score the pack against it.
POST /admin/packs/route-probe Score an arbitrary prompt through the live gate and see how it routes, and which pack claims it, without generating a completion. The fastest way to answer "why did this get through?"
GET /admin/detector Detector state: active encoder(s) and their fingerprints.

A pack's transitions are typed — refuse, sever, format, ground — so a pack declares what should happen on a match, not just that it matched.

Model & calibration

Method · Path Purpose
GET /admin/model Resolved steering params (golden layer, alpha) + tier (certified / beta) + calibration status.
GET /admin/models/available GGUF models present on disk (with sizes).
POST /admin/calibrate Full steering calibration: golden-layer sweep + alpha (GPU).
POST /admin/calibrate/alpha Alpha-only calibration (golden layer fixed).
POST /admin/calibrate/share Optionally submit the calibration payload to the Eagle Logic model registry.
POST /admin/model/reload Hot-reload the model.

Keys, license, config, runtime

Method · Path Purpose
GET /admin/keys List keys (prefix + role + label; never the secret).
POST /admin/keys Create a key; body {"role": "OBSERVER|OPERATOR|ADMIN", "label"?}. Raw key returned once.
DELETE /admin/keys/{key} Revoke a key.
GET /admin/license/status License variant, tier, capabilities, expiry, customer id.
POST /admin/license/upload Upload a license.bin (hot-applied, no restart).
POST /admin/license/clear Remove the active license.
GET / PATCH /admin/config Read / update engine config.
GET / PATCH /admin/runtime Live toggles (no restart): require_auth on /v1, log_level, json_logs, and logits_only (global backward-free steering mode — the path that runs on MoE). GET also reports diagnostics_available.
GET /admin/logs?tail=N&level=LEVEL Tail the in-memory log buffer.
GET /admin/whoami The calling key's role and label — useful for a UI deciding which controls to show.
GET /admin/stats Aggregate engine counters.
GET /admin/usage Per-key usage accounting: request and token tallies by API key.
GET /admin/activity Recent request activity. Prompt and response content is included only when the flag-gated log_content toggle is on — off by default, and it is the one surface that can carry prompt text, so treat it as sensitive.

Audit

Method · Path Purpose
GET /admin/audit Control-plane action log covering config/keys/license/model mutations, with actor + role.
GET /admin/audit/safety?tail=N&zone=RED&pack=harm_veto Durable per-request gate decisions, capturing decision id, zone, pack, score, steered flag, model, prompt hash. Survives restarts.

There is also a set of low-level triple-store routes (/admin/triples/*) and an /admin/ui/* static-dashboard mount. The triple editor is a Admin-only advanced/legacy tool; native inference does not read those triples. Most operators drive PRIOR through packs (above) and the separate WebUI.


Authentication & roles

API keys are SHA-256-hashed at rest; the raw secret is shown once at creation and never stored or re-served. Present a key as Authorization: Bearer <key>. Keys may carry a label and an optional expiry.

Role /v1 inference /admin governance Typical holder
Observer ❌ (read dashboards only where exposed) monitoring, dashboards
Operator ✅ except global config write / model reload / oracle flush day-to-day policy ops
Admin ✅ full: config write, licensing, calibration, lifecycle the account owner
  • /v1 auth is off by default; a fresh engine answers inference without a key. Turn it on with PRIOR_REQUIRE_AUTH=1 or live via PATCH /admin/runtime. Always enable it before exposing the engine off loopback.
  • /admin is always authenticated and requires Operator or Admin.
  • Seed a first Admin key at boot with PRIOR_API_KEY (env-only, not persisted), then create scoped keys through /admin/keys.

Errors & status codes

Code When
200 Success.
400 Malformed request, or a feature used without its prerequisite (e.g. ingest with no extractor configured, which returns a clear message and never a silent localhost dial).
401 / 403 Missing/invalid key, or an Observer key hitting /admin.
429 Per-caller rate limit exceeded on /v1 (token bucket, per API key).
503 Engine still loading the model (readiness).

Statelessness

The server holds no conversation sessions and no server-side user store. The client re-sends the full message history (and any ephemeral_memory) each turn. This is what makes horizontal scaling and air-gap deployment straightforward: any replica can serve any request.


CORS (browser clients)

To call the engine from a browser (e.g. the WebUI on a different origin), set PRIOR_ALLOWED_ORIGINS to your UI's origin(s). The engine lists Authorization + Content-Type explicitly in Access-Control-Allow-Headers (a * wildcard does not cover Authorization per the Fetch spec, so the Bearer key would otherwise be dropped). Restrict origins in production.


See also: Concepts · Policy & Packs · Deployment.