Agent Teams inbox polling doesn't work in non-interactive/SDK streaming mode
Description
Agent Teams inbox-based messaging does not work when Claude Code runs in non-interactive mode (e.g., via the SDK with --output-format stream-json and stdio: pipe). The InboxPoller is implemented as a React UI hook (setInterval every 1000ms) that only fires when the React TUI renders — which requires an interactive TTY.
Steps to Reproduce
- Use the Claude Code SDK (or any wrapper that spawns Claude Code with
stdio: ['pipe', 'pipe', 'pipe']) - Enable Agent Teams (
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1) - Have the lead agent spawn teammates via
TeamCreate+Task - Teammates complete their work and send messages to the lead's inbox
- Lead never receives the messages — the inbox JSON files are written but never read
Expected Behavior
The lead agent should receive teammate messages regardless of whether it's running in interactive (TTY) or non-interactive (pipe/SDK) mode.
Actual Behavior
- From terminal (interactive, TTY): Works perfectly.
InboxPollerReact hook fires every second, reads inbox JSON files, and delivers messages. - From SDK/non-interactive mode:
InboxPollernever fires because the React TUI doesn't render. Inbox JSON files accumulate but are never read. The lead agent hangs waiting for teammate responses that never arrive.
Root Cause Analysis
The non-interactive detection logic:
let z = A.includes("-p") || A.includes("--print") || A.includes("--init-only") || A.some($ => $.startsWith("--sdk-url")) || !process.stdout.isTTY;
When process.stdout.isTTY is false (pipe mode), Claude Code enters non-interactive mode → React TUI doesn't render → InboxPoller hook (setInterval) never fires → inbox messages are never delivered.
Suggested Fix
Add a non-UI inbox polling mechanism for non-interactive mode. For example:
- A simple
setIntervalin the main process (not tied to React) that reads inbox files whenisInteractive === falseand Agent Teams are enabled - Or expose an environment variable / CLI flag to force inbox polling regardless of interactivity
Environment
- Claude Code version: 2.1.44 / 2.1.45
- OS: Ubuntu Linux 6.8.0-90-generic
- Context: Using Claude Code via Happy app which spawns Claude Code with
--output-format stream-jsonand piped stdio
Workaround
Currently using an external Python script that polls the inbox JSON files directly (~/.claude/teams/{name}/inboxes/{agent}.json), implements debounce, and marks messages as read. This works but is fragile and shouldn't be necessary.
Related Issues
- #23415 - Agent teams message delivery
- #23620 - Agent teams coordination
- #24108 - Agent teams in non-interactive contexts
This issue has 11 comments on GitHub. Read the full discussion on GitHub ↗