feat(core): add run_in_background support for Agent tool#3076
feat(core): add run_in_background support for Agent tool#3076tanzhenxin wants to merge 7 commits intomainfrom
Conversation
Enable sub-agents to run asynchronously via `run_in_background: true` parameter. Background agents execute independently from the parent, which receives an immediate launch confirmation and continues working. A notification is injected into the parent conversation when the background agent completes. Key changes: - BackgroundTaskRegistry tracks lifecycle of background agents - Agent tool gains async execution path with fire-and-forget semantics - Background agents use YOLO approval mode to prevent deadlock - Independent AbortControllers survive parent ESC cancellation - CLI bridges notifications via useMessageQueue for between-turn delivery - State race guards prevent complete/fail after cancellation - Session cleanup aborts all running background agents
E2E Test Results
|
📋 Review SummaryThis PR introduces a well-designed background agent execution feature that enables sub-agents to run asynchronously with proper lifecycle management and notification delivery. The implementation demonstrates solid architectural thinking with careful attention to race conditions, cleanup, and user experience. Overall, this is a high-quality implementation that follows existing patterns in the codebase. 🔍 General Feedback
🎯 Specific Feedback🟡 High
🟢 Medium
🔵 Low
✅ Highlights
|
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
- Add prefix/separator protocol to distinguish background notifications from user input - Show concise summary in UI while sending full details to LLM - Add 'notification' history item type with specialized display - Add 'background' agent status for background-running agents - Prevent notifications from polluting prompt history (up-arrow) - Truncate long descriptions in display text This improves the UX for background agents by showing cleaner, more concise notifications while preserving full context for the LLM. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Headless mode skips AppContainer, so the notification callback is never registered and background agent results would be silently dropped. Return an error prompting the model to retry without run_in_background.
…tification queue Replace the stringly-typed \x00__BG_NOTIFY__\x00 prefix/separator encoding with a typed notification path using SendMessageType.Notification. - Add SendMessageType.Notification to the enum - Change BackgroundNotificationCallback to emit (displayText, modelText) - Move notification queue from AppContainer into useGeminiStream (mirrors the cron queue pattern): register on registry, queue structured items, drain on idle via submitQuery - prepareQueryForGemini short-circuits for Notification type (skips slash commands, shell mode, @-commands, prompt history logging) - Remove BACKGROUND_NOTIFICATION_PREFIX/SEPARATOR constants
Background agent cleanup belongs in Config.shutdown() alongside other resource teardown (skillManager, toolRegistry, arenaRuntime), not in AppContainer's registerCleanup. This also ensures headless mode gets cleanup for free.
da16bf6 to
bcce78d
Compare
Background agent notifications were missing after session resume because they were never recorded in the chat history. The model text was absent from the API history and the display item was lost. - Add recordNotification() to ChatRecordingService — stores as user-role message with subtype 'notification' and displayText payload - Thread notificationDisplayText through submitQuery → sendMessageStream - Restore as HistoryItemNotification in resumeHistoryUtils
Background agents were using YOLO approval mode which auto-approves all tool calls — too permissive. Replace with shouldAvoidPermissionPrompts which auto-denies tool calls that need interactive approval, matching claw-code's approach. The permission flow for background agents is now: 1. L3/L4 permission rules (allow/deny) — same as foreground 2. Approval mode overrides (AUTO_EDIT for edits) — same as foreground 3. PermissionRequest hooks — can override the denial 4. Auto-deny — if no hook decided, deny because prompts are unavailable
E2E Test ReportAll tests run against local build (
E1 details (new test — deny-by-default permissions)Parent session in |
TLDR
Add
run_in_backgroundparameter to the Agent tool, enabling sub-agents to run asynchronously. When set totrue, the parent agent receives an immediate launch confirmation and continues working. A notification is delivered to the parent conversation when the background agent completes.Ported from the claw-code reference implementation's background agent feature.
Screenshots / Video Demo
N/A — the feature is exercised via model tool calls, not a visual UI change. The observable behavior is:
Dive Deeper
Key design decisions
shouldAvoidPermissionPromptsapproach: hooks first, then auto-deny, never deadlock.Config.shutdown()).complete()andfail()are no-ops if the agent has already been cancelled, preventing race conditions during concurrent shutdown.SendMessageType.Notificationwith structured{ displayText, modelText }payloads instead of stringly-typed encoding. The display item shows a concise summary while the model receives the full result.subtype: 'notification'and adisplayTextpayload, so both the API history and UI display are restored correctly on resume.run_in_backgroundis rejected in headless mode because the notification delivery infrastructure requires the interactive message loop.Reviewer Test Plan
Build and bundle first:
npm run build && npm run bundleStart an interactive session with
--approval-mode yolo. Ask the model to launch a background agent (e.g. "use the Agent tool with run_in_background true, Explore subagent, prompt list files"). You should see:● Background agent "..." completed.Unit tests:
cd packages/core && npx vitest run src/agents/background-tasks.test.ts src/tools/agent.test.tsTesting Matrix
Follow-up work
nonInteractiveCli.tsso background agents can complete and deliver results before the process exits. See.claude/todos/background-agent-headless-mode.md.AgentViewContextso they appear as tabs in the tab bar with live output, status indicators, and keyboard navigation. Reuses the existing Arena multi-agent display infrastructure. See.claude/design/background-agent-ui.md.cronQueueRefto the same typed notification queue that background agents use. See.claude/todos/notification-unification.md.Linked issues / bugs
shouldAvoidPermissionPrompts(deny-by-default) which complements the mode resolution logic in that PR.