Core
Swarms
A swarm runs many agents together — a flat parallel fan-out or a coordinator-planned DAG with dependencies, conditional edges, bounded concurrency, and self-heal replan. Define one inline, or save a preset and run it repeatedly.
Run a swarm inline#
A coordinator plans and delegates to workers; an optional synthesizer folds the results. Guardrails set here are inherited by every member.
const { runId } = await bahini.runSwarm({
coordinatorAgentId: "agent_coord",
workerAgentIds: ["agent_scout", "agent_analyst", "agent_writer"],
synthesizerAgentId: "agent_editor",
prompt: "Produce the weekly BI digest.",
guardrails: { guards: ["pii", "secrets", "injection"], mode: "enforce" },
concurrency: 2, // parallelism cap
swarmMaxTokens: 500_000, // hard cost cap for the whole run
});Wire a DAG#
Pass a plan to shape the workers into a graph. Each node names a worker by key with dependsOn (hard — a failed upstream skips the node) and optionalDependsOn (soft — the node still runs on partial inputs). A condition makes a conditional edge for dynamic branching.
const { runId } = await bahini.runSwarm({
coordinatorAgentId: "agent_coord",
workerAgentIds: ["scout", "analyst", "writer"],
prompt: "Draft the competitor brief.",
plan: [
{ id: "a", agent: "scout" },
{ id: "b", agent: "analyst", dependsOn: ["a"] },
{ id: "c", agent: "writer", dependsOn: ["b"],
condition: { node: "b", contains: "PRICE_CHANGE" } },
],
});validateSwarmPlan — it returns { ok: false, errors } naming unknown agents, duplicate ids, unknown deps, or cycles.Watch the graph#
getRunDagjoins the persisted plan with each node's live status — poll it (or pair with waitForRun) to render the graph as nodes go running → completed / failed / skipped. Returns null for a non-coordinator run.
const dag = await bahini.getRunDag(runId);
for (const node of dag?.nodes ?? []) {
console.log(node.id, node.agentName, node.status);
}Presets (reusable swarms)#
createSwarmPreset(input)
Save a swarm's shape once, run it repeatedly with runPreset. kind: "basic" runs workers in parallel; "coordinator" adds an orchestrator.
const { id } = await bahini.createSwarmPreset({
key: "weekly-bi",
name: "Weekly BI",
kind: "coordinator",
coordinatorAgentId: "agent_coord",
workerAgentIds: ["scout", "analyst", "writer"],
});
// Persist a guardrail policy so every run of the preset is governed:
await bahini.setPresetGuardrails(id, { guards: ["pii"], mode: "enforce" });
await bahini.runPreset(id, { prompt: "Run this week's digest." });