# Agents & orchestration

The **team** that delivers one project is exactly one **orchestrator** and as many **worker agents** as the work needs. There is one team per project — no master orchestrator above it, no per-task free-for-all beneath it. Standing outside the team is the [Triage Agent](/concepts/triage/), which decides what is admitted as work in the first place.

## When this matters to you

You need this page when you are deciding *who* should do something, or when a run behaved in a way you did not expect:

- A task went to a worker you did not choose — the orchestrator routes by persona description, and this page lists the six it picks from.
- You want to interrupt a run mid-flight rather than wait for it — that is steering, and only the orchestrator accepts it.
- You asked an agent to implement something and it described the change instead of making it — that is consultation, and this page explains the difference.
- You are wondering why two tasks did not conflict — they never shared a checkout, and that is a property of the team, not of the coding agent.

## The topology

One orchestrator sits above six worker personas, and every worker runs a single task in its own git worktree inside the one Coding Workspace the project owns.

```text
Project
  │
  └── Orchestrator         plans · dispatches · evaluates · replans
        │
        ├── Senior Engineer
        ├── Product Engineer
        ├── UI Engineer          each worker runs ONE task,
        ├── QA Engineer          in its OWN git worktree,
        ├── Security Engineer    inside the ONE Coding Workspace
        └── Technical Writer     the project owns
```

## The orchestrator

The orchestrator is the project's **directly responsible individual**. It owns the intent end to end: it turns a brief into a roadmap, sequences that roadmap into cycles, dispatches a wave of work, evaluates what comes back, and decides what happens next — continue, retry, replan, or finish.

It does not write code. That separation is the reason one orchestrator can run many workers without becoming the bottleneck — it is holding the plan, not the keyboard.

### It reads live state, not a briefing

Each turn opens with a deliberately shallow orientation: which project this is, which repositories it has, and what stage the cycle in scope is at and for how long. That is all that is injected.

Everything else it pulls when it needs it, from the object that owns the answer — the task breakdown, the triage rationale behind a cycle's lane, the run history and what each run cost, the verified review evidence for a task, the approval queue. Nothing is a snapshot taken at the start of a conversation, which is why an orchestrator asked about a cycle mid-run answers about the cycle as it is now.

### Consultation is not execution

The single most expensive misreading of this system is treating an agent's *answer* as work that happened. The orchestrator has both kinds of tool and they are not interchangeable:

| | Consultation | Execution |
| --- | --- | --- |
| What it is | Delegating a question to a specialist persona | Dispatching a task to the Coding Workspace |
| What comes back | That specialist's text | A branch, a status, artifacts, and a cost |
| What it can touch | Nothing — these personas have no tools, no repository, no shell | The task's own git worktree |

If you ask for an implementation and get a description of the change, nothing was implemented. Code is written in exactly one way: a task, dispatched to the project's [Coding Workspace](/concepts/coding-workspace/), running in its own worktree.

### New work still goes through Triage

When the orchestrator decides a project needs work it does not yet have, it raises a **proposal**, not a cycle. That proposal lands in the same queue every other intake path uses, becomes a cycle at status `triage`, and is judged like everything else. The orchestrator has no privileged path around that, and it cannot submit a plan for a cycle still in triage.

Submitting a plan is what moves a cycle into execution, and it moves it through the same [governed transition](/running/cycles/#stage-history) machinery every other status change uses — attributed to the orchestrator, carrying its stated reason, stamped with the rules version in force.

### Its loop

As the project workflow implements it:

```text
project intake ──▶ roadmap planner ──▶ dispatch wave
                          ▲                  │
                          │                  ▼
                          └──── evaluate ◀── cycle outcome
                                  │
                       ┌──────────┴──────────┐
                       ▼                     ▼
                  finalize                 fail
```

The run suspends at each cycle outcome and resumes when the result arrives, which is what lets a project survive a backend restart mid-delivery.

## The Triage Agent

Not part of the team, and deliberately so. The Triage Agent judges a request *before* it becomes the orchestrator's problem: how well understood it is, how costly a mistake would be, how urgently it should jump the queue, and whether it should become a cycle at all.

It runs one-shot. It has no tools, no memory, and no conversation — it reads the request and the project it belongs to, and returns a structured judgement plus a rationale. It never names the risk lane or the priority those judgements produce; versioned platform rules do that, so the routing decision is deterministic and auditable rather than something a model improvised.

Its model is set separately from the rest of the team, on the **Triage** row of the workspace's AI-models settings. See [Triage](/concepts/triage/).

## Worker roles

Six personas. The orchestrator picks one per task by matching the work to the persona's description — you do not assign them by hand.

| Role | What it is for |
| --- | --- |
| **Senior Engineer** | General implementation, refactors, and hard changes |
| **Product Engineer** | Feature work driven from product intent |
| **UI Engineer** | Interface work, layout, and interaction |
| **QA Engineer** | Tests, verification, and reproducing failures |
| **Security Engineer** | Security-sensitive changes and review |
| **Technical Writer** | Documentation and written deliverables |

Each worker persona is defined in the DNA layer, so a role's identity and standards come from one place rather than being restated at each call site. See [Context, memory & DNA](/concepts/context-memory/).
**Personas route work; run history reports lanes:** These six names are how work is *assigned*. They are not what you will read back in a task's run history, which reports the **execution lane** a run occupied — `planner`, `builder`, `tester`, or `reviewer` — because all six personas share one model role and the sandbox derives the lane from the profile it ran under. So a Senior Engineer's work and a UI Engineer's work both appear as `builder` runs.

Which agent did the work is answered on the Canvas and on the task itself, where cards carry the agent's own name from your workspace roster. Per-persona cost and token breakdowns are not available today.

## Which coding agent actually runs

A worker role says *what kind of work this is*. The coding agent — the **harness** — says *what program does it*. They are independent, and the second one is yours to choose per task:

- **`hlix`** — our own harness, driven from the backend against the Coding Workspace toolbelt. This is what runs when a task names nothing else.
- **External ACP coders** — `claude-code`, `codex`, `openai-agents`, `aider`, `cursor-agent`. These run inside the project's sandbox through the in-pod driver.

The orchestration is the product, not the coder: the roadmap, the isolation, the context an agent is given, and the QA it answers to are identical whichever harness writes the diff. That is why bringing your own coder costs you nothing — and why we can ship one of our own without asking you to switch. See [Connect your agents](/guides/connect-agents/).

## Watching and steering the team

A run is not a black box. Four endpoints, all under `/v1/api/projects/:projectId/agents/:agentId`:

| Endpoint | Purpose |
| --- | --- |
| `POST …/orchestrator/stream` | Start an owned turn and stream it (SSE) |
| `GET …/:agentId/attach` | Observe an in-flight run without owning it (SSE) |
| `POST …/orchestrator/steer` | Inject a message into the running turn |
| `POST …/orchestrator/abort` | Stop the current run |
**Only the orchestrator accepts a turn:** `stream`, `steer`, and `abort` require the literal agent id `orchestrator`. A worker runs as a subagent inside the orchestrator's run, so there is nothing to steer independently — use `attach` with the worker's agent id to watch its slice of the stream. These endpoints are not in the published [OpenAPI contract](/api/openapi/) yet, so there is no generated SDK method for them.

Steering injects a message into the running turn, which means it first stops the turn in flight and then resumes with your input folded in.
**Abort stops the thinking, not the coding:** `abort` ends the orchestrator's current turn. It does **not** stop a coding agent that has already been dispatched: that task runs to completion in its own worktree, its run settles, and its cost is recorded. Only the orchestrator stops waiting for the answer.

This is deliberate. A coder killed part-way through leaves a half-written worktree behind, which is worse than a run you did not want — and it is the same reason an autonomous build wave will not interrupt one either. The orchestrator picks the outcome back up afterwards by reading the task and its run history.

## Why one team per project

Underneath, four pieces carry the work: Cloudflare serves the dashboard, the backend runs on Cloud Run and persists to Neon, and every agent's code executes in a Daytona sandbox in the EU — never on hlix's own infrastructure.

A project is a unit of intent — one product, one client engagement, one initiative. One orchestrator per project means there is always a single answer to "what are we building and why," and a single accountable coordinator for the delivery. Scale comes from adding workers, not from stacking orchestrators.

## Where to go next

| If you want to… | Read |
| --- | --- |
| Understand how the work itself is structured | [Work tree](/concepts/work-tree/) |
| See what decides whether a request becomes work | [Triage](/concepts/triage/) |
| See where the code actually executes | [The Coding Workspace](/concepts/coding-workspace/) |
| Watch and steer the team from the dashboard | [The dashboard](/running/dashboard/#watching-the-team-work) |

## Next steps

[Work tree](/concepts/work-tree/)
  [Triage](/concepts/triage/)
  [The Coding Workspace](/concepts/coding-workspace/)
  [Review & QA gates](/concepts/review-gates/)