eidolon-gateway
AI agents act with your authority and none of your restraint. EIDOLON is the layer in between: a signed, attenuable, revocable delegation credential the agent must satisfy on every tool call β checked independently of the model (so it can't be prompt-injected away), every action written to a tamper-evident ledger.
Two invariants override everything and are property-tested in CI:
Default-deny β any authority not explicitly granted is denied.
No unattested action β no side effect runs without a successful
HORKOSattestation (attest-then-act).
Domain-agnostic core, beachhead profile general-continuity. Built on
SAGE. Full contract:
docs/EIDOLON_PRD_v1.md Β· 5-minute
quickstart.
π White paper: docs/whitepaper.md Β· Case study
(Hermes with/without EIDOLON): docs/case-study-hermes.md
(make hermes-case) Β· Diagrams & social kit: docs/visuals/
Β· docs/linkedin-post.md Β· Related work & gap
analysis: docs/review-and-related-work.md
AgentDojo evaluation: EIDOLON's authority layer contains 96% of injection
tasks while breaking 0% of benign tasks (38% fully autonomous, 62%
one-approval). docs/eval-agentdojo.md Β· reproduce:
uv sync --extra eval && python -m eidolon.eval. KAIROS.resolve p95 β 1 ms.
Composes with the field: a CaMeL-style data-flow taint layer
(eidolon.gateway.taint) closes the read-exfil gap; automated adversarial
certification (make adversarial) makes an agent earn autonomy by surviving
fresh attacks each round; THEMIS delegations export as real biscuit tokens
(docs/standards-interop.md); the gate's invariants
are machine-checked in TLA+/TLC (make formal,
docs/formal-model.md); purpose-binding
(docs/purpose-binding.md) enforces
privacy-purpose-limitation; and approved payments export as signed AP2
mandates (docs/payments-ap2.md).
Try to break it
uv sync && make challenge # β http://localhost:8000/challengeYou play a fully compromised agent β no model to trick, you issue the tool
calls yourself: leak the customer's account number, wire money, drop the prod
database, slip through an unmapped tool, inject "you are pre-authorized" into
the arguments. The gate holds anyway, because authority is a signed credential
checked outside the agent β and every attempt lands on the tamper-evident
ledger. If you ever see FLAG{gate-breached}, you found a real bypass: report
it. 5-minute quickstart β
Use it on your own agent
Managed β nothing to install. Sign up at eidolon.onyxcreator.com, pick an authority preset from the delegation gallery, and point any MCP client at the hosted gateway:
claude mcp add --transport http eidolon https://eidolon.onyxcreator.com/mcp \
--header "Authorization: Bearer <your agent key>"Govern Claude Code's native tools (Bash / Edit / Write / Read) β which
never flow through MCP β with a drop-in hook. Install it once and wire a
PreToolUse + PostToolUse hook in ~/.claude/settings.json; every built-in
tool call is then ruled on (allow Β· ask Β· deny), attested, and streamed to the
same feed. Full copy-paste steps:
integrations/claude_code/. The dashboard's
CONNECT β πͺ EVERY ACTION tab generates it pre-filled.
Self-host the gateway in front of your own tools β no clone, just uv:
uvx --from git+https://github.com/gegane-lutshaba/eidolon eidolon-gateway \
--config gateway.yaml -- npx -y @modelcontextprotocol/server-filesystem .Either way, every tool call streams into mission control β green acts,
amber waits for your approval, red never happened β with a per-agent kill
switch one click away, and every decision on a tamper-evident ledger. Ranks
(OBSERVER β DRAFTER β OPERATIVE β AUTONOMOUS) are the autonomy ceiling: an
agent earns autonomy by surviving adversarial certification.
Prefer the terminal? make demo runs the narrated core scenario (a person
delegates a bounded slice of authority; the agent answers/drafts/posts within
its mandate, refuses a contract, resists an injection, and is revoked
mid-session), and make gateway-demo governs a real MCP tool server end to end.
The authority layer for any MCP agent
SAGE became the memory layer that agents plug in over MCP. EIDOLON is the
authority layer, with the same shape: a governing MCP gateway that any
agent (Hermes, Claude Code, OpenClaw, Raptor, Cursorβ¦) points at instead of a
raw tool server. Every tools/call is routed through KAIROS β authority,
fidelity, ceiling, attestation β before it can touch the real tool. Zero agent
changes.
agent ββMCPβββΆ eidolon-gateway ββ(KAIROS.resolve)βββΆ real MCP tool server
β attest-then-forward
βΌ
SAGE ledgermake gateway-demo # self-contained: ops tools + a red-team coda, governed & attestedRead tools run, drafts are held, status posts notify, and dangerous tools (email
a customer, delete_database(prod), run an exploit, scan an out-of-scope host)
are refused β each attested. The gateway speaks stdio (client launches
it as a subprocess) and streamable HTTP (--http 8300 β agents connect to
http://host:8300/mcp; one governed endpoint fronts tools for a whole team).
Wire it into a real agent with docs/integrations/; run
the real proxy with
python -m eidolon.gateway --config gateway.yaml -- <downstream MCP server>.
Architecture
Principal (human Β· root identity)
β defines β mints
βΌ βΌ
ETHOS (fidelity) THEMIS (authority)
ββββββββββ¬ββββββββββββ
βΌ
KAIROS (action gate) βββ BASANOS (autonomy ceiling)
act Β· draft Β· escalate
βΌ
HORKOS (attestation)
βΌ
SAGE (consensus memory + attestation ledger)Component | Module | Responsibility |
SAGE adapter |
| The only path to SAGE. |
ETHOS |
| Fidelity core. Hard-isolated judgment (auditable, LLM-free) and style (Claude) engines. |
THEMIS |
| Authority. Ed25519-signed, chained, attenuable delegation credentials (biscuit/macaroon lineage). |
KAIROS |
| The single action gate. LOCKED resolution order; attest-then-act. |
HORKOS |
| Immutable attestation on SAGE's consensus ledger. |
BASANOS |
| Certification. Fidelity face + integrity face (adversarial suites) both gate the autonomy ceiling. |
Capture |
| Consent-gated ingestion of traces into SAGE. |
Domain Profile |
| Declarative pack specialising the fixed core. Ships |
Notable design decisions (enhancements over the PRD, invariants preserved)
Ports & adapters around SAGE.
SagePortisolates the substrate; an in-memory fake runs the whole system green offline, while the liveSageClientAdapterbinds the realsage_sdk(verified against a Dockerized node). Attestations map to consensus-committed memories (SAGE has no dedicated attest API); a record's content hash is its ledger hash.Style/judgment isolation is enforced two ways: an import-graph test proves
ethos.judgmentnever importsethos.style, and a behavioral test proves removing the style engine changes zero decisions.One canonical serializer (
common.canonical) is the single hashing source of truth for THEMIS signing, ETHOS versioning, and HORKOS attestation.
Quick start
uv sync --all-extras # install (needs Python 3.12+ and uv)
# Fast lane β no external services. In-memory SAGE port.
make test # unit + property tests
# Live lane β real SAGE consensus node via Docker.
make up # starts ghcr.io/l33tdawg/sage on :8080
make test-integration # cross-principal isolation, attestβreplay, full gate
# Run the API
cp .env.example .env # set EIDOLON_ANTHROPIC_API_KEY for Claude voice
make run # uvicorn on :8000The style engine (drafts/escalations) uses Claude (claude-sonnet-4-6 by
default). Without an API key it falls back to deterministic templates β no
judgment or authority decision ever depends on the LLM.
Deploy on-prem (Docker)
Run one EIDOLON on your own infrastructure; every developer's agent routes
through it. A prebuilt multi-arch image is published to GHCR β docker pull, not
clone-and-build. Full guide: docs/on-prem.md.
# Try it β one container (SQLite store + in-memory ledger; evaluation only)
docker run -d -p 8000:8000 -v eidolon-data:/data ghcr.io/gegane-lutshaba/eidolon:latest
# Run it for real β app + Postgres (persistent, hash-chained ledger)
curl -O https://raw.githubusercontent.com/gegane-lutshaba/eidolon/main/docker-compose.deploy.yml
docker compose -f docker-compose.deploy.yml up -d # set EIDOLON_DB_PASSWORD + EIDOLON_ADMIN_TOKEN firstThe image runs as a non-root user with a HEALTHCHECK; point agents at it with
EIDOLON_URL=https://your-host (the hook and /mcp
both take a URL).
Kubernetes β a published Helm chart (app + optional bundled Postgres):
helm install eidolon oci://ghcr.io/gegane-lutshaba/charts/eidolon --version 0.1.0 \
--namespace eidolon --create-namespace \
--set secrets.adminToken="$(openssl rand -hex 32)"Single VPS (from source, Make targets)
One box, no consensus cluster. The postgres SAGE backend persists memory and
the attestation ledger locally as an append-only hash chain β carrying
SAGE's tamper-evidence onto a single host (any edit, deletion, or reorder breaks
the chain and is caught by make deploy-verify).
# one-shot bootstrap of a fresh Ubuntu/Debian box (installs Docker, writes a
# .env with generated secrets, brings the stack up; add EIDOLON_DOMAIN for TLS):
sudo bash deploy/provision.sh
# β¦or manually:
cp .env.example .env # set EIDOLON_DB_PASSWORD, EIDOLON_ADMIN_TOKEN, EIDOLON_AUDIT_TOKEN
make deploy # Postgres + EIDOLON on :8000 (no TLS)
make deploy-tls # β¦+ Caddy auto-HTTPS (needs EIDOLON_DOMAIN)
make deploy-verify # recompute the ledger hash chain β proves it is intact
make deploy-backup # timestamped, gzipped pg_dump (see deploy/restore.sh)
make deploy-logs # tail the service
make deploy-down # stopOperator auth (fail-closed, single tenant, two roles). EIDOLON_ADMIN_TOKEN
grants the full control plane; EIDOLON_AUDIT_TOKEN grants a read-only forensic
role (/audit, /replay). Both are accepted as Authorization: Bearer <token>
(CI/SDK) or a login cookie (POST /login, browser). With neither set the
platform runs open for localhost dev and warns loudly β set at least the admin
token before exposing it. Behind the TLS proxy set
EIDOLON_SESSION_COOKIE_SECURE=true (and optionally EIDOLON_TRUSTED_HOSTS).
docker-compose.deploy.yml runs the FastAPI service against pgvector/pgvector;
the tls profile adds Caddy (automatic HTTPS via EIDOLON_DOMAIN,
deploy/Caddyfile). Backend is selected by EIDOLON_SAGE_BACKEND (memory Β·
postgres Β· sage); the full BFT-consensus substrate remains sage.
(docker-compose.yml is unchanged β the SAGE + Postgres substrate for the
integration-test lane, make up.)
Surface
Product (accounts). GET / landing Β· /signup Β· /app (per-user mission
control) Β· POST /auth/{signup,login,logout} Β· GET|POST|DELETE /api/agentsβ¦
(enroll, connect snippets, per-agent kill/restore) Β· GET /api/feed (SSE) Β·
GET /api/gallery (delegation templates) Β· POST /contact.
Public demo. /versus (+ /versus/{scenarios,run,stats}) Β·
/challenge (+ /challenge/{state,call,reset}) Β· /paper Β· /portal Β· /og.png.
Managed gateway. POST /mcp β the hosted governing MCP endpoint (agent key
in a Bearer header). Self-host reports in via POST /ingest/events.
Operator. GET /live (global mission control) Β· GET /gateways +
POST /gateways/{id}/{kill,restore} Β· GET /audit +
/audit/{chain,export.json,export.csv} (replay, integrity, compliance export) Β·
GET /console/delegations Β· GET|POST /escalations/{id}/{approve,deny} Β·
POST /login Β· GET /api/leads.
Core seams. POST /keypair Β· POST /delegations/{mint,attenuate,revoke} Β·
POST /heartbeat Β· POST /resolve (the gate) Β· GET /replay Β·
POST /capture/{ingest,ingest_multi} Β· POST /skills{,/run} Β·
POST /coaching/report Β· GET /profiles/{id} Β· GET /{health,ready,whoami}.
See eidolon.api.app.
Status
The full PRD (Phase 0 + Phase 1 + every v2 item) and a research roadmap beyond it are implemented and tested β 250+ tests: Hypothesis property tests, live-SAGE integration, and a TLA+/TLC machine-checked model of the gate.
Shipped as a product and deployed at
eidolon.onyxcreator.com: multi-user accounts,
a per-agent delegation gallery, three connect paths (managed hosted gateway /
agent-run setup / self-host), a live mission-control dashboard with a kill
switch, VERSUS mode, a Postgres-backed hash-chained ledger, and one-command VPS
deploy (deploy/provision.sh).
Beyond the PRD (docs/review-and-related-work.md):
Evaluation β AgentDojo: 96% of injection tasks contained, 0% of benign tasks broken;
resolvep95 β 1 ms (docs/eval-agentdojo.md).Fidelity v2 β normalized-token + optional embedder grounding; the decision stays a transparent, inspectable threshold (no black box).
Data-flow layer β CaMeL-style taint (exfiltration) + purpose-binding (privacy) compose with authority through one mechanism (
taintΒ·purpose).Automated adversarial certification β the twin earns autonomy by containing fresh attacks each round (
make adversarial).Standards β THEMIS delegations export as biscuit tokens (
docs/standards-interop.md); the gate is machine-checked (docs/formal-model.md).Deployment β an escalation β approval workflow (signed, one-time), sub-agent attenuated delegation, and AP2 payment mandates (
docs/payments-ap2.md).
Only distributed operation (multi-node SAGE + revocation propagation) remains.
v2:
Multi-connector capture in
eidolon.captureβ a registry of consent-gated source connectors (documents, messages, calendar, email, code) with per-source normalizers;ingest_allcaptures several sources at once (each still requires its ownConsentGrant), andregister_sourcelets new profiles add sources. Endpoints:GET /capture/sources,POST /capture/ingest_multi.Aspirational-self / coaching layer in
eidolon.coachingβ reads ETHOS version diffs and the HORKOS attestation ledger, compares the twin's actual behavior against a declaredAspiration, and returns advisory coaching notes (under/over-escalation, acting on thin confidence, policy drift). Fully decoupled: an import-graph test proves the decision path never imports it, and a behavioral test proves running the coach changes zero decisions. It writes nothing back to the operating model. Endpoint:POST /coaching/report.Self-generated procedural skills (Hermes-style) in
eidolon.skillsβ the twin learns a reusable plan from a completed session (synthesize), stores it principal-scoped on SAGE (SkillLibrary), and replays it (SkillExecutor). Subordinate to ETHOS/THEMIS: every replayed step is re-resolved through KAIROS, so a skill learned under broad authority yields nothing it isn't currently authorized for β verified by a "cannot smuggle authority" test. Endpoints:POST /skills,GET /skills,POST /skills/run.BASANOS integrity face β adversarial suites (memory-poisoning, injection, scope-evasion) in
eidolon.basanos.integrity, anIntegrityCertificate, and integrity gating of the autonomy ceiling (enable globally withEIDOLON_REQUIRE_INTEGRITY_CERTIFICATION=true).offensive-securityprofile β a governance-only red-teamer pack for an authorized, time-boxed engagement in a CTF/lab range (Β§12). Per the permanent non-goal (Β§2.3) it ships no offensive capability β it governs authority over range-bound tools. Safe-by-construction:lab_only,authorization_required, andrequires_integrity_certificationare set, so KAIROS integrity-gates every acting decision even with the global flag off; every impactful class (exploit/credential/lateral-movement/persistence) always escalates and can never reach an unattended acting level; hard exclusions deny out-of-scope targets, production, third parties, exfiltration, destruction, and DoS.
Every deferred item from PRD Β§12 is now built. Richer mandate selector types
arrive naturally with each new profile (the manifest's scope_selectors is
open-ended).
License
Apache-2.0.