TTaper Loading runtime…
Credential broker for AI agents · v0.1 · unaudited

The agent never holds the key. It asks the desk.

Coding agents keep deleting production because they're handed credentials. Taper is a locked box that holds the keys and only carries out the specific, narrow operations an agent is allowed to ask for — and a helper can always be given less, never more. This page runs the real library in your browser.

The token

A signed list of typed operations with constraints — ssh.exec on this host running this program, pg.query of this statement kind on these tables. It only ever narrows: a subagent gets a strictly smaller one, signed offline, and a widening block is rejected structurally rather than by policy.

The broker

A separate process under a different Unix user holds the real credentials. It checks proof of possession, validates the typed request, evaluates policy, and performs the operation itself. The credential is never in the agent's memory, environment, or shell.

The second boundary

Taper is never the only thing saying no. The database role can't ALTER; sshd runs a force-command. Scripts in the repo prove each target refuses the dangerous operation with the broker removed from the path.

If you had to explain it at dinner

Today's agents get the hotel's master key: it opens every door, and if the agent is confused or tricked, the wrong door opens. Taper is the front desk. The agent never touches a key. It says "open room 412," the desk checks its list, and a staff member opens that one door. The agent can hand a helper a shorter list — just 412, just for five minutes — but can never write a longer one. Every request, allowed or refused, goes in a ledger where tearing out a page leaves a visible gap.

What it is not

Not a sandbox (it mediates the paths that go through it, nothing else), not a model guardrail (no LLM in the decision path), and not audited — about two thousand lines of Python by one person. The measured result so far is deliberately modest: in a rebuild of the PocketOS incident, an agent with a credential and an agent with a token both did the job, ten out of ten. Taper doesn't stop an agent working; it bounds what else it could have done.

Playground

Six steps, one property each. Every button drives the unmodified taper package — nothing is mocked, nothing leaves this tab.

1Write a policy and mint the root token

A policy is an operation plus a constraint per field. This is the widest this token will ever be — everything downstream is a subset of it.

Do: read the policy (three operations, each with typed constraints), optionally edit it, then click Mint root token. Notice an unknown constraint kind is refused rather than ignored — an old verifier that skipped what it didn't understand would silently widen authority.

2–3Narrow it for a subagent, then try to widen it

The helper gets one host, one program, one argument, five minutes — and pg.query disappears entirely. No server is contacted: the parent signs a new block with an ephemeral key.

Do: click Narrow. Open "effective capabilities" on the result and compare it with the root token above. Then, for step 3, click Try to widen it — the subagent asks for a second host it never had.

4–5Make a request, attack, then steal the token

Order matters: proof of possession first, then the typed schema, then policy. A refusal quotes the constraint that refused it. An allowed request shows the exact argv the broker would execute.

Do: click Send request and open "what the broker would run". Then click any attack — they are the payloads from validate/redteam.py, including the four that got through the first time. For step 5, untick with proof of possession and send again: that's someone who copied the token text out of a log.
Attack payloads — each fills the request above and sends it

6Revoke, expire, tamper

Revocation matches any id in the chain, so revoking the root kills the subagent too. TTLs only shrink down the chain. And the audit log on the right is hash-chained — delete a record and it tells you where.

Do: click Revoke root token and read the subagent's refusal. Click Advance clock to see the 300-second token expire. Then, in the audit panel, click × on any record.