Agent Network
Self-hosted hub where coding agents on several machines find each other and hand off tasks over MCP
Self-hosted multi-agent orchestration API whose MCP endpoint hands tasks, memory and schedules to agents
Official · Desplega Labs TypeScript Local · Streamable HTTP AI and MLKnowledge and memoryCommunication
72 popularity score ★ 1.0k ↓ 3.2k/wk
Opens the app, which asks before it adds the server.
claude mcp add --transport http agent-swarm http://localhost:3013/mcp{
"mcpServers": {
"agent-swarm": {
"url": "http://localhost:3013/mcp"
}
}
}{
"servers": {
"agent-swarm": {
"type": "http",
"url": "http://localhost:3013/mcp"
}
}
}[mcp_servers.agent-swarm]
url = "http://localhost:3013/mcp"gemini mcp add --scope user --transport http agent-swarm http://localhost:3013/mcpAGENT_SWARM_API_KEY secret |
Required: API key clients must send as a Bearer token; can also be given with --key (legacy name API_KEY). |
|---|---|
PORT |
Optional: Port for the API and MCP server, also set with --port. |
DATABASE_PATH |
Optional: SQLite file path, also set with --db. |
CAPABILITIES |
Optional: Comma list of tool groups to expose; replaces the default list of 16 groups. |
Agent Swarm, from Desplega Labs, is a self-hosted system where a lead agent breaks work into tasks and hands them to worker agents like Claude Code or Codex. Each worker normally runs in its own Docker container. The npm package's `agent-swarm api` command starts one HTTP process that serves the REST API and the MCP endpoint together, keeping state in a SQLite file (./agent-swarm-db.sqlite unless you pass --db).
Agents use the MCP endpoint to take part in the swarm. They join, poll for work, claim it and report back, and they can pass tasks to one another. Memories can be stored and searched. Schedules can be cron or one-off, and workflows can pause until a person approves a step. Skills, per-agent MCP servers, key-value state, pages and small apps are handled through tools as well. Once the integrations are set up, agents can also read and post in Slack or send WhatsApp messages.
The tool count is large. MCP.md at the current release lists 170 tools in 22 groups, and the CAPABILITIES setting picks which groups an agent sees. Sixteen are on by default. The six others stay hidden until you name them: prompt-templates, agentmail, kapso, chat-sdk, swarm-x and messaging. Note that setting CAPABILITIES replaces the default list instead of adding to it. It only hides MCP tools, too, because most REST routes are not gated.
The quickest way in is now the one-line installer from agent-swarm.dev. It runs onboarding with the full preset, a lead plus ten workers in Docker Compose, and unless you pass --no-tunnel it puts the API on a public localtunnel address.
| Runtime | Node.jsDocker |
|---|---|
| Runs on | macOS, Windows, Linux |
| Anthropic, OpenAI or another harness provider | Paid planWorkers need a credential for the chosen harness, such as an Anthropic or OpenAI key. The API process alone does not. |
| Also |
|
Start the server with `npx @desplega.ai/agent-swarm api`, giving an API key you choose with --key or AGENT_SWARM_API_KEY. Clients then connect to http://localhost:3013/mcp and send that key as a Bearer token plus the ID of an agent registered on the swarm in X-Agent-ID. For the whole system, `curl -fsSL https://agent-swarm.dev/install.sh | bash` checks for Docker and Compose v2, adds Bun if it is missing and starts the full preset. Add `bash -s -- --no-tunnel` to keep the API off the public internet.
It speaks MCP only over streamable HTTP at /mcp; there is no stdio mode, so the API process must be started and kept running before a client connects. Its MCP registry entry gives 3000 as the default port, but the CLI code at v1.173.0 defaults to 3013 (or PORT). The db-query tool is read-only and refuses queries on credential tables. script-run supports only fsMode "none" in this version. The README warns the repository changes daily, and the docs note that database retention defaults to dry-run.
Suits teams that want to run their own fleet of coding agents with shared tasks, memory and schedules on their own machines or cluster, and that are ready to operate a Docker or Kubernetes stack. It is a coordination layer for agents. Someone who only wants one assistant to remember notes or post to Slack will find a dedicated server smaller and simpler to set up. Because the tools can create tasks, change config, post messages and run inline TypeScript, it fits setups where every connecting agent is trusted. Anyone using the installer on a machine that should stay private should pass --no-tunnel.
9 only read, 24 change things, 3 can delete or overwrite. A ? marks an optional parameter.
join-swarm changesrequestedId?: stringlead?: booleanname: stringdescription?: stringrole?: stringcapabilities?: arraypoll-taskget-swarma?: stringincludeFull?: booleanget-tasksstatus?: enummineOnly?: booleanunassigned?: booleanofferedToMe?: booleanreadyOnly?: booleantaskType?: stringtags?: arraysearch?: stringscheduleId?: stringworkflowRunId?: stringkey?: anykeyPrefix?: anyincludeHeartbeat?: booleanlimit?: numberincludeFull?: booleansend-task changesagentId?: stringroutingReason?: enumroutingNote?: stringtask: stringkey?: anyofferMode?: booleantaskType?: stringtags?: arrayrequiredCapabilities?: arrayleadOnly?: booleanpriority?: numberdependsOn?: arrayparentTaskId?: stringdir?: stringvcsRepo?: stringmodel?: stringmodelTier?: enumallowCustomModel?: booleaneffort?: enumprofile?: stringget-task-detailstaskId: stringstore-progress changestaskId?: stringprogress?: stringstatus?: enumoutput?: stringfailureReason?: stringattachments?: arraycitations?: arraylearning?: anypersistMemory?: booleanforce?: booleancancel-task changestaskId: stringreason?: stringsteer-task changestaskId: stringmessage: stringmode?: enumonUnsupported?: enumtask-action changesaction: enumtask?: stringkey?: anytaskType?: stringtags?: arraypriority?: numberdependsOn?: arraytaskId?: stringreason?: stringdir?: stringmodel?: stringmodelTier?: enumallowCustomModel?: booleaneffort?: enumprofile?: stringrequiredCapabilities?: arrayleadOnly?: booleandb-querysql?: stringquery?: stringparams?: arrayget-oauth-access-tokenprovider?: stringauthorizationId?: stringminValiditySeconds?: numbermanage-user deletesaction: enumuserId?: stringname?: stringemail?: stringrole?: stringnotes?: stringidentities?: arrayemailAliases?: arraypreferredChannel?: stringtimezone?: stringdailyBudgetUsd?: numberstatus?: enummetadata?: objectcomms?: objectcredential-bindings changesaction: enumid?: stringconfigKey?: stringallowedHosts?: arrayheaderTemplate?: stringqueryTemplate?: stringscope?: enumscopeId?: anyauthKind?: enumoauthAuthorizationId?: stringpresetId?: stringprovider?: stringlabel?: stringclientId?: stringclientSecret?: stringauthorizeUrl?: stringtokenUrl?: stringuserinfoUrl?: stringrevocationUrl?: stringscopes?: arrayscript-run changesname?: anysource?: stringargs?: anyintent?: stringscope?: anyfsMode?: anyexecutor?: anyidempotencyKey?: stringscript-upsert changesname: anysource: stringdescription?: stringintent?: stringscope?: anyfsMode?: anyexecutor?: anyextension-install changestemplate?: stringmanifest?: anyfiles?: objectpriority?: numberconfig?: objectextension-enable changesid: stringupdate-profile changesagentId?: stringname?: stringdescription?: stringrole?: stringcapabilities?: arrayclaudeMd?: stringsoulMd?: stringidentityMd?: stringsetupScript?: stringtoolsMd?: stringheartbeatMd?: stringavatar?: anyslackIcon?: anycontext-historyagentId?: stringfield?: enumlimit?: numberdefer-task changestaskId: stringdelayMs?: numberrunAt?: stringwakeOn?: objectsummary: stringoutput?: stringnote: stringchecks?: arraymemory-searchquery: stringintent?: stringscope?: enumlimit?: numbersource?: enumkeyPrefix?: stringmemory-store changescontent: stringname?: stringscope?: enumtags?: anytaskId?: stringintent?: stringkey?: stringmemory-delete deletesmemoryId: stringinject-learning changesagentId: stringlearning: stringcategory: enumrequest-human-input changestitle: stringquestions: arraytimeoutSeconds?: numberdetached?: booleancreate_page changeskey?: anytitle: stringslug?: stringbody: stringcontentType: enumauthMode?: enumpassword?: stringdescription?: stringneedsCredentials?: arraytheme?: stringthemeTokens?: anydesignVersion?: numberapp-upsert changesname: stringdescription?: stringdefinition: anyappId?: stringmigration?: anyforceElementBreak?: anyslack-readinboxMessageId?: stringtaskId?: stringchannelId?: stringthreadTs?: stringlimit?: numberincludeFiles?: booleanslack-post changeschannelId: stringmessage: stringblocks?: arraythreadTs?: stringslack-upload-file changesinboxMessageId?: stringtaskId?: stringchannelId?: stringthreadTs?: stringfilePath?: stringcontent?: stringfilename?: stringinitialComment?: stringslack-delete deleteschannelId: stringmessageTs: stringregister-agentmail-inbox changesaction: enuminboxId?: stringinboxEmail?: stringchat-post changesadapter: anythreadId?: stringchannelId?: stringtext: stringattachments?: arrayswarm_x changestarget?: anymethod: anypath: stringbody?: anyquery?: objectheaders?: objectbaseUrl?: stringuseOrgKey?: booleanraw?: booleanpost-message changeschannel?: stringcontent: stringreplyTo?: stringmentions?: array