SANCTUM

Where agents are summoned, bound, and set to work.

A minimal, local-first orchestration engine for AI agents: cyclic state graphs executed by supersteps (Pregel/BSP), built from the ground up for models that run on your machine.

$ pip install sanctum-engine
0core dependencies
~60 µssuperstep overhead
120+tests, no GPU needed
MITlicense
The whole loop, in one call

An agent is a cycle, not a chain

Sanctum executes cyclic state graphs — think → act → observe → think — with parallel nodes, deterministic state merging, and a superstep budget so no loop runs away. summon() assembles the full ReAct loop from the same public API you build on.

Tools are plain typed functions; their JSON schemas are inferred. Point it at any local backend and invoke.

agent.py
from sanctum import Tome, spell, summon
from sanctum.oracle.openai_compat import OpenAICompatibleOracle

@spell
def add(a: float, b: float) -> float:
    """Add two numbers."""
    return a + b

oracle = OpenAICompatibleOracle(
    arcana="qwen2.5:7b",
    base_url="http://127.0.0.1:8080/v1",  # llama-server, Ollama, vLLM…
)

entity = summon(oracle, Tome([add]), spell_calling="auto")
result = entity.invoke({"messages": [
    {"role": "user", "content": "What is 19 + 23?"},
]})
The engine

Small surface, serious machinery

The core is pure Python standard library. Everything below ships in it.

Cyclic state graphs

BSP supersteps: active nodes run in parallel, return partial deltas, conditional edges close the loops. Bounded by recursion_limit. Not a DAG — on purpose.

Deterministic state

Every state channel declares its reducer (overwrite, append, add, or yours). Deltas merge in node-registration order — identical runs, even under parallelism.

Seals & time-travel

A JSON checkpoint per superstep (memory, SQLite, Postgres). Resume, pause with interrupt() for human approval, or replay from any historic Seal.

Streaming Omens

Typed, timestamped events for every boundary of the run — plus live tokens from inside a node. Combinable modes, ready for SSE.

Resilience policies

Declarative per-node timeout, retries with jittered backoff, and fallback nodes that read the reserved __errors__ channel. No try/except soup.

Wards middleware

Intercept every state delta before it merges: audit to JSONL, tally token usage, redact secrets, or veto outright. A pipeline, in registration order.

robust tool-calling — what actually happens with a 7B
# the model emits a broken call…
assistant: {"spell": "calculate", "arguments": {"expr": "19+23"
# …sanctum repairs it, or answers with a correction the model understands
repaired:  calculate({"expr": "19+23"})  ← unclosed JSON recovered
assistant: calls unknown spell "compute"
corrected: "Unknown Spell 'compute'. Available: calculate.
            Write the call again using one of those exact names."
# no native tool support at all? schemas travel in the prompt:
prompted:  <spell_call>{"spell": …}</spell_call>  ← parsed from plain text
Local-first, for real

Built for the models you actually run

Small local models break tool-calls: malformed JSON, hallucinated tools, missing arguments. Most frameworks assume a frontier API that never fails. Sanctum treats those failures as the normal case — a repair layer fixes what it can and converses the model through the rest, bounded by max_repair_rounds.

Validated end-to-end against llama.cpp: native grammar-constrained tools when the server supports them, automatic fallback to prompted calling when it doesn't. Never a proprietary API in the core.

Observability without services

See every superstep — no SaaS attached

Record a run with TraceRecorder and render it to a single self-contained HTML file: the graph, the timeline, every delta, every tool call. No accounts, no telemetry, no external requests — it works on a plane.

The sanctum trace viewer: graph, timeline and per-node detail rendered to a single HTML file
Positioning

An honest comparison

Sanctum doesn't chase feature parity with LangGraph. It competes on a niche: reliability with local 7–14B models, an impeccable out-of-the-box experience, and observability that never leaves your disk.

SanctumLangGraphn8n
Core dependencies0 (stdlib)langchain-core +Node.js stack
Local models as the defaultyes — the design centerpossiblevia integrations
Repairs broken tool-callsfirst-class layer
Tracing without a SaaSone local HTML fileLangSmith (cloud)self-host UI
Cyclic graphs / superstepsyes (Pregel/BSP)yes (Pregel/BSP)workflow DAG

Full 13-row comparison, including where LangGraph is the better choice →

Ecosystem

The engine and the spellbook

sanctum-engine

The orchestration engine — this project. Graphs, state, checkpoints, streaming, oracles, resilience, tracing.

GitHub · PyPI

AgentGrimoire

A community spellbook of local-first tools. Each spell carries a JSON manifest; Tome.load_from_directory() loads the whole tree into any agent in one line.

GitHub