# Build multi-Agent and long-horizon systems

> Build planner–executor, supervisor, specialist, critic, and long-running Agents with durable children, bounded joins, and explicit state.

## Before you begin {#before-you-begin}

Use multiple Agents only when work needs independent durable identity, authority, ownership, retry, or scaling. Different prompts alone do not require different Agents. Define a bounded worker set, the evidence each child returns, the join rule, and the supervisor’s budget. For long-horizon work, define explicit serializable progress and terminal conditions before adding loops.

## Steps {#steps}

1. Use a planning turn to produce a validated, bounded task set. Register each executable task as a versioned subtask.
2. Spawn independent work and join Handles with ordinary derived helpers such as `all`, `select`, or `race`. These helpers are not new primitives.
3. Give a synthesis or critic turn the child results and acceptance criteria. Commit the accepted result and the evidence used.
4. Move to durable mode when planning, execution, review, or waiting crosses invocations. Advance one meaningful phase per step and stop on budgets or explicit terminal state.

```ts
import { agent, subtask } from "@constal/sdk";
import { all } from "@constal/std";

const specialist = subtask<{ role: string; report: string }>({
  id: "specialist", version: "1",
  async run(input: { role: string; objective: unknown }, ctx) {
    const turn = await ctx.turn({
      system: `Act as the ${input.role} specialist. Return evidence and uncertainty.`,
      objective: input.objective,
    });
    return { role: input.role, report: turn.message.content };
  },
});

export default agent({
  id: "supervisor", version: "1.0.0", model: "model", subtasks: [specialist],
  async onMessage(objective, ctx) {
    const workers = ["research", "risk", "implementation"].map((role) =>
      ctx.spawn(specialist, { role, objective }, { retries: 2 }),
    );
    const reports = await all(workers);
    const synthesis = await ctx.turn({
      system: "Resolve disagreements, preserve uncertainty, and produce one bounded recommendation.",
      objective,
      context: { reports },
    });
    await ctx.commit({ kind: "supervised-result", reports, result: synthesis.message.content });
    return synthesis.message.content;
  },
});
```

Planner–executor is this pattern with tasks chosen by a validated plan. Supervisor–specialist uses fixed roles. Generator–critic uses one child result and a gate or review turn. A long-horizon Agent composes the same operations across explicit durable phases; it does not run an unbounded hidden loop or gain broader authority over time.

## Verify {#verify}

Inspect parent and child Runs together. Confirm every child uses a registered task and inherited accepted authority, the worker count is bounded, failures remain visible, and synthesis cannot fabricate missing reports. Test cancellation, partial completion, budget exhaustion, and resume. A long-running Agent must resume from recorded state without redoing proven effects.

## Next steps {#next-steps}

Read [Durable execution](/docs/sdk/durable-execution.md), [Runs and sessions](/docs/runs.md), [Scale with map and reduce](/docs/foundations/volume.md), and [Identity, Policy, and authority](/docs/foundations/authority.md).
