Background Tasks
“Slow Operations Go to the Background”
The agent can keep reasoning while slow work completes elsewhere.
Slow operations execute in background threads so the agent can continue reasoning. Results are pushed to an event bus with no polling required. This dramatically improves throughput for long-running tests, network calls, file downloads, and similar operations.
Architecture Flow
The Problem: Blocking Operations Kill Agent Throughput
When the agent runs a slow command such as npm install, a test suite, or a git clone, the loop blocks. The model sits idle, waiting for the result. A thirty-second test run means thirty seconds of dead time. Background tasks solve this by decoupling execution from reasoning. The agent starts the task, continues reasoning (planning next steps, preparing follow-up work), and collects the result when it arrives through the event bus. This transforms sequential wait time into parallel productivity.
Event Bus: The Glue Between Parallel Workstreams
The event bus is a simple publish-subscribe mechanism. Background tasks emit events on completion; the agent loop listens for those events and incorporates results into the conversation. This pattern is more flexible than callbacks (multiple listeners can react to the same event) and more efficient than polling (no wasted cycles checking task status). The event bus also solves the join problem: if the agent dispatches multiple background tasks, it can wait for all of them or respond to the first one that completes.
Real Implementation: Promotion Pattern
OpenCode's actual BackgroundJob system (packages/core/src/background-job.ts) uses a promotion pattern rather than a simple start-and-await approach. Jobs transition through states: start, extend (chained sequential work), promote (mark as background), then wait for promotion. The key insight is that a job can start in foreground mode and later get promoted to background, or vice versa. This enables a start-foreground-decide-later pattern: the agent begins a task synchronously, then promotes it to background if it takes too long. The subagent task tool uses this exact pattern: foreground subagents await the result, while background subagents continue independently.
Design Decisions
Background tasks use the agent's own tool system. Running 'npm run build' uses the same bash tool: the only difference is the agent does not wait for the result. Background tasks inherit all tool capabilities and security controls.
The event bus runs synchronously within the agent process. There is no message queue, no serialization, and no network. This keeps latency near zero and avoids the complexity of distributed systems.
Comparison: Claude Code
Claude Code processes tasks synchronously: each tool call blocks the agent loop. OpenCode's background job system is a clear differentiator. Long-running operations (web searches, code compilation, test suites) run in the background while the agent continues reasoning. Results arrive through the event bus and are injected into the conversation when ready, enabling a non-blocking, concurrent workflow.
Deep Dive: Design Decisions
The Agent Should Never Wait
Slow operations (long-running commands, network calls, file downloads) execute in the background. The agent continues reasoning and can check on results later. This keeps the agent responsive.
Result Notification via Event Bus
When a background task completes, it pushes a notification to an event bus. The agent's main loop picks up notifications and processes results when it's ready, without polling.