| title | Steering |
|---|---|
| description | Redirect active sessions and teammates without destructive resets. |
This fork adds a more explicit steering workflow for both normal sessions and Agent Teams. Steering means injecting new guidance into work already in progress instead of tearing the session down and starting over.
:::note
Team steering is fork-specific and experimental.
Enable it with OPENCODE_EXPERIMENTAL_AGENT_TEAMS=1.
:::
For a normal session, steering injects corrective instructions into the conversation without cancelling the current run first. If the session is idle, the loop is woken up. If it is already busy, the new guidance is queued into the active flow.
For a teammate, steering is status-aware. The lead can:
- send a direct message while the teammate is busy
- resume a paused teammate with a redirect
- restart a ready or errored teammate with new instructions
- broadcast new guidance to all active teammates
Agent Teams only works well if the lead can keep teammates aligned without reclaiming every task personally. Steering gives the lead a fast feedback loop for:
- clarifying scope
- correcting direction
- resuming checkpointed work
- nudging teammates toward consensus
- recovering idle or errored members
When a non-team session is busy, the TUI exposes a steering prompt action via session_steer (ctrl+s by default).
That action posts to the session steering route and injects follow-up instructions.
Lead sessions show a Steer team action via session_steer (ctrl+s by default) and in the command palette.
The team steer dialog supports:
- Message one teammate
- Pause one teammate
- Resume one teammate, optionally with redirect text
- Cancel one teammate or all active teammates
- Steer all active teammates at once
The TUI also supports direct lead-to-teammate messaging from the prompt. When a teammate is selected, prompt submission goes to the team message route instead of the normal chat loop.
| Method | Path | Purpose |
|---|---|---|
POST |
/session/:sessionID/steer |
Inject instructions into a normal session without cancelling its current work |
POST |
/session/:sessionID/team-message |
Send a direct lead message to a teammate from the active session |
| Method | Path | Purpose |
|---|---|---|
POST |
/team/:name/steer |
Message, resume, or restart one teammate depending on status |
POST |
/team/:name/pause |
Pause one teammate without shutting the session down |
POST |
/team/:name/resume |
Resume a paused teammate, optionally with a redirect |
POST |
/team/:name/steer-all |
Broadcast updated instructions to active teammates |
POST |
/team/:name/cancel |
Cancel one teammate or all active teammates |
All /team routes require the caller session in the x-opencode-session header.
If a teammate is spawned with plan approval enabled:
- They start in read-only plan mode.
- They research and send a plan back with
team_message. - The lead reviews it.
- The lead uses
team_approve_planto approve or reject it. - Approval removes only the plan-mode deny rules, unlocking write tools.
If checkpoint mode is enabled, the system pauses the teammate at configured boundaries. The lead can then inspect progress and resume the teammate with a redirect.
| Area | Files |
|---|---|
| Normal session steering | packages/opencode/src/server/routes/instance/session.ts, packages/opencode/src/team/runtime.ts |
| Team steering routes | packages/opencode/src/server/routes/instance/team.ts |
| Team lifecycle hooks | packages/opencode/src/team/index.ts |
| TUI steer dialog | packages/opencode/src/cli/cmd/tui/routes/session/dialog-team-steer.tsx |
| Sidebar/footer and prompt wiring | packages/opencode/src/cli/cmd/tui/feature-plugins/sidebar/team.tsx, packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx, packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx, packages/opencode/src/cli/cmd/tui/routes/session/index.tsx |
| Team state refresh | packages/opencode/src/cli/cmd/tui/context/sync.tsx, packages/opencode/src/server/routes/instance/event.ts |
user steers busy session
→ POST /session/:id/steer
→ SessionPrompt.steer()
→ inject instruction into the session
→ wake the loop only if the session is idle
lead chooses teammate action
→ POST /team/:name/steer
→ check teammate status
├─ busy → send message
├─ paused → resume with redirect
├─ ready → restart with new instructions
└─ error → restart with new instructions
team action happens
→ team.* event is published
→ /event stream emits redacted update
→ TUI notices team.*
→ TUI refetches /team/by-session/:sessionID
→ header, sidebar, and dialogs refresh from server truth
Team state appears in:
- the session header
- the session sidebar
- the team dialog
- the steer dialog
The UI renders dedicated message cards for:
team_createteam_spawnteam_delegateteam_request_spawn
Those cards can link directly to spawned child sessions.
- Session steering is non-destructive by design.
- Team steering is only available to the lead for that team.
- Plan approval is exposed through the
team_approve_plantool, not a dedicated/teamHTTP route. - Steering works best when paired with
team_status,team_inbox, andteam_collectso the lead can react to current state instead of guessing.