Skip to content

Team Protocols: Inter-Agent Communication Standards

Overview

Team Protocols define the communication, synchronization, and coordination rules between team members. They ensure reliable cooperation even when agents operate in parallel across different processes.

Core Protocols

1. Permission Synchronization Protocol

Ensures all teammates respect consistent permission rules set by team lead.

Flow: Permission Request

Teammate Query:
  1. Tool called: Edit("/forbidden-file.ts")
  2. Check: Local permission rules
  3. Local rules: DENIED
  4. Check: Team rules (team.json)
  5. Team rules: NEUTRAL (not specified)
  6. Action: Send permission request to lead

Message to Lead:
  {
    id: "perm-req-123",
    from: "frontend-agent",
    type: "permission_request",
    tool: "Edit",
    path: "/forbidden-file.ts",
    timestamp: 1712000000000
  }

Lead Processing:
  1. Receives mailbox message
  2. Evaluates: Is this path safe to edit?
  3. Decision: allow | deny | ask_user
  4. Response:
     {
       id: "perm-req-123",
       type: "permission_response",
       decision: "allow",
       reason: "Required for integration"
     }

Teammate Resumes:
  1. Polls mailbox for response
  2. Receives permission_response
  3. Decision: allow → proceed with Edit
  4. Tool execution continues

Permission Rule Inheritance

Lead grants permission:
  teamAllowedPaths: [
    {
      path: "src/**",
      toolName: "Edit",
      addedBy: "lead-agent"
    }
  ]

Teammate inherits:
  "I can edit src/** per team rules"

Teammate checks permission:
  1. Edit("/src/main.ts")
  2. Does "src/main.ts" match "src/**"? YES
  3. Permission: ALLOW (no request needed)

Teammate checks:
  1. Edit("/config/secrets.json")
  2. Does "config/secrets.json" match "src/**"? NO
  3. Permission: ASK LEAD

2. Task Notification Protocol

All team members receive notifications when tasks change.

Flow: Task Status Change

Teammate Updates:
  TaskUpdate({
    taskId: "1",
    status: "in_progress",
    owner: "frontend-agent"
  })

System Broadcasts:
  Notification to all teammates:
  {
    type: "task_notification",
    taskId: "1",
    change: {
      status: { old: "pending", new: "in_progress" },
      owner: { old: null, new: "frontend-agent" }
    },
    timestamp: 1712000000000
  }

Teammates Process:
  1. Receive notification
  2. Update local task cache
  3. Check if any of my tasks are now unblocked
  4. If unblocked: Log message "Task 2 now ready to start"
  5. Can immediately claim: TaskUpdate(taskId: 2, in_progress)

Example Cascade:
  Task 1 complete
    → Task 2 unblocked (was blockedBy 1)
    → Task 3 unblocked (was blockedBy 1 and 2)
    → Multiple teammates can now start their work

3. Session Reconnection Protocol

Allows teammates to recover from disconnection.

Flow: Session Recovery

Teammate Session Active:
  Agent running in tmux pane
  Session: "session-456"

Connection Lost:
  (Network issue, terminal closed, etc.)

Lead Detection:
  1. Poll team session status
  2. Detect: session-456 no longer active
  3. Mark: teammate "inactive"
  4. Log: "frontend offline at 2024-04-01 15:32"

Reconnection:
  1. User reconnects to tmux pane
  2. System detects: same session resumed
  3. Process: Still running or crashed?
     → If crashed: Restart
     → If running: Resume normal operation
  4. Mark: teammate "active"
  5. Replay: Any missed messages (permission updates, task changes)

4. Mailbox Message Protocol

Generic message passing system between lead and teammates.

Message Structure

interface TeamMessage {
  id: string                 // Unique message ID
  from: AgentId             // Sender agent ID
  to: AgentId               // Recipient agent ID
  type: MessageType
  content: unknown          // Message-specific content
  timestamp: number         // Unix ms
  acknowledged?: boolean    // Has recipient processed?
}

type MessageType =
  | "permission_request"    // Teammate: ask lead
  | "permission_response"   // Lead: respond to request
  | "task_notification"     // Any: task changed
  | "status_update"         // Teammate: report progress
  | "error_report"          // Teammate: report failure
  | "instruction"           // Lead: direct teammate
  | "question"              // Teammate: ask for guidance
  | "acknowledgment"        // Any: confirm receipt

Mailbox Storage

~/.claude/teams/my-team/mailbox/

Frontend mailbox:
  [
    {
      id: "msg-1",
      from: "lead",
      type: "task_notification",
      content: { taskId: "2", status: "unblocked" }
    },
    {
      id: "msg-2",
      from: "lead",
      type: "permission_response",
      content: { decision: "allow", reason: "..." }
    }
  ]

Backend mailbox:
  [ ... ]

Lead doesn't have personal mailbox,
instead receives messages via polling.

Message Lifecycle

1. Create
   Message created and written to recipient mailbox

2. Deliver
   Recipient polled and reads mailbox
   → Message loaded into memory
   → Processed according to type

3. Acknowledge
   Recipient marks as processed
   → Removed from mailbox file
   → Frees disk space

4. Archive (optional)
   Processed messages can be archived for history

5. Execution Synchronization Protocol

Coordinates parallel work and prevents conflicts.

Sequential Constraint: Blocked Tasks

Task DAG:
  Database Schema → API Implementation → UI Integration

Execution:
  Time 0:
    Frontend: TaskList() → sees Task 3 (blockedBy 2)
    Backend: TaskList() → sees Task 2 (blockedBy 1)
    Database: Claims Task 1 → in_progress

  Time 5 minutes:
    Database: Task 1 complete
    → Notification sent: Task 1 completed
    → Task 2 unblocked

    Backend: Receives notification
    → Updates local TaskList
    → Task 2 no longer blocked
    → Claims Task 2 → in_progress

    Frontend: Task 3 still blocked (waiting for Task 2)

  Time 15 minutes:
    Backend: Task 2 complete
    → Notification sent: Task 2 completed
    → Task 3 unblocked

    Frontend: Receives notification
    → Task 3 now runnable
    → Claims Task 3 → in_progress

Conflict Prevention: File Locking

Scenario: Both teammates try to edit same file

Frontend attempts:
  Edit("/src/api.ts")
  1. Checks: Is file locked?
  2. Locked by: Backend
  3. Action: Ask lead
     "Backend is editing /src/api.ts, should I wait?"
  4. Lead response: "Wait for backend to complete"
  5. Frontend: Waits or works on different file

Backend completes:
  1. Releases lock
  2. Notification: "/src/api.ts now available"

Frontend resumes:
  1. Lock acquired
  2. Edit proceeds

Communication Channels

1. Mailbox (Asynchronous)

Used for permissions, task changes, status updates: - Non-blocking - Persistent (survives disconnection) - Polled by teammates - Good for: decisions, notifications

2. WebSocket (Synchronous, optional)

For real-time coordination: - Instant delivery - Requires connection - Used if available - Fallback to mailbox if unavailable

3. Shared Task List (Eventual Consistency)

All agents see same task state (with slight delay): - File system source of truth - Locked for consistency - Written by: TaskUpdateTool - Read by: TaskListTool

Protocol Examples

Example 1: Frontend and Backend Racing

Scenario: Frontend and backend both want to edit same API response format

Time 0:
  Frontend: "I'll modify API response to include user profile"
  Backend: "I'll modify API response to add pagination"

Flow:
  1. Frontend attempts: Edit("/src/api.ts")
     → Checks file lock: not locked
     → Acquires lock
     → Edit proceeds

  2. Backend attempts: Edit("/src/api.ts")
     → Checks file lock: locked by Frontend
     → Sends permission request: "Can I edit?"
     → Lead responds: "Wait, frontend is editing"
     → Backend: Works on different file for now

  3. Frontend completes edit, releases lock
     → Notification sent: "File released"

  4. Backend retries: Edit("/src/api.ts")
     → Checks file lock: not locked
     → Acquires lock
     → Edit proceeds
     → But now conflicts with frontend changes!

  5. Backend detects conflict
     → Sends to lead: "Merge conflict in /src/api.ts"
     → Lead: Reviews both changes, decides merge strategy
     → Lead: Instructs both teammates on resolution

Example 2: Permission Boundary Crossing

Scenario: Backend wants to edit frontend file (shouldn't normally happen)

Flow:
  1. Backend: "I need to fix UI component"
     → Edit("/src/components/Header.tsx")

  2. System checks:
     → Local rules: Denied (backend can't edit src/components)
     → Team rules: Denied (backend not in path allowlist)

  3. Sends permission request to lead:
     {
       tool: "Edit",
       path: "/src/components/Header.tsx",
       reason: "Need to update API integration with UI"
     }

  4. Lead reviews:
     → Is backend expertise needed? YES (API integration)
     → Grant temporary permission for this file

  5. Response to backend:
     {
       decision: "allow",
       reason: "API integration changes need backend knowledge",
       scope: "/src/components/Header.tsx only"
     }

  6. Backend: Edit proceeds
     → Makes necessary changes
     → Notifies frontend: "Updated Header.tsx for API"

  7. Frontend reviews and approves
     → Integration successful

Example 3: Parallel Work with Dependencies

Initial Task Setup:
  Task A: "Database schema" (independent)
  Task B: "Backend API" (blockedBy: A)
  Task C: "Frontend UI" (independent)
  Task D: "Integration tests" (blockedBy: B, C)

Time 0:
  Database: Claims A → in_progress
  Frontend: Claims C → in_progress
  Backend: Task B blocked, waits

Time 5:
  Database: Task A complete → notification
  → Backend: Receives notification
  → Task B unblocked!
  → Backend: Claims B → in_progress

Time 10:
  Frontend: Task C complete
  → Database and Backend both working (not needed)

Time 15:
  Backend: Task B complete
  → Tester: Receives notification
  → Task D unblocked (both A and C done)
  → Tester: Claims D → in_progress

Time 25:
  Tester: Task D complete
  → All work finished!

Protocol Compliance

Guarantees

Guaranteed: - All teammates see same task state (eventually) - Permission decisions are consistent - No concurrent writes to same file - Messages are delivered in order

Not guaranteed: - Real-time synchronization (async) - Instant message delivery (relies on polling) - Perfect conflict prevention (must use locks)

Trade-offs

Resilience over Consistency: - Teammates can work offline - Mailbox persists across disconnections - Catch up when reconnected

Simplicity over Efficiency: - File-based storage (no database) - Polling (no complex signaling) - Human-friendly conflict resolution

Implementation Details

Lead-Teammate Permission Bridge

// leaderPermissionBridge.ts
function syncPermissionsToTeammate(lead, teammate) {
  // 1. Teammate makes tool call
  // 2. Check: Is this permitted?
  // 3. Local rules: apply first
  // 4. No match: Query lead via bridge

  const leadDecision = await askLeadForPermission(tool, input)
  // Bridge queries lead's permission state
  // Returns: allow | deny | ask_user

  return leadDecision
}

Task Update Notification

// taskNotification.ts
function notifyTasksUpdated(taskId, changes) {
  // 1. Task file updated
  // 2. System detects: task change
  // 3. Broadcasts to all teammates:
  //    - Message in each mailbox
  //    - Local task cache invalidation
  //    - UI refresh
}

Mailbox Polling

// teammateMailbox.ts
async function pollMailbox(agentId) {
  // Every 5 seconds:
  // 1. Check mailbox file for this agent
  // 2. Read new messages
  // 3. Process by type:
  //    - task_notification → update task list
  //    - permission_response → unblock waiting tool
  //    - instruction → execute lead's direction
  // 4. Mark processed messages
  // 5. Remove from mailbox
}

Best Practices

1. Clear Responsibility Boundaries

✅ Good:

{
  "frontend-agent": {
    "allowedPaths": ["src/components/**", "src/hooks/**"],
    "cannotEdit": ["src/api/**", "src/db/**"]
  }
}

❌ Bad:

{
  "all-agents": {
    "allowedPaths": ["**"],
    "cannotEdit": []
  }
}
// No boundaries = conflicts inevitable

2. Explicit Task Dependencies

✅ Good:

Task 1: "Schema design" (independent)
Task 2: "API impl" (blockedBy: 1)
Task 3: "Tests" (blockedBy: 2)

❌ Bad:

All tasks independent
// Teammates guess order
// Risk of rework

3. Regular Synchronization Check-ins

✅ Good:

Team lead: Poll team status every iteration
→ Check for stalled teammates
→ Resolve permission disputes
→ Update blockers

❌ Bad:

Team lead: Set and forget
// Teammates stuck waiting
// Problems accumulate

Key Files

File Purpose
src/utils/swarm/permissionSync.ts Permission protocol
src/utils/swarm/teamHelpers.ts Team utilities
src/utils/swarm/leaderPermissionBridge.ts Lead-teammate bridge
src/utils/swarm/reconnection.ts Reconnection logic
src/utils/swarm/taskNotification.ts Task notifications
src/utils/teammateMailbox.ts Mailbox implementation

See Also