Work on Repeat
Menu
All posts

Trust

Why every tool starts disabled

Permission design for AI that acts — why capability and autonomy are two separate grants, and why a server's own safety hints cannot be trusted.

4 min readWork on Repeat — Product team

Connect an agent product to your systems and you usually get one switch: connected, or not. Once it flips, the agent can use whatever the integration exposes, whenever it decides to.

That design collapses two decisions that should never have been the same one.

Capability is not autonomy

"This routine may read our repository" and "this routine may act on our repository while nobody is watching" are different sentences. They carry different risk, and — importantly — they are usually decided at different moments.

You grant capability while designing the work. You are thinking about what the job needs: read the diff, read the issues, look at the security findings.

You grant autonomy after you have watched it work. You have read a trace, you have seen which tools it reaches for and how, and you have formed an opinion about whether it uses them sensibly.

Compressing those into one switch means you make the second decision at the moment you have the least information about it.

So Work on Repeat models three states rather than two:

State Model can see it Model can call it unattended
Disabled (the default) No No
Enabled Yes No
Enabled + automatic execution Yes Yes

Every discovered tool starts in the first row. Moving to the third requires a confirmation that names the specific tool and states plainly that it may read or change connected data. It is not a preference you set once for a project.

The hint problem

The Model Context Protocol lets a server annotate its tools. A tool can declare readOnlyHint: true, and a client can display that.

It is genuinely useful information. It is also, structurally, not authorization.

The annotation is supplied by the same server that implements the tool. If a client treats readOnlyHint as permission, then any server can grant itself permission by asserting it is harmless. The trust boundary and the thing being trusted are the same party.

This is not a hypothetical about malice. The ordinary version is drift: a tool that was read-only in v1 gains a write path in v4, and the annotation does not get updated because nothing forced it to.

So annotations are shown as context and ignored for authorization. The grant comes from you.

Rediscovery resets approvals

There is a related failure mode that is easy to miss. You approve a tool. Six weeks later the server changes what that tool does. Your approval is still sitting there, now attached to different behaviour.

When tools are rediscovered, prior approvals are cleared and the routine goes back to draft. You re-approve, and you re-prove with a manual run before it can be scheduled again.

That is deliberately annoying. The alternative is an approval that silently outlives the thing it described.

Two boundaries, not one

The tool policy is a good boundary. It should not be your only one.

The credential you hand a connection is the harder boundary, because it is enforced by the other system rather than by ours. A restricted Stripe key that cannot issue refunds is stronger than a tool policy that merely does not enable the refund tool — the first survives a bug in the second.

The practical rule: give the connection a credential that cannot perform the action you never want taken, then enable the narrow set of tools the work actually needs. Neither layer is redundant.

Prefer reversible write paths

When a routine does need to act, the shape of the action matters more than its size.

"Open a pull request" touches many files and changes nothing until a person says so. "Merge" touches one thing and is final. The first is a larger action and a smaller risk.

The same asymmetry shows up everywhere: draft versus publish, queue versus send, propose versus apply. Give routines the left-hand side. You keep the speed and someone keeps the veto.

What this costs

Being honest about the trade: this is more setup than flipping one switch. You discover tools per routine, you enable a handful, and you confirm automatic execution one tool at a time. First configuration takes a few extra minutes.

What you get back is the ability to answer, precisely, what a scheduled routine is permitted to do — without reading its instructions and hoping. Every call it made is in the trace, and every capability it holds was granted by a person on purpose.

For work that repeats fifty times a year while nobody watches, that is a good trade.


How tool permissions work in the documentation, including discovery, rediscovery, and the confirmation flow.

Try it

Give the responsibility a schedule.

Approved models, approved tools, bounded execution, and a trace of every run.

Put your first routine to work