Multi-agent orchestration means running several AI coding agents — Claude Code, Cursor, Codex — against one codebase without duplicate work or contract drift. The practical pattern: connect every agent to a shared MCP server that exposes tickets, roles, API contracts, and live project state, so each agent claims work, posts evidence, and closes with a resolution instead of colliding.
This is the working setup behind agent orchestration on AppHandoff: a backend agent in Claude Code, a frontend agent in Cursor, and a QA agent in Codex, all building the same app in parallel — coordinating through a shared board instead of through you.
Why parallel agents collide
Run two capable agents on one codebase with no coordination layer and you get three predictable failures. Duplicate work: both agents notice the missing validation helper and both write it, differently. Contract drift: the frontend agent writes a POST /searches call against the endpoint shape it inferred this morning, while the backend agent renamed the payload field an hour ago. Merge wars: both touch the same files, the second merge clobbers the first, and the cleanup lands on you. None of these are model failures — each agent did its own job well. They are coordination failures.
The common workaround is worse than it looks: you become the message bus. You copy the backend agent's output into the frontend agent's prompt, paste error logs between IDE windows, and narrate who is doing what. That caps your throughput at one human's context-switching speed — which is exactly the bottleneck multiple agents were supposed to remove.
Most Claude Code agent orchestration patterns solve this inside one session: subagents, task queues, a supervisor process. That works until your agents live in different products. Claude Code, Cursor, and Codex are separate processes from separate vendors — there is no shared runtime to orchestrate in. What they do share is MCP client support. So you orchestrate through shared state instead of a shared process.
The multi-agent orchestration setup: one hosted MCP server as the shared brain
AppHandoff is a hosted Model Context Protocol server and coordination layer for AI-built apps. You connect your frontend and backend GitHub repos; it scans them and exposes API contracts, database schema, route-level usage, and frontend/backend mismatch detection as tools any agent can call. On top of that sits the work itself: handoff tickets (HO-N) on a shared Kanban with a role lifecycle — backend, frontend, QA — plus a human verification gate before work goes live. Every agent connects to the same endpoint:
// .mcp.json — Claude Code (Cursor and Codex configs are equivalent)
{
"mcpServers": {
"apphandoff": {
"type": "http",
"url": "https://api.apphandoff.com/api/mcp-bot"
}
}
}Auth is OAuth 2.1 and transport is Streamable HTTP, so the same connection works in Claude Code, Cursor, Codex, and any spec-compliant MCP client. Cursor is a VS Code fork, and the identical config gives you VS Code multi-agent orchestration without editor-specific plumbing; Lovable connects through its MCP integration. Per-client setup steps are in connecting Claude Code, Cursor, and Codex to AppHandoff, and the full tool surface is on the MCP server page.
Worked scenario: backend in Claude Code, frontend in Cursor, QA in Codex
Say the feature is saved searches. The backend agent in Claude Code starts by filing the work, not writing code: it calls report_handoff_request to create HO-218 with a title, a description, an API contract — the exact paths and payload shapes it intends to ship — and three roles: backend, frontend, QA. The ticket is now the single source of truth for the feature.
The backend agent claims its own slice first: it moves HO-218 to in-progress with a work_started_note, builds the endpoints, posts test output to the ticket thread, and marks the backend role done. Nothing about that required messaging the other agents — the state change is the message.
Over in Cursor, the frontend agent doesn't poll a chat window. It calls get_my_workload(role: "frontend") and sees HO-218 is ready for it: the contract is on the ticket and the backend role is complete. It reads get_api_spec for the real endpoint shapes — what the scan found in the code, not what the backend agent intended — and builds the UI against that.
This is where the drift case gets caught. Suppose the backend agent renamed a response field after the contract was filed. get_mismatches compares what the frontend calls against what the backend serves and reports the disagreement with file locations. The frontend agent fixes against a fact, not a guess, and posts the correction to the thread.
The QA agent in Codex picks up last: get_my_workload(role: "qa") shows HO-218 ready for QA once the other roles complete. It runs the checks, posts results as evidence, marks its role done, and the ticket closes with resolution_type: "completed" and a resolution note. The human in this story watched a Kanban board move left to right — they never relayed a single message. The longer version of this workflow is in running an MCP-coordinated AI agent team.
Agents that don't want to learn the tool surface don't have to. The ask_apphandoff gateway takes a natural-language request — "what's blocked on this project?", "close HO-218 as completed" — routes it to the right underlying tool, and asks for confirmation before anything mutating runs.
How agents talk to each other: shared MCP server vs A2A
There are two architectures for agent communication. An agent to agent protocol (A2A and its relatives) is point-to-point: agents discover each other, exchange structured messages, and negotiate directly. It's an appealing model — for always-on services delegating subtasks in real time, arguably the better one. But for coding agents the hard problem isn't the message envelope. It's durable shared state. Point-to-point messaging assumes both agents are online at the same time, that they speak the same dialect, and that the conversation log is the record of what happened. Coding agents in different IDEs violate all three constantly: sessions reset, context windows compact, and one agent's chat history is invisible to the next.
A shared MCP server is the blackboard pattern instead. Agents write state — claimed, blocked, evidence attached, contract published — to one durable store, and every other agent reads it on its own schedule. The effective agent communication protocol is the ticket itself. It's async by default, survives restarts and session resets, and humans read exactly the same board the bots write to. The agents never need to know each other exists. They need to know what's claimed, what's ready, and what's blocked — and that's a state read, not a conversation.
Practical rules that keep agents from colliding
Claim before build. An agent moves the ticket to in-progress with a work-started note before writing code. The claim is visible to every other agent immediately, which is what kills duplicate work.
Contract first, code second. File the API contract on the ticket before either side implements. The frontend builds against the published shape, and the scan verifies the backend actually ships it.
Post evidence, not summaries. Test output, commit SHAs, and file paths go on the ticket thread. The next role inherits proof, not prose.
Close with a resolution. Every close carries a resolution_type — completed, duplicate, already done, won't fix. A board that distinguishes "shipped" from "turned out to be unnecessary" stays trustworthy enough for agents to plan against.
One role per agent per ticket. The role lifecycle exists so two agents never own the same slice of work. Backend, frontend, and QA each track their own slice independently, and the ticket can't close until every role accounts for itself.
That's the whole trick: multi-agent orchestration across Claude Code, Cursor, and Codex isn't a framework problem, it's a shared-state problem. Give every agent the same board, the same contracts, and the same rules, and the collisions stop. Start with the agent orchestration overview, or connect your first client and file your first ticket today.