Quickstart
Three commands to a gateway that stops a runaway agent at a budget — no secrets required.
The 3-command path (docker)
No API keys needed: the stack ships a mock provider, so you see real enforcement (real mandate, real ledger, real witness) with zero setup.
git clone https://github.com/mandarelabs/mandare && cd mandaredocker compose up -d --waitdocker compose run --rm demoThe demo releases a runaway agent loop against your gateway. It will not
stop on its own — the €20/day mandate stops it: 23 calls settle €19.17, then
call #24's reservation would cross €20 and the loop dies with
403 PER_DAY_EXCEEDED. The refusal is itself a ledger entry, and mandare verify proves the
chain is valid, the budget counters equal a fresh replay of the ledger, and
the witnessed head history covers the whole chain.
Then open the dashboard: http://127.0.0.1:8788 — fleet view, spend per
agent, the ledger trail, and a working kill button. Its witness badge is
labeled SELF-ANCHORED: out of the box it checks the witness under the source
the ledger file declares. Give the dashboard the door's public key
out-of-band (MANDARE_DOOR_PUBLIC_KEY) to bind it — see
Self-hosting.
What's running:
| Service | Port (loopback only) | Role |
|---|---|---|
gateway | 8484 | The door: policy → ledger → provider |
witness | 9411 | External head history (mock anchor by default) |
dashboard | 8788 | Fleet view over the ledger |
mock-provider | — | Stands in for Anthropic/OpenAI (no secrets) |
Point it at real providers
Put real keys in .env (compose picks it up) and override the mock base URL:
cp .env.example .env
# in .env:
# ANTHROPIC_API_KEY=sk-ant-...
# ANTHROPIC_BASE_URL=https://api.anthropic.com
docker compose up -d --force-recreate gatewayYour agents keep their existing SDKs — point them at the door:
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({ baseURL: 'http://127.0.0.1:8484' });Every call is now metered against the mandate and recorded on the ledger.
Keys in .env behind an unauthenticated door are a starting point, not a
boundary. Any process on the host that can read .env — including a hijacked
agent — can take the provider key and call the provider directly, bypassing
the mandate; and anything that can reach the door's port can spend through
it. Before real agents run against real money, move provider keys into the
vault and turn on token or passport auth — see
Self-hosting.
For authenticated doors (scoped tokens / passports), see SDKs.
No docker: the solo installer
./install.shpnpm demoinstall.sh checks Node ≥ 22.13, installs with a frozen lockfile (install
scripts stay disabled — see Security), builds, and links
./bin/mandare. pnpm demo is the same runaway-loop acceptance test CI runs.
Issue a real mandate
The demo mandate is a generated dev artifact. The real flow takes two commands — the human signs once, the gateway enforces every call:
./bin/mandare passport issue --agent-name my-agent
./bin/mandare mandate issue --agent <did:key from above> \
--per-tx 5 --per-day 20 --total 100 --approval-above 5 \
--out mandate.sdjwt
MANDARE_MANDATE_PATH=mandate.sdjwt <restart the gateway>passport issue writes the credential and the agent's private key (0600)
to ~/.mandare/agents/ — outside your checkout, so a git add -A or a
docker build can't pick the key up.
Everything else — vault-backed credentials, witness keys, card rail — is in Self-hosting.