// L3 — the new feature

Swarm. Fan out, then synthesize.

N role-specialized agents run the same task in parallel — each the same Orchestrator unit with a different role-lens. A separate synthesizer merges their answers into one. Diverse perspectives, not N identical runs.

┌─ the shape

One task, many lenses, one answer.

tachi-agent swarm topology One task with a unique traceId fans out to three parallel role agents — implementer, critic, and researcher — running concurrently behind a small cap, each an independent Orchestrator run that writes its own isolated dokoro session keyed swarm:traceId:role. The three labeled answers converge into a single synthesizer agent, which merges them — calling tachibot_council or tachibot_jury to adjudicate disagreement like a jury — into one final answer that is logged once under swarm:traceId. // one task in one task unique traceId fan out · parallel · cap 4 ▍ member · lane 1 implementer role-lens system prompt own driver (optional) swarm:<traceId>:implementer ▍ member · lane 2 critic role-lens system prompt may be marked critical swarm:<traceId>:critic ▍ member · lane 3 researcher role-lens system prompt independent run swarm:<traceId>:researcher each member writes its own isolated dokoro session · never reads peers labeled answers synthesizer merges labeled answers tachibot_council / _jury ↩ council / jury adjudicate one answer logged once · swarm:<traceId>
// how it works

Same unit, different lens.

Each member is the same Orchestrator you already run — just given a different role-lens system prompt and, optionally, a different driver. They all execute the identical task in parallel.

A separate synthesizer agent then runs over the members' labeled answers and returns one merged result. When the council tools are present it calls tachibot_council / tachibot_jury to adjudicate disagreements — so the final answer is reconciled, not just concatenated.

┌─ behavior

Bounded, fault-tolerant, isolated.

parallel, bounded

Concurrency cap

Members run concurrently behind a small cap (default 4) so big rosters don't fan out unbounded. Each member inherits the orchestrator's maxIterations / timeoutMs / cost tracking.

failure-tolerant + quorum

Errors don't sink it

A member that errors or times out is recorded with an empty answer and excluded from synthesis. Too few answers — or a missing critical role — surfaces a non-fatal warning, never a crash.

synthesis

Merge, then adjudicate

A dedicated synthesizer runs over the labeled answers and returns one merged result. If council tools are connected it uses tachibot_council / tachibot_jury to resolve disagreement.

memory isolation

No peeking at peers

Each run gets a unique traceId. Members are independent: each writes its own session swarm:<traceId>:<role> and never reads peers' or prior runs' memory. The final answer is logged once under swarm:<traceId>.

// usage

Run it three ways.

Default roster: implementer · critic · researcher.

bash — default roles
npm run swarm -- "design a rate limiter for the gateway"
# default roles: implementer · critic · researcher
bash — custom roster via env
# comma-separated: `name` or `name:driver` · empty = defaults
export TACHI_SWARM_ROLES="implementer,critic:hermes,security,researcher"
npm run swarm -- "review this auth flow"
typescript — programmatic
import { buildSwarmFromEnv } from "tachi-agent";

const swarm = await buildSwarmFromEnv();
try {
  const { answer, members, warnings } = await swarm.run("design a rate limiter");
  console.log(answer);
} finally {
  await swarm.close();
}

Progress streams to stderr — one line per member, any warnings, and the trace id. The final synthesized answer prints to stdout.