Axiom is a deterministic Decision Contract Runtime for Python 3.11+.
It sits between an application and a Language Model, guaranteeing that AI decisions are structured, validated, inspectable, and enforceable before execution. It converts raw, untrusted LLM text generation into completely structured and verifiable system decisions.
Axiom treats AI as non-deterministic hardware. The model never has execution authority. The Axiom runtime always owns authority.
Note: Axiom is infrastructure only. It is NOT an AI agent framework and NOT a chatbot toolkit. It does not implement memory, RAG, tool calling, or chat UIs.
Instead of the traditional flow where an application blindly accepts raw string generation, Axiom forces the model into a rigid structure:
App → Axiom Runtime → LLM proposal → Decision Contract → Validation → Policy Enforcement → Execution Approval
All outputs must match a strict JSON schema. If the output deviates—whether via syntax errors or missing fields—Execution is instantly rejected. No natural language is permitted outside the JSON boundary.
All approved decisions conform strictly to this immutable schema:
{
"goal": "string",
"state": "string",
"decision": "string",
"constraints": ["string"],
"confidence": 0.95,
"explanation": "string (max 20 words)"
}Currently, Axiom has zero external dependencies (other than a local LLM). Simply drop the axiom package into your Python project directory.
Requires Python 3.11+.
Axiom relies on an LLM inference server. Currently, an Ollama adapter is natively supported. Keep your Ollama daemon running in the background.
from axiom import Axiom
# Start the runtime
ax = Axiom(model="ollama:qwen3-vl:8b")
# Evaluate a prompt
result = ax.evaluate(
prompt="Market volatility is high. Should we open a new position?",
context={"current_portfolio_risk": "moderate"}
)
# Execution authority natively branches by status:
if result.status == "APPROVED":
print("✅ Decision Approved by Runtime")
# Access strictly typed variables (type: axiom.models.decision.Decision)
decision = result.decision
print(f"Goal: {decision.goal}")
print(f"Confidence: {decision.confidence}")
print(f"Action: {decision.decision}")
elif result.status == "REJECTED":
print("❌ Execution Denied")
print(f"Reason: {result.reason}")
print(f"Raw Output: {result.raw_output}")Axiom's schema prevents syntax hallucinations and field bounds violations, but the Policy Engine evaluates the content's safety based on your business logic before giving an app approval to execute.
You can inject custom rules using Axiom.policy_engine.add_rule():
from axiom import Axiom
from axiom.policy import PolicyDecision
def deny_low_confidence_trades(data):
"""Custom policy to prevent trades if AI confidence is below 85%"""
confidence = float(data.get("confidence", 0.0))
action = data.get("decision", "").lower()
if "buy" in action and confidence < 0.85:
return PolicyDecision.DENY
return PolicyDecision.ALLOW
ax = Axiom(model="ollama:llama3")
ax.policy_engine.add_rule(deny_low_confidence_trades)
# If the LLM returns "buy" with 0.82 confidence, result.status will equal "REJECTED".Axiom ships with examples of non-financial workflows to demonstrate safety logic routing out of the box:
- IoT Smart Home Safety (
examples/smart_home_iot.py): Tests strict override logic for edge computational home hardware (e.g. denying an LLM the ability to "ignore" issues when a water leak sensor or fire alarm triggers, or mandating high-confidence thresholds for emergency action). - Automated Content Moderation (
examples/content_moderation.py): Demonstrates multi-tier boundary rules. For instance, allowing an AI to automatically "hide a post" at >= 75% confidence, but strictly requiring >= 90% confidence to execute a "hard ban."
An application should be transparent. Axiom writes all approved decisions into an append-only, thread-safe JSONL file (axiom_audit.jsonl). Every execution contains an exact timestamp and a SHA-256 hash mathematically binding the exact state and output of that AI decision.
{"goal": "preserve capital", "state": "high volatility", "decision": "hold", "constraints": ["limit risk"], "confidence": 0.9, "explanation": "Too risky.", "timestamp": 1771556978.76, "decision_hash": "416b36390...a927a"}By default, Axiom uses a strict built-in Decision object to shape AI paths natively. But developers can inject completely dynamic constraints by passing any Python @dataclass. Axiom automatically interprets the types, generates a valid JSON schema prompt for the LLM, and forces validation.
from dataclasses import dataclass
from typing import List
from axiom import Axiom
@dataclass
class GridMove:
action: str
target_x: float
target_y: float
safeties_engaged: List[str]
# Evaluates against GridMove schema instead of default schema!
result = ax.evaluate(
prompt="Pursue the target to the North.",
context={"current_x": 0, "current_y": 0, "target": [0, 5]},
contract_type=GridMove
)When using smaller local models, they may sometimes hallucinate string literals when an integer is expected, or forget a required field. Rather than immediately rejecting the payload, Axiom contains a localized feedback loop.
If you pass retries=3 into the evaluator, Axiom will intercept parsing errors and gracefully prompt the model with its own exception:
"Your previous output threw an error: Field 'temperature' has incorrect type. Expected float. Rewrite your response perfectly matching the JSON schema."
result = ax.evaluate(
prompt="...",
retries=3
)Because LLM generation is inherently I/O bound, calling .evaluate() in a production web framework (like FastAPI or Sanic) would block the main event loop. Axiom natively supports non-blocking asynchronous execution via the python standard library (asyncio.to_thread).
You can rapidly fire hundreds of distinct system state decisions concurrently:
import asyncio
from axiom import Axiom
ax = Axiom(model="ollama:qwen3-vl:8b")
async def evaluate_multiple_states():
task1 = ax.evaluate_async(prompt="State Check 1")
task2 = ax.evaluate_async(prompt="State Check 2")
results = await asyncio.gather(task1, task2)
# results = [ApprovedDecision, RejectedDecision]axiom/runtime.py- Single entrypoint and orchestratoraxiom/contract.py- Exact-bounds JSON parseraxiom/validator.py- Strict schema assertionsaxiom/policy.py- Safe evaluation rulesaxiom/audit/logger.py- Append-only loggingaxiom/models/- Immutable dataclasses for Decisions and Exceptionsaxiom/adapters/- Provider backends (Ollama built-in)