Open-source governance for AI agents: give every agent a scoped identity and a kill switch, gate every model, tool, and command it uses through Agenthof's doors, run it credential-starved in an isolated sandbox, and keep a verifiable ledger of who ran what.
Define your AI workforce as roles in YAML — a role owns workflows, a workflow
composes agents. Agents hold no credentials of their own: every model, tool,
sub-agent, or command an agent reaches goes through an Agenthof gateway that
authorizes it, injects the credential the agent never sees, and records it —
attributed to the human who asked. Each agent runs in an operator-provided
sandbox (a no-network reference runtime ships in deploy/refbox); that sandbox's
confinement is the operator's responsibility, and Agenthof records what crossed
the door rather than trusting the agent.
Agenthof — from the German Hof: the court. Where your agents are housed, and what they answer to.
One governed run through every door — model, exec, tool, and sub-agent spawn — then investigate --run shows the whole tree and audit verify confirms the hash-chained ledger. Recorded against the hermetic harness (stand-ins, no container runtime; the containment proof is make acceptance-podman). See the quickstart, the demos, and governance in action.
Agenthof is a governance layer for AI agents:
- a scoped identity and kill switch for every agent;
- credential-injecting gateways for the four doors an agent uses — model, tool/MCP, exec, and spawn — so the agent reaches each one through Agenthof and never holds the credential itself;
- least privilege by default — an agent reaches a tool only because you named it; naming none is rejected, never silently widened to every tool;
- a hash-chained audit ledger that attributes every action and refusal to the human who asked, with OIDC + RBAC on every door.
Agenthof is not a sandbox, and doesn't pretend to be:
- it governs and audits; it does not contain the agent. Confinement is the
operator's sandbox's job — a no-network reference runtime ships in
deploy/refbox, but that containment guarantee is the sandbox's, not Agenthof's; - the ledger is tamper-evident, not tamper-proof — hash-chaining makes edits detectable, not impossible. Operator signing of the installed configuration and external anchoring of the ledger head extend that evidence — an install the ledger does not vouch for is refused at every execution read, a pinned execution point also refuses one signed by another key, unsigned, replayed, or rolled back, and a rewrite of the whole control root is detectable by anyone holding an anchored head's reference and the log's key — and none of it makes the ledger tamper-proof;
- its enforcement is self-enforcement, not third-party enforcement: an
agent cannot exceed its grant without the gateway agreeing, and the gateway
is yours. A refused call is stated up front in
agenthof audit. Independent corroboration of the gateway's decisions is a reserved future direction, not something claimed today; - only shipped items are guarantees — what is shipped versus coming is in the roadmap.
Pre-release, and the governed core is real and runnable today:
- config → validated registry → event-sourced engine (linear + fail-back).
Every agent is an external service Agenthof reaches over HTTP or a local Unix
socket; a minimal reference agent ships in
examples/echo-agent; - agents are credential-starved and reach everything through gateways — the
model and tool/MCP doors are enforced (Agenthof sits in the call path
and injects the per-role or per-resource credential the agent never holds); a
stdio-only MCP server is reached the same way through the reference bridge in
deploy/refbridge, which attests first-hand what it ran on every call, recorded when the resource declaresruntime: refbridge; the exec door is first-hand through the reference runtime indeploy/refexec, which runs the allowlisted command in a confined compartment with direct network access denied (rootless podman on Linux, macOS Seatbelt) and attests what ran — Agenthof records that account and never runs the command itself (an agent's own report of a command is refused and recorded); and the spawn door runs each sub-agent as its own governed child run — run in its own compartments and workspace by the reference supervisor indeploy/refspawn— with the caller's delegation binding carried down; - isolated agents — a reference sandbox runtime (
deploy/refbox) runs an agent — a Go echo agent or a Python LangChain agent, both shipped as reference images — with no network at all, reaching Agenthof only over a bind-mounted Unix socket, so credential-starvation and no-egress hold by construction on the operator's host. What the runtime does and does not guarantee is stated plainly, not assumed; - a hash-chained ledger where every action and refusal is attributed to the
human who invoked it, with
audit verifyfor integrity; - the kill switch and OIDC + RBAC, with every door governed and recorded;
- a control-plane audit — every
applyand kill-switch flip is recorded to its own hash-chained control ledger, attributed to the human who invoked it, withaudit control,audit verify control, andaudit repair control; - a control-plane API —
agenthof servehosts concurrent runs as a long-lived process, verifies the human's OIDC token on every call, and takesapplyandconfig pullover the network —applyunder a compare-and-swap on the installed hash (seedocs/reference/serve.md); - installed, content-addressed configuration —
applyinstalls a validated snapshot under its hash, andrun,serveand the control commands execute and authorize against that snapshot, its bytes verified against the hash on every read — never the working directory; - integrity in layers, each with its bound stated — the execution and
authorization reads require the control ledger to vouch for the installed
pointer as its last recorded install; the install can be signed by the
operator and verified against a pinned key at the execution point before
it runs; and the control-ledger head can be anchored into a transparency
log (
anchor: tlog,audit anchor) and checked byaudit verify control, which fails only on a head the chain no longer reproduces, a proof that fails under a verified key, or a log answering with a different body for the recorded entry, and reports a log it cannot reach or a key it does not hold as unverifiable, never as tampering (seedocs/control-plane-lifecycle.mdanddocs/reference/config.md); - a control ledger that seals and rotates —
audit sealcloses the active log into a sealed segment and opens a fresh one, so a long-running control ledger is an ordered set of sealed segments plus a live active, read, verified and appended as one hash chain with one sequence; the seal is itself a recorded, authorized control action, and an interrupted rotation is completed on the next run, never left broken. The limit is stated plainly: a sealed segment is a regular file whoever owns the host can still rewrite — the chain detects a dropped, duplicated, reordered or inconsistently edited segment, not a consistent rewrite of the whole set. Declaringsink: wormbuilds on that foundation: each seal also writes the sealed segment's exact bytes to write-once storage you bring (S3 Object Lock, compliance mode), under a retention lock the provider enforces, and does not complete until that copy is confirmed;audit verify controlfails on a copy that is missing, under-locked or holds other bytes, andaudit restore controlputs a damaged sealed segment back from it. The bound is stated too: the active segment and every local file stay ordinary files, and the copy is protected for the retention period alone, by the provider's compliance mode, not by Agenthof.sink: externalremains reserved (seedocs/control-plane-lifecycle.md); - incident investigation —
agenthof investigatemerges the control log and every run log into one filterable, time-ordered timeline (human or--json), andaudit <run-id>names the exactapplythat put a run's config on record.
The reference runtimes (ref*) are operator-side runtimes that run on the
host and drive the operator's confinement backend — rootless podman, or macOS
Seatbelt for refexec and refspawn — so the agent reaches a capability only through
Agenthof and the operator's sandbox contains it — Agenthof itself runs and
isolates nothing. Each ships as a reference you can run or replace:
deploy/refbox— the no-network sandbox an agent runs in, reaching Agenthof only over a bind-mounted Unix socket;deploy/refexec— runs an allowlisted command first-hand in a confined compartment (rootless podman or macOS Seatbelt, with the tier named in the ledger) and attests what ran (the exec door);deploy/refbridge— fronts a stdio-only MCP server over a socket and attests first-hand on every call (the tool door for stdio tools);deploy/refspawn— gives each sub-agent run its own compartments and workspace, under the same selectable confinement tiers as refexec (the spawn door).
The containment guarantee is the sandbox's, not Agenthof's, and is stated plainly in each runtime's docs.
What's shipped versus what's coming — governed skills, multi-resource scope, finer-grained privileges — is laid out in the roadmap. Only shipped items are guarantees.
Requires: Go >= 1.27 toolchain; Linux or macOS.
Agents are external HTTP services. The example config points every agent at
http://127.0.0.1:8080/, where examples/echo-agent — a credential-free
reference agent — listens. Start it first, in its own terminal, and leave it
running:
go run ./examples/echo-agent
Then, from the repository root:
go build -o agenthof ./cmd/agenthof
./agenthof apply --as [email protected] --groups platform-eng --config examples/config
./agenthof run software-engineer fix-bug --input "fix the login bug" --as [email protected] --config examples/config
./agenthof audit <run-id>
apply prints the registry summary and records itself to the control ledger,
attributed to --as (or your OS user if omitted):
registry ok: 5 agents, 2 workflows, 3 roles
control head: seq=1 sha256=<hex>
The first apply on a fresh checkout is a bootstrap: nothing is installed
yet, so it is permitted and installs the example config. From then on
--groups platform-eng is what authorizes control changes: the installed
config's platform-admin role grants the control-plane operations to that
group, and a caller no role grants is refused — and that refusal is recorded.
run executes what apply installed, from the same --control-log (pass the
same path to both when you pass one) — edit the directory, then apply; until
something is installed, run is refused and names the apply to run.
run prints the run id it assigned (run <run-id> finished: succeeded). Pass
that id to audit to see who asked, what ran, and whether the record can be
trusted:
run <run-id> — fix-bug (role software-engineer)
invoked by [email protected] (asserted, issuer local)
status: succeeded
ledger integrity: verified (8 events)
...
step plan succeeded — artifact f7459994: fix the login bug
step code succeeded — artifact f7459994: fix the login bug
step review succeeded — artifact f7459994: fix the login bug
See docs/quickstart.md for the kill switch, retention,
choosing another port if 8080 is taken, and the full walkthrough. audit control shows the control-plane audit.
agenthof apply ./config # roles, workflows, agents — validated, governed
agenthof run software-engineer fix-bug --input "..."
agenthof audit <run-id> # who asked → what ran → what it touched
agenthof investigate --since 24h --agent coder --outcome refused
agenthof investigate --json | jq # the stable investigate/1 contract
agenthof investigate --json | jq -r '.events[].anchor.verdict // empty' # each successful anchor's offline verdict: verified | mismatch | unverifiable
One filterable, time-ordered timeline across the control plane and every run —
who changed what, which apply authorized each run's config, and whether the
record can be trusted. Integrity is always shown, never assumed; an anchored
head's verdict is shown on its event (informational — audit verify control
is the gate). See
docs/reference/config.md for the flags, exit codes,
and the investigate/1 JSON contract.
Walk through CONFIG (registry management), AUDIT (run traceability), GOVERNANCE (RBAC), and INVESTIGATE (incident investigation across the control plane and every run) with scripted end-to-end examples.
See docs/demo.md for the full walkthrough.
ROADMAP.md— what's shipped, next, later, and exploratory.docs/quickstart.md— build, run, kill switch, retention.docs/agent-protocol.md— the agent wire contract: how to build an agent in any language (the step JSON, the gateway headers, and the model/tool/exec/spawn call patterns).docs/showcase.md— governance in action: a real model choosing the doors on its own, and how to read the audit that proves it was governed (bring your own provider key; not a CI run).docs/concepts.md— the ideas behind Agenthof: planes, gateways, identity, the ledger.docs/lifecycle.md— the life of a run: how one invocation flows through identity, authorization, execution, and the ledger, including the isolated compartment an agent runs in.docs/lifecycle-model.md— the life of a model call: logical model, injected provider key,model_call.docs/lifecycle-exec.md— the life of an exec: allowlist, the operator's runtime, and the first-hand record.docs/lifecycle-tool.md— the life of a tool call: the two MCP legs, the injected resource credential, andtool_call.docs/lifecycle-spawn.md— the life of a spawn: a governed child run under the same human, in compartments of its own, bounded and linked to its parent.docs/control-plane-lifecycle.md— the life of a control action: apply, the kill switch, the control ledger, and the life of an anchor that pins its head to a transparency log.docs/reference/config.md— every YAML field, required/optional, defaults, and validation rules.docs/reference/logging.md— the operational log on stderr: levels, formats, fields, and what is never logged.docs/reference/serve.md— the control-plane API: the endpoints, per-call authentication, applying configuration over the API with a compare-and-swap, binding and TLS, who may read, and the honest limits.docs/demo.md— the scripted demos (CONFIG, AUDIT, GOVERNANCE, INVESTIGATE).docs/constitution.md— the binding invariants every change must honor.docs/standards.md— the security & AI-governance standards and prior art Agenthof aligns with, mapped to the design.
Agenthof's guarantees build on established security and governance standards, not novel claims. The design aligns with — honestly, alignment not certification:
- Least privilege & zero trust — Saltzer & Schroeder; NIST SP 800-207.
- Access control & audit — NIST SP 800-53 (AC/AU families); NIST RBAC.
- Identity — OpenID Connect + OAuth 2.0 client-credentials.
- Tamper-evident audit — Schneier–Kelsey and Crosby–Wallach; Certificate
Transparency (RFC 9162) for external anchoring of the control-ledger head
(
anchor: tlog). - Tool / MCP security — the MCP Authorization spec's no-token-passthrough mandate.
- AI governance & agent threats — OWASP Top 10 for Agentic Applications, NIST AI RMF, MITRE ATLAS, the EU AI Act.
The full mapping — each standard to the Agenthof guarantee it supports, with
links, and where the design deliberately diverges — is in
docs/standards.md.
Beyond standards, Agenthof takes inspiration from the agent-infrastructure ecosystem — notably agentgateway (a governed data plane for agent-to-tool and agent-to-agent traffic) and SPIFFE/SPIRE (cryptographic workload identity). Agenthof sits at a different layer: a governance-only control plane — not a harness, not just a proxy — where every action carries three verifiable identities, passes through governed doors, and is recorded in an append-only, hash-chained ledger, with behavior traceable to declarative config (config is law).
Apache-2.0
Every change is held to the invariants in
docs/constitution.md: containment, identity, the
ledger, compliance floors, the license, and scope discipline. They change
only by an explicit commit that amends that file.
How the project is maintained — and why trust rests on the license, the constitution, and the DCO rather than on any identity — is in GOVERNANCE.md.
Contributions are welcome under the DCO — see CONTRIBUTING.md. Security reports: see SECURITY.md.
