Aleph
Gateway RPCMethods Reference

teams.*

Team and multi-agent orchestration RPC methods

teams.* is the per-team CRUD + coordination surface. About thirty methods are wired across two registrations:

  • register_teams_handlers (src/bin/aleph-server/commands/start/builder/handlers/agents.rs:207-552) — store-only handlers, always registered when a team_store is constructed.
  • Two hand-wired methods inside agent_init/mod.rsteams.chat.send and teams.chat.cancel — registered only when the team store is present, because they need the GatewayContext + execution path to drive a leader run and abort a fan-out tree.

A team's work thread is durable (CoordTask board + team_messages); live conversational bubbles (leader / member narrative) are streamed over team.<id>.* on the event bus and are not queryable as a teams.* RPC. On reload, the Panel shows the durable record (tasks + deliverables), not the live narrative.

Methods

CRUD

teams.create

Create a persistent team. The leader is auto-enrolled with role="leader". auto_name: true arms the one-shot auto-naming flag so the first teams.chat.send replaces the provisional name with an LLM-generated topic.

ParameterTypeRequiredDescription
namestringyesTeam name (non-blank)
descriptionstringnoFree-text description
leader_idstringyesAgent id of the leader (plans + reviews member work)
membersobject[]noEach { "agent_id", "role" } (default role: member). The leader is auto-enrolled; duplicates are skipped.
auto_namebooleannotrue arms first-message auto-naming

Response: { "team_id", "name", "leader_id" }.

teams.get

Fetch a team's full record (team, members, and tasks).

ParameterTypeRequiredDescription
team_idstringyesTeam id

Response: { "team": { ...Team... }, "members": [ ...TeamMember... ], "tasks": [ ...CoordTask... ] }.

teams.list

List all teams. Response: { "teams": [ ...TeamSummary... ] }.

teams.rename

Rename a team. The Panel sidebar inline-edit drives this.

ParameterTypeRequiredDescription
team_idstringyesTeam id
namestringyesNew name (non-blank)

Response: { "ok": true } on success; RESOURCE_NOT_FOUND (-32004) on unknown id.

teams.disband

Mark a team as disbanded (working state torn down, history preserved). Fires a team.changed event so the group-chat sidebar and the teams tab both refresh.

ParameterTypeRequiredDescription
team_idstringyesTeam id

Response: { "success": true }.

teams.delete

Permanently delete a team with cascade cleanup. The full variant (handle_delete) cascades through five subordinate stores (tasks / artifacts / events / messages / snapshots). The basic variant (handle_delete_basic) is used when the subordinate stores are not configured. Only one is wired at runtime, depending on which stores exist.

ParameterTypeRequiredDescription
team_idstringyesTeam id

Response: { "success": true }.

agents.teams

List all teams an agent belongs to (as leader or member). When the live AgentManager + MessageStore are supplied, each team summary is enriched with members_preview (up to 4 members with name + emoji) and last_message / last_message_at (most recent transcript entry, truncated to 60 chars).

ParameterTypeRequiredDescription
agent_idstringyesAgent id

Response: { "teams": [ ...TeamSummary with members_preview + last_message + last_message_at... ] }.

Chat

The team work thread is durable (tasks + artifacts), but live conversation bubbles are streamed live. After reload, the Panel shows the durable record.

teams.chat.send

Start (or continue) the team work thread. Stores the user message into the shared transcript, then fans out by @mention (no @ → leader fallback) via the GroupChatBroadcaster. The fan-out tree is registered as a tracker node first, so the run_id returned is immediately cancellable.

On the very first message, if the team was created with auto_name: true, the topic LLM fires in the background to replace the provisional name.

ParameterTypeRequiredDescription
team_idstringyesTeam id
messagestringyesUser message (non-empty)

Response: { "run_id": "<uuid>" }. Use this run_id with teams.chat.cancel to stop the fan-out.

teams.chat.cancel

Stop an in-flight teams.chat.send fan-out tree. The tree-level token is poisoned first, then every still-running member run is cancelled through the engine's per-run CancellationToken. A run_id that is unknown or already settled returns RESOURCE_NOT_FOUND.

ParameterTypeRequiredDescription
run_idstringyesThe run_id returned by teams.chat.send

Response: { "run_id", "cancelled": true, "members_running", "members_signalled" }.

teams.chat.history

Replay the team's durable group-chat transcript as attribution bubbles. Drops directed inbox traffic (notifier digests, router hints, discovery pings) — only conversation rows (MessageType::Message) and the broadcaster's in-chat notices are surfaced. Returns the newest 200 chat-visible rows.

ParameterTypeRequiredDescription
team_idstringyesTeam id

Response: { "items": [ ...{from_agent, content, msg_type, kind: "user"|"agent"|"system", created_at}... ] } sorted oldest first.

teams.chat.thread

Hydrate a team's durable work thread: CoordTasks and their submitted artifacts merged chronologically. The live conversational bubbles are intentionally NOT included — they are streamed over team.<id>.* while the run is live.

ParameterTypeRequiredDescription
team_idstringyesTeam id

Response: { "items": [ ...{kind: "task"|"artifact", agent_id, title, content, timestamp, artifact_id?}... ] } sorted by timestamp.

Tasks / Kanban

The board state machine is Pending → InProgress → WaitingReview → Completed (with Blocked / Failed / Cancelled / Skipped / Paused / Unsatisfiable for the panel-drawn paths).

teams.create_task

Create a CoordTask on the team's board. When owner is supplied, the task is stamped with metadata.managed_by = "dispatcher" so the autonomous dispatcher claims it; without that stamp, select_schedulable filters the task out and the kanban silently never advances.

ParameterTypeRequiredDescription
team_idstringyesTeam id
subjectstringyesNon-blank task subject
descriptionstringnoFree-text description
ownerstringnoAgent id; triggers managed_by=dispatcher
prioritystringnolow / normal / high / critical (unknown id rejected with INVALID_PARAMS)
blocked_bystring[]noOther task ids this task is blocked by
metadataobjectnoPer-task metadata (kept verbatim)

Response: { "task": { ...CoordTask... } }.

teams.update_task

Patch a task. metadata is a shallow merge patch (the previous metadata is read and merged), so a metadata.managed_by=... write from a Panel user never wipes the dispatcher's other control keys.

status accepts pending / in_progress / completed / failed / cancelled. blocked is derived, not stored — sending status="blocked" is rejected with INTERNAL_ERROR.

ParameterTypeRequiredDescription
task_idstringyesTask id
statusstringnoNew status (see above)
ownerstringnoNew owner agent id
resultstringnoFree-text task result (cleared on retry / reset)
metadataobjectnoShallow merge patch

Response: { "task": { ...updated CoordTask... } }.

teams.list_tasks

List a team's tasks, optionally filtered.

ParameterTypeRequiredDescription
team_idstringyesTeam id
statusstringnoOne of: pending / blocked / in_progress / waiting_review / completed / failed / cancelled / skipped / paused / unsatisfiable (full 10-variant vocabulary; unknown strings are an explicit error)
ownerstringnoFilter by owner agent id

Response: { "tasks": [ ...CoordTask... ] }.

teams.list_task_runs

Per-attempt execution history for a task, oldest first.

ParameterTypeRequiredDescription
task_idstringyesTask id

Response: { "runs": [ ...CoordTaskRun... ] }.

teams.add_task_comment / teams.list_task_comments

Free-text per-task handoff notes. Used by members to leave context and by panel users to annotate state.

add_task_comment:

ParameterTypeRequiredDescription
task_idstringyesTask id
authorstringyesNon-blank author
bodystringyesNon-blank body

Response: { "comment": { ...CoordTaskComment... } }.

list_task_comments:

ParameterTypeRequiredDescription
task_idstringyesTask id

Response: { "comments": [ ...CoordTaskComment... ] } (oldest first).

teams.list_task_events

Read the team's event log filtered to a single task.

ParameterTypeRequiredDescription
task_idstringyesTask id

Response: { "events": [ ...EventLogStore::Event... ] } (oldest first, payload task_id matches).

teams.task.trace

Unified audit timeline for a single task: task + runs + comments + events + artifacts + journal in one round-trip. Missing optional stores (event_store / artifact_store) degrade to empty arrays. The Panel's "Replay" drawer fires this on open.

ParameterTypeRequiredDescription
task_idstringyesTask id

Response: { "task", "runs": [...], "comments": [...], "events": [...], "artifacts": [...], "journal": CoordTaskJournal | null }.

teams.task.journal.get / teams.task.journal.list

Per-task exit journal read surface (the write side is the task_exit_journal builtin tool). The exit journal is the durable record a member writes when its run completes.

| Method | Parameters | Description | |--------|------|------------|------| | teams.task.journal.get | task_id | { "journal": CoordTaskJournal | null } | | teams.task.journal.list | team_id | { "journals": [ ...CoordTaskJournal... ] } (newest first) |

teams.task.pause / resume / retry / skip

Admin-context task controls (any state; reviewer-context tasks use teams.workflow.{approve,reject,retry}_step instead).

  • teams.task.pause — only valid from pending / blocked / unsatisfiable. Stamps paused_from so resume can restore the right state. The dispatcher does not claim paused tasks.
  • teams.task.resume — only valid from paused. Restores the origin status (waiting_review for review-parked tasks, otherwise pending) and clears the stamp.
  • teams.task.retry — re-arms the automatic retry budget and clears result. Releases any leftover lock (with the actual lock holder, not "").
  • teams.task.skip — admin skip, equivalent to the reviewer skip but without needing a finished run.

Each takes task_id. Responses: { "status": "paused" | "pending" | "skipped" } (resume returns the restored status).

Workflow

teams.workflow.approve_step / reject_step / retry_step

Reviewer-context workflow step review. The latest run is stamped with the verdict; the task is then transitioned to Completed / Failed. A comment (when non-blank) is also appended as a task comment authored by review:<kind> (or the explicit reviewer_id).

reviewer_kind must be one of user / lead_agent / auto.

| Method | Parameters | Description | |--------|------|------------|------| | teams.workflow.approve_step | task_id, reviewer_kind, reviewer_id?, comment? | { "status": "completed" } | | teams.workflow.reject_step | task_id, reviewer_kind, reviewer_id?, comment? | { "status": "failed" } (the comment is also stored as the task result so the next planner can read it) | | teams.workflow.retry_step | task_id | { "status": "pending" } (re-arms the retry budget and releases the leftover lock with its actual holder) |

teams.workflow.export_canvas / import_canvas

Workflow canvas as Obsidian JSON Canvas 1.0. The Panel's canvas engine accepts the same wire shape, so the "Workflow" tab is wired straight to this.

export_canvas:

ParameterTypeRequiredDescription
team_idstringyesTeam id
statusstringnoSame 10-variant vocabulary as teams.list_tasks (full 10 variants, unknown id is INVALID_PARAMS)
ownerstringnoFilter by owner

Response: { "team_id", "canvas": { ...CanvasDocument... }, "node_count", "edge_count" }.

import_canvas:

ParameterTypeRequiredDescription
team_idstringyesTeam id
canvasobjectyesJSON Canvas document (aleph_protocol::canvas_format::Document)
dry_runbooleannoProject without writing

Response (dry_run): { "team_id", "planned", "tasks": [ ...{subject, description, blocked_by, metadata}... ] }.

Response (live): { "team_id", "created", "tasks": [ ...{id, subject}... ] }. Edges become blocked_by; the algorithm does a topological pass, deferring blockers still in this batch and rewriting canvas-node ids to live task ids.

ACP members

External coding-CLI sessions (Claude Code, Codex, etc.) attached as first-class team members. The dispatcher routes tasks owned by an ACP member through the ACP adapter pool instead of the in-process agent registry.

| Method | Parameters | Description | |--------|------|------------|------| | teams.acp_member.add | team_id, harness_id, cwd, session_name?, role (default acp-worker) | Idempotent on (team, harness, cwd, name); returns { "member": { ...NewTeamMember::for_acp_session... } } | | teams.acp_member.remove | team_id, agent_id | Removes the ACP-backed row. The underlying ACP session in the pool is not killed (other teams may still reference it). Refuses non-ACP rows. | | teams.acp_member.list | team_id | { "members": [ ...ACP members only... ] } (filters kind == TeamMemberKind::AcpSession) |

Usage

teams.usage

Per-team provider token aggregation, derived from task_traces ProviderUsage events (the gateway execution engine already writes these). MoA advisor spend is rolled into a dedicated moa_advisors bucket since their synthetic ids are not in any team's member list. Cost is intentionally not computed here — tokens are factual, cost is rate-card policy.

ParameterTypeRequiredDescription
team_idstringyesTeam id
sincenumbernoLower bound, epoch seconds (default: all time)
untilnumbernoUpper bound, epoch seconds (default: all time)

Response: { "team_id", "since", "until", "member_count", "total": { "call_count", "input_tokens", "output_tokens", "cache_read_tokens", "cache_creation_tokens", "reasoning_tokens", "cache_hit_ratio" }, "per_agent": [ ...AgentUsageTotal... ], "moa_advisors": { ... } | null }.

teams.list_templates

List available team templates (built-in + user). Materialization itself is via the team_from_template builtin tool, so the heavy deps are not double-plumbed through the gateway.

Request: no params.

Response: { "templates": [ ...{name, description, default_goal, leader_id, leader_role, member_count, task_count}... ] }.

Snapshots

Mirrors the team_snapshot builtin tool so panels and external callers can hit the snapshot store without going through tool-invoke. All five handlers share the same backing functions, so behaviour, dry-run defaults, and edge-restoration semantics are identical to the tool.

| Method | Parameters | Description | |--------|------|------------|------| | teams.snapshot.create | team_id, tag?, note? | { ...capture result... } | | teams.snapshot.list | team_id? | { "snapshots": [ ...SnapshotMeta... ] } (newest first) | | teams.snapshot.get | snapshot_id | { "meta", "payload" } or RESOURCE_NOT_FOUND | | teams.snapshot.restore | snapshot_id, apply: false (default dry-run) | { ...SnapshotDiff... } (diff in both modes; apply=true also restores dependency edges) | | teams.snapshot.delete | snapshot_id | { "snapshot_id", "existed": <bool> } (idempotent) |

The snapshot handlers are only registered when the SqliteSnapshotStore was constructed at boot; otherwise their RPCs are absent.

See Also

On this page