Writing · 2026-08-30
The agent that cannot merge
My autonomy daemon opens draft pull requests and nothing else, because the merge function was removed rather than forbidden.
The most important thing about my autonomy daemon is a tool it does not have.
It is called agentd. It runs on a schedule, works through a queue, and leaves draft pull requests for me to read. There is no merge function in it. Not disabled, not permission-gated, not fenced off by a line in a prompt. Absent. Git is not in the AI's toolset either. Draft PRs are opened by a separate deterministic path that the model can trigger but cannot steer, so the model never touches the repository directly, and secrets never enter its environment.
Let me be careful about how I describe this, because the marketing version is a lie. These are background agents, on your schedule. They start at an hour you pick, on hardware you control, and they stop at a budget you set.
There are two lanes. Monitors are deterministic read-only checks over the ontology graph and the repos: contract drift, gate failures, service-level breaches. On a healthy night they cost nothing, because nothing was asked of a model. Builders are spec-gated. Each one runs a free readiness check first, and if the spec is not ready, it stops there and spends nothing. If it is ready, the builder produces plan, scope, and task artifacts and opens them as a draft PR. A model is used where judgment is needed, within a budget you set. The nightly ceiling is hard, and when it is reached the daemon stops rather than degrading quietly.
Every PR traces back to a run ID. State survives interruption, which I proved by injecting crashes across a hundred runs and checking that no run came back unparseable. Crash safety sounds like a footnote until you remember that a daemon which loses its place is a daemon that repeats work you already reviewed.
Now the part I actually care about: why "cannot" beats "should not."
A prompt that says "never merge" is a request. It is a good request, and it works most of the time, which is exactly the problem, because most of the time is the failure mode. Prompts are text, and everything downstream of the model treats text as negotiable: a confusing diff, an unusual repo state, a well-meant instruction elsewhere in the context that reads as an exception. I do not want to reason about which of those cases my rule survives. I want the question to be unanswerable. A model can be talked out of a rule. It cannot be talked into calling a function that was never registered.
Capability removal is also the only guardrail that does not decay. Prompt rules rot as the surrounding system changes, and nobody notices, because a rule that is quietly no longer enforced looks identical to one that is. A missing function stays missing. It survives a bad night, a model upgrade, and my own future carelessness, which is the one I trust least.
The genuinely hard part was none of this. It was making the reports honest.
"I could not look" must never be reported as "nothing found." Those are two different outcomes and the system has to carry them separately from the check all the way up to me. A monitor that reached its source and found nothing wrong emits a clean result. A monitor that could not reach its source, because a credential expired or an extractor failed or the graph artifact was mid-rebuild, emits an unavailable result. Three outcomes, never two: found something, looked and clean, could not look.
Conflating the last two is precisely how an autonomy system lies to you, and it lies in the worst possible direction. A quiet morning reads as a good night. You start trusting the silence, and the silence has stopped meaning anything. Getting this right meant every monitor had to distinguish an empty result from an unavailable source, and every report had to preserve that difference without smoothing it into a summary sentence. Findings that need a person sit at an explicit awaiting-human state and are deduplicated across runs, so the same issue does not shout at me four mornings in a row while the real new thing scrolls past.
None of this makes the daemon good at engineering. It makes it safe to leave running, which is a smaller and more useful claim. The draft PRs still need me. Some are worth reading and some are not, and I have no measurement of the ratio.
Two things I cannot claim. It has run in exactly one place: the engineering team I work with at Genea, a physical-security company, depends on it every day, and nobody outside has tried to break it. And there is no benchmark on the quality of what it produces on the nights it runs. I know what it cannot do because I removed those functions and can show you the absence. I do not know how often what it does produce is worth the budget.
The part I have not solved: the daemon can tell me it could not look, but how much judgment is worth spending on what it did find is still a call I make by hand, every morning.