Short answers to what readers ask most about this topic.
01Why does an autonomous agent sometimes produce zero commits?
Because an open-ended brief has no completion criterion the agent can check, no turn budget, and it rewards choosing the hardest item. The agent explores until the limit is reached, and exploring feels productive. The fix is a numbered procedure with explicit turn budgets and a rule that a zero-commit run is a failure.
02Which instruction surface actually controls an agent's behaviour?
The persistent instruction file, not the one-shot run prompt. In my project a daily brief asking for a specific feature was overridden by the persistent file's own priorities — the agent fixed a red pipeline instead, which was the better call. Steer through the durable surfaces and a curated backlog, not through today's message.
03What is a landing deadline and why does it matter?
A turn number after which the agent stops adding commits and spends its remaining budget pushing, opening the pull request and merging. Without it a run can produce eleven good commits, use every turn doing so, and strand them on a branch nobody merged. A guaranteed merge of six commits beats eleven unreachable ones.
04What kind of task fits inside one unattended run?
One test for one uncovered branch, one type tightened or exhaustiveness check added, one small documented bug fix with a regression test, or one documentation correction. What does not fit: new features, anything requiring a new dependency, and anything touching more than a handful of files.
05How should you verify that an agent's merge really happened?
Against the platform API, not against your own monitoring script. Mine reported a merge that never occurred because it compared origin against a hardcoded base commit, and a false success report is more damaging than no report. Read one full run log end to end as well — turn counts and retries are visible only there.
Autonomous Agent Prompt Design: Tiny Commits That Land
Why an open-ended daily brief produces zero commits, and the numbered procedure — first commit by turn six, land by turn thirty — that produced merged PRs.
An unattended agent given an open-ended task explores until it runs out of turns and commits nothing. Replacing the brief with a numbered procedure — one small item, first commit within six turns, push early, stop committing by turn thirty, never end with zero commits — turned floundering runs into merged pull requests.
My daily coding agent spent two consecutive nights doing this: create a branch, read files for thirty-five turns, and stop. No commits, no pull request, no error. The model was working exactly as instructed, and the instruction was the problem.
What follows is the difference between a brief that sounds reasonable to a human and a procedure that a weaker model can actually execute unattended. It is the single highest-leverage thing I changed in the whole project.
Why open-ended briefs fail unattended
Pick the top item from the backlog and implement it is a perfectly good instruction for a person. For an unattended agent on a limited budget it has three fatal properties.
It has no completion criterion the agent can check. Implement it is satisfied by an arbitrary amount of reading, and reading feels productive.
It has no turn budget. Every run is a race against a limit the brief never mentions, so the agent discovers the limit by hitting it.
It rewards ambition. The top item is usually the hardest item, which is the worst possible choice for a run that must finish in one sitting.
The most expensive version of this I saw was a run that spent eighty turns and several million tokens grinding on one genuinely hard task — a database integration test — and produced a single unpushed commit. Nothing crashed. It simply chose a task it could not finish and worked on it until the budget was gone.
The only outcome that counts. Commits on a branch nobody merged are not throughput, and an agent optimised for commit count will happily produce them all day. Diagram: Bunyk / Wikimedia Commons, CC BY-SA 4.0
The procedure that replaced it
The rewrite turned a goal into a numbered sequence with explicit budgets and an escape hatch. Every clause exists because its absence caused a specific failure.
# The prompt that produced zero commits, twice:
"Pick the top item from BACKLOG.md and implement it."
# The prompt that produced a merged pull request:
"1. Check main is green before starting.
2. Create a branch named chore/refine-<date>.
3. Choose ONE small, self-contained improvement: a single test, one
type tightened, one doc fix. NO new dependencies. NO refactors.
4. Land your FIRST commit within 6 turns. Stop reading and start editing.
5. Push after the first commit and every ~3 commits after that.
6. By turn 30 STOP committing and open the pull request.
ESCAPE HATCH: a run that ends with zero commits is a failure. If you
are stuck, commit whatever compiles, push, and open the PR anyway."
Two clauses do most of the work. Land your first commit within six turns kills the exploration spiral, because it converts reading from the default activity into something the agent must budget. And the escape hatch — a run ending with zero commits is a failure — removes the option that the model kept choosing when it felt uncertain.
Write the budget in turns, not in words like quickly or briefly. A turn is something the agent can count; quickly is something it can rationalise. Every soft instruction in my prompts eventually got replaced with a number.
Where the instruction has to live
Prompt content is only half the question. The other half is which surface carries it, and they do not have equal authority in practice.
Surface
What it is good for
What I learned the hard way
The one-shot run prompt
Today's specific task and its constraints
It does not reliably override a persistent instruction file; the agent will follow the file and its own judgement instead
The persistent instruction file
Standards, discipline, the definition of done
This is the real control surface. Quality habits belong here, not in a daily prompt
A curated backlog file
Choosing what gets worked on next
Curating the top item is how you steer, because the instruction file points at it
A skill or runbook
The repeatable procedure itself
Keeps the same sequence across every run without repeating it in each prompt
I found this out by briefing a specific feature and getting something else entirely: the agent noticed the pipeline was red and fixed that instead. It was the right call, and it happened because the persistent file told it to check the pipeline first. The lesson is that steering happens through the durable surfaces, not through today's message.
Contradictions between surfaces are worse than either instruction alone. A daily prompt saying do one tiny thing and stop, against an instruction file saying work through the backlog, produced the lowest output of any configuration I ran — the agent split the difference and did almost nothing.
Landing is a separate budget from working
The failure that replaced floundering was subtler and more annoying: a run that produced eleven good commits, used every available turn doing so, and never opened the pull request. The work existed and was unreachable.
Two rules fixed it. Push after the first commit and every few commits after that, so work reaches the remote even if the run dies mid-way. And set an explicit landing deadline several turns before the hard limit, at which point the agent stops adding commits regardless of how much is left on its list. A guaranteed merge of six commits beats eleven stranded ones, and that trade is worth stating in the prompt in exactly those words.
Why landing gets its own budget. Committing, pushing, opening the pull request and waiting for the required check cost turns whether or not the work went well, so a task sized to spend every turn on the change itself ends the night with commits nobody merged.
Choosing work the agent can finish
Prompt structure only helps if the task is the right size. Four categories reliably fit inside one unattended run.
One test for one uncovered branch. Small, verifiable, and it improves the safety net for every future run.
One type tightened or one exhaustiveness check added. Mechanical, low-risk, and the compiler verifies it.
One small documented bug fix with a regression test. This is where the real value shows up, and coverage reports are a good way to point at candidates.
One documentation or changelog correction. Unglamorous, but it keeps a run productive on a day when the code is already clean.
What does not fit: new features, anything needing a new dependency, and anything touching more than a handful of files. Those are for a supervised session where a human can course-correct in the moment.
Four checks before you trust the loop
Before leaving a schedule unattended, verify these — I have been burned on each one.
Check the merge against the platform API, not against your own monitoring script. Mine reported a merge that never happened because it compared against a hardcoded base commit.
Read one full run log end to end. Turn counts, retries and where the time went are all visible there and nowhere else.
Confirm the run works from a cold container, not just from the one you have been poking at. Volume remnants hide broken image builds.
Verify the branch names and commit authorship are what you intend. Anything an agent pushes carries your name in the history.
That first one is worth repeating: monitoring you wrote yourself, in a hurry, to watch an agent is exactly the code least likely to be tested, and a false success report is more damaging than no report at all.
The gap between an agent that flounders and one that ships is not model quality, it is procedure. Give it one small item, a turn number by which the first commit must exist, a push habit, a landing deadline, and an explicit rule that zero commits is a failure — and a modest model becomes a reliable daily contributor.