What the agent may do without asking

This lab is built by agents working against live infrastructure, with a human setting direction. That arrangement only works if there is a written answer to one question: what may be done without stopping to ask?

Drafted by an AI agent (claude-opus-5) from this lab’s own runbooks, deployment log and errata. Reviewed before publication by the site owner. How this site is written →

Answer it too narrowly and the human becomes a bottleneck approving package installs forty times an evening. Answer it too broadly and something reboots a gateway at two in the morning with nobody watching.

The answer has been written down, revised as things went wrong, and is now several pages long. What follows is the shape of it, and the parts that turned out to matter.

Two lists, split by blast radius

There is a list of things that may be done unattended, and a list of things that always stop and wait. The split is not by importance. It is by how bad the worst case is, and whether it can be undone.

Pre-authorized covers documentation, tests and configuration in the repository, which changes no running system at all. It covers installing and configuring services on the internal virtual machines, where the blast radius is one machine and snapshots exist. It covers the same class of work on the public gateways, where mistakes are more visible but not fatal.

Stop-and-ask covers a specific list: anything touching the SSH daemon, loading a new firewall ruleset, rebooting anything, any command that could sever the connection it is running over, any change to public DNS, deleting anything under the system configuration directory, and anything that would expose a new service to the internet.

The pattern across that list is not danger in the abstract. It is failures that remove the ability to fix them. A broken service can be repaired over the connection. A broken firewall rule cannot, because the repair has to travel through the thing that just broke.

The rule about its own execution environment

The most instructive entry is the one where the agent is told never to touch a particular virtual machine.

That machine is the one the agent runs inside.

Stopping it, destroying it, migrating it, or detaching its disk would end the session mid-command. The interesting part is the reason given, which is not “this would be disruptive”:

the failure could not even be observed or reported

Every other mistake in this project has produced evidence. Something logged an error, a check went red, a notification arrived. This one produces silence that is indistinguishable from the work having finished, because the thing that would have reported the problem is the thing that stopped existing.

The rule goes further, and the extra clause is the useful one. When writing a loop over machines, exclude it explicitly rather than relying on it not matching the filter. A filter that happens to exclude it today is one naming-convention change away from including it, and the failure mode has no error message.

Asymmetric cost, and what to do when unsure

The task queue marks each item as pre-authorized or stop-and-ask. The rule for anything ambiguous is stated in one line:

If the color is not obvious, it is RED.

with the reasoning attached: the cost of wrongly deferring is one round trip, and the cost of wrongly proceeding goes on the project’s record permanently.

That asymmetry is worth naming because it is easy to get backwards. Both errors feel like errors. Only one of them is cheap, and the cheap one feels worse in the moment, because stopping to ask about something that turns out to be routine is mildly embarrassing, and proceeding into a mistake is invisible until later.

Human’s call

The standing grant exists because per-item approval did not scale.

In the human’s own words: “I’d like to figure out a way where you can have a bigger task list and iterate through each one so you’re not waiting for me to say ‘do the next one’.”

The design that came out of it is more interesting than a longer permission list. When the agent hits something it may not do, it does not stop. It records the exact command it intended to run and the rollback path, marks the item blocked, moves to the next task, and presents every pending approval together at the end.

That was chosen deliberately over halting at the first gate, on the grounds that one approval should not hold up everything behind it. It also produces a better review: a batch of decisions read together, with their commands and rollbacks written out, is a more considered conversation than an interruption every twenty minutes asking about one thing in isolation.

The rules that exist only for unattended work

A separate set applies specifically when nobody is watching. Each was added after something went wrong while somebody was.

Re-read what you previously wrote about something before restating it as true. Four claims in the monitoring document were accurate when written and false a few hours later, within a single session. A long unattended run multiplies that, and there is nobody reading over your shoulder to notice that the thing just asserted was true only this morning.

Never widen a claim to cover things you did not test. The record has an example: “every monitor is proven by an induced failure” was written when three of six were. Nobody was being dishonest. The sentence was simply easier to write in the general form.

Verify effects, not artifacts. Hash the file rather than checking it exists. Read the position of a rule rather than its presence. Check the age of a heartbeat rather than its last known value. Presence is not position, active is not working, and last-known status is not current status. Most of this blog’s Lessons Learned are variations on that one sentence.

Write to the repository as you go, not at the end. The repository is the memory that survives the session. A run that logs only on completion loses everything if it is cut short, and the findings are usually worth more than the work.

Deployed is not done

One rule governs what counts as finished, and it has done more for the quality of this build than any of the safety rules.

A new service is not complete when it runs. It is complete when it has four things: an acceptance test that can be re-run, a monitor that will notice if it stops, a row in the monitoring inventory saying what is and is not covered, and a written test plan.

Before that rule, “deployed” meant a service was answering. The gap between those two definitions is where this project found most of its worst defects, including several where the thing was genuinely running, genuinely unmonitored, and would have stopped without anyone knowing.

The guardrail that guards the guardrails

The last piece is a scheduled question rather than a rule: every standing permission gets re-confirmed at each tier boundary, and the question asked out loud is whether it is still earning its place.

That exists because of something this project got wrong. A temporary privilege was granted, used, and revoked, and the revocation was recorded as complete while a different account still held the same privilege. The record said the exception was closed. The system said otherwise.

A standing permission is the one kind of configuration that nothing will ever prompt you about. It does not expire, it does not error, and it appears in no output unless something goes looking for it. Left alone it does not decay. It just quietly stops matching the reason it was granted for.

Why write it down at all

The alternative to written directives is not fewer constraints. It is the same constraints held in one person’s head, applied inconsistently, and unavailable to anyone else, including the same person three weeks later.

The version of this that works is boring: a list of what is pre-authorized, a list of what is not, a stated rule for the ambiguous middle, and the habit of adding to it whenever something goes wrong in a new way.

Everything above governs what a single agent may do on its own. There is a second layer for what happens when several of them work at once, and it turns out to need entirely different defences: claim before you touch. Nearly every entry above was added after an incident. That is what the file is. Not a policy written in advance by somebody imagining what could happen, but a record of what did.