Roadmap: Evolving Ensemble into a Multi-Agent Coordination System¶
1. Overview¶
The objective is to transform Ensemble from a static collection of Agent templates into a dynamic, relationship-aware coordination layer. This enables agents within a pack to work as a cohesive team via subagent workflows.
Current status (as of 2026-04-16)¶
| Phase | Status | Summary |
|---|---|---|
| Phase 1: Schema | Done | PersonaRelationship, Relationships[], WorkflowType on EnsembleSpec |
| Phase 2: Canvas (read-only) | Done | ReactFlow canvas on persona detail Workflow tab |
| Phase 2b: Canvas (editable) | Done | Drag-to-connect with type picker, edge deletion, Save syncs to CRD |
| Phase 2c: Global canvas | Done | Persona Packs list page canvas showing all enabled packs with live run status |
| Phase 3a: Persona-targeted spawning | Done | TargetPersona/PackName on SpawnRequest, resolution + edge validation in Spawner |
| Phase 3b: AwaitingDelegate phase | Done | Controller handles AwaitingDelegate phase, skips timeout while parent waits |
| Phase 3c: Delegate tool for agents | Done | delegate_to_persona tool blocks until child completes, returns result to LLM |
| Phase 3d: Controller await/resume | Done | SpawnRouter subscribes to spawn requests, creates child AgentRuns, delivers results back via NATS/IPC |
| Phase 4: Policy & safety | Not started | Relationship-scoped delegation rules, cycle detection, timeouts |
What exists today¶
| Capability | Location | Notes |
|---|---|---|
| Subagent spawning | internal/orchestrator/spawner.go |
Creates child AgentRun CRs via IPC file protocol (/ipc/spawn/request-*.json) |
| Persona-targeted spawning | spawner.go resolvePersonaTarget() |
Resolves targetPersona → instance name via Ensemble, validates relationship edges |
| Parent-child tracking | AgentRun.Spec.Parent (ParentRunRef) |
Stores RunName, SessionKey, SpawnDepth; labels include sympozium.ai/parent-run |
| Depth/concurrency guards | SubagentsSpec on Agent |
MaxDepth (default 2), MaxConcurrent (default 5), MaxChildrenPerAgent (default 3) |
| Policy-level limits | SympoziumPolicy.Spec.Subagents |
MaxDepth, MaxConcurrent enforced by controller |
| Response gate pattern | AgentRun PostRun gate |
Runs pause for external approval before completing — reusable pattern for await/resume |
| Relationship graph in CRD | EnsembleSpec.Relationships[] |
Typed edges (delegation, sequential, supervision) with condition, timeout, resultFormat |
| AwaitingDelegate phase | AgentRunPhase enum + DelegateStatus |
Controller transitions parent to AwaitingDelegate, SpawnRouter transitions back to Running on child completion |
| SpawnRouter | internal/controller/spawn_router.go |
Subscribes to spawn events, creates child AgentRuns, tracks pending delegations, delivers results via NATS |
| Blocking delegate tool | cmd/agent-runner/tools.go |
delegate_to_persona blocks up to 10 min, polls for result file, returns child output to LLM |
| Visual canvas | web/src/components/ensemble-canvas.tsx |
Per-pack editable canvas + global read-only canvas with live run status highlighting |
| Default research-delegation-example pack | config/agent-configs/research-delegation-example.yaml |
4-persona pack demonstrating all 3 relationship types + shared memory |
| OTel instrumentation | spawnerTracer in spawner |
Traces parent run, instance, spawn depth, target persona attributes |
What's missing (to complete the delegation chain)¶
- Delegate tool for agents (Phase 3c). Agents need a tool (e.g.,
delegate_to_persona) that writes a spawn request to/ipc/spawn/request-*.jsonwithtargetPersonaandpackName. Without this, agents have no way to trigger delegation — they can only do generic subagent spawns. - Controller await/resume (Phase 3d). When a parent run delegates, it should enter
AwaitingDelegate. The controller needs to watch childAgentRuncompletion and write the result to the parent's IPC volume, then transition the parent back toRunning. - Policy enforcement (Phase 4). Relationship-scoped delegation rules, runtime cycle detection, timeout enforcement.
2. Phase 1: Schema & API Evolution (The Foundation) — DONE¶
Goal: Add the ability to define typed relationships between personas within a pack.
Delivered¶
PersonaRelationshiptype withsource,target,type(delegation/sequential/supervision),condition,timeout,resultFormatRelationships[]andWorkflowType(autonomous/pipeline/delegation) onEnsembleSpecWorkflowprint column onkubectl get ensembles- CRD manifests regenerated and deployed
- PATCH API support for relationships and workflowType
Key files¶
api/v1alpha1/ensemble_types.gointernal/apiserver/server.go(PatchEnsembleRequest)
3. Phase 2: Visual Representation (The Canvas) — DONE¶
Goal: Let users see and edit the persona relationship graph.
Delivered¶
Per-pack canvas (persona detail page, Workflow tab): - ReactFlow canvas with custom persona nodes showing name, model, skills, live run status - Typed edges: delegation (animated blue), sequential (dashed amber), supervision (dotted gray) - Interactive editing: drag-to-connect with type picker, edge deletion, Save syncs to CRD - Relationship table below the canvas - Status legend
Global canvas (Persona Packs list page): - Table/canvas view toggle - All enabled packs rendered as clusters with their persona nodes and relationship edges - Live run status highlighting on nodes (pulsing rings, phase labels, task preview) - Nodes draggable, read-only (no edge creation on global view)
Live run status highlighting (both canvases): - Running: pulsing blue ring with glow + task preview - Serving: pulsing violet ring with glow - AwaitingDelegate: pulsing amber ring with glow - Failed: red ring with glow - Succeeded: subtle green ring
Key files¶
web/src/components/persona-canvas.tsx(shared: PersonaNode, GlobalPersonaCanvas, PersonaCanvas)web/src/pages/persona-detail.tsx(Workflow tab)web/src/pages/personas.tsx(view toggle)
4. Phase 3a: Persona-Targeted Spawning — DONE¶
Goal: Let agents reference personas by name instead of raw instance names.
Delivered¶
TargetPersonaandPackNamefields onSpawnRequest(orchestrator + IPC protocol)resolvePersonaTarget()in Spawner: looks up Ensemble, finds installed instance, validates relationship edge exists, inherits target persona's system prompt and skills- OTel span attributes for target persona and pack name
Key files¶
internal/orchestrator/spawner.gointernal/ipc/protocol.go
5. Phase 3b: AwaitingDelegate Phase — SCHEMA ONLY¶
Goal: Enable a parent run to pause, wait for a delegate's result, and continue.
Delivered (schema)¶
AgentRunPhaseAwaitingDelegatephase constantDelegateStatustype:ChildRunName,TargetPersona,Phase,Result,ErrorDelegates []DelegateStatusonAgentRunStatus- Frontend types updated
Not yet delivered (controller logic)¶
The controller does not yet:
1. Transition parent runs to AwaitingDelegate when a delegation spawn occurs
2. Watch child AgentRun completion
3. Write child result to parent's IPC volume (/ipc/input/delegate-result.json)
4. Transition parent back to Running
Key files¶
api/v1alpha1/agentrun_types.gointernal/controller/agentrun_controller.go(TODO)
6. Phase 3c: Delegate Tool for Agents — NOT STARTED¶
Goal: Give agents a tool to trigger persona-aware delegation.
Design¶
Agents need a tool (registered in the agent runner) that:
1. Accepts targetPersona, task, and optional resultFormat
2. Writes a spawn request to /ipc/spawn/request-{uuid}.json with:
{
"task": "Write a report based on these findings: ...",
"targetPersona": "writer",
"packName": "research-delegation-example"
}
The packName can be auto-injected by the agent runner from the instance's labels (sympozium.ai/persona-pack).
Key files¶
- Agent runner tool registration (new tool definition)
internal/ipc/protocol.go(SpawnRequest already has the fields)
7. Phase 3d: Controller Await/Resume Loop — NOT STARTED¶
Goal: Close the delegation round-trip so parent runs receive child results.
Design¶
┌─────────────┐ spawn request ┌─────────────┐
│ Persona A │ ──────────────────────► │ Persona B │
│ (Researcher)│ targetPersona: │ (Writer) │
│ │ "writer" │ │
│ Running │ │ Running │
│ ↓ │ │ ↓ │
│ Awaiting │ │ Succeeded │
│ Delegate │ ◄────── result ──────── │ │
│ ↓ │ (controller └─────���───────┘
│ Running │ delivers via
│ (resumes) │ IPC /ipc/input/
│ ↓ │ delegate-result.json)
│ Succeeded │
└��────────────┘
Implementation steps¶
- When spawner creates a child run with
TargetPersona, update parent'sStatus.Delegatesand transition toAwaitingDelegate - AgentRun controller watches for child runs with
sympozium.ai/parent-runlabel transitioning to terminal phase - On child completion: write result to parent's IPC volume, update
DelegateStatus, transition parent back toRunning - Reuse the existing
ResponseGatepattern —AwaitingDelegateis structurally identical (run pauses, waits for external signal)
Key files¶
internal/controller/agentrun_controller.gointernal/orchestrator/spawner.go(update parent status)
8. Phase 4: Policy & Safety — NOT STARTED¶
Goal: Ensure coordinated workflows respect constraints.
Existing guards (already built)¶
SubagentsSpec.MaxDepth— prevents infinite delegation chainsSubagentsSpec.MaxConcurrent— caps total concurrent runs per instanceSubagentsSpec.MaxChildrenPerAgent— limits fan-out per parentresolvePersonaTarget()validates relationship edge exists before spawning
Remaining work¶
- Relationship-scoped policy:
AllowedDelegationsrules inSympoziumPolicy(source/target persona allow/deny) - Runtime cycle detection: reject delegation requests that would create a cycle (A→B→A) by checking parent lineage
- Timeout enforcement: controller starts timer when parent enters
AwaitingDelegate; resumes with error if timeout expires
9. Default Pack: research-delegation-example¶
The research-delegation-example Ensemble is included in the default packs and demonstrates all three relationship types:
Lead ──delegation──► Researcher ──delegation──► Writer ──sequential──► Reviewer
│ ▲ ▲
└──────────────────── supervision ────────────────────────┘──────────────┘
Personas: Lead, Researcher, Writer, Reviewer WorkflowType: delegation Category: research
Currently the pack serves as a visual demo of the relationship graph. To enable runtime delegation, Phase 3c (delegate tool) and Phase 3d (controller await/resume) must be completed.
10. Implementation Order (remaining work)¶
| Step | Phase | Depends on | Ships value |
|---|---|---|---|
| 1 | Delegate tool (3c) | — | Agents can trigger persona-aware delegation |
| 2 | Controller await/resume (3d) | Step 1 | Full delegation round-trip works end-to-end |
| 3 | Pipeline orchestration | Step 2 | Sequential edges auto-chain runs (A completes → B starts) |
| 4 | Policy (4) | Step 2 | Relationship-scoped rules, cycle detection, timeouts |
11. Success Metrics¶
- [x] A user can define a pack where "Researcher" delegates to "Writer" via a single CRD with
relationshipsedges - [x] The persona detail page shows a visual graph linking "Researcher" → "Writer" with edge type labels
- [x] The persona packs list page shows all enabled packs on a global canvas with live run status
- [x] Canvas nodes glow/pulse to indicate which personas are currently running
- [ ] An
AgentRunfor "Researcher" entersAwaitingDelegate, triggers anAgentRunfor "Writer", and automatically resumes with Writer's output on completion - [ ] Delegation respects
MaxDepth, timeout constraints, and policy-definedAllowedDelegations
12. Key Files Reference¶
| Area | Files |
|---|---|
| Ensemble CRD | api/v1alpha1/ensemble_types.go |
| AgentRun CRD | api/v1alpha1/agentrun_types.go |
| Instance CRD (SubagentsSpec) | api/v1alpha1/sympoziuminstance_types.go |
| Policy CRD | api/v1alpha1/sympoziumpolicy_types.go |
| Ensemble controller | internal/controller/ensemble_controller.go |
| AgentRun controller | internal/controller/agentrun_controller.go |
| Spawner | internal/orchestrator/spawner.go |
| IPC protocol | internal/ipc/protocol.go, internal/ipc/bridge.go |
| API server | internal/apiserver/server.go |
| Canvas components | web/src/components/persona-canvas.tsx |
| Persona pages | web/src/pages/personas.tsx, web/src/pages/persona-detail.tsx |
| Frontend hooks | web/src/hooks/use-api.ts |
| Frontend types | web/src/lib/api.ts |
| Default research pack | config/personas/research-delegation-example.yaml |
| Cypress tests | web/cypress/e2e/ensemble-workflow-canvas.cy.ts, web/cypress/e2e/ensemble-research-delegation-example-workflow.cy.ts |