Skip to content

    Back to articles

    6 min read

    Worktrees move agent risk to integration contracts

    Isolation solves only one kind of conflict

    Coverage of Meta’s reported Muse Code launch describes persistent subagents working in isolated Git worktrees, a useful prompt to think about parallel coding as a concurrency problem rather than an invitation to start more agents (DevOps.com’s coverage of Muse Code). I use coding agents, but I am not claiming expertise in building agent systems. The architectural question is familiar, though: what changes when several workers can make progress at once?

    A Git worktree gives each worker a separate working directory and checked-out branch while keeping those worktrees associated with the same repository (Git’s worktree documentation). That separation can prevent one worker’s uncommitted edits from directly overwriting another’s. It does not make their changes compatible. Two workers can independently change the same public method, assume different meanings for a field, or make incompatible choices about where validation belongs. Each branch may be internally consistent and still fail when brought together.

    I would describe worktrees as an isolation boundary, not a coordination protocol. They reduce direct edit collisions; they do not decide who owns a concern, establish an interface, or choose between conflicting designs. Those responsibilities do not disappear when the workers are agents. They move toward task definition and integration.

    Agree on ownership before parallel work

    Before I split a task, I want a clear boundary for each worker’s change. “Work on the API” is not a boundary. “Add the request model and validation; do not change the endpoint signature or persistence layer” is closer. The point is not to dictate every line. It is to identify which files or responsibilities have one owner, and which seams workers must treat as shared contracts.

    I would write the assignment in terms of an outcome, allowed scope, and explicit exclusions. For example:

    Task: Add request validation for the create-order endpoint.
    Own: request model and validator.
    Do not change: endpoint signature, persistence model, or response format.
    Assume: the endpoint calls the validator before creating an order.
    Return: commit, tests run, and any contract assumption that needs review.

    This is a sketch of a task contract, not a claim about a particular tool’s configuration. It makes an assumption visible before an implementation hardens it into code. If another worker owns the endpoint, both assignments can refer to the same agreed behavior without editing the same surface area.

    I also want the interface written down before implementation proceeds in parallel. That might be a method signature, a request and response shape, an event schema, or simply a short statement of behavior. If a worker cannot do useful work without inventing that contract, the task is not ready to fan out. I would either define the contract first or keep the work with one owner until the uncertainty is resolved.

    This is where more agents can make a task worse. If every worker independently fills in an ambiguous requirement, parallelism produces multiple plausible designs and pushes the cost of choosing among them to the end. The faster the branches arrive, the less time there is to discover that their assumptions diverged.

    Treat shared interfaces as owned work

    A parallel plan should identify not only separate tasks, but also the places where their outputs meet. I would make one person responsible for the shared contract: its shape, semantics, and compatibility expectations. That person might implement the interface, or might only approve it before others build against it. What matters is that the decision has an owner.

    For a service change, the contract could cover a route, message, or database boundary. For a library change, it could be a method signature and the behavior callers can rely on. In either case, naming the files alone is not enough. Two changes can touch different files and still conflict semantically. A new status value in one branch, for instance, is not useful if another branch assumes the old set is exhaustive. That is a hypothetical example of the class of mismatch, not an account of an event I have witnessed.

    I would ask each worker to report assumptions as part of its result, not just code and test status. Tests can show that a branch passes in isolation; they cannot prove that another branch made the same assumptions. A concise handoff should say what changed, what it depends on, what it deliberately did not change, and which decisions remain open.

    This contract-first approach has a cost: it asks for design work before all the code exists. I consider that a good trade when parallel changes cross a shared boundary. If the contract is still genuinely uncertain, the right next step may be a small investigation or a single implementation that establishes the seam—not extra parallel implementations of competing guesses.

    Keep integration as a human decision

    I would not treat a successful merge as proof that integration is complete. Git can identify textual conflicts and combine changes that do not overlap; neither outcome establishes that the combined behavior is right. The integration owner needs to review the joined change against the contract, run checks across the combined result, and decide what to do when two workers made incompatible choices.

    That decision may be to keep one implementation, revise both, or change the contract. It is not a mechanical cleanup step. The person integrating needs enough context to understand why each change exists and what each worker assumed. If the handoffs omit that context, the apparent time saved through parallel work can reappear as investigation at the merge boundary.

    I would also keep the final integration path narrow. A designated owner should bring changes together in a deliberate order, check the full result, and make the final call on disagreements. This does not mean every line needs a human to type it. It means someone remains accountable for deciding whether the system, rather than each isolated branch, satisfies the requirement.

    Persistent workers make that discipline more important, not less. A worker that continues operating after the initial assignment still needs a stable scope and a way to surface changed assumptions. Persistence is useful only if the work remains attached to a contract someone can review. Otherwise, it can extend the life of an incorrect assumption alongside the life of the task.

    I would start parallel agent work only when I can name each owner, state the shared interface, and identify who will integrate the result. Worktrees help keep edits apart. The contract and the integration decision are what make the changes fit.

    Drafted with AI assistance, reviewed and edited by Ali.