October 2, 2026 / 9 min read

Getting your repo ready for background coding agents

Coding AgentsSoftware DevelopmentAI DeliveryHarness Engineering

I wanted to hand an agent a task, let it work in the background, and come back to a pull request I could review. Several agents doing that at once would be even better. The repo I wanted to use was a monorepo with hundreds of AWS Lambda functions and an Angular frontend, built long before I expected agents to work in it on their own.

In The last level of coding-agent autonomy is a harness problem I said the next post would go through the harness-audit controls one by one. Running the audit gave me something more useful to write about: the work it took to make this repo usable for background agents, and what still needed attention once they could run.

It scored L01. The local environment assumed one developer running one copy, the advertised test command could not pass on hundreds of projects, and an agent needed help just to get enough of the application running to check its work. That gave me a fairly concrete place to start.

Decide what an agent can verify locally

Running this application locally meant dealing with managed auth, object storage, queues, hundreds of migrations, and a frontend that takes minutes to compile. The first plan wanted to emulate everything. That is a lot of infrastructure to build before an agent can verify a small UI change.

We narrowed the scope to read-only navigation. The local environment needed enough of the application for an agent to open supported screens and verify reads. Writes, updates, deletes and the integrations outside that scope had to be explicitly unavailable. Expanding local coverage became separate work.

I think "fully" is the word that causes trouble when we talk about running a system fully locally. A background agent needs to know which behavior it can exercise and which behavior it cannot. If a screen depends on something the local environment does not support, that needs to be visible in the instructions and in the application. Otherwise the agent can spend its entire run trying to fix an emulator limitation as though it were a product bug.

For this repo, a useful local environment was a prerequisite for delegating work. It also determined which tasks I could reasonably hand off.

Each task needs its own running environment

A separate git worktree gives an agent its own files. The audit found that everything underneath those files was still shared: a hardcoded database container name, a fixed port, one database volume, and fixed ports for local Lambda execution.

Two agents could edit independently and still interfere with each other's verification. One could run migrations or change fixture data while the other was testing against the same database. A failure in that setup tells you very little about the patch.

The local stack now belongs to the worktree. Each copy has its own saved ports and local state, and the agent has a command to discover where its copy is running. Startup and shutdown belong to that copy too. The instructions explicitly tell the worker to discover the frontend URL instead of assuming the usual port.

This is the part I would check before launching a second agent: can both copies start, use their own data, and stop independently? Until that works, concurrency adds another explanation for every failure.

Try the workload you actually intend to run

Once the copies could run independently, I tried four background agents on a 16-core machine with 62 GiB of RAM and no swap. I did not put CPU or memory caps on the individual workers.

Two had the local database, auth emulator, Lambda emulator and Angular dev server running, with Playwright on top. A third was running headless Chrome suites. The fourth was running about a thousand unit tests. All four opened PRs within an hour and a half.

One Angular build hit Node's default heap limit, and that worker continued with the task. That failure still belonged in its verification report. Opening a PR tells me the worker reached a handoff; I still need to know which checks passed and which did not.

Four worked for that mix of tasks on that machine. I still don't know the useful upper limit. Four workers all compiling the frontend would be a different experiment, and I want that measurement before assuming I can keep adding agents.

Make the checks mean something

The test command was one of the more uncomfortable findings. Hundreds of projects had a test target and zero test files. Each of those targets exited non-zero, so the advertised command could not pass by construction. No workflow ran it either.

An agent starting from that checkout gets a bad baseline. If the tests fail before it changes anything, it has to work out which failures it inherited before it can tell whether its own work broke something. Leave that unresolved and every background task pays for the same investigation.

Since the audit, CI runs tests for the projects a pull request touches, with a pass-with-no-tests flag. That makes the command usable, but it leaves an important limitation: a project with zero tests can now show green. The green result does not provide evidence about that project's behavior.

For a task to be ready for a background agent, I want the handoff to say how the changed behavior will be checked. That might be a focused test or a browser check against the supported local screens. If the environment cannot verify it, the worker needs to say so. A reviewer should be able to distinguish a passing test from a project that had nothing to run.

Keep the task small enough to finish and review

Getting the application running made larger assignments tempting. The local navigation work alone covered enough screens and dependencies to produce a very long task list.

My working rule is to split a change when its list passes about twenty tasks. I use OpenSpec2, but the useful part is having an explicit list with a clear completion condition. Twenty is a heuristic from these runs, not a measured limit on what an agent can do.

Long assignments make it harder to keep the spec, implementation and verification together. Context fills up, compaction drops something, or tasks get checked off because the code exists while the proof is still missing. A checkpoint can describe the remaining work perfectly and the worker can still stop there.

The navigation effort became a series of smaller changes, covering the local contracts, capability handling and groups of screens. Each needs an exit condition that someone can actually verify. That also gives me a smaller diff to review and a useful place to resume when a run stops.

The worker prompt now tells the agent to use the task list as the completion source of truth and to keep going beyond the foundation work. The PR feedback helper also treats success literally: a comment saying everything is fixed does not mean the reviewer agreed. The background workflow needs to account for the checks and review feedback that arrive after the PR opens.

I care about task size partly because I still review the result. A thousand-line PR takes work to review. At ten thousand lines, reviewing turns into deciding how far to trust the result, and I still have trust issues with agents.

Choose the worker when you hand off the task

I used the strongest models at high reasoning effort for much of the planning. Working out the local environment and its boundaries justified that attention. Once the spec settled a bounded implementation task, I found much less value in having an expensive model reason through those decisions again.

Model selection is now an explicit step in the background workflow. Before creating the worktree, the foreground agent asks which worker gets the task and records the model and reasoning effort in the handoff. The default is a balanced tier, with stronger models for ambiguity or architectural risk and cheaper ones for straightforward chores.

That matters because I tend to use an expensive model in the foreground. Letting every worker inherit that choice would apply the same budget to planning the local stack and opening a PR with an existing template. I want to make that decision for the task I am handing off.

What I still need to prove

At the time of these runs, the repo had not been re-audited, so it was still L0 on paper. Four agents opening PRs was a useful result, but I still needed to verify the remaining controls before claiming a higher level of autonomy.

The instructions needed attention too. The original audit found two long, near-duplicate agent rulebooks that contradicted each other about tooling and pointed at a directory that did not exist. A worker reading that material starts with the wrong map of the repo. Adding more instructions after every incident also gives me more material to keep current.

For someone preparing a repo for background agents, I would start with one small task whose behavior can be checked locally. Make the environment usable for that task, give the worker its own state, and write down what evidence you expect back. Then run two copies and see where the assumptions break.

That is the workflow I am building toward: I choose a bounded task, the agent works through it in its own environment, and I come back to a reviewable change with evidence of what it checked and an explicit account of what remains.

TL;DR

The audit scored this monorepo L0. Making it usable for background agents came down to a local environment scoped to what an agent can actually verify, a separate running stack for every worktree, checks whose green result means something, tasks small enough to finish and review, and a deliberate model choice for each worker. With that in place, four agents on one machine each opened a PR within an hour and a half.

A PR is only the handoff. I still need each worker to report which checks passed, which failed and what the environment could not verify, and the repo still needs a re-audit before I claim a higher level. If you are starting out, pick one small task you can check locally, give the worker its own state, and run two copies to see what breaks.

Footnotes

  1. The audit's levels. L0 Assisted, a human drives and the agent suggests edits. L1 Supervised, the agent produces a branch and a human reviews and verifies it. L2 Unattended to PR, a task becomes a self-verified PR with no intervention and a human merges it. L3 Unattended to merge, the agent merges small changes and humans only see escalations. A repo gets the highest level whose required controls all pass. ↩

  2. OpenSpec ↩

Written by

Joseph Arrieta

Founder & CTO, Code Carvers

16 years in software engineering. He works directly with clients from planning through launch and handoff.

Put it into practice

Apply these ideas to your team’s software.

Help your existing team deliver improvements with fewer release problems and a clearer path from idea to production. An intro call is a chance to talk through your situation and identify a useful next step.