Add the paired-agent workflow for issues - #152
Open
Oleg-Melnik wants to merge 6 commits into
Open
Conversation
Two agents work one GitHub issue through a shared Markdown document: one plans and implements, the other reviews the plan before any code is written and the resulting diff afterwards. The issue is the only accepted input, so the reviewer checks the work against acceptance criteria that neither agent wrote. The driver invokes whichever agent owns the turn, keeps a transcript per turn, and validates each transition against the protocol. Neither agent may change Git state; the driver compares refs and the index after every turn and aborts on any difference. Opening a pull request is opt-in, performed by the driver after a finished run. Both agent commands keep their CLI approval and sandbox boundaries by default, and a command containing a known bypass flag is refused unless the caller confirms an external isolation boundary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Codex's `workspace-write` sandbox excludes gitignored paths from its writable set, and `.agents/work/` is gitignored by design — the working document is a scratch artifact that is never committed. `agent2` could therefore read the document but not write its review into it, and every run aborted with "agent2 did not modify ... plan.md". Name the work root with `--add-dir` in the default `AGENT2_CMD`. This widens the sandbox by exactly one directory inside the repository, and `unsafe_agent_roles()` does not classify it as a bypass flag, so the approval and sandbox boundaries are otherwise unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`pair.sh` runs `agent1` with `--setting-sources project`, which loads `.claude/settings.json` only. That file did not exist, so every Gradle and `java` invocation was refused with "This command requires approval", and the agent handed off an implementation it had never compiled. `agent2` then had to spend its review round on that fact instead of on the code. Allow the verification commands `AGENTS.md` prescribes — module `test`, `check`, `compileKotlin`, `detekt`, the license-report tasks, the local publishing tasks, and the JDK checks — plus the read-only `gh` commands the agents use to inspect issues and pull requests. Publishing tasks (`publish`, `publishCodegenPlugins`) are deliberately absent: `AGENTS.md` reserves those for CI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four failures showed up in one run of issue #148, none of them in the protocol itself. Each is addressed where it belongs. The Git tripwire accused the agent. It compares two snapshots taken around a turn and cannot see who moved between them, so a user switching branches mid-run produced "agent2 wrote to Git". Report the movement, name the innocent cause, and leave attribution to the reader. The skill and the run guide now say the guard cannot attribute, and the guide asks the user not to touch Git while a run is live. A turn that died immediately said only that the agent exited non-zero. The two things that actually fail first — a CLI on `PATH` but not signed in, and a model identifier only the API rejects — are now named in that message, and the run guide separates being on `PATH` from being authenticated. Verification could report green from cache. When every compile and test task is `UP-TO-DATE`, `BUILD SUCCESSFUL` describes an earlier build, not the change in the worktree. The tester skill now requires reading the task list and forcing the work with `--rerun-tasks` before calling a result green. Finally, record why `--add-dir` and `.claude/settings.json` are load-bearing, in the protocol and in the guide, so neither is dropped by someone overriding an agent command. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Oleg-Melnik
force-pushed
the
pair-agents-workflow
branch
from
July 31, 2026 20:58
29970fa to
388da74
Compare
Both fixes in this branch live in configuration rather than in the driver's logic, so nothing failed when they were wrong until a turn was already running — several minutes in, with a message about the symptom. These assert them directly. `--add-dir` is read out of the `AGENT2_CMD` assignment rather than from the usage output, which describes the flag in prose: matching that text passed even with the flag deleted from the default that actually runs. The companion check asserts `.agents/work` really is gitignored, which is the reason the flag is needed at all. The `.claude/settings.json` checks cover the file agent1 loads under `--setting-sources project` and the verification tasks it must allow. Without them agent1 hands off an implementation it never compiled. Each check was confirmed to fail when the thing it guards is removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Oleg-Melnik
marked this pull request as ready for review
July 31, 2026 23:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a workflow that hands one GitHub issue to two different AI agents. One
plans and implements it; the other reviews the plan before any code is written,
and the resulting diff afterwards. They exchange turns through a single Markdown
document under
.agents/work/, which is gitignored.A GitHub issue is the only accepted input. That is what makes the second opinion
meaningful: the reviewer checks the work against acceptance criteria that
neither agent wrote, and the run stops on the first turn if the issue does not
state what to do and what "done" means.
Neither agent may change Git state. The driver compares
HEAD, every ref, andthe staged index after each turn and aborts on any difference. Publishing a pull
request is opt-in and performed by the driver itself once a run has finished, so
the prohibition on the agents holds either way.
Both agent commands keep their CLI's approval and sandbox boundaries by default,
and a command containing a known bypass flag is refused unless the caller
confirms an external isolation boundary.
Changes
.agents/workflows/pair.sh— the driver: reads the working document's state,invokes whichever agent owns the turn, validates every transition against the
protocol, and optionally opens a draft pull request afterwards.
.agents/workflows/pair-test.sh— a regression suite that exercises thedriver against a throwaway repository with stub agents.
.agents/skills/pair-workflow/— the protocol both agents read, the workingdocument template, and the interface metadata.
.claude/commands/pair.md— a/pair <issue>entry point that relays theagents' questions and results in the conversation.
PAIR_AGENTS_RUN_GUIDE.md— the user guide, including how to change the modeland effort of each agent.
README.md,.agents/skills/README.md— pointers to the above..gitignore— ignore the per-task working directory.