Every other agent stack eventually puts the real API key in the process the model is driving. Paladin never does. The agent holds paladin://stripe_sk — safe to log, safe in context — and the secret resolves only at egress. With sandboxed egress, the key never enters the tool process at all: Paladin makes the authenticated call itself.
Secrets live in one encrypted vault. The agent only ever receives a paladin:// pointer. Every resolution is gated by an explicit grant and written to a tamper-evident log — deny-by-default, always audited.
paladin://stripe_skThink password manager + .env manager for agents — but the agent gets a reference, never the secret. A human manages the vault like 1Password; the agent gets exactly one verb, through the broker, gated by a grant that names precisely who may resolve what, up to which authority band, optionally expiring.
The ordinary path injects a secret into a child process's environment — which any code in that child, including a prompt-injected payload, can read. Sandboxed egress closes that gap entirely. The tool runs under bwrap --unshare-all — no network at all, the vault masked, a rebuilt minimal environment — and its only way out is a Unix socket to Paladin. The tool sends an unauthenticated request; Paladin attaches the credential host-side and returns only the response. The key is never in an env var, never in memory, never in a *_FILE — verified by tests that confirm the secret is absent from the child's environment and /proc/self/environ, and that direct network egress is unreachable.
Honest scope: covers HTTP(S)-shaped secrets today; needs Linux + unprivileged user namespaces, and fails closed when that isn't available (it refuses rather than silently leaking to an env var). It confines the credential, not the data a call returns.
One AES-256-GCM vault, scrypt-derived key. Names, values, metadata, and the grant table all live inside the ciphertext — an attacker with the file learns only its size.
No requester resolves anything without an explicit grant naming it. Scope by host, method, and path; ceiling by authority band; expire on a TTL. The grant narrows, never widens.
The only way a value leaves the vault is into a child process Paladin launches — never in argv, never in this process, never printed by any CLI command.
Every resolve, deny, and grant lands in a hash-chained, HMAC-signed log. Editing, reordering, or truncating it breaks the chain — and forging one needs the vault key.
Every released value registers its hash. If a secret comes back in a tool result — even one the agent never saw go out — the guard trips and redacts before the model sees it.
pip install custodian-kernel[paladin] and you have a working vault with zero AI-agent framework installed. Paladin depends on nothing but cryptography.
No paladin command ever prints a secret — not list, not show, not an error. The only way a value leaves is egress into a child process you launch.
# store a secret (value prompted, never echoed) paladin add stripe_sk --profile prod --env-var STRIPE_SECRET_KEY # grant: exactly who may resolve what, scoped and expiring paladin grant 'stripe*' --to skill:stripe-spend \ --host api.stripe.com --method POST --path-prefix /v1/refunds --ttl 3600 # egress: run a command with the secret injected into ITS env paladin exec --with stripe_sk -- python bill.py # sandboxed egress: the child has no network but the broker socket — # the key never enters its process at all paladin exec --sandbox --as sandbox:job --with stripe_sk -- python tool.py # audit — walk the hash chain paladin audit verify
Paladin is standalone — it imports nothing from the kernel, and the kernel imports nothing from it (enforced by a test, not just documented). They meet only through the adapter convention.
Decides whether an action is allowed — bands, caps, kill switch. Its built-in adapters recognize the paladin:// URI by regex, the same way they'd recognize https:// — never by importing Paladin.
Decides whether a credential may be materialized for that action — and materializes it so the agent process never observes the value. Works with zero AI framework installed.
The one layer that imports both — wiring a specific broker to a specific kernel for a specific agent (Hermes). A future Claude/Codex integration would sit here, never inside the other two.
The agent can't steal a key it never holds, can't bypass a broker it must go through, and can't use a credential for a host the grant didn't authorize.