@hasna/swarm
v1.0.1
Published
Multi-agent swarm framework on the Vercel AI SDK — model + process agents, LLM planner, blackboard, actor/verifier loops, budget governor, topologies. CLI + MCP + REST.
Maintainers
Readme
@hasna/swarm
Multi-agent swarm framework built on the Vercel AI SDK. Turn a goal into a task DAG, fan it out across many agents, and fan the results back in — with a budget governor, resumable state, and a first-class actor/verifier loop.
Why
swarm is a thin, opinionated orchestration layer over the AI SDK's multi-step
tool loop. It gives you two execution tiers, a real LLM planner, a shared
blackboard, cross-agent budget enforcement, and the topologies you actually
want — pipeline, fanout, hierarchical, mesh, self-expanding.
Architecture
goal
└─ planner (LLM) → typed task DAG (deps, roles, tier, verify flags)
└─ topology → reshape the DAG (pipeline / fanout / hierarchical / mesh / self-expanding)
└─ orchestrator → schedule waves, concurrency-capped fan-out, fan-in
├─ Tier B: model-agent → in-process ai-sdk ToolLoopAgent (generateText + tools + stopWhen)
├─ Tier A: process-agent → spawn a coding-agent CLI (claude / codex)
└─ actor/verifier → workhorse produces, frontier (Opus) approves before accept
↕ blackboard (shared KV, persisted & resumable)
↕ budget governor (aggregate usage → USD, halt on ceiling)
↕ conversations bus (each agent registers + reports)Two execution tiers
- Tier B — model-agents (default): one
ToolLoopAgentper task, in-process, on the AI SDK. Fan out many lightweight agents that read/write the shared blackboard via tools and stop withstopWhen: stepCountIs(n). - Tier A — process-agents: spawn a coding-agent CLI (
claude,codex) as a subprocess for heavyweight, long-horizon tasks.
Provider registry
Agents reference models through aliases of the form <provider>:<tier>, e.g.
anthropic:workhorse, openai:frontier, kimi:k2. Built with
createProviderRegistry + customProvider + createOpenAICompatible, mixing
Anthropic, OpenAI, Google, and OpenAI-compatible Kimi/DeepSeek — per agent, per
step. Missing keys (or --mock) fall back to a deterministic offline model, so
the whole framework runs and tests without credentials.
Actor / verifier loop (the headline)
A cheap workhorse model produces; a frontier verifier (Opus) critiques.
The verifier must call an approved tool (stopWhen: hasToolCall("approved"))
or a revise tool that feeds feedback back to the actor for another round.
Results are only accepted once approved.
Budget governor
Every model agent reports its AI SDK token usage; the governor converts it to
USD via a pricing table and aggregates it across the swarm. Dispatch halts when
the spend ceiling (or time budget) is exceeded. Best-effort sync to the
economy service.
Install
npm install -g @hasna/swarm # or: bun install -g @hasna/swarmProvider keys are read from the environment (ANTHROPIC_API_KEY,
OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, MOONSHOT_API_KEY/KIMI_API_KEY,
DEEPSEEK_API_KEY). Nothing is hardcoded.
CLI
swarm --help
# Plan a goal into a DAG (no execution)
swarm plan "research and benchmark embedding models" --topology fanout
# Run a swarm (offline, no keys needed)
swarm run "build and verify a small feature" --mock --verify --topology fanout
# Run live with a model alias and a $2 ceiling
swarm run "refactor the auth module" -m anthropic:workhorse -b 2 --verify
# Inspect
swarm status # latest run: tasks, agents, cost
swarm blackboard # shared scratchpad for the latest run
swarm list
swarm events
swarm providers # which providers have keys
swarm resume <run-id> # continue a persisted runCommon run/plan flags: --topology, --tier model|process, -m/--model,
--verifier-model, -a/--max-agents, -b/--budget, --max-steps, --verify,
--mock, --json.
MCP server
swarm-mcp # stdio MCP serverTools: swarm_run, swarm_plan, swarm_resume, swarm_status,
swarm_blackboard, swarm_list, swarm_events, swarm_providers,
swarm_delete.
REST API
swarm-serve # binds 0.0.0.0:19440 (SWARM_PORT / SWARM_HOST to override)GET /healthGET /api/providersPOST /api/plan—{ goal, topology?, mock? }POST /api/runs—{ goal, topology?, model?, max_budget_usd?, verify?, mock? }GET /api/runs·GET /api/runs/:id·GET /api/runs/:id/blackboard·GET /api/runs/:id/events·POST /api/runs/:id/resume·DELETE /api/runs/:id
SDK
import { executeSwarm } from "@hasna/swarm";
const result = await executeSwarm({
goal: "summarize the repo and propose three improvements",
topology: "fanout",
defaultTier: "model",
model: "anthropic:workhorse",
verifierModel: "anthropic:frontier",
maxAgents: 4,
maxBudgetUsd: 2,
maxDurationMs: 600_000,
maxStepsPerAgent: 6,
workdir: process.cwd(),
verify: true,
});
console.log(result.status, result.totalCostUsd, result.blackboard);Lower-level building blocks are exported too: runSwarm, resumeRun,
planGoal, applyTopology, runModelAgent, actorVerify, runProcessAgent,
BudgetGovernor, buildRegistry, Blackboard.
Data
State lives in ~/.hasna/swarm/swarm.db (override with SWARM_DB_PATH). Runs,
tasks, agents, events and the blackboard are persisted, so runs survive restart
and can be resumed.
Development
bun install
bun test # full suite, runs offline against the mock provider
bun run typecheck
bun run buildLicense
Apache-2.0 — see LICENSE.
