ATalk README.md
Rendered verbatim from the public MIT baseline Gene7-Ai/ATalk v0.3.0a2. Markdown shown as plain text for now.
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/brand/atalk-lockup-dark.png">
<img src="docs/brand/atalk-lockup-light.png" width="560" alt="ATalk — Agent 协作通信">
</picture>
</p>
# ATalk
*by Gene7 — a message bus built for a family of AI agents.*
ATalk is a small, reliable message bus for AI agents (and the humans who run them).
It is built for the case where several agents live on different machines, must never
silently lose a message, and must be able to prove to each other that a message was
not only delivered but actually acted on.
**Status: early-stage / pre-release (0.3.0a2).** The server, protocol, adapters and
tooling are in daily production use by the authors. The human-facing clients are still
under development and are published here for reference only.
## What is done
- **Core communication** — JSON over HTTP, a durable event log, a server-assigned
`id` recovery cursor, a per-source monotonic `seq`, idempotent `event_id`, and an
SSE wake stream (`GET /stream`) so online agents react immediately while polling is
only a recovery path.
- **`received` / `applied` dual ACK** — every event carries two acknowledgements:
*received* (it landed in the target's inbox) and *applied* (the target actually did
the work). Senders can query `GET /acks` for either. This is the distinction that
makes "did you get it" and "did you do it" two different, auditable questions.
- **Raft high availability** — the `rqlite` backend runs the event log on a three-node
Raft ledger; the SQLite backend is for single-node and development use. Both expose
the same API and pass the same tests.
- **Authentication and authority** — per-peer tokens, token rotation with a grace
window, device tokens with `full` or `notify` scope and single-token revocation,
command tokens with an explicit grant table, an audit log, and an outbound target ACL
for restricted peers.
- **Adapters** — a generic HTTP adapter, a file-inbox adapter for agents that read a
directory, adapters for OpenClaw runtimes (persistent thread or one-shot), a
chat-HTTP adapter for simple `/chat` services, a tmux adapter, and a stdout adapter.
An optional `--wait-event-driven` mode keeps waiting tasks durable without polling
the model.
- **Task, rescue and presence tooling** — a task-ledger helper (`tools/tasklib.py`),
a whitelist-driven rescue executor (`tools/rescue_executor.py`) that runs recovery
commands on behalf of a peer that has lost its own agent, and a presence heartbeat
(`tools/atalk_presence.sh`). The detailed written conventions are being generalized
and are held back from this snapshot.
## What is not done
- **Human client.** `clients/web` (a PWA) works against a running server but is
unpolished, has no packaging, and changes often. A desktop (Electron) client
exists in the private tree and is held back from this snapshot until generalized.
- Push notifications, multi-device UX, sent-history views, federation between
independent ATalk deployments, and a hosted-service story. See `STATUS.md`.
## Quick start (single node, SQLite)
```bash
git clone <this repo> atalk && cd atalk
python3 -m atalk.cli --db /tmp/atalk.db init
python3 -m atalk.cli --db /tmp/atalk.db peer-add alice --token tok-alice --role agent --platform demo
python3 -m atalk.cli --db /tmp/atalk.db peer-add bob --token tok-bob --role agent --platform demo
python3 -m atalk.server --db /tmp/atalk.db --host 127.0.0.1 --port 7070
```
Then send, receive and acknowledge one message (the same flow is scripted in
`examples/quickstart.sh`):
```bash
curl -X POST http://127.0.0.1:7070/events -H 'Authorization: Bearer tok-alice' \
-H 'Content-Type: application/json' \
-d '{"source":"alice","target":"bob","type":"message","event_id":"<uuid>","payload":{"text":"hello"}}'
curl 'http://127.0.0.1:7070/events?target=bob&since_id=0&limit=10&state=pending' -H 'Authorization: Bearer tok-bob'
curl -X POST http://127.0.0.1:7070/ack -H 'Authorization: Bearer tok-bob' -H 'Content-Type: application/json' \
-d '{"agent_id":"bob","event_id":"<uuid>","ack_type":"received"}'
```
Requires Python 3.11+ and no third-party packages. For the Raft backend install
[rqlite](https://rqlite.io), initialize the cluster schema once (see
`docs/OPERATIONS.md`), then start the server with
`--backend rqlite --rqlite-endpoints https://n1:4001,https://n2:4001,https://n3:4001`.
## Layout
| Path | Contents |
|---|---|
| `atalk/` | server, storage backends (`storage.py` SQLite, `raftsql.py` rqlite), core logic, CLI, adapters, inbox tool, `migration.py` (SQLite→rqlite tool), `schema.sql` |
| `docs/PROTOCOL.md` | wire protocol and endpoint reference |
| `docs/OPERATIONS.md` | running it as a service, backups, token rotation |
| `deploy/` | sample systemd units and timers |
| `examples/` | example env, ACL, whitelist and the quick-start script |
| `tools/` | rescue executor, task ledger helpers, presence heartbeat |
| `tests/` | unit and adapter tests (`python3 -m unittest discover -s tests`) |
| `clients/web` | early-stage human client (PWA) |
## Security
Tokens are bearer secrets: keep them in `0600` env files, never on a command line.
See `SECURITY.md` for the threat model, what is and is not protected, and how to
report a vulnerability.
## License
MIT, Copyright (c) 2026 Gene7. See `LICENSE`.