AgentX docs

Agent Teams (Agent Alloy)

Agent Teams is AgentX’s multi-agent orchestration system (Phase 16, v1 shipped 2026-04-27 as Agent Alloy — the internal module, API routes, and config keys keep that name; only the user-facing vocabulary changed, same precedent as Workspaces→Projects). It lets one agent delegate focused subtasks to teammates, coordinating their work over a shared memory channel. UI terminology: a workflow is a Team, the supervisor is the Lead, and specialists are Members.

Delegation comes in two flavors:

  • Structured teams — a saved workflow (workflow_id on the chat request) puts the team’s lead in charge of the conversation with an aggressive “orchestrate, don’t execute” supervisor prompt.
  • Ad-hoc delegation — in ordinary chats, any agent can hand a subtask to any profile that joined the team roster (available_for_delegation, opt-in, off by default). The agent gets the delegate_to tool and a roster block in its system prompt listing each teammate’s specialty (delegation_hint, falling back to the profile description) with deliberately soft guidance: handle it yourself by default, delegate when a teammate is clearly better suited. Enabled by default (alloy.allow_adhoc_delegation); nothing delegates until profiles opt onto the roster. AgentX ships two already-opted-in specialists — the Researcher (web search, cited answers) and the Deluxe Image Creator (delegate a visual brief; the finished image lands in the conversation) — edit or delete them freely; they never re-seed. A per-conversation Solo/Team toggle in the Relay sends disable_delegation to suppress it for a chat — ignored under a workflow, since a team run is delegation.

See the multi-agent delegation diagram on the System Design page.

Set it up

Two ways to get agents working together — one takes seconds, the other gives you a repeatable team.

The quick path — an ad-hoc roster

For teammates you reach for now and then, with no setup ceremony:

  1. Open each agent you want available (Agent Profiles) → Core → Team membership → turn on Join the team roster and write a one-line Specialty.
  2. That’s it. In any ordinary chat, your active agent now sees those teammates in its prompt and can hand one a subtask when it’s clearly the better fit. It still handles most things itself — delegation is an option, not a reflex.
  3. Want a chat to stay single-agent? Flip the Solo/Team toggle in the Relay to Solo.

AgentX ships two agents already on the roster — the Researcher and the Deluxe Image Creator — so “research this” or “make me an image of…” delegates out of the box.

The structured path — a saved Team

For a workflow you run repeatedly (a lead that always orchestrates a fixed set of specialists):

  1. Command palette (⌘K) → Manage agent teamsNew team.
  2. Pick a Lead — the agent that owns the conversation and decides when to delegate. Give it a capable model; the orchestration is only as good as the lead.
  3. Add member for each specialist, each with an optional hint about what to send it.
  4. Save, then attach the Team to a conversation. The lead now runs the show under an “orchestrate, don’t execute” brief, delegating to members over a shared memory channel and synthesizing their results into one answer.

What you’ll see

When an agent delegates, its teammate’s work renders inline as a delegation card in the transcript — you watch the subtask run, not just its result. A Trace on the conversation opens the Team Run Trace: who delegated to whom, and each step’s tokens, cost, and wall-clock time. Nothing happens off-screen.

Data Model

A workflow binds exactly one supervisor to zero or more specialists. Members are referenced by their immutable Docker-style agent_id (e.g. bold-cosmic-falcon), not by display name — so renaming a profile never breaks a workflow.

Workflow (api/agentx_ai/alloy/models.py):

FieldTypeDescription
idstringKebab-case identifier (^[a-z0-9][a-z0-9-]*$)
namestringDisplay name
descriptionstring?Free-text description
supervisor_agent_idstringagent_id of the supervisor profile
membersWorkflowMember[]Supervisor + specialists
routesWorkflowRoute[]Declarative routing — schema only in v1, not executed
shared_channelstringWorkflow-scoped memory channel; auto-derived as _alloy_{id} when blank
canvasobjectOpaque editor state for the (future) Factory UI; no backend semantics

WorkflowMember:

FieldTypeDescription
agent_idstringThe member’s immutable agent identifier
role"supervisor" | "specialist"Exactly one member must be supervisor
delegation_hintstring?Expertise hint shown to the supervisor in the delegate_to tool description

Validation (on create/update) requires: a valid id pattern, exactly one supervisor, and every agent_id resolving to an existing profile in data/agent_profiles.yaml.

Delegation at Runtime

When a workflow is active, the supervisor gains a single extra tool, delegate_to:

{
  "agent_id": "specialist-agent-id",
  "task": "A self-contained task description with all the context the specialist needs"
}

The AlloyExecutor (alloy/executor.py) intercepts the call, resolves the specialist’s profile, and spawns a fresh Agent for it. Specialists run in isolation — they receive only the delegated task plus relevant memories from the shared channel, never the full conversation history. Specialists do not receive the delegate_to tool, so they cannot re-delegate. The specialist’s full output is returned to the supervisor as a tool result, which the supervisor then synthesizes into its reply.

All members read and write the shared channel (_alloy_{workflow_id}), so delegated results and extracted facts are visible across the workflow. Each delegation also creates a child Goal (Phase 15 goal tracking) linked to that channel.

Configuration

KeyDefaultDescription
alloy.max_delegation_depth3Maximum delegation nesting depth
alloy.specialist_inherits_supervisor_toolstrueWhether specialists get the supervisor’s tool set
alloy.allow_adhoc_delegationtrueAllow delegate_to + the roster prompt in ordinary (workflow-less) chats. Safe default: the roster itself is opt-in per profile (available_for_delegation defaults false)
alloy.delegation_timeout_secondsPer-delegation timeout

Execution & Streaming

Workflows execute through the existing streaming chat endpoint — pass a workflow_id:

POST /api/agent/chat/stream
{
  "message": "Research and summarize the latest on X",
  "agent_profile_id": "some-profile",
  "workflow_id": "my-workflow",
  "session_id": "optional"
}

When workflow_id is set, the supervisor profile becomes the active agent, its memory_channel is switched to the workflow’s shared_channel, and the delegate_to tool is added with an enum of the workflow’s specialists. Without workflow_id, behavior is unchanged (single-agent mode).

In addition to the standard chat SSE events, delegations emit:

EventKey fields
delegation_startdelegation_id, target_agent_id, task, depth, supervisor_agent_id, shared_channel
delegation_chunkdelegation_id, target_agent_id, content (streamed specialist tokens)
delegation_tool_calldelegation_id, target_agent_id, tool, tool_call_id, arguments
delegation_tool_resultdelegation_id, target_agent_id, tool, content, success, duration_ms
delegation_completedelegation_id, target_agent_id, status, error, result_preview, exhibits? (wires for exhibits produced inside the delegation, cap 5)

Multimodal specialist output passes through: a specialist’s exhibit and workspace_attached events are forwarded top-level, unchanged (the image/exhibit renders under the delegation card, and workspace auto-attach works exactly like the main loop). The delegating agent’s tool result carries an “already displayed” note so it doesn’t re-invent image URLs, and the wires are persisted as present_exhibit turns so reloaded conversations rebuild the cards. Specialist internal tools run under the specialist’s own identity (usage attribution) with the conversation’s user/workspace inherited, and the specialist profile’s allowed_tools/blocked_tools gating applies inside delegations.

Storage & API

Workflows are persisted to data/workflows.yaml and managed by the WorkflowManager singleton (mirroring ProfileManager). CRUD is exposed under /api/alloy/workflows — see Multi-Agent endpoints.

On the client, AlloyWorkflowContext (contexts/AlloyWorkflowContext.tsx) manages the workflow list and selection; the active workflow’s id is passed to the chat stream.

Ambassador — the parallel relay

An ambassador is a normal agent profile (kind: 'ambassador') that runs parallel to a conversation and briefs you on it — without ever entering or polluting the main transcript. That no-pollution invariant is load-bearing: the ambassador writes only to a Redis sidecar (the amb_thread: family), never conversation_logs / conv_summary:, and its tool belt is SELECT-only.

  • What it does — you ask it about the conversation (“what did my agents decide?”, “summarize this”, “explore that turn”) and it answers from a curated read-only tool belt (summarize_conversation · explore_conversation · read_conversation · list_conversations) over a bounded agentic loop. It briefs to you (second person, names the agent) and never speaks into the transcript as itself.
  • Two-way voice — spoken briefings (TTS via a provider’s /audio/speech) and hold-to-talk questions (STT via /audio/transcriptions); a transcript routes through the same answer core, so voice gets the same tools and continuity as text.
  • Outbound relay — it can draft a message you review and send into the conversation as a real user turn (ghostwriter, not speaker) — so the invariant still holds.
  • One thread — briefings and Q&A are one ordered “Inquiry” thread; the panel docks beside the chat (non-modal), so you can watch the agent work and talk to the ambassador at once.

Configure it in Settings → Ambassador (the default ambassador profile) and per-profile (the ambassador block: personas, speech/voice model, verbosity). Ambassador v2 — a fully conversational, tool-using relay with a standalone command-deck thread — is in progress.

Status

Shipped (v1 plus the routing/delegation waves through v0.21.5):

  • Data model + WorkflowManager, the delegate_to tool, AlloyExecutor, and specialist isolation
  • Live delegation_* SSE streaming, goal-tracking integration, the workflow CRUD API, and the client context
  • Parallel / fan-out delegation with a client trace/replay modal (per-delegation tokens, cost, and wall-clock)
  • Per-turn attributionagent_id on turns and conversation_logs, restored to display names on reload
  • Explicit routingtarget_agent_id on the chat-stream request (priority workflow_id > target_agent_id > agent_profile_id > default)
  • Per-agent tool isolationallowed_tools / blocked_tools enforced per profile
  • Ad-hoc agent-to-agent delegationdelegate_to in workflow-less chats, gated by alloy.allow_adhoc_delegation (depth-limited, no self-delegation)
  • First-class conversational delegation — a delegation_roster system-prompt block (teammates + specialties from the opt-in roster, same source as the tool enum), per-profile delegation_hint, opt-in available_for_delegation (default off), the global gate default-ON, and a per-conversation Solo/Team toggle (disable_delegation)
  • @-mention routing — an inline @agent-id / @name routes a turn; AgentParticipant graph nodes + a client @-autocomplete composer

Deferred (see Roadmap → Phase 16): the visual Factory canvas editor, execution of declarative routes (accepted and stored but ignored), async (background) delegation, and per-workflow tool subsetting.