A minimal, local-first orchestration engine for AI agents: cyclic state graphs executed by supersteps (Pregel/BSP).
Project description
Sanctum
Where agents are summoned, bound, and set to work — a minimal, local-first orchestration engine for cyclic state graphs.
Sanctum models multi-agent orchestration as a ritual of invocation: knowledge lives in the Grimoire (tools), the Sanctum prepares and controls the ritual (the engine), entities are summoned (agents), and all of them cooperate over a shared energy — the Aether (state) — until a result is manifested. Beneath the metaphor sits a precise execution model: a cyclic state graph run by supersteps (Pregel/BSP), where nodes execute in parallel, return partial state deltas merged through per-channel reducers, and conditional edges close the loops that make agentic behavior (think → act → observe → …) possible. The core is pure Python standard library — no proprietary APIs, no mandatory dependencies — designed to run entirely on local models.
Documentation · Getting started · Comparison with LangGraph / n8n / ADK · Design document
Features
| Cyclic state graphs | BSP supersteps, static fan-out, conditional edges, cycles bounded by recursion_limit — not a DAG |
| Deterministic state | Per-Conduit reducers applied in Sigil insertion order; identical runs, even under parallelism |
| Wait-all joins | join="all" turns a Sigil into a barrier over its predecessors — uneven branches converge, across supersteps, surviving checkpoints |
| Circles — subgraphs | Mount a compiled Rite as one Sigil: a summoned agent becomes a node of a larger pipeline, its inner events echoed to the outer stream |
| Scatter — map-reduce | Fan out over a runtime-sized list with bounded concurrency; results land in item order |
| Local-first Oracles | Ollama (native & /v1), llama-server, vLLM, LM Studio, in-process GGUF — never a proprietary API in the core |
| Robust tool-calling | Malformed JSON repaired, unknown Spells corrected conversationally, prompted fallback for models without tools |
| Seals & time-travel | JSON checkpoints per superstep (memory/SQLite/Postgres), resume, interrupt() human-in-the-loop, replay from any Seal |
| Streaming Omens | Typed, timestamped events; combinable modes; live tokens from inside a Sigil |
| Resilience policies | Per-Sigil timeout, retries with backoff+jitter, fallback Sigils reading __errors__ |
| Wards middleware | Transform or veto deltas, observe every event: audit JSONL, usage tally, redaction |
| Local tracing | One-file HTML viewer, zero external requests: python -m sanctum.trace render run.sanctum-trace.json |
| Zero-dependency core | Python stdlib only; everything else is an optional extra |
Quickstart
pip install sanctum-engine
from sanctum import END, Ritual
ritual = Ritual()
ritual.add_sigil("cleanse", lambda aether: {"text": aether["text"].strip()})
ritual.add_sigil("transmute", lambda aether: {"text": aether["text"].upper()})
ritual.set_entry_point("cleanse")
ritual.add_edge("cleanse", "transmute")
ritual.add_edge("transmute", END)
rite = ritual.compile()
print(rite.invoke({"text": " fiat lux "}))
# {'text': 'FIAT LUX'}
Summoning an Entity
summon() builds the canonical ReAct loop (oracle → spells → oracle → …
→ END) entirely on the public primitives:
import asyncio
from sanctum import Tome, spell, summon
from sanctum.oracle.ollama import OllamaOracle # pip install "sanctum-engine[ollama]"
@spell
def word_count(text: str) -> int:
"""Count the words in a text."""
return len(text.split())
entity = summon(
OllamaOracle(arcana="qwen2.5:7b"),
Tome([word_count]),
role="You are a scribe.",
spell_calling="auto", # prompted fallback if the model lacks native tools
)
result = asyncio.run(entity.ainvoke(
{"messages": [{"role": "user", "content": "How many words in 'fiat lux'?"}]}
))
print(result["messages"][-1]["content"])
Examples
The examples/ gallery runs on scripted oracles by default —
no model required — and every script takes --oracle ollama:
quickstart_ollama.py— chat with a tool in thirty lines.research_ritual/— two entities scout in parallel (fan-out), a third synthesizes (fan-in, append reducer).human_in_the_loop/—interrupt()+ Codex: pause for approval, resume where it stopped.resilient_pipeline/— retries, timeouts, and a fallback Sigil in one observable run.sse_flask.py— bridgeastreamto Server-Sent Events.
Ecosystem
Sanctum owns execution; AgentGrimoire
owns capability — a folder-per-Spell tool library loadable by convention
with Tome.load_from_directory(path). Either side evolves without
touching the other.
Development
pip install -e ".[dev]"
ruff check . && pytest --cov=sanctum # unit suite: no models, no services
python benchmarks/superstep_overhead.py # engine overhead: tens of µs/superstep
Contributions welcome — see CONTRIBUTING.md (includes how to run the opt-in integration tests against a local Ollama) and the design document for the rationale behind every trade-off. Licensed MIT.
E N · S I
O M · G
· · I
∘ +· L
R + · ∘ L
E · +
H ∘ · V
M
T + · ✦ ∘
E ·· ···· · ·
··· ·· + S
A ∘ ··
· + ∘· A
∘ + ·· N
S ·C
V T T
I R · M V
the chamber is open · local-only · no telemetry
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sanctum_engine-0.4.0.tar.gz.
File metadata
- Download URL: sanctum_engine-0.4.0.tar.gz
- Upload date:
- Size: 177.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6858646715459478dd9656ac1558f4f9221fd742c861865cb103262a0b7b6eda
|
|
| MD5 |
a7a60a3b8822d6d2a1414c5f3b9d5dc9
|
|
| BLAKE2b-256 |
1331f6ffe696d8264ac28b53fe9fd7427437619e133c38f2d6b826175b523139
|
Provenance
The following attestation bundles were made for sanctum_engine-0.4.0.tar.gz:
Publisher:
release.yml on zquintero246/sanctum-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sanctum_engine-0.4.0.tar.gz -
Subject digest:
6858646715459478dd9656ac1558f4f9221fd742c861865cb103262a0b7b6eda - Sigstore transparency entry: 2211795700
- Sigstore integration time:
-
Permalink:
zquintero246/sanctum-engine@af91b6a1419ea155ac974970af872afa3783651e -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/zquintero246
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af91b6a1419ea155ac974970af872afa3783651e -
Trigger Event:
push
-
Statement type:
File details
Details for the file sanctum_engine-0.4.0-py3-none-any.whl.
File metadata
- Download URL: sanctum_engine-0.4.0-py3-none-any.whl
- Upload date:
- Size: 89.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ba7bcb3cb0372df4719bda93444e99f7acf97daf6bc5bfcd93d30e9a8f69fa1
|
|
| MD5 |
7da209031a029e37a752793035648d8a
|
|
| BLAKE2b-256 |
480c8d9e49bc8b309773034389533c32100e60804955ee62e86f8bbc25a3ca51
|
Provenance
The following attestation bundles were made for sanctum_engine-0.4.0-py3-none-any.whl:
Publisher:
release.yml on zquintero246/sanctum-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sanctum_engine-0.4.0-py3-none-any.whl -
Subject digest:
4ba7bcb3cb0372df4719bda93444e99f7acf97daf6bc5bfcd93d30e9a8f69fa1 - Sigstore transparency entry: 2211795715
- Sigstore integration time:
-
Permalink:
zquintero246/sanctum-engine@af91b6a1419ea155ac974970af872afa3783651e -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/zquintero246
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af91b6a1419ea155ac974970af872afa3783651e -
Trigger Event:
push
-
Statement type: