Isolated Enough to Be Safe, Integrated Enough to Be Useful

My agents read my lab notes, draft posts, open pull requests, and run playbooks against lab gear. I want all of that, and I also want to be able to lose any one agent without losing sleep. Those two wants pull in opposite directions, and the design that holds them together is a boundary that lives outside the agent.

An agent that can expand its own access is an administrator with a chat interface. So none of the controls below live on the agent. They live in the firewall, the secrets manager, the Git server, and the run system, places the agent has no route to change.

Start with the network

Every agent runs in its own unprivileged container. No root, no host access, no installing packages, no firewall changes. A container is disposable by design: if one gets compromised I rebuild it from an image and the agent loses nothing it cares about.

The containers sit in their own segment, away from management interfaces, and the reach out of that segment is short. Agents use a read-only memory gateway to search my notes and prior work, plus a handful of fixed API endpoints for the services they are allowed to use. The gateway is a forced command with no write path. Read is read; there is no second mode.

Short tokens and a wrapper that owns the password

Agents do not hold passwords, and I mean that literally. When an agent needs a secret it asks the secrets manager, gets a token scoped to one namespace, and the token expires after the job. There is nothing durable on the agent’s disk worth stealing.

The publishing path is the same idea taken further. The agent creates drafts through a wrapper that fetches the application password itself. The agent never sees the password and cannot print it. The wrapper also rejects the fields the agent account is not allowed to change. I watched it return 403 when an agent tried to edit a post it did not own. That refusal is the point, and seeing it in a log is the closest thing to a health check this system has.

Git: contributor by default

Agent accounts on the Git server are contributors. They open branches and pull requests, and that is where their write power ends. No pushes to main, no force-push, no self-merge. A merge needs a human and a green pipeline.

The pipeline is not optional. Every push runs the same checks as mine: secret scanning with gitleaks, plus the project tests and lint. A commit that leaks a token fails, and the branch cannot merge until the leak is gone. The agent account cannot turn the checks off, because it cannot change repository settings, and it cannot rewrite history because force-push is denied at the server.

Automation stays scoped

Agents can run automation, but the run system holds fixed templates, one per approved playbook. A template names the playbook, the allowed inventory, and the fixed arguments. There is no field for free text and no way to point a template at an arbitrary playbook.

Before an agent may act, three questions get answered, and any yes stops it:

Does it change state outside the approved inventory? Does it need a credential the wrapper cannot provide? Does it require a role the account does not have? The third one is why there is no template for the core network gear or the hypervisor. No template, no run. The scoping does the enforcing for me.

How I test it

I try the denied paths on purpose, at least weekly. Push to main as the agent account: rejected. Run a playbook with no template: refused. Ask the wrapper for a field the account cannot change: 403. Read a password from the agent’s own session: not possible, because the password was never there. The checks also run without me: every push goes through the secret scan and the test pipeline, and every automation run lands in the run log.

The useful part and the honest limit

None of this makes the agents useless. They still read every document, search prior work, draft posts, open pull requests, and run the approved lab playbooks. The boundary removes actions that need review, and every remaining action lands somewhere reviewable: a pull request, a draft, or a run log.

The limit is that the whole thing only holds if the policies behind it stay correct. A template added without review or a token scoped too wide widens the agent’s reach, and the controls do nothing against an agent probing the network from inside its container. That is why the container is disposable and the tokens are short-lived. When something changes, I re-check the boundary the same way I test it.