12. Worktree + Task Isolation

"Each works in its own directory, no interference"

30 min read
πŸ’‘New to this?

What is a git worktree?

A worktree is a separate working directory linked to the same git repository. Each worktree can be on a different branch, letting multiple agents work on different tasks without file conflicts.

Why do agents need isolation?

When multiple agents edit the same files simultaneously, they can overwrite each other's work. Worktrees give each agent its own copy of the codebase to work in safely.

How do tasks and worktrees connect?

Each task gets assigned a worktree by ID. The task tracks what needs to be done, the worktree provides where to do it. When the task completes, the worktree can be merged and cleaned up.

The Problem

In the Agent Teams through Autonomous Agents sessions, teammates coordinate through tasks and mailboxes β€” but they all share the same working directory. If two agents edit the same file simultaneously, they’ll corrupt each other’s work. The team can plan together, but they can’t execute together.

The Solution

Give each agent its own directory. Git worktrees provide exactly this: separate working directories linked to the same repository, each on its own branch. One task = one worktree = one isolated execution lane.

Task s12-feat-auth  ──→  .worktrees/s12-feat-auth/   (branch: task/s12-feat-auth)
Task s12-fix-typo   ──→  .worktrees/s12-fix-typo/    (branch: task/s12-fix-typo)
Task s12-add-tests  ──→  .worktrees/s12-add-tests/   (branch: task/s12-add-tests)

Worktree Lifecycle

def create_worktree(task_id: str) -> str:
    branch = f"task/{task_id}"
    path = f".worktrees/{task_id}"
    subprocess.run(["git", "worktree", "add", "-b", branch, path], check=True)
    return path

def cleanup_worktree(task_id: str):
    path = f".worktrees/{task_id}"
    subprocess.run(["git", "worktree", "remove", path], check=True)

Three operations:

  1. Create β€” git worktree add makes a new directory with its own branch
  2. Work β€” the agent operates entirely within that directory
  3. Cleanup β€” git worktree remove deletes the directory after merging

Binding Tasks to Worktrees

def assign_worktree(task_id: str) -> dict:
    worktree_path = create_worktree(task_id)
    task = task_manager.get(task_id)
    task["worktree"] = worktree_path
    task["branch"] = f"task/{task_id}"
    task_manager.update(task)
    return task

The task record now carries its execution context. Any agent picking up this task knows exactly where to work.

The Full Pattern

Lead Agent:
  1. Create task in task system
  2. Create worktree for task
  3. Bind task to worktree
  4. Teammate claims task
  5. Teammate works in worktree
  6. Teammate completes task
  7. Lead merges branch
  8. Lead removes worktree

This is the culmination of the entire course: the Tasks session manages goals, the Team Protocols session manages communication, the Autonomous Agents session manages assignment, and worktrees manage isolation. Each mechanism handles one concern. Together, they enable true parallel execution.

What Changed from Autonomous Agents

ComponentAutonomous AgentsWorktree + Task Isolation
Task claimingAuto-claim from shared boardSame
ExecutionShared directoryIsolated worktree per task
BranchesNoneOne branch per task
CleanupManualWorktree remove after merge

Key Takeaway

Isolation is the final piece. With worktrees, agents can truly work in parallel β€” each in their own directory, on their own branch, with no interference. The harness is now complete: loop, tools, planning, knowledge, context management, persistence, teams, protocols, autonomy, and isolation. You have learned to build the world the intelligence inhabits.

Interactive Code Walkthrough

Worktree Lifecycle: Create, Assign, Cleanup
1def create_worktree(task_id: str) -> str:
2 branch = f"task/{task_id}"
3 path = f".worktrees/{task_id}"
4 subprocess.run(
5 ["git", "worktree", "add", "-b", branch, path],
6 check=True
7 )
8 return path
9 
10def assign_worktree(task_id: str) -> dict:
11 worktree_path = create_worktree(task_id)
12 task = task_manager.get(task_id)
13 task["worktree"] = worktree_path
14 task["branch"] = f"task/{task_id}"
15 task_manager.update(task)
16 return task
17 
18def cleanup_worktree(task_id: str) -> None:
19 path = f".worktrees/{task_id}"
20 subprocess.run(
21 ["git", "worktree", "remove", path],
22 check=True
23 )
24 
create_worktree() runs git worktree add with -b to create a new branch simultaneously. The worktree lives in .worktrees/<task_id>/ β€” a fully functional git working directory on its own branch.
Step 1 of 3
πŸ§ͺ Try it yourself
πŸ”₯ Warm-up ~5 min

What happens if two worktrees modify the same file on different branches? When do conflicts appear, and who resolves them?

Hint

Conflicts only appear at merge time. The lead agent (or a human) resolves them.

πŸ”¨ Build ~20 min

Create 3 tasks, assign each a worktree, and verify they can edit the same file independently.

Hint

After each completes, merge the branches and resolve any conflicts.

πŸš€ Stretch ~45 min

Build an automatic merge system: after a task completes, auto-merge its branch. If there's a conflict, spawn a subagent to resolve it. Track merge success rate.

Hint

Use git merge --no-commit to detect conflicts before committing. Parse conflict markers to understand what changed.

Found a mistake? Report it β†’