Skip to main content

Multi-Repo Coordination

Multi-repo coordination is the governed layer for work that spans more than one repository. It gives you one coordinator workspace, one super_run_id, coordinator-specific hooks and barriers, and repo-local execution that still treats each child repo's .agentxchain/ state as the source of truth.

If you only need one repository, stay on the normal governed lifecycle. Reach for multi when one change needs ordered work across repos, shared gates, or barrier-aware coordination.

If you want the literal cold-start path first, use Quickstart. This page stays focused on the full coordinator contract.

Live Coordinator Proof

The coordinator is not only covered by fixture E2E. A real model-backed proof now lives at examples/live-governed-proof/run-multi-repo-proof.mjs.

node examples/live-governed-proof/run-multi-repo-proof.mjs --json

The latest checked-in proof artifact is examples/live-governed-proof/evidence/multi-repo-proof.latest.json.

Recorded invocation:

node examples/live-governed-proof/run-multi-repo-proof.mjs --json --output examples/live-governed-proof/evidence/multi-repo-proof.latest.json

Fresh recorded run on 2026-04-18:

  • CLI: agentxchain v2.134.1
  • super_run_id: srun_1776532275887_1c3cf362
  • Child repos: api and web
  • Coordinator dispatches: 4
  • Accepted projections: 4
  • Repo-local role order: api(pm -> dev), web(pm -> dev)
  • Coordinator context proof: the first web dispatch bundle included COORDINATOR_CONTEXT.json with one upstream acceptance from api
  • Barrier result: planning_sync_completion and implementation_sync_completion both reached satisfied
  • Checked-in evidence: examples/live-governed-proof/evidence/multi-repo-proof.latest.json
  • Total API cost: $0.0300

This proof intentionally keeps repo-local approvals real. Repo-local approvals remained required throughout the proof: each child repo turn was executed with agentxchain step --resume --auto-reject, then cleared with repo-local approve-transition or approve-completion before the coordinator advanced. The coordinator did not bypass child-repo gates.

Workspace Contract

The coordinator workspace is a directory with an agentxchain-multi.json file at its root plus checked-out governed repos underneath it.

Phase order is not negotiable: every child repo participating in the coordinator must declare the same ordered routing phases as the coordinator initiative. If the coordinator runs planning -> implementation -> qa, the child repos must expose the same routing order. If the coordinator is implementation-only, the child repos must also be implementation-only. multi init now rejects phase-order mismatches instead of letting them fail later during dispatch.

agentxchain-multi.json
{
"schema_version": "0.1",
"project": {
"id": "agent-platform",
"name": "Agent Platform Rollout"
},
"repos": {
"web": {
"path": "./repos/web",
"default_branch": "main",
"required": true
},
"cli": {
"path": "./repos/cli",
"default_branch": "main",
"required": true
}
},
"workstreams": {
"protocol_doc_sync": {
"phase": "implementation",
"repos": ["web", "cli"],
"entry_repo": "cli",
"depends_on": [],
"completion_barrier": "all_repos_accepted"
}
},
"routing": {
"implementation": {
"entry_workstream": "protocol_doc_sync"
}
},
"gates": {
"initiative_ship": {
"requires_human_approval": true,
"requires_repos": ["web", "cli"]
}
}
}

The shipped coordinator state lives under .agentxchain/multirepo/, not in a separate .coordinator/ tree:

workspace/
agentxchain-multi.json
.agentxchain/
multirepo/
state.json
history.jsonl
decision-ledger.jsonl
barriers.json
barrier-ledger.jsonl
hook-audit.jsonl
hook-annotations.jsonl
context/
<context_ref>/
COORDINATOR_CONTEXT.json
COORDINATOR_CONTEXT.md
repos/
web/
agentxchain.json
.agentxchain/
state.json
cli/
agentxchain.json
.agentxchain/
state.json

Custom Coordinator Phases

Coordinator workflows are not limited to planning -> implementation -> qa.

If you need an intermediate phase such as design, declare it in the coordinator routing and in every participating child repo's agentxchain.json. The order must match exactly across all repos. Coordinator gates derive phase order from declaration order, so planning -> design -> implementation -> qa is valid, but planning -> implementation is not if design is declared in between.

agentxchain-multi.json (custom phases excerpt)
{
"workstreams": {
"initiative_plan": {
"phase": "planning",
"repos": ["api", "web"],
"entry_repo": "api",
"depends_on": [],
"completion_barrier": "all_repos_accepted"
},
"initiative_design": {
"phase": "design",
"repos": ["api", "web"],
"entry_repo": "api",
"depends_on": ["initiative_plan"],
"completion_barrier": "all_repos_accepted"
},
"initiative_build": {
"phase": "implementation",
"repos": ["api", "web"],
"entry_repo": "api",
"depends_on": ["initiative_design"],
"completion_barrier": "all_repos_accepted"
},
"initiative_qa": {
"phase": "qa",
"repos": ["api", "web"],
"entry_repo": "qa",
"depends_on": ["initiative_build"],
"completion_barrier": "shared_human_gate"
}
},
"routing": {
"planning": { "entry_workstream": "initiative_plan" },
"design": { "entry_workstream": "initiative_design" },
"implementation": { "entry_workstream": "initiative_build" },
"qa": { "entry_workstream": "initiative_qa" }
}
}

The same order must exist in each child repo:

repos/api/agentxchain.json (routing excerpt)
{
"routing": {
"planning": { "entry_role": "pm", "exit_gate": "planning_signoff" },
"design": { "entry_role": "architect", "exit_gate": "design_review" },
"implementation": { "entry_role": "dev", "exit_gate": "implementation_complete" },
"qa": { "entry_role": "qa", "exit_gate": "qa_ship_verdict" }
}
}

phase_transition_request may only target the immediate next declared phase. In the example above, planning -> design is valid; planning -> implementation is rejected with phase_skip_forbidden.

Command Lifecycle

The coordinator loop is explicit. The coordinator never auto-runs child repos behind your back.

  1. agentxchain multi init
    • Loads agentxchain-multi.json
    • Verifies coordinator/child repo phase-order alignment before writing coordinator state
    • Links existing active child runs or initializes idle governed repos
    • Writes .agentxchain/multirepo/state.json and barrier snapshots
  2. agentxchain multi step
    • Detects divergence first
    • Auto-resyncs from repo authority when the drift is safe to repair
    • Selects the next assignable workstream and repo
    • Writes the child repo dispatch bundle with COORDINATOR_CONTEXT.json and COORDINATOR_CONTEXT.md
  3. Inside the selected child repo, complete the repo-local turn normally
    • agentxchain accept-turn
    • The repo-local history is authoritative; the coordinator projects from that accepted result
  4. Run agentxchain multi step again
    • Projects repo-local acceptance into coordinator history
    • Updates barrier state
    • Either dispatches the next repo assignment or requests a coordinator gate
  5. If the coordinator enters blocked, fix the cause, fill in .agentxchain/multirepo/RECOVERY_REPORT.md, and run agentxchain multi resume
    • The system scaffolds RECOVERY_REPORT.md on any blocked coordinator transition, including hook-driven blocks and ambiguous resync results
    • Fill in ## Trigger, ## Impact, and ## Mitigation with real content before resume
    • multi resume validates the recovery report, then resyncs from repo authority
    • Restores the coordinator to active when dispatch can continue
    • Restores the coordinator to paused when a coherent pending_gate still exists
  6. When a gate is pending, run agentxchain multi approve-gate
    • Approves a phase-transition or completion gate for the coordinated initiative
  7. When you want an explicit divergence check, run agentxchain multi resync --dry-run
    • Shows divergence without mutating state
    • Follow with agentxchain multi resync to rebuild coordinator state from repo truth

Barrier Types

The shipped coordinator supports five completion-barrier modes:

Barrier typeMeaning
all_repos_acceptedThe workstream completes only after every repo listed in the workstream has an accepted projection
ordered_repo_sequenceDownstream repos stay blocked until upstream acceptance order is satisfied
interface_alignmentCross-repo contract alignment barrier. The workstream must declare interface_alignment.decision_ids_by_repo, and the barrier is satisfied only when each repo has accepted the declared DEC-NNN decisions for that repo.
named_decisionsGeneral decision-checkpoint barrier. The workstream must declare named_decisions.decision_ids_by_repo, and the barrier is satisfied only when each repo has accepted the declared DEC-NNN decisions for that repo.
shared_human_gateNever auto-satisfies from repo acceptances; requires human approval through multi approve-gate

Barrier transitions are tracked in .agentxchain/multirepo/barriers.json and audited in .agentxchain/multirepo/barrier-ledger.jsonl.

interface_alignment is explicit, not magical. The coordinator does not infer semantic compatibility from changed files. You declare the required accepted decision IDs per repo in agentxchain-multi.json, and the barrier tracks progress per repo until every declared decision ID has been accepted.

Use named_decisions when the checkpoint is governance-driven rather than interface-specific. The evaluation logic is the same; the label is different because the operator intent is different.

Interface alignment end-to-end example

1. Config — declare what alignment means

agentxchain-multi.json
{
"schema_version": "0.1",
"project": { "id": "payments", "name": "Payment API v2" },
"repos": {
"api": { "path": "./repos/api", "default_branch": "main", "required": true },
"web": { "path": "./repos/web", "default_branch": "main", "required": true }
},
"workstreams": {
"payment_flow": {
"phase": "implementation",
"repos": ["api", "web"],
"entry_repo": "api",
"depends_on": [],
"completion_barrier": "interface_alignment",
"interface_alignment": {
"decision_ids_by_repo": {
"api": ["DEC-101"],
"web": ["DEC-201"]
}
}
}
},
"routing": {
"implementation": { "entry_workstream": "payment_flow" }
},
"gates": {
"initiative_ship": { "requires_human_approval": true, "requires_repos": ["api", "web"] }
}
}

The config says: api must accept a turn containing decision DEC-101, and web must accept a turn containing decision DEC-201, before the workstream barrier is satisfied.

2. Turn result — include the decision IDs

When the agent working in the api repo accepts a turn, its turn-result.json must include the decision in the decisions array:

.agentxchain/staging/<turn_id>/turn-result.json (excerpt)
{
"decisions": [
{ "id": "DEC-101", "title": "Payment endpoint contract", "status": "accepted" }
]
}

After agentxchain accept-turn in the api repo and the next agentxchain multi step, the coordinator projects that acceptance and evaluates the barrier. At this point:

  • api has accepted DEC-101 — aligned
  • web has not accepted DEC-201 — not aligned
  • Barrier status: partially_satisfied

3. Coordinator context — what the next repo sees

When multi step dispatches to web, the generated COORDINATOR_CONTEXT.md surfaces what is still required:

## Active Barriers
- barrier_payment_flow: interface_alignment (partially_satisfied)
Required decision IDs for web: DEC-201.

## Required Follow-ups
- Accept declared interface-alignment decisions for web: DEC-201.

COORDINATOR_CONTEXT.json carries the same data in machine-readable form, including the full alignment_decision_ids map and satisfied_repos list.

4. Completion — barrier satisfied

After the web repo accepts a turn with DEC-201 in its decisions array and the coordinator projects the result, the barrier reaches satisfied and the workstream can advance to the completion gate.

Cross-Repo Context

Every coordinator dispatch generates cross-repo context for the selected child repo:

  • COORDINATOR_CONTEXT.json
  • COORDINATOR_CONTEXT.md

Those artifacts summarize:

  • upstream acceptance projections from related workstreams
  • active non-satisfied barriers relevant to the target repo
  • declared decision IDs still required for the target repo (interface_alignment or named_decisions)
  • required follow-ups derived from dependencies and barrier notes

The generated context is also stored under .agentxchain/multirepo/context/<context_ref>/ so the coordinator can audit and invalidate stale context when upstream repos accept new work.

Coordinator Hooks

Coordinator hooks are defined in agentxchain-multi.json and are separate from repo-local hook phases.

Hook phaseBehavior
before_assignmentPre-action guard — blocks dispatch but does not persist blocked state
after_acceptancePost-action audit — failure persists status: "blocked" and fires on_escalation
before_gatePre-action guard — blocks gate approval but does not persist blocked state
on_escalationAdvisory — fires when the coordinator enters a blocked state

Coordinator hooks protect .agentxchain/multirepo/ files and repo-local protected files. They are not allowed to mutate child repo state, child repo history, or dispatch bundles.

Hook-Stop Semantics

Pre-action hooks (before_assignment, before_gate) and post-action hooks (after_acceptance) behave differently when they halt execution. This asymmetry is intentional.

Pre-action hooks prevent something from happening. When they block, no coordinator state changes. The coordinator remains active (or paused). Recovery is: fix the condition the hook is checking, then re-run multi step or multi approve-gate. No multi resume is needed.

Post-action hooks audit work that already happened. after_acceptance fires after a turn result has been projected into coordinator state. If the hook detects a problem (tamper, policy violation, failure), the coordinator state may be inconsistent. The coordinator persists status: "blocked", fires on_escalation, and requires explicit recovery via multi resume.

ScenarioCoordinator state after haltRecovery path
before_assignment blocks dispatchUnchanged (active or paused)Fix hook condition → re-run multi step
before_gate blocks gate approvalUnchanged (gate still pending)Fix hook condition → re-run multi approve-gate
after_acceptance fails or detects tamperPersisted as blockedInvestigate → fix root cause → multi resume → continue

Pre-action blocks do not fire on_escalation because they represent expected operational friction (policy gates, maintenance windows, approval holds). Post-action failures fire on_escalation because they represent unexpected integrity events that need investigation.

Coordinator Blocked States

When a coordinator enters blocked, the blocked_reason field in .agentxchain/multirepo/state.json describes why. Governance reports surface these reasons with structured diagnostic detail. The most common blocked states are:

Blocked stateCauseDiagnosisRecovery
Hook violationafter_acceptance hook failed or detected tamperCheck hook audit log in .agentxchain/multirepo/hooks/Fix root cause → fill RECOVERY_REPORT.mdmulti resume
Run identity drift (repo_run_id_mismatch)A child repo's run_id no longer matches what the coordinator recorded at initializationReport shows expected vs actual run_id per repoInvestigate why the child repo was re-initialized → restore the correct run or multi resume after filling RECOVERY_REPORT.md
Gate coherence failurePending gate references repos whose state no longer supports the gateCheck pending_gate in coordinator stateFix child repo state → multi resyncmulti resume

Run Identity Drift

Run identity drift is the most dangerous coordinator blocked state. It means a child repo was re-initialized (or its .agentxchain/state.json was replaced) after the coordinator linked it. The coordinator refuses to continue because the child repo's audit trail no longer belongs to the same governed run.

How it appears in reports:

  • Blocked reason: includes run identity drifted
  • Run ID mismatches: section lists each affected repo with expected and actual run IDs
  • Next Actions: includes per-repo repo_run_id_mismatch diagnostics

How it appears in CLI output:

  • multi step prints [repo_run_id_mismatch] with expected/actual run IDs
  • multi resync detects the drift and blocks instead of auto-adopting the new run

Recovery: Determine why the child repo's run changed. If it was accidental re-initialization, restore the correct .agentxchain/state.json from backup or git history. If it was intentional, fill in RECOVERY_REPORT.md explaining why, then agentxchain multi resume.

Dashboard And Recovery

The local dashboard exposes coordinator state through the Initiative and Cross-Repo views, with gate and blocked panels reading from the same .agentxchain/multirepo/ artifacts.

Do not blur the coordinator inspection commands together:

  • Use agentxchain audit from the current coordinator workspace when you need the live current multi-repo state.
  • Use agentxchain export when you need a portable coordinator artifact you can attach, compare, verify, or archive.
  • Use agentxchain report --input <coordinator-export.json> when you want a derived summary from an existing verified artifact, not the live workspace.
  • Use agentxchain replay export <coordinator-export.json> when you want the read-only dashboard for an existing artifact instead of a text, markdown, json, or html report.

That distinction matters most for partial coordinator artifacts. report --input keeps repo_ok_count / repo_error_count, preserves the failed repo row plus error, and does not invent missing child drill-down. replay export keeps the same verified coordinator artifact readable in the dashboard, but restores a placeholder child repo for failed nested exports so coordinator layout validation still works. audit is different from both: it inspects the current workspace directly and does not read a saved export artifact.

Recovery follows one hard rule: repo-local governed state is authoritative. The coordinator is a derived control plane, not the source of truth. If someone accepts or rejects a turn directly in a child repo, multi step will detect that divergence and auto-resync when safe; otherwise multi resync rebuilds or blocks explicitly instead of guessing.

Blocked-state recovery is a separate operator action:

  • Use agentxchain multi resync --dry-run / agentxchain multi resync to inspect or rebuild divergence from repo truth
  • When the coordinator enters blocked, including a resync that finds an ambiguous gate, a RECOVERY_REPORT.md is scaffolded in .agentxchain/multirepo/
  • Fill in ## Trigger, ## Impact, and ## Mitigation with real content describing the incident
  • Use agentxchain multi resume only after the recovery report is complete and the blocked cause is fixed
  • After multi resume, continue with agentxchain multi step or agentxchain multi approve-gate depending on the restored status

Intake Handoff

When a delivery signal is detected in a single repo but the resulting fix spans multiple repos, use intake handoff to bridge repo-local intake into a coordinator workstream.

# In the source repo: record, triage, approve, plan
agentxchain intake record --source ci_failure --category test_regression
agentxchain intake triage <event_id>
agentxchain intake approve <intent_id>
agentxchain intake plan <intent_id>

# Hand off to the coordinator workstream
agentxchain intake handoff <intent_id> --coordinator-root ../workspace --workstream payment_flow

The handoff writes a read-only reference to the coordinator at .agentxchain/multirepo/handoffs/<intent_id>.json. The coordinator's COORDINATOR_CONTEXT.md then includes the original intent charter and acceptance contract so agents in sibling repos understand why the workstream exists. The source repo retains authority over the intent — only intake resolve in the source repo can close it.

See Continuous Delivery Intake for the full intake lifecycle and handoff contract.

For the command-level reference, see CLI Reference. For the protocol overview, see Protocol.