Blog

Parallel AI coding agents: get alerted when two edit the same files

Parallel AI coding agents collide at merge time, even in separate git worktrees. How to see two branches touching the same files while the agents are still working, and send it to whatever runs them.

Three agents, three branches, each in its own git worktree, all green. Then you merge the second one and it conflicts with the first, because both rewrote the same handler an hour ago. Nobody saw it coming, because until merge time nothing compares open branches with each other.

The last post looked at why this happens and what helps. This one is the practical part: getting told about the overlap while the agents are still working, and passing it to whatever runs them.

What you end up with

  • An Overlaps page listing pairs of open branches that change the same files, right now and as recorded on each push.
  • An overlap marker on the push in the dashboard feed.
  • Optionally a push.overlap webhook the moment an overlapping push arrives, so your orchestrator (or a chat channel) hears about it.

Nothing here blocks or delays a push. It only tells you.

You can click around a live example first: demo.nimblegate.com/overlaps.

Step 1: Push through a gateway in enforce mode

The comparison runs on nimblegate, a self-hosted gateway your agents push to instead of pushing to GitHub directly. It already sees every branch, which is what makes branch-to-branch comparison possible. Setup is one Docker container; the quick start walks through it in about ten minutes.

The repo needs to be in enforce mode. Observe mode records pushes but doesn’t compute overlaps.

Step 2: Have agents push early, not only when done

The gateway can only compare what it has. An agent that pushes once, at the end, shows up once, at the end - by then the overlap is a merge conflict.

Give each agent its own branch (and worktree, if you use them), and have it push checkpoints as it goes. A line in the agent’s instructions is enough:

Commit and push your branch after each working step, not only at the end.

Step 3: Read the Overlaps page

Open Overlaps in the dashboard. Two sections:

  • Now: pairs of open branches that share files at this moment, computed fresh each time the page loads.
  • Recorded on push: every accepted push that overlapped another branch when it arrived, with the files and both commits.

Each branch’s changes are measured from where it split off the default branch, so work that has already been merged never counts. Two branches touching one file on purpose is fine - the page reports, it doesn’t judge.

Step 4: Send overlaps to what runs your agents

In the dashboard, open the repo’s Policy page and expand the Notification rail:

  1. Tick Enable notifications for this repo.
  2. Set the webhook URL of your receiver, auth mode HMAC, and a shared secret.
  3. Tick Also send overlap events, then Save.

Each overlapping push now POSTs JSON like this, signed with your secret in an X-Nimblegate-Signature header:

{
  "event": "push.overlap",
  "overlaps": [
    {"ref": "refs/heads/agent/b/task-9",
     "other_ref": "refs/heads/agent/a/task-7",
     "files": ["internal/gateway/doctor.go"],
     "sha": "20848da5...", "other_sha": "74f09898..."}
  ]
}

A minimal receiver in Python, standard library only:

import hashlib, hmac, json
from http.server import BaseHTTPRequestHandler, HTTPServer

SECRET = b"your-shared-secret"   # the same secret you typed into the gateway

class Hook(BaseHTTPRequestHandler):
    def do_POST(self):
        body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
        want = "sha256=" + hmac.new(SECRET, body, hashlib.sha256).hexdigest()
        if not hmac.compare_digest(self.headers.get("X-Nimblegate-Signature", ""), want):
            self.send_response(401)
            self.end_headers()
            return
        event = json.loads(body)
        if event.get("event") == "push.overlap":      # other events share this URL
            for o in event["overlaps"]:
                print(f'{o["ref"]} and {o["other_ref"]} both change: {", ".join(o["files"])}', flush=True)
        self.send_response(200)
        self.end_headers()

HTTPServer(("0.0.0.0", 8080), Hook).serve_forever()

Check event before acting: the same URL also receives rejected-push notifications if you use them.

What to do with an overlap

Replace the print with whatever fits how you run agents:

  • Pause one agent until the other merges, then have it rebase.
  • Reorder the queue so the next task for that agent avoids those files.
  • Tell both agents which files they share, and let them continue knowingly.
  • Post it to a chat channel and decide yourself.

Catching it an hour into the work costs a rebase. Catching it at merge costs untangling two finished branches.

Limits worth knowing

  • Advisory only: a push is never rejected or slowed for overlapping, and the agent that pushed isn’t told - only the dashboard and the webhook are.
  • Branches with no commit in 14 days are skipped, and at most the 50 most recent branches are compared.
  • On a very large repo the check has a time budget; if it runs out, the push still goes through and the failure is logged on the Events page.

More detail: multiple agents on one repo and the overlap webhook reference.


nimblegate is free for non-commercial use; commercial use needs a license. Questions: contact@nimblegate.com.

← All posts · nimblegate is a self-hosted push gateway for AI agents - how it works · live demo