Org in a Box
Features

Dispatch & Agent Teams

Route tasks to isolated sandbox VMs, parallel agent teams, or the user's local machine — automatically.

Overview

The dispatch system lets the orchestrator classify any task and send it to the right execution environment. Instead of everything running in one shared sandbox, the agent chooses where work happens:

User: "Audit our codebase security, implement the fixes, and test them in isolation"

dispatch tool → mode: team_multi_vm

  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
  │ Auditor VM   │  │ Implementer  │  │ Tester VM    │
  │ (isolated)   │  │ VM (isolated)│  │ (isolated)   │
  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘
         └─────────────────┴──────────────────┘

                    Synthesizer collects results

                    Final response in parent session

Dispatch Modes

ModeDescriptionBest for
localChild session in the current sandboxQuick lookups, stateless Q&A, tasks under 30s
remoteFresh isolated ACA container from the warm poolLong-running tasks, file-heavy work, anything that should not affect the current environment
team_single_vmMultiple parallel agents sharing this sandboxParallel subtasks that need the same filesystem
team_multi_vmEach team member gets its own isolated sandboxParallel work where per-task isolation matters (e.g. competing implementations)
user_pcRoutes to the user's local machine via agent-tunnelDesktop automation, local file access

How the Agent Classifies

The orchestrator agent calls the dispatch tool before starting any non-trivial task. The LLM fills in the mode and a one-sentence rationale — there are no hard-coded rules:

Agent calls: dispatch(
  mode: "remote",
  rationale: "Task involves cloning an external repo and running tests — should not affect current environment",
  task_summary: "Clone github.com/acme/service, run full test suite, report failures"
)

The tool checks pool availability, writes an audit row to dispatch_decisions, and returns next-step instructions to the agent. For remote/multi-VM modes, the agent follows up with await_dispatch to collect the result once it arrives.

Explicit hints

Users can override the classifier by saying things like:

  • "run this in a clean environment" → forces remote
  • "do this async" → forces remote
  • "use a team for this" → forces team_single_vm or team_multi_vm

Agent Teams

Teams are the multi-agent coordination primitive. A lead agent spawns teammates, each running in their own opencode session, coordinating through message passing.

How messaging works

  1. A teammate sends a message (team_message) — it's appended to the recipient's JSONL inbox and injected directly into their session as a synthetic user message.
  2. The recipient's prompt loop restarts automatically (auto-wake) — no polling needed.
  3. After processing, the recipient sends a delivery receipt back to the sender.
  4. Any member can message any other member directly — not just the lead.

Team tools

ToolWhat it does
team_createCreate a named team (does not spawn members)
team_spawnFire-and-forget spawn a teammate with a role and initial prompt
team_messageSend a message to a specific member
team_broadcastSend a message to all members simultaneously
team_tasksView the status of all team members
team_claimAtomically claim a task from the shared list
team_approve_planLead approves/rejects the team's proposed plan
team_shutdownGracefully cancel all members
team_cleanupDelete inbox files and remove team from memory

Sub-agent isolation

When a team member spawns its own helper session (for searching, reading files, etc.), that helper cannot access any team tools. This prevents sub-agent chatter from flooding the coordination channel.

Sandbox Pool

The sandbox pool keeps warm ACA containers ready so remote and team_multi_vm dispatches start in milliseconds rather than waiting 30+ seconds for a cold container.

Pool lifecycle

provisioning → warm → claimed → draining → warm (recycled)
                                         ↘ destroying (pool full or unhealthy)
  • The pool manager maintains at least POOL_MIN warm containers at all times.
  • After a job completes, the container is wiped (sessions deleted) and returned to warm — unless the pool is already at POOL_MAX, in which case it is destroyed.
  • A health-check loop (every 30s) evicts unhealthy warm containers and triggers replenishment.
  • An autoscaler (every 15s) grows the pool when jobs are queuing and shrinks it when idle, with 2-minute hysteresis to prevent flapping.

Pool env vars (on the worker)

VariableDescription
ACA_SUBSCRIPTION_IDAzure subscription ID
ACA_RESOURCE_GROUPResource group for sandbox containers
ACA_ENVIRONMENTFull resource ID of the ACA managed environment
ACA_SANDBOX_IMAGEACR image to use for each sandbox container
ACA_LOCATIONAzure region (e.g. eastus)
POOL_MINMinimum warm containers (default 2)
POOL_MAXMaximum total containers (default 8)
POOL_AUTOSCALE_ENABLEDSet true to enable queue-depth autoscaling

Result Delivery

Remote sandboxes return results via the agent-tunnel result.submit protocol:

Remote sandbox → result.submit (HMAC-signed) → tunnel relay → Postgres NOTIFY → dispatch handler

                                                                          Injects "[Dispatch result]: ..."
                                                                          into parent session → auto-wake

For multi-VM teams, the synthesizer collects all member results and runs a synthesis pass before injecting the final answer.

Crash Recovery

If the worker restarts while a team is running:

  • Busy team members are marked ready but their prompt loops are not restarted automatically.
  • The lead session receives: "[System]: Server was restarted. Teammates interrupted: researcher, implementer. Use team_message to resume."
  • The user re-engages the lead, which re-coordinates the team.

This is intentional — automatic restart would risk runaway agents burning API credits on stale tasks.

On this page