Skip to content

Teams

Teams group multiple sub-agents under a single team identity with a shared task queue, inter-member message bus, and per-team event log. A coordinator session spawns a lead plus zero or more teammate members, decomposes the goal into tasks, and watches the team progress through completion or shutdown.

Maturity: Opt-in coordination surface. Teams is for multi-agent goals where you want named members, shared tasks, and cross-member messaging — it is not required for normal single-agent or sub-agent workflows.

  • You have a goal that decomposes naturally into parallel tasks owned by different members.
  • You want a durable team identity and event log so you can inspect or resume coordination later.
  • You need cross-member messaging and broadcast — not just sequential spawn-and-collect.

If you only need a single sub-agent, use the regular sub-agent / A2A surfaces and leave teams disabled.

In your config (e.g. bmo.toml or ~/.config/bmo/bmo.toml):

[options.teams]
enabled = true

For a multi-host setup, point at a remote teams server (another BMO instance running the /v1/teams/* route group):

[options.teams]
enabled = true
server_url = "https://teams.example.com"

Teams is opt-in; leaving the section absent (or enabled = false) is the default and keeps all team-aware tools and routes off.

Every operator surface reads from the same shared snapshot (app.BuildTeamsStatusSnapshot) so CLI / TUI / HTTP / agent see the same posture at the same instant.

CLI

Terminal window
bmo team list # active teams (one row per team)
bmo team status <team-id> # detailed per-team inspector
bmo team cleanup --all # remove stale / orphaned team state
bmo config show-teams # merged config + recent events tail

TUI

  • /teams — full posture report (config, team count, recent events).
  • /team <id> — per-team inspector dialog (members, tasks, messages).
  • Sidebar chip — idle, <n> active, <n> blocked, or warn: <action> when the recent ring tail surfaces a failure or degraded arm. Click-equivalent routes to the /teams report.

HTTP

The same routes work for both local and remote teams servers (same auth middleware as /v1/teams/*):

GET /v1/teams # list teams
POST /v1/teams # create a team
GET /v1/teams/{id} # one team
DELETE /v1/teams/{id} # cleanup
GET /v1/teams/{id}/events # per-team event log (existing)
GET /v1/teams/posture # merged posture snapshot (this feature)

Agent tool

list_recent_team_events(limit=16)

Returns the last n metadata-only events from the in-process ring as JSON — same shape the slash command and HTTP posture endpoint serve.

Teams emits two slog channels via teamsEmitter:

  • teams.fired — once per lifecycle invocation (paired with one or more teams.action records via invocation_id).
  • teams.action — one record per bounded action (team_created, member_joined, task_completed, remote_degraded, …).

The full enum and copy-paste jq recipes live in the Tracing recipes for Teams maintainer page.

Field discipline. Identifiers are stored as 8-char FNV32 hex prefixes (team_id_hash, session_id_hash) — never raw goal text, member names, message bodies, or auth tokens. The remote URL is stored host-only (no scheme, no path) on every operator surface.

Sticky remote_degraded. When the configured remote server returns ≥3 consecutive failures on any operation, the snapshot’s remote_degraded flag flips sticky. The first transition into degraded emits exactly one remote_degraded arm; the next successful operation emits exactly one remote_recovered arm and clears the flag. Subsequent failures while already degraded do not re-emit. This is the same containment contract used by the workspace strategy persistence-degraded surface.

Orphan cleanup. bmo team cleanup --all walks the local team state directory, removes teams whose lead session no longer exists, and emits a single cleanup_completed arm with removed=N / scope=all (or scope=single for the single-team path). A run with zero stale teams still emits one cleanup_completed arm with removed=0 so the audit trail captures every cleanup attempt.

Teams is a coordination surface — not a workflow engine. The following are explicitly out of scope:

  • No retries on remote failures. The 3-failure threshold flips the sticky degraded flag; it does not silently retry the failing operation.
  • No mid-flight chaos containment. A remote partition during an in-flight operation surfaces as remote_failed and (eventually) remote_degraded; the operation itself is not auto-recovered.
  • No goal text or message body in telemetry. Operators inspect payloads through the per-team events.jsonl log; the bounded teams.action channel carries metadata only.
  • No global team registry. Teams remain per-data-dir / per-server; cross-server team aggregation is not provided.

See the maintainer topic docs/topics/orchestration/teams.md for the architecture and the per-team event log shape.