Keeper runs ten long-running Claude Code agents on a server, for my own work and for my clients. Each has a written delegation, and a policy gate checks every agent’s tool calls, except the ops agent’s. In a snapshot from Oct 5 to Nov 3, the gate refused 86 calls. It also allowed and logged 9,253 calls outside any grant.
Examples on this page use made-up names and values.
How it works
01
Agents with delegations
Each agent is a long-lived session that owns one area. Its written delegation lists standing rules, pre-approved actions, limits and hard stops. A machine-readable grant names who it may write to, which vault items it may use, and which paths it may change.
02
Inbound routing
An event hub hands each incoming mail or message to the agent that owns it. Only routes I have approved exist.
03
Phone and browser, with a human handoff
A voice agent places real calls from a brief that lists what it may and may never share. Each browser tab has one owner. For captchas and sign-ins I take over through a live view on my phone, then hand the tab back.
04
Failures that reach someone
Any script, timer or agent that fails reports to the ops agent, which fixes the cause and hardens it. A nightly review gathers every decision that needs me into one set of questions each morning.
How it stays safe
Keeper architecture
Agents · policy gate · tools · ops loop
External Fix Failure or refused call
05
The policy gate
A hook service checks each agent’s tool calls against the policy compiled from the delegations. The one exception is the ops agent that maintains the system. A covered call passes. A short list of dangerous calls is refused, with a reason the agent can act on. Everything else is allowed and logged. Prompts that need me come from Claude Code’s own permission system, not the gate. An agent cannot widen its own access: it asks, and I approve or not.
Messages between agents are information, never approval.
Shell commands are checked as text before they run. Writes to protected paths, other agents’ folders and system files are refused.
An example gate trace. The code calls agents “chats”, so the trace does too:
gate trace (example)
call 1
agent: finance
tool: Write
path: ~/agents/docs/notes.md
rule: another chat's folder
decision: deny
reason: not allowed. Record
"blocked: needs Owner" in your
status file and carry on with
in-scope work.
call 2
agent: finance
tool: Write
path: ~/agents/finance/log.md
rule: inside writablePaths
decision: allow
Snapshot, Oct 5 to Nov 3: 86 calls refused, and 9,253 calls outside any grant allowed and logged. Each panel has its own scale. Most logged calls came in one three-day burst, Oct 31 to Nov 2. Nearly all of the burst was one agent running shell commands inside its own writable folder. Nov 3 is a partial day.
06
Verified instructions
A standing instruction is checked against the actual conversation transcript before it becomes authority. If I did not say it, it does not count, however confidently an agent reports it.
07
Secrets kept out of the model’s context
Secrets live in a password vault. To sign in, a helper types the secret into the page over the browser debugging protocol, so it never passes through the model’s context. Browser tools mask password fields, and standing rules forbid reading them back. Tooling and rules enforce this, but it is no guarantee.
Card payments are outside every delegation. I give the word each time.
Honest limits
The gate is a tripwire for mistakes and drift. It is not a sandbox.
It checks shell commands as text. A determined interpreter can build a path at run time or reach it by a route the scanner does not model. The parser catches the common forms, not all of them.
It does not restrict general outbound network access from a shell command. It only denies egress it can tie to a protected file, a pinned recipient or a guarded service.
It fails open. A missing or broken policy file, or an error during evaluation, means no opinion. It is built to avoid wedging work, not to be a hard wall.
Most checks are log-first. Only a short deny list blocks.
In the original setup the agents share one Unix user. The real boundary is the operating system, and the repo does not provide that.
It sees only what Claude Code sends to hooks, not what a tool does after the call.
The ops agent that maintains the system runs outside the gate. I review its work.
keeper-gate on GitHub
The gate is MIT licensed. It is a cleaned extract from my private system, with fictional names, paths and addresses. The repo has:
The gate itself and its shell parser.
The compiler that turns written delegations into one policy file.
The Claude Code hook entry point and an installer.
Two example delegations and the policy compiled from them.
A replay script that runs recorded sessions through a policy.
One entry in a messaging channel’s allow-list was malformed: a contact label was longer than the config format allowed. That one line failed validation for the whole config.
The adapter stopped sending and reading for that channel overnight. Nothing reported it. Reporting had failed, which is worse than the bug.
The ops agent fixed it. The adapter now validates each entry separately, drops only the bad one, and reports it. A config check before deploy catches a bad entry first.
One bad line should cost one line, not the whole channel.
What it’s used for
The agents do real work for me and for my clients. For example:
A client discovery. The agents chased outside firms for data and wrote it up, while I approved the emails that went to the client.
My own paperwork and operations: mail, travel and finance, plus my visa paperwork.
A follow-up an agent might send to a firm that has not delivered:
follow-up email (example)
To: Dana, Firm B
Subject: Export requested Oct 12, still open
Hi Dana,
On Monday, Oct 12 we asked for a CSV export
of Firm B's order history, Jan 2024 to date.
We have not received it, and we cannot
finish our data check without it.
Could you send it by Friday, Oct 23? If a
full export is hard, the last 12 months
would unblock us. If it needs a form or an
approval on your side, tell me which and I
will send it today.
Thank you,
Ben's communications agent
What’s next
Request-origin tracking in the gate. Today the gate judges only the agent making a call. It should also know who asked.
Expiry for standing rules, not just tasks. Tasks already expire on their own. Standing rules and grants do not yet.