swarmly 0.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swarmly-0.9.0/LICENSE +21 -0
- swarmly-0.9.0/MANIFEST.in +4 -0
- swarmly-0.9.0/PKG-INFO +402 -0
- swarmly-0.9.0/README.md +357 -0
- swarmly-0.9.0/THIRD_PARTY_NOTICES.md +70 -0
- swarmly-0.9.0/pyproject.toml +92 -0
- swarmly-0.9.0/setup.cfg +4 -0
- swarmly-0.9.0/swarmly/__init__.py +42 -0
- swarmly-0.9.0/swarmly/_aliases.py +30 -0
- swarmly-0.9.0/swarmly/adapters/__init__.py +17 -0
- swarmly-0.9.0/swarmly/adapters/base.py +54 -0
- swarmly-0.9.0/swarmly/adapters/deepseek.py +58 -0
- swarmly-0.9.0/swarmly/adapters/gemini.py +60 -0
- swarmly-0.9.0/swarmly/adapters/hermes.py +46 -0
- swarmly-0.9.0/swarmly/adapters/openai_swarm.py +68 -0
- swarmly-0.9.0/swarmly/bus.py +331 -0
- swarmly-0.9.0/swarmly/client.py +216 -0
- swarmly-0.9.0/swarmly/crypto.py +221 -0
- swarmly-0.9.0/swarmly/github/__init__.py +5 -0
- swarmly-0.9.0/swarmly/github/client.py +305 -0
- swarmly-0.9.0/swarmly/github/watch.py +293 -0
- swarmly-0.9.0/swarmly/keygen.py +247 -0
- swarmly-0.9.0/swarmly/logsetup.py +121 -0
- swarmly-0.9.0/swarmly/models.py +394 -0
- swarmly-0.9.0/swarmly/server.py +301 -0
- swarmly-0.9.0/swarmly/swarm/__init__.py +23 -0
- swarmly-0.9.0/swarmly/swarm/cli.py +483 -0
- swarmly-0.9.0/swarmly/swarm/doc.py +124 -0
- swarmly-0.9.0/swarmly/swarm/doorbell.py +237 -0
- swarmly-0.9.0/swarmly/swarm/envelope.py +195 -0
- swarmly-0.9.0/swarmly/swarm/governor.py +344 -0
- swarmly-0.9.0/swarmly/swarm/inbox.py +287 -0
- swarmly-0.9.0/swarmly/swarm/keys.py +95 -0
- swarmly-0.9.0/swarmly/swarm/lanes.py +376 -0
- swarmly-0.9.0/swarmly/swarm/mcp.py +181 -0
- swarmly-0.9.0/swarmly/swarm/mcp_setup.py +617 -0
- swarmly-0.9.0/swarmly/swarm/projection.py +719 -0
- swarmly-0.9.0/swarmly/swarm/protocol.py +288 -0
- swarmly-0.9.0/swarmly/swarm/protocol.yaml +268 -0
- swarmly-0.9.0/swarmly/telegram/__init__.py +82 -0
- swarmly-0.9.0/swarmly/telegram/acks.py +140 -0
- swarmly-0.9.0/swarmly/telegram/adapters/__init__.py +146 -0
- swarmly-0.9.0/swarmly/telegram/adapters/antigravity.py +1304 -0
- swarmly-0.9.0/swarmly/telegram/adapters/base.py +796 -0
- swarmly-0.9.0/swarmly/telegram/adapters/claude.py +337 -0
- swarmly-0.9.0/swarmly/telegram/adapters/codex.py +616 -0
- swarmly-0.9.0/swarmly/telegram/adapters/handover.py +141 -0
- swarmly-0.9.0/swarmly/telegram/adapters/hermes.py +74 -0
- swarmly-0.9.0/swarmly/telegram/adapters/reasonix.py +297 -0
- swarmly-0.9.0/swarmly/telegram/channel.py +3961 -0
- swarmly-0.9.0/swarmly/telegram/cli.py +995 -0
- swarmly-0.9.0/swarmly/telegram/commands.py +120 -0
- swarmly-0.9.0/swarmly/telegram/config.py +1310 -0
- swarmly-0.9.0/swarmly/telegram/endpoint.py +800 -0
- swarmly-0.9.0/swarmly/telegram/git_sync.py +109 -0
- swarmly-0.9.0/swarmly/telegram/guard.py +244 -0
- swarmly-0.9.0/swarmly/telegram/init.py +403 -0
- swarmly-0.9.0/swarmly/telegram/oslock.py +92 -0
- swarmly-0.9.0/swarmly/telegram/poll.py +2134 -0
- swarmly-0.9.0/swarmly/telegram/projects.py +141 -0
- swarmly-0.9.0/swarmly/telegram/relay.py +131 -0
- swarmly-0.9.0/swarmly/telegram/replies.py +330 -0
- swarmly-0.9.0/swarmly/telegram/roles/__init__.py +140 -0
- swarmly-0.9.0/swarmly/telegram/roles/coordinator.md +29 -0
- swarmly-0.9.0/swarmly/telegram/roles/developer.md +21 -0
- swarmly-0.9.0/swarmly/telegram/roles/qa-tester.md +20 -0
- swarmly-0.9.0/swarmly/telegram/roles/researcher.md +17 -0
- swarmly-0.9.0/swarmly/telegram/roles/reviewer.md +21 -0
- swarmly-0.9.0/swarmly/telegram/roster.py +270 -0
- swarmly-0.9.0/swarmly/telegram/selftest.py +405 -0
- swarmly-0.9.0/swarmly/telegram/templates/a2a_config.json +8 -0
- swarmly-0.9.0/swarmly/telegram/templates/config.example.yaml +66 -0
- swarmly-0.9.0/swarmly/telegram/topic_memory.py +228 -0
- swarmly-0.9.0/swarmly/telegram/topic_open.py +131 -0
- swarmly-0.9.0/swarmly/telegram/topics.py +141 -0
- swarmly-0.9.0/swarmly/telegram/wire.py +302 -0
- swarmly-0.9.0/swarmly/transports/__init__.py +58 -0
- swarmly-0.9.0/swarmly/transports/base.py +149 -0
- swarmly-0.9.0/swarmly/transports/folder.py +62 -0
- swarmly-0.9.0/swarmly/transports/gdrive.py +206 -0
- swarmly-0.9.0/swarmly/transports/git.py +344 -0
- swarmly-0.9.0/swarmly.egg-info/PKG-INFO +402 -0
- swarmly-0.9.0/swarmly.egg-info/SOURCES.txt +85 -0
- swarmly-0.9.0/swarmly.egg-info/dependency_links.txt +1 -0
- swarmly-0.9.0/swarmly.egg-info/entry_points.txt +7 -0
- swarmly-0.9.0/swarmly.egg-info/requires.txt +27 -0
- swarmly-0.9.0/swarmly.egg-info/top_level.txt +1 -0
swarmly-0.9.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eftychios Eftychiou and swarmly contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
swarmly-0.9.0/PKG-INFO
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: swarmly
|
|
3
|
+
Version: 0.9.0
|
|
4
|
+
Summary: Coordinate coding-agent CLIs (Claude Code, Codex, Antigravity, Hermes) across machines over Telegram and a git-backed message bus
|
|
5
|
+
Author: swarmly contributors
|
|
6
|
+
Author-email: Eftychios Eftychiou <eftychios.eftychiou@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/eeftychiou/swarmly
|
|
9
|
+
Project-URL: Documentation, https://github.com/eeftychiou/swarmly/blob/main/docs/GETTING-STARTED.md
|
|
10
|
+
Project-URL: Source, https://github.com/eeftychiou/swarmly
|
|
11
|
+
Project-URL: Issues, https://github.com/eeftychiou/swarmly/issues
|
|
12
|
+
Keywords: agents,multi-agent,a2a,telegram,claude,codex,antigravity,hermes,gitbus,google-drive
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
26
|
+
Requires-Dist: aiogram>=3.13.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: cryptography>=42.0.0
|
|
29
|
+
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
|
|
30
|
+
Provides-Extra: crypto
|
|
31
|
+
Requires-Dist: cryptography>=42.0.0; extra == "crypto"
|
|
32
|
+
Provides-Extra: telegram
|
|
33
|
+
Requires-Dist: aiogram>=3.13.0; extra == "telegram"
|
|
34
|
+
Requires-Dist: pyyaml>=6.0; extra == "telegram"
|
|
35
|
+
Provides-Extra: gdrive
|
|
36
|
+
Requires-Dist: google-api-python-client>=2.100.0; extra == "gdrive"
|
|
37
|
+
Requires-Dist: google-auth>=2.23.0; extra == "gdrive"
|
|
38
|
+
Provides-Extra: swarm
|
|
39
|
+
Requires-Dist: cryptography>=42.0.0; extra == "swarm"
|
|
40
|
+
Requires-Dist: pyyaml>=6.0; extra == "swarm"
|
|
41
|
+
Requires-Dist: tomli>=1.1.0; python_version < "3.11" and extra == "swarm"
|
|
42
|
+
Provides-Extra: test
|
|
43
|
+
Requires-Dist: coverage>=7.4; extra == "test"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# Swarmly
|
|
47
|
+
|
|
48
|
+
[](https://github.com/eeftychiou/swarmly/actions/workflows/tests.yml)
|
|
49
|
+
[](LICENSE)
|
|
50
|
+
|
|
51
|
+
> **Not the Agent2Agent protocol.** Swarmly is an independent project. It does not
|
|
52
|
+
> implement, and is not affiliated with, the Agent2Agent (A2A) Protocol that started at Google and
|
|
53
|
+
> is now hosted by the Linux Foundation. Its message formats are its own; their identifiers
|
|
54
|
+
> (`a2a/v1`, `a2a/2`) and the `A2A_*` variables only abbreviate "agent-to-agent". It coordinates
|
|
55
|
+
> coding-agent command-line tools through a git repository, a synced folder and Telegram, rather
|
|
56
|
+
> than through A2A's HTTP/JSON-RPC interface and Agent Cards. To interoperate with A2A-compliant
|
|
57
|
+
> agents, use the official specification and SDKs at [a2a-protocol.org](https://a2a-protocol.org).
|
|
58
|
+
|
|
59
|
+
**Coordinate coding-agent CLIs from different vendors, on different machines, on one project, with
|
|
60
|
+
a human in charge.**
|
|
61
|
+
|
|
62
|
+
Swarmly connects agent runtimes such as the **Antigravity CLI**, **OpenAI Codex CLI**,
|
|
63
|
+
**Claude Code** and **Nous Research Hermes Agent** through two planes that need no public IP and no open ports:
|
|
64
|
+
|
|
65
|
+
- **The durable plane** holds the record. Signed message envelopes are stored in one of three
|
|
66
|
+
places: a git repository (**gitbus**, `.agents/inbox/`), a **synced folder** (Google Drive for
|
|
67
|
+
desktop, Dropbox, OneDrive, Syncthing, a network share), or **Google Drive** through its API.
|
|
68
|
+
The record survives restarts, works offline and catches up on its own.
|
|
69
|
+
- **Telegram** is the instant plane. Every agent has a bot in one group, and the human can watch and
|
|
70
|
+
override everything there. Messages are short and point at the durable record.
|
|
71
|
+
|
|
72
|
+
An optional TCP gateway (the "fast plane") is included for agents on the same network.
|
|
73
|
+
|
|
74
|
+
> **Swarm kernel (a2a/2, preview):** signed per-agent lanes off `main`, one validated write
|
|
75
|
+
> path (`swarmly` CLI and MCP server) and a safety guard. See [docs/SWARM.md](https://github.com/eeftychiou/swarmly/blob/main/docs/SWARM.md).
|
|
76
|
+
|
|
77
|
+
> **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](https://github.com/eeftychiou/swarmly/blob/main/docs/PROJECTS.md).
|
|
78
|
+
|
|
79
|
+
> **Roles:** give each agent a role (coordinator, developer, reviewer, QA tester, researcher, or
|
|
80
|
+
> your own) and its turns follow that role's workflow. See [docs/ROLES.md](https://github.com/eeftychiou/swarmly/blob/main/docs/ROLES.md).
|
|
81
|
+
|
|
82
|
+
> **New here?** [Getting started](https://github.com/eeftychiou/swarmly/blob/main/docs/GETTING-STARTED.md) brings a node up in about fifteen
|
|
83
|
+
> minutes. Then see the [envelope cheat-sheet](https://github.com/eeftychiou/swarmly/blob/main/docs/ENVELOPES.md),
|
|
84
|
+
> [adopting Swarmly in your project](https://github.com/eeftychiou/swarmly/blob/main/docs/ADOPT.md) and the [runnable demo](https://github.com/eeftychiou/swarmly/blob/main/examples/README.md).
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Supported agents
|
|
89
|
+
|
|
90
|
+
| Runtime | `adapter.type` | How it is driven | Setup |
|
|
91
|
+
|---|---|---|---|
|
|
92
|
+
| Antigravity CLI | `antigravity`, `antigravity_thread` | `agy -p`, or queued into an open Antigravity conversation | [SETUP-ANTIGRAVITY](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/SETUP-ANTIGRAVITY.md) |
|
|
93
|
+
| OpenAI Codex CLI | `codex`, `codex_thread` | `codex exec`, or queued into an open Codex task | [SETUP-CODEX](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/SETUP-CODEX.md) |
|
|
94
|
+
| Claude Code | `claude`, `claude_thread` | `claude -p`, or one persistent session per topic (recommended) | [SETUP-CLAUDE](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/SETUP-CLAUDE.md) |
|
|
95
|
+
| Hermes Agent | `hermes` | `hermes -z` | [SETUP-HERMES](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/SETUP-HERMES.md) |
|
|
96
|
+
| Reasonix (DeepSeek) | `reasonix` | `reasonix run -p` | [SETUP-REASONIX](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/SETUP-REASONIX.md) |
|
|
97
|
+
| Anything with a CLI | `custom` | any command line with a `{prompt}` placeholder | [telegram-channel.md §4](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram-channel.md) |
|
|
98
|
+
|
|
99
|
+
## Coordination planes
|
|
100
|
+
|
|
101
|
+
| Plane | Transport | Role | Status |
|
|
102
|
+
|---|---|---|---|
|
|
103
|
+
| Durable | GitHub issues & PRs (`github:` backstop) | default durable coordination plane across projects | stable |
|
|
104
|
+
| Durable | gitbus (`.agents/inbox/` of the repository named in `bus.repo`) | the record: tasks, handoffs, reviews, blockers | stable |
|
|
105
|
+
| Durable | synced folder (`bus.transport: folder`) | the same record without git | new |
|
|
106
|
+
| Durable | Google Drive API (`bus.transport: gdrive`) | the same record for headless nodes | new |
|
|
107
|
+
| Instant | Telegram group, one bot per agent | low-latency pings, ACKs, human override | stable |
|
|
108
|
+
| Fast | TCP gateway with challenge-response auth (`swarmly/server.py`) | same-network broadcast, archived to gitbus | experimental |
|
|
109
|
+
|
|
110
|
+
Each project picks a durable coordination plane — GitHub issues and PRs (see [`docs/PROJECTS.md`](https://github.com/eeftychiou/swarmly/blob/main/docs/PROJECTS.md)) or an envelope bus transport. Telegram runs beside it:
|
|
111
|
+
`swarmly-telegram post` writes the envelope durably and then pings the peer on Telegram with a
|
|
112
|
+
pointer to it. [`docs/TRANSPORTS.md`](https://github.com/eeftychiou/swarmly/blob/main/docs/TRANSPORTS.md) covers the setup for each transport
|
|
113
|
+
and how to choose between them. The channel rules (delivery semantics, the escalation ladder)
|
|
114
|
+
are in [`docs/telegram/PROTOCOL.md`](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/PROTOCOL.md); the bus poller's gates and
|
|
115
|
+
dedupe keys are in [`docs/telegram-channel.md` §6](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram-channel.md#6-durable-bus-poller-bus-poll---once--scheduling-per-host-gates).
|
|
116
|
+
|
|
117
|
+
## Install
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pipx install swarmly # or: uv tool install swarmly, or pip install swarmly in a venv
|
|
121
|
+
swarmly-telegram --help
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Python 3.10 or newer and git are the only prerequisites. One install gives you the three
|
|
125
|
+
commands: `swarmly-telegram` (the Telegram transport and bus poller), `swarmly-keygen` (signing
|
|
126
|
+
keys) and `swarmly` (the swarm kernel). Google Drive as a bus needs `pipx install
|
|
127
|
+
"swarmly[gdrive]"`. To work on Swarmly itself, install from a clone instead:
|
|
128
|
+
`pip install -e ".[test]"`.
|
|
129
|
+
|
|
130
|
+
> [!WARNING]
|
|
131
|
+
> **Keep the Telegram group and the gitbus repository private.** Every agent runs with full
|
|
132
|
+
> permissions by default (`adapter.permissions: full`): no approvals and no sandbox. Anyone
|
|
133
|
+
> who can post in the group or push to the bus repository can make an agent run any command
|
|
134
|
+
> as the user it runs as, with that user's files, GitHub token and API keys. Use a private
|
|
135
|
+
> Telegram group with only your own bots and people you trust, and a private GitHub
|
|
136
|
+
> repository for the gitbus. Run the agents as a dedicated OS user, or in a VM or container,
|
|
137
|
+
> and set `adapter.permissions: standard` or `strict` on any Claude, Codex or Reasonix bot
|
|
138
|
+
> that does not need more (Hermes and the default Antigravity command have no such levels).
|
|
139
|
+
|
|
140
|
+
## Quickstart
|
|
141
|
+
|
|
142
|
+
**1. Try the bus with no tokens at all.** From a clone, two agents exchange a signed message
|
|
143
|
+
through a throwaway git repository, or through a plain shared folder:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
git clone https://github.com/eeftychiou/swarmly.git && cd swarmly
|
|
147
|
+
examples/minimal-bus-demo.sh # gitbus
|
|
148
|
+
examples/folder-bus-demo.sh # folder bus (what Drive or Dropbox would sync)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**2. Set up an agent.** Each agent gets its own Telegram bot (from @BotFather) and its own
|
|
152
|
+
`config.yaml`. Run this in the project repository your agents will share; its
|
|
153
|
+
`.agents/inbox/` becomes the durable bus:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
cd ~/projects/your-project
|
|
157
|
+
swarmly-telegram init --alias Hermes --adapter hermes --bus-repo .
|
|
158
|
+
echo 'A2A_TELEGRAM_BOT_TOKEN_HERMES=123456:ABC...' >> ~/.a2a-telegram.env
|
|
159
|
+
swarmly-keygen --agent hermes --env-file ~/.a2a-telegram.env --registry .agents/bus/config/a2a_config.json
|
|
160
|
+
git -C .agents/bus add .gitignore config/a2a_config.json
|
|
161
|
+
git -C .agents/bus commit -m "Register hermes" && git -C .agents/bus push -u origin agents-bus
|
|
162
|
+
swarmly-telegram whoami # proves the bot token
|
|
163
|
+
swarmly-telegram discover # lists the chats the bot sees: your group's id is home_channel_id
|
|
164
|
+
# edit config.yaml: agent.name (the bot's username), home_channel_id, admin_user_id, peers
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`init` writes `config.yaml`, an empty signing-key registry and the `.gitignore` lines that keep
|
|
168
|
+
the config and the transport's state out of git. The agent commits its bus messages in this
|
|
169
|
+
checkout, so the host needs a git identity (`git config user.name` and `user.email`). `--adapter` is `hermes`, `codex`, `claude`,
|
|
170
|
+
`antigravity` (or a `*_thread` variant), `echo` to test the channel without an agent CLI, or
|
|
171
|
+
`custom`. `swarmly-keygen` writes the private key to the env file (owner-only) and only the
|
|
172
|
+
public key to the registry; every peer verifies against that committed registry.
|
|
173
|
+
|
|
174
|
+
**3. Check it, then run it.**
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
swarmly-telegram check # validates the config and says what is still missing
|
|
178
|
+
swarmly-telegram run # serve the Telegram channel and poll the bus
|
|
179
|
+
swarmly-telegram post --to Codex "PR #7 is ready" # durable write + Telegram ping
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Every command reads `./config.yaml` unless you pass `--config path/to/config.yaml`. [Getting started](https://github.com/eeftychiou/swarmly/blob/main/docs/GETTING-STARTED.md) walks through the Telegram side (the group,
|
|
183
|
+
bot-to-bot mode, admin rights) and running the transport as a service.
|
|
184
|
+
|
|
185
|
+
A minimal agent config:
|
|
186
|
+
|
|
187
|
+
```yaml
|
|
188
|
+
agent:
|
|
189
|
+
name: HermesBot
|
|
190
|
+
alias: Hermes
|
|
191
|
+
bot_token_env: A2A_TELEGRAM_BOT_TOKEN_HERMES
|
|
192
|
+
home_channel_id: -1001234567890
|
|
193
|
+
admin_user_id: 1234567890 # your numeric Telegram user id (from @userinfobot)
|
|
194
|
+
adapter:
|
|
195
|
+
type: hermes
|
|
196
|
+
cwd: /home/user/your-project
|
|
197
|
+
|
|
198
|
+
# Optional: route Telegram forum topics to separate project repos & checkouts
|
|
199
|
+
# projects:
|
|
200
|
+
# webapp:
|
|
201
|
+
# repo: example-org/webapp
|
|
202
|
+
# cwd: /home/user/webapp
|
|
203
|
+
# topics: [12, 15]
|
|
204
|
+
# worktrees: true
|
|
205
|
+
# github:
|
|
206
|
+
# login: hermes-bot
|
|
207
|
+
# poll_minutes: 5
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Telegram needs **Bot-to-Bot Communication Mode** enabled for each bot in @BotFather, and each bot
|
|
211
|
+
promoted to group admin. [`docs/telegram/SETUP-ADMIN.md`](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/SETUP-ADMIN.md) walks
|
|
212
|
+
through it.
|
|
213
|
+
|
|
214
|
+
## Messages
|
|
215
|
+
|
|
216
|
+
Every message is an envelope that conforms to
|
|
217
|
+
[`schemas/a2a_envelope.schema.json`](https://github.com/eeftychiou/swarmly/blob/main/schemas/a2a_envelope.schema.json), stored as YAML
|
|
218
|
+
front matter followed by a readable body:
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
---
|
|
222
|
+
protocol: a2a/v1.0
|
|
223
|
+
message_id: msg-20260913T124500Z-codex
|
|
224
|
+
correlation_id: pr-47
|
|
225
|
+
timestamp_utc: '2026-09-13T12:45:00.123456+00:00'
|
|
226
|
+
sender:
|
|
227
|
+
agent_id: codex
|
|
228
|
+
model_family: openai
|
|
229
|
+
framework: codex
|
|
230
|
+
recipient:
|
|
231
|
+
agent_id: antigravity
|
|
232
|
+
intent: PR_REVIEW_VERDICT
|
|
233
|
+
priority: HIGH
|
|
234
|
+
signature: 'hmac-sha256:7f8a9b2c3d4e5f...'
|
|
235
|
+
payload_json: >-
|
|
236
|
+
{"pr_number": 47, "verdict": "CHANGES_REQUESTED"}
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
# Review: PR #47
|
|
240
|
+
Two findings, both in the retry path.
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Intents include `TASK_PROPOSE`, `TASK_CLAIM`, `TASK_HANDOFF`, `PR_REVIEW_REQUEST`,
|
|
244
|
+
`PR_REVIEW_VERDICT`, `STATUS_UPDATE`, `QUERY_REQUEST` and `ESCALATE_BLOCKER`. The full list is in
|
|
245
|
+
[`swarmly/models.py`](https://github.com/eeftychiou/swarmly/blob/main/swarmly/models.py) and [`docs/ENVELOPES.md`](https://github.com/eeftychiou/swarmly/blob/main/docs/ENVELOPES.md).
|
|
246
|
+
|
|
247
|
+
Send and read from the command line:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# codex's key, from `swarmly-keygen --agent codex --env-file .env --registry config/a2a_config.json`
|
|
251
|
+
set -a; . ./.env; set +a # sending refuses without A2A_KEY_CODEX
|
|
252
|
+
python scripts/a2a_bus.py send --sender codex --recipient antigravity \
|
|
253
|
+
--intent PR_REVIEW_REQUEST --priority HIGH --payload '{"pr_number": 47}'
|
|
254
|
+
python scripts/a2a_bus.py inbox # lists messages and verifies signatures
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Security model
|
|
258
|
+
|
|
259
|
+
**Read this before you run an agent.** Every agent this project drives can run code on its host,
|
|
260
|
+
and messages from the bus and from the Telegram group become that agent's prompts. Treat anyone
|
|
261
|
+
who can write to your bus or post in your group as someone who can run commands as the agent's
|
|
262
|
+
OS user. These limits remain:
|
|
263
|
+
|
|
264
|
+
- **The default permission level is full: no checks and no sandbox.** Every runtime starts
|
|
265
|
+
at `adapter.permissions: full`, so an agent can pull, commit, push and run `gh` out of the
|
|
266
|
+
box. Keep the group and the bus repository private (the warning above). `standard` still
|
|
267
|
+
lets the agent run interpreters, package managers and git, which amounts to arbitrary code
|
|
268
|
+
execution; `strict` only edits files. The default Antigravity command passes
|
|
269
|
+
`--dangerously-skip-permissions` (an explicit `adapter.command` without it keeps approvals).
|
|
270
|
+
- **Agents run as the transport's OS user.** Runtimes do not inherit variables whose names look
|
|
271
|
+
like secrets (tokens, `A2A_KEY_*`, passwords), but that is a denylist: the CLI's own API key
|
|
272
|
+
passes, and so does a secret with an unusual name. As the same user an agent can also read
|
|
273
|
+
the transport's `.env` files and, on Linux, `/proc/<pid>/environ`. The real boundary is the
|
|
274
|
+
OS: run each agent as a separate low-privilege user, or in a container or VM, with only that
|
|
275
|
+
agent's secrets.
|
|
276
|
+
- **With HMAC, every receiver can sign as every sender.** Each node holds each HMAC sender's
|
|
277
|
+
secret to verify it. Prefer Ed25519 for bus senders: the registry then holds only public
|
|
278
|
+
keys.
|
|
279
|
+
- **Write access to the bus repository is the trust anchor.** Each node trusts the keys and
|
|
280
|
+
revocations in its bus checkout's `config/a2a_config.json`, so anyone who can push there can
|
|
281
|
+
add a trusted sender, replace a key or drop a revocation. Restrict who can write to the bus
|
|
282
|
+
repository and protect that file (branch protection, CODEOWNERS or required review).
|
|
283
|
+
- **Revocation needs every node's copy of the registry.** `revocation_list` is read from
|
|
284
|
+
`config/a2a_config.json` in each node's bus checkout, so a revocation takes effect on a node
|
|
285
|
+
only once that checkout carries it.
|
|
286
|
+
- **The fast-plane gateway (`swarmly/server.py`) is experimental:** raw TCP with newline-delimited
|
|
287
|
+
JSON, plaintext, and the client does not authenticate the server. It binds `127.0.0.1` by
|
|
288
|
+
default; reach it from another machine only through an SSH tunnel or a TLS proxy.
|
|
289
|
+
- **The swarm safety guard is advisory** for every CLI except Claude Code, which has an
|
|
290
|
+
enforcing hook.
|
|
291
|
+
|
|
292
|
+
What does hold today:
|
|
293
|
+
|
|
294
|
+
- **No bus by default.** Without `bus.repo` nothing is polled, and the first cycle on a bus
|
|
295
|
+
records what is already there without delivering any of it.
|
|
296
|
+
- **Bus messages are verified on delivery.** A message is delivered only when its signature
|
|
297
|
+
verifies against a registered, non-revoked sender. The signature covers the whole envelope
|
|
298
|
+
(payload, sender, recipient, message id, intent, timestamps), so a copied message cannot be
|
|
299
|
+
re-addressed or given a new id, and it is accepted only within 7 days of its signed
|
|
300
|
+
timestamp. Old payload-only signatures are refused unless the registry sets
|
|
301
|
+
`"accept_v1_signatures": true` for a rollout; `bus.allow_unsigned: true` turns the checks off
|
|
302
|
+
for a local demo bus. See [docs/ENVELOPES.md](https://github.com/eeftychiou/swarmly/blob/main/docs/ENVELOPES.md).
|
|
303
|
+
- **No keys ship, and signing fails closed.** The registry (`config/a2a_config.json`) starts
|
|
304
|
+
with no agents. `swarmly-keygen --agent <id> --env-file <file> --registry <registry>` creates an
|
|
305
|
+
Ed25519 key per agent: the private key stays in that agent's env file, and only the public key
|
|
306
|
+
is registered, with `key_type: ed25519`, so only `ed25519:` signatures verify against it.
|
|
307
|
+
Sending refuses without `A2A_KEY_<SENDER>`. (An HMAC agent is registered by the *name* of an
|
|
308
|
+
environment variable, and has no key while that variable is unset.)
|
|
309
|
+
- **Telegram authorization.** People are authorised by numeric user id only (`admin_user_id`,
|
|
310
|
+
`allowed_users`); strangers are ignored by default; forwards and anonymous-admin posts are not
|
|
311
|
+
treated as bots.
|
|
312
|
+
- **No shell.** Agent CLIs are started from argument lists, never through a shell. On Windows an
|
|
313
|
+
npm `.cmd` shim is replaced by the script it wraps and any other `.cmd`/`.bat` is refused, so
|
|
314
|
+
prompt text never reaches `cmd.exe`. Timeouts kill the whole process tree.
|
|
315
|
+
- **The gateway checks what it archives.** Message ids and header fields are validated, so a
|
|
316
|
+
client cannot write outside the inbox; idle connections are closed and their number capped.
|
|
317
|
+
|
|
318
|
+
[SECURITY.md](https://github.com/eeftychiou/swarmly/blob/main/SECURITY.md) lists the same limits and says how to report a vulnerability.
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
## Python SDK
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
import asyncio
|
|
325
|
+
from swarmly import A2AClient, MessageIntent, MessagePriority
|
|
326
|
+
|
|
327
|
+
async def main():
|
|
328
|
+
client = A2AClient(agent_id="codex", private_key="...", host="127.0.0.1", port=8765)
|
|
329
|
+
await client.connect() # answers the challenge automatically
|
|
330
|
+
client.on_message(lambda msg: print(msg.sender.agent_id, msg.payload))
|
|
331
|
+
await client.send_message(
|
|
332
|
+
intent=MessageIntent.PR_REVIEW_VERDICT,
|
|
333
|
+
payload={"pr_number": 47, "verdict": "APPROVED"},
|
|
334
|
+
recipient_id="antigravity",
|
|
335
|
+
priority=MessagePriority.HIGH,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
asyncio.run(main())
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Documentation
|
|
342
|
+
|
|
343
|
+
| Topic | Where |
|
|
344
|
+
|---|---|
|
|
345
|
+
| First node in fifteen minutes | [docs/GETTING-STARTED.md](https://github.com/eeftychiou/swarmly/blob/main/docs/GETTING-STARTED.md) |
|
|
346
|
+
| Durable transports (git, folder, Google Drive) and Telegram | [docs/TRANSPORTS.md](https://github.com/eeftychiou/swarmly/blob/main/docs/TRANSPORTS.md) |
|
|
347
|
+
| Using Swarmly in another project | [docs/ADOPT.md](https://github.com/eeftychiou/swarmly/blob/main/docs/ADOPT.md) |
|
|
348
|
+
| Telegram channel, adapters, rules | [docs/telegram-channel.md](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram-channel.md) |
|
|
349
|
+
| Channel protocol v1.1 | [docs/telegram/PROTOCOL.md](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/PROTOCOL.md) |
|
|
350
|
+
| Safe upgrade and rollback | [docs/telegram/UPGRADE.md](https://github.com/eeftychiou/swarmly/blob/main/docs/telegram/UPGRADE.md) |
|
|
351
|
+
| Every document, by audience | [docs/README.md](https://github.com/eeftychiou/swarmly/blob/main/docs/README.md) |
|
|
352
|
+
| How this repository is maintained | [AGENTS.md](https://github.com/eeftychiou/swarmly/blob/main/AGENTS.md) |
|
|
353
|
+
|
|
354
|
+
## Status and roadmap
|
|
355
|
+
|
|
356
|
+
This repository is developed by the agents it connects. Claude Code, Antigravity, Codex and Hermes
|
|
357
|
+
coordinate here over their own gitbus and Telegram, under a human maintainer.
|
|
358
|
+
|
|
359
|
+
Planned:
|
|
360
|
+
|
|
361
|
+
- more cloud transports beside git, folders and Google Drive (S3-compatible storage, OneDrive's API);
|
|
362
|
+
- carrying the GitHub event watcher used in production gitbus deployments back into this library.
|
|
363
|
+
|
|
364
|
+
## Running the tests
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
pip install -e ".[test]"
|
|
368
|
+
python -m unittest discover tests
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## How this was built
|
|
372
|
+
|
|
373
|
+
I designed Swarmly and wrote its protocol and the process rules in
|
|
374
|
+
[AGENTS.md](https://github.com/eeftychiou/swarmly/blob/main/AGENTS.md): every pull request gets an independent review with a merge or fix-first
|
|
375
|
+
verdict before whoever acts as maintainer, usually an agent, merges it; I make the calls the
|
|
376
|
+
agents escalate to me.
|
|
377
|
+
Most of the implementation was written by the coding agents it connects. This public repository
|
|
378
|
+
starts from a single commit; the development history stays in a private repository, because it
|
|
379
|
+
carries the identifiers of the deployment it was built on. Of its roughly 320 non-merge commits
|
|
380
|
+
at the time of writing, about 280 were made by Claude Code, Hermes, OpenAI Codex CLI and
|
|
381
|
+
Antigravity agents under their own git identities (for example `Codex <codex@a2a.local>`). They
|
|
382
|
+
claim tasks, review each other's pull requests and report status over this project's own bus and
|
|
383
|
+
Telegram channel. In the first week, before per-agent identities were introduced, some agent
|
|
384
|
+
work was committed under my name.
|
|
385
|
+
|
|
386
|
+
— Eftychios Eftychiou
|
|
387
|
+
|
|
388
|
+
## Acknowledgements
|
|
389
|
+
|
|
390
|
+
- [ductor](https://github.com/PleasePrompto/ductor) (MIT) by PleasePrompto: the Telegram
|
|
391
|
+
transport's forum topics, typing indicator, busy queue, `/stop`, incoming files and long-reply
|
|
392
|
+
splitting were reimplemented from its Telegram transport. See [THIRD_PARTY_NOTICES.md](https://github.com/eeftychiou/swarmly/blob/main/THIRD_PARTY_NOTICES.md).
|
|
393
|
+
- [superpowers](https://github.com/obra/superpowers) (MIT) by Jesse Vincent: the format of the
|
|
394
|
+
repository's agent skill (`.agents/skills/vacuous-green/`) and its "verify red" step follow
|
|
395
|
+
superpowers' skills.
|
|
396
|
+
- [aiogram](https://github.com/aiogram/aiogram) (MIT), the Telegram Bot API framework the
|
|
397
|
+
transport is built on.
|
|
398
|
+
|
|
399
|
+
## Contributing and license
|
|
400
|
+
|
|
401
|
+
Contributions are welcome. See [CONTRIBUTING.md](https://github.com/eeftychiou/swarmly/blob/main/CONTRIBUTING.md). Released under the
|
|
402
|
+
[MIT License](https://github.com/eeftychiou/swarmly/blob/main/LICENSE).
|