Skip to main content

Swarmly

tests License: MIT

Not the Agent2Agent protocol. Swarmly is an independent project. It does not implement, and is not affiliated with, the Agent2Agent (A2A) Protocol that started at Google and is now hosted by the Linux Foundation. Its message formats are its own; their identifiers (a2a/v1, a2a/2) and the A2A_* variables only abbreviate "agent-to-agent". It coordinates coding-agent command-line tools through a git repository, a synced folder and Telegram, rather than through A2A's HTTP/JSON-RPC interface and Agent Cards. To interoperate with A2A-compliant agents, use the official specification and SDKs at a2a-protocol.org.

Coordinate coding-agent CLIs from different vendors, on different machines, on one project, with a human in charge.

Swarmly connects agent runtimes such as the Antigravity CLI, OpenAI Codex CLI, Claude Code and Nous Research Hermes Agent through two planes that need no public IP and no open ports:

  • The durable plane holds the record. Signed message envelopes are stored in one of three places: a git repository (gitbus, .agents/inbox/), a synced folder (Google Drive for desktop, Dropbox, OneDrive, Syncthing, a network share), or Google Drive through its API. The record survives restarts, works offline and catches up on its own.
  • Telegram is the instant plane. Every agent has a bot in one group, and the human can watch and override everything there. Messages are short and point at the durable record.

An optional TCP gateway (the "fast plane") is included for agents on the same network.

Swarm kernel (a2a/2, preview): signed per-agent lanes off main, one validated write path (swarmly CLI and MCP server) and a safety guard. See docs/SWARM.md.

Topic-to-project routing (multi-project): Telegram forum topics bound to project repositories, with GitHub issues and pull requests as the default durable plane, git worktree isolation, and a missed-ping notification backstop. See docs/PROJECTS.md.

Roles: give each agent a role (coordinator, developer, reviewer, QA tester, researcher, or your own) and its turns follow that role's workflow. See docs/ROLES.md.

New here? Getting started brings a node up in about fifteen minutes. Then see the envelope cheat-sheet, adopting Swarmly in your project and the runnable demo.


Supported agents

Runtime adapter.type How it is driven Setup
Antigravity CLI antigravity, antigravity_thread agy -p, or queued into an open Antigravity conversation SETUP-ANTIGRAVITY
OpenAI Codex CLI codex, codex_thread codex exec, or queued into an open Codex task SETUP-CODEX
Claude Code claude, claude_thread claude -p, or one persistent session per topic (recommended) SETUP-CLAUDE
Hermes Agent hermes hermes -z SETUP-HERMES
Reasonix (DeepSeek) reasonix reasonix run -p SETUP-REASONIX
Anything with a CLI custom any command line with a {prompt} placeholder telegram-channel.md §4

Coordination planes

Plane Transport Role Status
Durable GitHub issues & PRs (github: backstop) default durable coordination plane across projects stable
Durable gitbus (.agents/inbox/ of the repository named in bus.repo) the record: tasks, handoffs, reviews, blockers stable
Durable synced folder (bus.transport: folder) the same record without git new
Durable Google Drive API (bus.transport: gdrive) the same record for headless nodes new
Instant Telegram group, one bot per agent low-latency pings, ACKs, human override stable
Fast TCP gateway with challenge-response auth (swarmly/server.py) same-network broadcast, archived to gitbus experimental

Each project picks a durable coordination plane — GitHub issues and PRs (see docs/PROJECTS.md) or an envelope bus transport. Telegram runs beside it: swarmly-telegram post writes the envelope durably and then pings the peer on Telegram with a pointer to it. docs/TRANSPORTS.md covers the setup for each transport and how to choose between them. The channel rules (delivery semantics, the escalation ladder) are in docs/telegram/PROTOCOL.md; the bus poller's gates and dedupe keys are in docs/telegram-channel.md §6.

Install

pipx install swarmly          # or: uv tool install swarmly, or pip install swarmly in a venv
swarmly-telegram --help

Python 3.10 or newer and git are the only prerequisites. One install gives you the three commands: swarmly-telegram (the Telegram transport and bus poller), swarmly-keygen (signing keys) and swarmly (the swarm kernel). Google Drive as a bus needs pipx install "swarmly[gdrive]". To work on Swarmly itself, install from a clone instead: pip install -e ".[test]".

Quickstart

1. Try the bus with no tokens at all. From a clone, two agents exchange a signed message through a throwaway git repository, or through a plain shared folder:

git clone https://github.com/eeftychiou/swarmly.git && cd swarmly
examples/minimal-bus-demo.sh        # gitbus
examples/folder-bus-demo.sh         # folder bus (what Drive or Dropbox would sync)

2. Set up an agent. Each agent gets its own Telegram bot (from @BotFather) and its own config.yaml. Run this in the project repository your agents will share; its .agents/inbox/ becomes the durable bus:

cd ~/projects/your-project
swarmly-telegram init --alias Hermes --adapter hermes --bus-repo .
echo 'A2A_TELEGRAM_BOT_TOKEN_HERMES=123456:ABC...' >> ~/.a2a-telegram.env
swarmly-keygen --agent hermes --env-file ~/.a2a-telegram.env --registry .agents/bus/config/a2a_config.json
git -C .agents/bus add .gitignore config/a2a_config.json
git -C .agents/bus commit -m "Register hermes" && git -C .agents/bus push -u origin agents-bus
swarmly-telegram whoami     # proves the bot token
swarmly-telegram discover   # lists the chats the bot sees: your group's id is home_channel_id
# edit config.yaml: agent.name (the bot's username), home_channel_id, admin_user_id, peers

init writes config.yaml, an empty signing-key registry and the .gitignore lines that keep the config and the transport's state out of git. The agent commits its bus messages in this checkout, so the host needs a git identity (git config user.name and user.email). --adapter is hermes, codex, claude, antigravity (or a *_thread variant), echo to test the channel without an agent CLI, or custom. swarmly-keygen writes the private key to the env file (owner-only) and only the public key to the registry; every peer verifies against that committed registry.

3. Check it, then run it.

swarmly-telegram check      # validates the config and says what is still missing
swarmly-telegram run        # serve the Telegram channel and poll the bus
swarmly-telegram post --to Codex "PR #7 is ready"   # durable write + Telegram ping

Every command reads ./config.yaml unless you pass --config path/to/config.yaml. Getting started walks through the Telegram side (the group, bot-to-bot mode, admin rights) and running the transport as a service.

A minimal agent config:

agent:
  name: HermesBot
  alias: Hermes
  bot_token_env: A2A_TELEGRAM_BOT_TOKEN_HERMES
  home_channel_id: -1001234567890
  admin_user_id: 1234567890        # your numeric Telegram user id (from @userinfobot)
adapter:
  type: hermes
  cwd: /home/user/your-project

# Optional: route Telegram forum topics to separate project repos & checkouts
# projects:
#   webapp:
#     repo: example-org/webapp
#     cwd: /home/user/webapp
#     topics: [12, 15]
#     worktrees: true
# github:
#   login: hermes-bot
#   poll_minutes: 5

Telegram needs Bot-to-Bot Communication Mode enabled for each bot in @BotFather, and each bot promoted to group admin. docs/telegram/SETUP-ADMIN.md walks through it.

Messages

Every message is an envelope that conforms to schemas/a2a_envelope.schema.json, stored as YAML front matter followed by a readable body:

---
protocol: a2a/v1.0
message_id: msg-20260913T124500Z-codex
correlation_id: pr-47
timestamp_utc: '2026-09-13T12:45:00.123456+00:00'
sender:
  agent_id: codex
  model_family: openai
  framework: codex
recipient:
  agent_id: antigravity
intent: PR_REVIEW_VERDICT
priority: HIGH
signature: 'hmac-sha256:7f8a9b2c3d4e5f...'
payload_json: >-
  {"pr_number": 47, "verdict": "CHANGES_REQUESTED"}
---

# Review: PR #47
Two findings, both in the retry path.

Intents include TASK_PROPOSE, TASK_CLAIM, TASK_HANDOFF, PR_REVIEW_REQUEST, PR_REVIEW_VERDICT, STATUS_UPDATE, QUERY_REQUEST and ESCALATE_BLOCKER. The full list is in swarmly/models.py and docs/ENVELOPES.md.

Send and read from the command line:

# codex's key, from `swarmly-keygen --agent codex --env-file .env --registry config/a2a_config.json`
set -a; . ./.env; set +a          # sending refuses without A2A_KEY_CODEX
python scripts/a2a_bus.py send --sender codex --recipient antigravity \
  --intent PR_REVIEW_REQUEST --priority HIGH --payload '{"pr_number": 47}'
python scripts/a2a_bus.py inbox      # lists messages and verifies signatures

Security model

Read this before you run an agent. Every agent this project drives can run code on its host, and messages from the bus and from the Telegram group become that agent's prompts. Treat anyone who can write to your bus or post in your group as someone who can run commands as the agent's OS user. These limits remain:

  • The default permission level is full: no checks and no sandbox. Every runtime starts at adapter.permissions: full, so an agent can pull, commit, push and run gh out of the box. Keep the group and the bus repository private (the warning above). standard still lets the agent run interpreters, package managers and git, which amounts to arbitrary code execution; strict only edits files. The default Antigravity command passes --dangerously-skip-permissions (an explicit adapter.command without it keeps approvals).
  • Agents run as the transport's OS user. Runtimes do not inherit variables whose names look like secrets (tokens, A2A_KEY_*, passwords), but that is a denylist: the CLI's own API key passes, and so does a secret with an unusual name. As the same user an agent can also read the transport's .env files and, on Linux, /proc/<pid>/environ. The real boundary is the OS: run each agent as a separate low-privilege user, or in a container or VM, with only that agent's secrets.
  • With HMAC, every receiver can sign as every sender. Each node holds each HMAC sender's secret to verify it. Prefer Ed25519 for bus senders: the registry then holds only public keys.
  • Write access to the bus repository is the trust anchor. Each node trusts the keys and revocations in its bus checkout's config/a2a_config.json, so anyone who can push there can add a trusted sender, replace a key or drop a revocation. Restrict who can write to the bus repository and protect that file (branch protection, CODEOWNERS or required review).
  • Revocation needs every node's copy of the registry. revocation_list is read from config/a2a_config.json in each node's bus checkout, so a revocation takes effect on a node only once that checkout carries it.
  • The fast-plane gateway (swarmly/server.py) is experimental: raw TCP with newline-delimited JSON, plaintext, and the client does not authenticate the server. It binds 127.0.0.1 by default; reach it from another machine only through an SSH tunnel or a TLS proxy.
  • The swarm safety guard is advisory for every CLI except Claude Code, which has an enforcing hook.

What does hold today:

  • No bus by default. Without bus.repo nothing is polled, and the first cycle on a bus records what is already there without delivering any of it.
  • Bus messages are verified on delivery. A message is delivered only when its signature verifies against a registered, non-revoked sender. The signature covers the whole envelope (payload, sender, recipient, message id, intent, timestamps), so a copied message cannot be re-addressed or given a new id, and it is accepted only within 7 days of its signed timestamp. Old payload-only signatures are refused unless the registry sets "accept_v1_signatures": true for a rollout; bus.allow_unsigned: true turns the checks off for a local demo bus. See docs/ENVELOPES.md.
  • No keys ship, and signing fails closed. The registry (config/a2a_config.json) starts with no agents. swarmly-keygen --agent <id> --env-file <file> --registry <registry> creates an Ed25519 key per agent: the private key stays in that agent's env file, and only the public key is registered, with key_type: ed25519, so only ed25519: signatures verify against it. Sending refuses without A2A_KEY_<SENDER>. (An HMAC agent is registered by the name of an environment variable, and has no key while that variable is unset.)
  • Telegram authorization. People are authorised by numeric user id only (admin_user_id, allowed_users); strangers are ignored by default; forwards and anonymous-admin posts are not treated as bots.
  • No shell. Agent CLIs are started from argument lists, never through a shell. On Windows an npm .cmd shim is replaced by the script it wraps and any other .cmd/.bat is refused, so prompt text never reaches cmd.exe. Timeouts kill the whole process tree.
  • The gateway checks what it archives. Message ids and header fields are validated, so a client cannot write outside the inbox; idle connections are closed and their number capped.

SECURITY.md lists the same limits and says how to report a vulnerability.

Python SDK

import asyncio
from swarmly import A2AClient, MessageIntent, MessagePriority

async def main():
    client = A2AClient(agent_id="codex", private_key="...", host="127.0.0.1", port=8765)
    await client.connect()                       # answers the challenge automatically
    client.on_message(lambda msg: print(msg.sender.agent_id, msg.payload))
    await client.send_message(
        intent=MessageIntent.PR_REVIEW_VERDICT,
        payload={"pr_number": 47, "verdict": "APPROVED"},
        recipient_id="antigravity",
        priority=MessagePriority.HIGH,
    )

asyncio.run(main())

Documentation

Topic Where
First node in fifteen minutes docs/GETTING-STARTED.md
Durable transports (git, folder, Google Drive) and Telegram docs/TRANSPORTS.md
Using Swarmly in another project docs/ADOPT.md
Telegram channel, adapters, rules docs/telegram-channel.md
Channel protocol v1.1 docs/telegram/PROTOCOL.md
Safe upgrade and rollback docs/telegram/UPGRADE.md
Every document, by audience docs/README.md
How this repository is maintained AGENTS.md

Status and roadmap

This repository is developed by the agents it connects. Claude Code, Antigravity, Codex and Hermes coordinate here over their own gitbus and Telegram, under a human maintainer.

Planned:

  • more cloud transports beside git, folders and Google Drive (S3-compatible storage, OneDrive's API);
  • carrying the GitHub event watcher used in production gitbus deployments back into this library.

Running the tests

pip install -e ".[test]"
python -m unittest discover tests

How this was built

I designed Swarmly and wrote its protocol and the process rules in AGENTS.md: every pull request gets an independent review with a merge or fix-first verdict before whoever acts as maintainer, usually an agent, merges it; I make the calls the agents escalate to me. Most of the implementation was written by the coding agents it connects. This public repository starts from a single commit; the development history stays in a private repository, because it carries the identifiers of the deployment it was built on. Of its roughly 320 non-merge commits at the time of writing, about 280 were made by Claude Code, Hermes, OpenAI Codex CLI and Antigravity agents under their own git identities (for example Codex <codex@a2a.local>). They claim tasks, review each other's pull requests and report status over this project's own bus and Telegram channel. In the first week, before per-agent identities were introduced, some agent work was committed under my name.

— Eftychios Eftychiou

Acknowledgements

  • ductor (MIT) by PleasePrompto: the Telegram transport's forum topics, typing indicator, busy queue, /stop, incoming files and long-reply splitting were reimplemented from its Telegram transport. See THIRD_PARTY_NOTICES.md.
  • superpowers (MIT) by Jesse Vincent: the format of the repository's agent skill (.agents/skills/vacuous-green/) and its "verify red" step follow superpowers' skills.
  • aiogram (MIT), the Telegram Bot API framework the transport is built on.

Contributing and license

Contributions are welcome. See CONTRIBUTING.md. Released under the MIT License.

Metadata

Release files for swarmly 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for swarmly 0.9.0
File Size Uploaded
swarmly-0.9.0.tar.gz 347.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for swarmly 0.9.0
File Interpreter ABI Platform
swarmly-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 727.2 kB

Release files / swarmly-0.9.0.tar.gz

Download URL swarmly-0.9.0.tar.gz
Size 347.2 kB
Tags Source
SHA-256 checksum
How to use checksums
3e6f89203e64635f164ff4ec98ac1acbff94bc349be14c46a05257c9a6c9924b
BLAKE2b-256 checksum
How to use checksums
409695fc6a580f2fb9c382e92510df3d1a312c455ac7884501edea95ab2c0511
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / swarmly-0.9.0-py3-none-any.whl

Download URL swarmly-0.9.0-py3-none-any.whl
Size 380.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
123803ff76a991d4778e9097d2d7aac679c76eea7ba64b8e952fa8d80ac81378
BLAKE2b-256 checksum
How to use checksums
a58d5116c88f60c1825c204ef81cba356c704da73af9a053b505e9f670f9f64b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page