Skip to main content
Mythos

Running several AI coding agents against one repository at the same time breaks down fast without rules: 📝branch conflicts, merge collisions, and — if you're not careful — production incidents. This is the protocol I run in production to let multiple agents work a single codebase in parallel without any of that. It isn't a style guide. These are the rules, every command is copy-paste, and every rule exists to prevent a specific, previously-observed failure.

Environment Model

Three environments, three gates, three risk levels:

Three gates total: your 📝PR host (e.g. 📝GitHub) enforces the staging→main review requirement, and your deploy platform enforces the manual production-deploy click. Staging is fast because staging is allowed to break. Production is slow because production isn't.

Branch Protection

Strict is on for staging because multiple agents merge there concurrently. The PR host rejects a merge if another agent merged ahead of this one, forcing this agent to merge the latest staging into its branch and re-run 📝CI before retrying. This is how parallel agents self-serialize without a lock file — the platform does the coordination for you.

Strict is off for main because staging→main is always sequential by design. There is only ever one production-deploy PR in flight at a time. Strict would add friction without adding safety.

Forbidden Operations

These fail at the platform level or break the system outright. Enforce mechanically wherever the platform lets you; enforce by written rule everywhere else.

  • Never check out staging or main directly. All work happens on feature/* branches inside isolated 📝worktrees. The main checkout is a **📝command center**: it stays on staging, stays clean, and is never used to write commits.
  • **Never 📝force-push to any branch.** 📝Branch protection blocks it on staging/main; policy forbids it on feature branches too.
  • Never 📝cherry-pick between branches. Use full merges via PR. Cherry-picking individual commits between long-lived branches silently diverges their histories — eventually a real merge between them produces dozens of spurious conflicts because Git can't tell the cherry-picked commits are "the same" change.
  • Never push directly to staging or main. Branch protection blocks this. Use a PR.
  • Never approve your own PR to production. Approval comes from a designated reviewer only.
  • Never delete or rename staging or main. Blocked by branch protection.
  • Never delete a feature branch on the remote until its PR has merged. Most PR hosts auto-close the PR when the head ref is deleted, and a closed PR can't be merged. Branch deletion is always the post-merge step — see the Merge Retry Protocol below for why it must never be part of a retry.
  • Never modify branch protection, CI config, or deploy-infra files without human sign-off first. These are infrastructure, not code — a bad change here is a bad change to the safety net itself.
  • Never touch another agent's worktree or feature branch. Any feature/* branch you didn't create in this session belongs to someone (or something) else.

Why Agents Merge via the API, Not the Local Merge Command

The command center holds staging checked out at all times. A local-merge CLI command (like gh pr merge --merge) tries to check out staging in the agent's own worktree to perform the merge there — and that checkout fails immediately, because the command center already holds that branch.

The fix: merge server-side, via the platform's API. The API call never touches the agent's local worktree; the platform does the merge in its own copy and returns the new commit SHA.

gh api -X PUT repos/<org>/<repo>/pulls/<n>/merge -f merge_method=merge

After the merge succeeds (verify by reading "merged":true in the response), delete the remote branch as a separate step:

gh api -X DELETE repos/<org>/<repo>/git/refs/heads/feature/<task-slug>

Never combine these into a single retry path. If the merge fails (e.g. a strict-checks rejection because staging moved while CI was running), do not delete the branch — the PR still needs it to retry against. Deleting prematurely auto-closes the PR and forces a re-open plus a fresh push to recover.

Agent Session: Normal Lifecycle

  1. Session start — agent reads its operating context, this protocol, and its task list for the session.
  2. Work on a feature branch — agent commits locally, tests locally, iterates.
  3. Pre-PR sync — before opening the PR, the agent runs git fetch origin && git merge origin/staging to pull in whatever other agents have already merged. Resolve any conflicts on the feature branch, not on staging.
  4. Open the PRgh pr create --base staging with a summary and test plan. This is the hand-off event: whatever tracking system you use for in-flight work, the item leaves the "in progress" list the moment the PR opens — its review and staging state now live in the PR itself.
  5. Wait for CI — required checks must pass.
  6. Merge to staging via the API — see above. Don't use the local-merge shortcut.
  7. Verify the merge succeeded — confirm "merged":true and a commit SHA before proceeding.
  8. Delete the remote feature branch — only after step 7 is confirmed. Never delete on a failed merge.
  9. Close out — confirm the work landed clean, update whatever tracking artifact the task came from, and leave a short, factual record of what happened. Git is the technical record; anything you write elsewhere should be a pointer to it, not a duplicate of it.
  10. Session end — leave the worktree clean.

Merge Retry Protocol

When strict checks are on and multiple agents are merging, later ones will hit a rejection from the API merge call saying (in effect) that a required check is out of date. This is the platform saying "your branch is behind — re-run CI against the latest base before I'll let you merge." Expected, not an error. The retry:

git fetch origin
git merge origin/staging       # merge latest staging into the feature branch
# resolve any conflicts if they appear
git push                       # trigger a fresh CI run
# once CI passes, re-attempt the API merge:
gh api -X PUT repos/<org>/<repo>/pulls/<n>/merge -f merge_method=merge
# only AFTER the merge succeeds, delete the branch:
gh api -X DELETE repos/<org>/<repo>/git/refs/heads/feature/<task-slug>

Branch-deletion ordering is load-bearing. Deleting the remote branch as part of a retry auto-closes the PR; recovery means re-opening the PR and force-pushing to recreate the branch, after which another full CI cycle is usually required.

A rejection specifically about "a merge already in progress" is a different failure — it usually means an earlier merge call from the same agent is racing this retry, not that the branch is stale. Check the PR's actual state before re-issuing the merge call; if it already merged, skip straight to branch deletion.

If the merge call fails twice in a row even after the retry, stop and flag it rather than retrying indefinitely. Two consecutive failures usually means something else is wrong.

Production Deploy Lifecycle

Once one or more PRs have landed on staging and been verified there:

  1. Open a release PR: gh pr create --base main --head staging --title "release: YYYY-MM-DD".
  2. The PR sits in "review required" state.
  3. A human (or a specifically-authorized account) reviews and approves it.
  4. Merge via the platform's API — same reasoning as above; the local-merge shortcut hits the same command-center conflict here too.
  5. The deploy platform detects the push to production and pauses for manual approval.
  6. A human reviews the pending deploy and clicks Deploy.
  7. Production updates.

The manual-approval gate on the deploy platform is intentional. It catches "right code, wrong timing" — the case where the code is correct but this is not the moment to ship it (nobody's watching, a high-traffic window, etc.).

If your project is public-facing, write the user-facing change-log entry from the release's git diff at this point — never from memory, and never by copying internal task-tracker language. Git is the full technical record; a public change log is a curated, plain-language subset of it.

Cleanup After a Merge

Once a feature branch has merged to staging and its remote copy is deleted:

cd <command-center>
git worktree remove <worktree-path>       # delete the worktree folder + metadata
git branch -D feature/<task-slug>         # delete the local branch
git pull origin staging                   # refresh the command center

If git worktree remove refuses because of uncommitted changes, go look — don't force it blindly.

Parallel Agent Ground Rules

  • One agent per worktree. Never run two agents in the same working directory.
  • One agent per feature branch. A feature/* branch you didn't create this session belongs to someone else.
  • Pre-PR sync is mandatory. Always merge the latest staging into your branch before opening the PR. Strict checks will catch you if you forget, but catching it proactively is faster than the retry loop.
  • If you hit an error involving another agent's branch, stop. Log it. Don't guess your way out.

Why This Scales

This protocol is designed for many-agent parallelism — the bottleneck at scale is not how fast any one agent works, it's whether merges serialize reliably. A PR host's strict status checks solve that atomically, without needing a custom coordination layer. The mechanism (branch protection, required checks, a manual production gate) is what makes the rules hold — not agent discipline. Build the guard, not the reminder.

Contexts

Created with 💜 by One Inc | Copyright 2026