Agent Communication Protocol
Last amended: 2026-05-07 (NQU-757 thread — field-discipline + PR-signaling + advance-or-escalate)
Defines how the two AI agents in this workspace communicate, hand off work, and escalate to human input.
Roles
- CC (Claude Code). Code, tests, migrations, git operations, PR mechanics, runtime debugging, infrastructure/Terraform, observability.
- CD (Cowork / Claude Desktop). Strategic scoping, doc writing, spec drafting, content review, cross-cutting analysis, planning, requirements detailing.
- Joe. Strategic decisions, business judgment, customer-facing and contractual decisions, final merge approval.
The role split is summarized in MEMORY.md under "CD vs CC role split." Don't take work in the other agent's lane — reassign instead.
Channels
All durable agent-to-agent communication happens in Linear. Issues, comments, labels, the delegate field, and the assignee field are the source of truth. Other channels (file-system handoffs, journal entries) are supplementary.
Identities and attribution
- CC posts comments via its registered Linear identity. Any Linear MCP comment tool that posts as CC is acceptable.
- CD posts comments via
linear-agent-cd:comment. Never use the standardsave_comment— that attributes the post to Joe. - Both agents have distinct delegate identities (
delegate=CCanddelegate=CD). - Setting
delegate=CCordelegate=CDis the canonical way to route work between lanes.
Routing primitives
| Action | How |
|---|---|
| Hand off work to CC | Set delegate=CC on the issue. Comment summarizing what CC needs. |
| Hand off work to CD | Set delegate=CD on the issue. Comment summarizing what CD needs. |
| Ask the other agent a question | Comment on the relevant issue, address the other agent explicitly. |
| Escalate to Joe | Apply Review-Joe label. Comment with the question, options, and recommendation. |
Field, not comment. Routing decisions live in the delegate field, not in comment text. Stating "Marking delegate=CD" or "Reassigning to CC" in a comment without also updating the field is a discipline failure — the inbox-check skills, Joe's morning queue, and the state-drift audit all filter on the field, not on comment scrape. Update the field in the same step you announce the reassignment. If your only available tool for the field edit is Joe-attributed (CD's case for delegate changes today), surface that explicitly in the comment so attribution stays honest.
Signaling Joe for PR-merge gates
Per post-NQU-700 PR protocol, Joe's "go" gate moved from GitHub UI to chat. Two signaling rules:
- One PR per ask. Don't bundle multiple PRs into a multi-PR table inside a longer status — those are easy to skim past. When a PR is ready, post a single chat message:
PR #N ready — [one-line summary]. Risk: [low/med/high]. Go? - Linear-side mirror. If you also post in Linear (e.g., on the originating issue), lead the comment with
✅ READY FOR JOE GO — PR #N: [one-liner]so it stands out in Joe's inbox-check feed.
Either chat-only or chat-plus-Linear-header is acceptable; bundling-into-tables is not.
Wake-up: Scheduled Inbox Checks
Both agents are session-based — neither runs continuously between sessions. To enable agent-to-agent communication without Joe acting as a relay, both agents run scheduled tasks that poll Linear for unhandled work directed at them.
CD schedule
Cron: 0 9,10,13,17 * * * (Eastern US local time). Four runs daily: 9 AM, 10 AM, 1 PM, 5 PM.
CD's scheduled task:
- Reads memory for current project context
- Queries Linear for unhandled CD-directed items (
delegate=CD, new comments, mentions) - Responds, reassigns, or escalates each item
- Awaiting-Joe surface. Queries
label:Review-Joe AND state.type NOT IN (completed, canceled, triage_waiting_for)and lists the result in the run log under a 🟠 section. - State-drift audit. Lists issues with comments or updates in the last 24 h that are still in Backlog or Todo. Includes who last touched them. Does not auto-promote; surfaces for next interactive pickup.
- Logs a run summary to
Nquiry/docs/working/cd-inbox-runs.md
CC schedule
Cron: TBD on the CC side. Recommended 0 9,10,13,17 * * * (Eastern US) to match CD's cadence.
CC's scheduled task mirrors CD's: query for delegate=CC and CC-directed items, respond/reassign/escalate, run the same Awaiting-Joe surface and state-drift audit (steps 4 and 5 above), log a run summary.
Latency expectation
The shared cadence means routine items resolve within ~4 hours during business hours. Items posted overnight resolve at the 9 AM run. Plan against this latency — don't post time-sensitive work agent-to-agent and expect a 5-minute response. Real-time items go through Joe.
Escalation: Review-Joe
When either agent encounters an item that requires Joe's judgment, the protocol is:
- Apply the
Review-Joelabel to the issue. - Post a comment containing:
- The decision needed (one sentence)
- The options under consideration
- The agent's recommendation and reasoning
- What's blocked until Joe decides
- Set
delegate=Joeto make ownership explicit.
Joe's filter for "what needs my attention" is label:Review-Joe. Anything not labeled Review-Joe is presumed agent-handleable.
Filter spec (precise): label:Review-Joe AND state.type NOT IN (completed, canceled, triage_waiting_for). The Waiting For state is excluded because it represents a different stall semantic — see below.
Review-Joe vs. Waiting For — semantic distinction. Both pause an issue, but they represent different blockers:
- Review-Joe (in Backlog/Todo/In Progress): blocked specifically on Joe's judgment. Goes onto Joe's review queue.
- Waiting For: blocked on something other than Joe — third-party response, scheduled date, another open ticket, external dependency. Stays out of Joe's queue but tracked elsewhere.
Don't conflate them. If an item is awaiting Joe's ratification, sign-off, or direction, the correct combination is state=In Progress (or whatever the work state was) + Review-Joe label, not state=Waiting For. Use Waiting For only when Joe's action would not unblock the issue.
Removing Review-Joe. Strip the label the moment Joe acts (or when state moves to Done/Canceled). A Done issue with Review-Joe still attached is a discipline failure — clean it up. Any agent that reads such an issue in passing should fix it.
When to escalate
Escalate to Joe when any of the following apply:
- Decision affects pricing, billing, retention values, contracts, or other customer-facing policy
- Decision crosses a scope boundary an agent shouldn't unilaterally redraw
- Cross-functional dependency (legal, finance, outside counsel)
- Disagreement between CC and CD that the agents can't resolve in 2-3 rounds of comments
- Cost or risk threshold exceeded (define explicit thresholds in repo CLAUDE.md — e.g., changes touching billing flow, anything affecting external API contracts, anything destructive in production)
- Issue mentions "urgent," "blocker," "production," or refers to legal/financial/customer risk
- Comment thread has gone >3 rounds without resolution
When in doubt, escalate. Better to ask Joe and find out it was unnecessary than to make a call Joe wouldn't have made.
State Discipline
Issue state must reflect actual progress. Both agents must transition state when starting substantive work — not on issue creation, but at the moment of first real action.
Required transitions:
Backlog→Todowhen CD or CC commits the issue to active work (next session, this week, etc.)Todo→In Progresswhen an agent posts substantive content (a draft, a spec, a PR, a code change, etc.)In Progress→DoneorCanceledat completionIn Progress→Waiting Foronly when a non-Joe external blocker appears- For Joe-action items:
In Progress+Review-Joelabel (neverWaiting For)
Why this matters: the CD inbox-check, Linear filters, and Joe's morning review all rely on state to identify what's actively moving. Items grinding away in Backlog or Todo lie about WIP. The state-drift audit step in the CD inbox-check (see "Wake-up" above) catches items with recent activity in non-started states; that audit only works if discipline is consistent across humans and agents.
On the human side: Joe is bound by the same rule. When picking up an issue, bump it to In Progress so the system sees it.
On the agent side: when CD or CC opens an issue and does substantive work, the work itself counts as "starting." Don't leave a freshly-commented Todo issue in Todo. Use linear-agent-cd:state for CD-attributed transitions; CC uses its own state tool.
Use linear-agent-cd:state for CD-attributed transitions, never save_issue for state changes (the latter attributes the change to Joe).
In Progress: advance or escalate, never status-sweep
When an item has been In Progress across multiple sessions without commits, comments, or PRs, the default response is not "no progress this session." Items must advance per session or get explicit Review-Joe escalation with a specific question.
Two failure modes to avoid:
- Status-sweep on stalled items. Reading the issue body, noting "no movement," and parking is the wrong default. It costs queue legibility — Joe can't tell whether the item is stuck on him, on the other agent, or on you. Either commit a focused multi-session sprint and say so explicitly in a comment, or escalate the specific decision blocking progress via
Review-Joe. - Read the body once more before flagging "needs Joe scoping." Many In Progress items already contain proceed-defaults ("defaulting to X unless told otherwise"), pre-decided scope numbers, or stated tooling choices that resolve apparent open questions. Reread the issue body and any linked specs before flagging an item as scope-blocked. The 2026-05-07 review found a 4-of-6 false-positive rate on "needs Joe scoping" flags that traced to body-skimming during status sweep.
Pre-Review (recommended)
CC has the Agent SDK and can spawn subagents internally. Before posting Plans or PR descriptions for external review by CD or Joe, CC is encouraged to run an internal code-reviewer subagent for a self-review pass. This catches mechanical issues before external review and reduces iteration count.
CD doesn't have the equivalent surface today; this is a CC-side recommendation.
Examples
Example 1: CC has a technical question for CD
CC working on a refactor encounters a design decision (e.g., "should this helper assert the user exists in the DB on every call?"). Rather than waiting for Joe:
- CC posts the question as a comment on the Linear issue, addresses CD.
- CC's session ends.
- CD's next scheduled run (within 4 h during business hours) picks up the comment.
- CD posts a response with reasoning.
- CC's next scheduled run sees the response and proceeds.
- Joe sees the resolved thread on his next Linear scan but didn't have to mediate.
Example 2: CC encounters a billing-affecting change
CC working on a billing handler realizes they need to change how a quota is calculated, which will affect what customers see in invoices.
- CC applies
Review-Joelabel anddelegate=Joe. - CC posts comment: "This change shifts the quota math — current customers will see different numbers next billing cycle. Options: (a) grandfather existing, (b) apply to all on next cycle, (c) wait for end of contract term. Recommend (a). Blocked until your call."
- Joe sees the
Review-Joefilter, makes the call, removes the label, setsdelegate=CC. - CC's next run picks up the resolution and proceeds.
Example 3: CD identifies missing test coverage during spec review
CD reviewing a CC plan notices test coverage gaps but can't write tests itself.
- CD comments on the plan with the gap analysis.
- CD reassigns:
delegate=CC. - CC's next run reads the gap analysis and either accepts or pushes back via comment.
- Iteration continues agent-to-agent until resolution or escalation.
Anti-patterns
- Don't use
save_commentfor CD posts (attributes to Joe). Alwayslinear-agent-cd:comment. - Don't take work in the other agent's lane. Reassign instead.
- Don't make policy or business decisions on Joe's behalf. Escalate via
Review-Joe. - Don't leave items in limbo. Every reviewed item should advance to a clear next state (responded, reassigned, escalated, closed).
- Don't announce a delegate reassignment in a comment without updating the
delegatefield in the same step. - Don't bundle multiple PRs into a single status table when asking Joe for merge "go" — one PR per chat ask.
- Don't status-sweep stalled In Progress items. Advance them or escalate the specific blocker via
Review-Joe. - Don't spawn new tickets without Joe's go-ahead. Recommend creation via
Review-Joeinstead.
Sibling docs
git-workflow.md— GitHub Flow + branch protection rulesMEMORY.md(auto-memory) — agent identities, role split, project context