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.
Files changed (87) hide show
  1. swarmly-0.9.0/LICENSE +21 -0
  2. swarmly-0.9.0/MANIFEST.in +4 -0
  3. swarmly-0.9.0/PKG-INFO +402 -0
  4. swarmly-0.9.0/README.md +357 -0
  5. swarmly-0.9.0/THIRD_PARTY_NOTICES.md +70 -0
  6. swarmly-0.9.0/pyproject.toml +92 -0
  7. swarmly-0.9.0/setup.cfg +4 -0
  8. swarmly-0.9.0/swarmly/__init__.py +42 -0
  9. swarmly-0.9.0/swarmly/_aliases.py +30 -0
  10. swarmly-0.9.0/swarmly/adapters/__init__.py +17 -0
  11. swarmly-0.9.0/swarmly/adapters/base.py +54 -0
  12. swarmly-0.9.0/swarmly/adapters/deepseek.py +58 -0
  13. swarmly-0.9.0/swarmly/adapters/gemini.py +60 -0
  14. swarmly-0.9.0/swarmly/adapters/hermes.py +46 -0
  15. swarmly-0.9.0/swarmly/adapters/openai_swarm.py +68 -0
  16. swarmly-0.9.0/swarmly/bus.py +331 -0
  17. swarmly-0.9.0/swarmly/client.py +216 -0
  18. swarmly-0.9.0/swarmly/crypto.py +221 -0
  19. swarmly-0.9.0/swarmly/github/__init__.py +5 -0
  20. swarmly-0.9.0/swarmly/github/client.py +305 -0
  21. swarmly-0.9.0/swarmly/github/watch.py +293 -0
  22. swarmly-0.9.0/swarmly/keygen.py +247 -0
  23. swarmly-0.9.0/swarmly/logsetup.py +121 -0
  24. swarmly-0.9.0/swarmly/models.py +394 -0
  25. swarmly-0.9.0/swarmly/server.py +301 -0
  26. swarmly-0.9.0/swarmly/swarm/__init__.py +23 -0
  27. swarmly-0.9.0/swarmly/swarm/cli.py +483 -0
  28. swarmly-0.9.0/swarmly/swarm/doc.py +124 -0
  29. swarmly-0.9.0/swarmly/swarm/doorbell.py +237 -0
  30. swarmly-0.9.0/swarmly/swarm/envelope.py +195 -0
  31. swarmly-0.9.0/swarmly/swarm/governor.py +344 -0
  32. swarmly-0.9.0/swarmly/swarm/inbox.py +287 -0
  33. swarmly-0.9.0/swarmly/swarm/keys.py +95 -0
  34. swarmly-0.9.0/swarmly/swarm/lanes.py +376 -0
  35. swarmly-0.9.0/swarmly/swarm/mcp.py +181 -0
  36. swarmly-0.9.0/swarmly/swarm/mcp_setup.py +617 -0
  37. swarmly-0.9.0/swarmly/swarm/projection.py +719 -0
  38. swarmly-0.9.0/swarmly/swarm/protocol.py +288 -0
  39. swarmly-0.9.0/swarmly/swarm/protocol.yaml +268 -0
  40. swarmly-0.9.0/swarmly/telegram/__init__.py +82 -0
  41. swarmly-0.9.0/swarmly/telegram/acks.py +140 -0
  42. swarmly-0.9.0/swarmly/telegram/adapters/__init__.py +146 -0
  43. swarmly-0.9.0/swarmly/telegram/adapters/antigravity.py +1304 -0
  44. swarmly-0.9.0/swarmly/telegram/adapters/base.py +796 -0
  45. swarmly-0.9.0/swarmly/telegram/adapters/claude.py +337 -0
  46. swarmly-0.9.0/swarmly/telegram/adapters/codex.py +616 -0
  47. swarmly-0.9.0/swarmly/telegram/adapters/handover.py +141 -0
  48. swarmly-0.9.0/swarmly/telegram/adapters/hermes.py +74 -0
  49. swarmly-0.9.0/swarmly/telegram/adapters/reasonix.py +297 -0
  50. swarmly-0.9.0/swarmly/telegram/channel.py +3961 -0
  51. swarmly-0.9.0/swarmly/telegram/cli.py +995 -0
  52. swarmly-0.9.0/swarmly/telegram/commands.py +120 -0
  53. swarmly-0.9.0/swarmly/telegram/config.py +1310 -0
  54. swarmly-0.9.0/swarmly/telegram/endpoint.py +800 -0
  55. swarmly-0.9.0/swarmly/telegram/git_sync.py +109 -0
  56. swarmly-0.9.0/swarmly/telegram/guard.py +244 -0
  57. swarmly-0.9.0/swarmly/telegram/init.py +403 -0
  58. swarmly-0.9.0/swarmly/telegram/oslock.py +92 -0
  59. swarmly-0.9.0/swarmly/telegram/poll.py +2134 -0
  60. swarmly-0.9.0/swarmly/telegram/projects.py +141 -0
  61. swarmly-0.9.0/swarmly/telegram/relay.py +131 -0
  62. swarmly-0.9.0/swarmly/telegram/replies.py +330 -0
  63. swarmly-0.9.0/swarmly/telegram/roles/__init__.py +140 -0
  64. swarmly-0.9.0/swarmly/telegram/roles/coordinator.md +29 -0
  65. swarmly-0.9.0/swarmly/telegram/roles/developer.md +21 -0
  66. swarmly-0.9.0/swarmly/telegram/roles/qa-tester.md +20 -0
  67. swarmly-0.9.0/swarmly/telegram/roles/researcher.md +17 -0
  68. swarmly-0.9.0/swarmly/telegram/roles/reviewer.md +21 -0
  69. swarmly-0.9.0/swarmly/telegram/roster.py +270 -0
  70. swarmly-0.9.0/swarmly/telegram/selftest.py +405 -0
  71. swarmly-0.9.0/swarmly/telegram/templates/a2a_config.json +8 -0
  72. swarmly-0.9.0/swarmly/telegram/templates/config.example.yaml +66 -0
  73. swarmly-0.9.0/swarmly/telegram/topic_memory.py +228 -0
  74. swarmly-0.9.0/swarmly/telegram/topic_open.py +131 -0
  75. swarmly-0.9.0/swarmly/telegram/topics.py +141 -0
  76. swarmly-0.9.0/swarmly/telegram/wire.py +302 -0
  77. swarmly-0.9.0/swarmly/transports/__init__.py +58 -0
  78. swarmly-0.9.0/swarmly/transports/base.py +149 -0
  79. swarmly-0.9.0/swarmly/transports/folder.py +62 -0
  80. swarmly-0.9.0/swarmly/transports/gdrive.py +206 -0
  81. swarmly-0.9.0/swarmly/transports/git.py +344 -0
  82. swarmly-0.9.0/swarmly.egg-info/PKG-INFO +402 -0
  83. swarmly-0.9.0/swarmly.egg-info/SOURCES.txt +85 -0
  84. swarmly-0.9.0/swarmly.egg-info/dependency_links.txt +1 -0
  85. swarmly-0.9.0/swarmly.egg-info/entry_points.txt +7 -0
  86. swarmly-0.9.0/swarmly.egg-info/requires.txt +27 -0
  87. 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.
@@ -0,0 +1,4 @@
1
+ # The sdist carries the package and its docs; the test suite lives in the repository.
2
+ prune tests
3
+ prune build
4
+ prune a2a
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
+ [![tests](https://github.com/eeftychiou/swarmly/actions/workflows/tests.yml/badge.svg)](https://github.com/eeftychiou/swarmly/actions/workflows/tests.yml)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-purple.svg)](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).