MCPcopy
hub / github.com/codeaashu/claude-code / getTeammateMailboxAttachments

Function getTeammateMailboxAttachments

src/utils/attachments.ts:3532–3769  ·  view source on GitHub ↗

* Get teammate mailbox attachments for agent swarm communication * Teammates are independent Claude Code sessions running in parallel (swarms), * not parent-child subagent relationships. * * This function checks two sources for messages: * 1. File-based mailbox (for messages that arrived betwee

(
  toolUseContext: ToolUseContext,
)

Source from the content-addressed store, hash-verified

3530 * allowing teammates to receive messages without waiting for the turn to end.
3531 */
3532async function getTeammateMailboxAttachments(
3533 toolUseContext: ToolUseContext,
3534): Promise<Attachment[]> {
3535 if (!isAgentSwarmsEnabled()) {
3536 return []
3537 }
3538 if (process.env.USER_TYPE !== 'ant') {
3539 return []
3540 }
3541
3542 // Get AppState early to check for team lead status
3543 const appState = toolUseContext.getAppState()
3544
3545 // Use agent name from helper (checks AsyncLocalStorage, then dynamicTeamContext)
3546 const envAgentName = getAgentName()
3547
3548 // Get team name (checks AsyncLocalStorage, dynamicTeamContext, then AppState)
3549 const teamName = getTeamName(appState.teamContext)
3550
3551 // Check if we're the team lead (uses shared logic from swarm utils)
3552 const teamLeadStatus = isTeamLead(appState.teamContext)
3553
3554 // Check if viewing a teammate's transcript (for in-process teammates)
3555 const viewedTeammate = getViewedTeammateTask(appState)
3556
3557 // Resolve agent name based on who we're VIEWING:
3558 // - If viewing a teammate, use THEIR name (to read from their mailbox)
3559 // - Otherwise use env var if set, or leader's name if we're the team lead
3560 let agentName = viewedTeammate?.identity.agentName ?? envAgentName
3561 if (!agentName && teamLeadStatus && appState.teamContext) {
3562 const leadAgentId = appState.teamContext.leadAgentId
3563 // Look up the lead's name from agents map (not the UUID)
3564 agentName = appState.teamContext.teammates[leadAgentId]?.name || 'team-lead'
3565 }
3566
3567 logForDebugging(
3568 `[SwarmMailbox] getTeammateMailboxAttachments called: envAgentName=${envAgentName}, isTeamLead=${teamLeadStatus}, resolved agentName=${agentName}, teamName=${teamName}`,
3569 )
3570
3571 // Only check inbox if running as an agent in a swarm or team lead
3572 if (!agentName) {
3573 logForDebugging(
3574 `[SwarmMailbox] Not checking inbox - not in a swarm or team lead`,
3575 )
3576 return []
3577 }
3578
3579 logForDebugging(
3580 `[SwarmMailbox] Checking inbox for agent="${agentName}" team="${teamName || 'default'}"`,
3581 )
3582
3583 // Check mailbox for unread messages (routes to in-process or file-based)
3584 // Filter out structured protocol messages (permission requests/responses, shutdown
3585 // messages, etc.) — these must be left unread for useInboxPoller to route to their
3586 // proper handlers (workerPermissions queue, sandbox queue, etc.). Without filtering,
3587 // attachment generation races with InboxPoller: whichever reads first marks all
3588 // messages as read, and if attachments wins, protocol messages get bundled as raw
3589 // LLM context text instead of being routed to their UI handlers.

Callers 1

getAttachmentsFunction · 0.85

Calls 15

isAgentSwarmsEnabledFunction · 0.85
getAgentNameFunction · 0.85
getTeamNameFunction · 0.85
isTeamLeadFunction · 0.85
getViewedTeammateTaskFunction · 0.85
logForDebuggingFunction · 0.85
readUnreadMessagesFunction · 0.85
isInProcessTeammateFunction · 0.85
isShutdownApprovedFunction · 0.85

Tested by

no test coverage detected