ÆTHERYA inserts a deterministic decision boundary between an LLM and any sensitive action:
LLM → policy/gates/confirmation → allow|deny|escalate → execution
It separates:
- Principles — constitutional constraints
- Signals — risk sources (guard chain, constitution, confirmation state)
- Aggregation — deterministic decision logic
- Execution state mapping — policy engine output
- Audit trail — verifiable, tamper-evident log
This separation enables: deterministic decisions, configurable thresholds, snapshot testing, and explainable outcomes.
flowchart LR
Input --> Parser
Parser --> ActionContract
ActionContract --> IntentEscalation
IntentEscalation --> Mode
Mode --> RateLimiter
RateLimiter --> ExecutionGate
ExecutionGate --> CapabilityGate
CapabilityGate --> JailbreakGuard
JailbreakGuard --> ProceduralGuard
ProceduralGuard --> Constitution
Constitution --> RiskAggregator
RiskAggregator --> ConfirmationGate
ConfirmationGate --> PolicyEngine
PolicyEngine --> FinalDecision
RiskAggregator --> Explainability
FinalDecision --> LLMShadow
FinalDecision --> PolicyAdapterShadow
FinalDecision --> Audit
Explainability --> Audit
LLMShadow --> Audit
PolicyAdapterShadow --> Audit
Deterministic runtime order:
- Parse + ABI contracts (
actor,action) - Intent escalation (
ask→operateon executable command shape — monotone) - Rate limiter (per-actor sliding-window — fail-closed if exceeded)
- Guard chain:
execution_gate→capability_gate→jailbreak_guard→procedural_guard - Constitution signal evaluation
- Risk aggregation + optional confirmation (token/context and optional signed proof)
- Policy state mapping and decision contract
- Explainability + shadow telemetry (
llm_shadow,policy_adapter_shadow) - Audit logging (
decision_id,context_hash, chain/hash attestation)
Fail-closed guarantee: any exception in any stage returns fail_closed:<stage> with allowed=false.
ExecutionGate and CapabilityGate only evaluate requests whose intent is
operate. That made the whole guard chain depend on the parser's verb list: an
executable command using a verb the parser did not know — dd if=/dev/zero of=/dev/sda — was classified ask, skipped both gates, and could reach
allow. The escalation stage re-derives operative intent from the raw input
using command shape (command substitution, pipes into a shell, redirects to
absolute paths, known binaries carrying flags, device operands, sudo prefixes)
plus any ProceduralGuard hit.
The transform is monotone: it only ever raises ask/consultive to
operate/operative, never the reverse, so it cannot be used to relax a
request the parser already classified as operative. When it fires, the audit
context carries an intent_escalation block naming the signals that triggered it.
The SemanticEvaluator is the only component in the decision path whose output
depends on a learned model. Two properties keep the core verdict deterministic:
- Non-authoritative. Its risk contribution is capped at
constitution.semantic_max_risk(default 60), validated at policy load to sit strictly below every mode'sdeny_at. It can therefore raise a request toescalate— never todenyorhard_deny— and it emits no hard-deny tags. Swapping the model can change whether a human is asked, never whether an action is refused outright. - Never blocking. Loading
all-MiniLM-L6-v2costs ~5 s in a fresh process. Withconstitution.require_warm_semantic_model(defaulttrue) the layer declines to run when the model is not already in the process cache, and the trace recordsconstitution.semantic_skipped: model_not_warm. Long-lived deployments callaetherya warmupat boot to make the layer available without ever paying that cost inside a decision.
Aggregates signals from all guards and the constitution:
- Weighted scoring
- Mode-aware thresholds (
consultivevsoperative) - Hard-deny tags bypass the score entirely:
critical_tag_detected,jailbreak_attempt,tool_not_allowed,capability_tool_denied - Deterministic outcome given same config
Snapshot-friendly output:
allowed— booleanrisk_score— 0–100reason— stringviolated_principle— nullablestate—ALLOW | DENY | REQUIRE_CONFIRM | ESCALATEmode—consultive | operative
Builds a deterministic justification graph per decision:
- Per-signal weighted contribution
- Graph nodes/edges from signals to aggregate and final state
- Explicit transition from aggregate decision to final policy state
See release-and-verification.md for rendering commands.
Provider contract for non-authoritative telemetry:
LLMRequest/LLMResponsetyped contractsLLMProviderprotocolDryRunLLMProvider— deterministic, no external callsOpenAILLMProvider— real external shadow (OPENAI_API_KEY)shadow_suggestion+ethical_divergencetrace for shadow-vs-core drift- Core decision authority remains in ÆTHERYA. LLM output never overrides
allowed.
Future-proof adapter for external context engines (LLM, vector DB) without coupling runtime execution:
PolicyDecisionRequest/PolicyDecisionResponsetyped contractsPolicySignalCandidateandPolicyDecisionCandidatePolicyDecisionAdapterprotocol +ensure_policy_decision_adaptercontract guardDryRunPolicyDecisionAdapterdeterministic reference implementationpolicy_adapter_shadowpipeline mode — no decision override, projected-risk trace only
Per-actor sliding-window check. Single-process safeguard: in multi-worker deployments (uvicorn --workers N), effective limit = N × requests_per_window.
- Determinism over heuristics
- Explicit evaluation over implicit behavior
- Strict typing over dynamic shortcuts
- Reproducibility over magic
- Auditability as a first-class concern