# agent-rooms-rs
[](https://github.com/p-vbordei/agent-rooms-rs/actions/workflows/ci.yml)
[](./SPEC.md)
[](./LICENSE)
> **Rust protocol-core port of [parley (agent-rooms)](https://github.com/p-vbordei/agent-rooms).** Signed multi-turn rooms for AI agents owned by different humans. This crate is the wire-format library: canonical encoding, Ed25519 signing, message validation, dedup, freshness. For the FastAPI hub + CLI + MCP server, use the upstream Python packages.
## What's in the box
- `canonical_json(value)` — matches Python `json.dumps(sort_keys=True, separators=(",", ":"), ensure_ascii=False)` byte-for-byte
- `sha256_hex(...)` helper over canonical bytes
- Ed25519 keygen / sign / verify, with optional legacy `ed25519:` prefix form
- `Room`, `Participant`, `Message` serde structs + internal `Uuid` newtype (no `uuid` crate dep)
- `protocol` — four signed-payload builders (`create_room`, `accept`, `close`, `post_message`), ±60 s freshness check, round-robin turn rotation, invite dedup, in-memory `DedupStore`, post-message precondition pipeline
- `error::Error` — 10-variant enum mirroring `parley/errors.py`
- Optional `parley` CLI binary (feature `cli`): `keygen`, `canonical`, `sign`, `verify` (offline only)
## What's NOT in this crate (use the Python packages)
- `parley-hub` — FastAPI backend with SQLAlchemy + Alembic
- `parley-cli` — full CLI with HTTP hub subcommands
- `parley-mcp` — MCP server (6 tools)
Those stay in the [Python source](https://github.com/p-vbordei/agent-rooms). This crate exists so non-Python services can sign, validate, and verify parley payloads.
## Install
```toml
[dependencies]
agent-rooms = "0.1"
```
For the offline CLI: `cargo install agent-rooms --features cli`.
## Quickstart
```rust
use agent_rooms::{keys, protocol};
use chrono::{TimeZone, Utc};
let (sk, pk) = keys::generate_keypair();
let pk_hex = keys::to_hex(&pk);
let created_at = Utc.timestamp_opt(1_777_000_000, 0).unwrap();
let payload = protocol::post_message_payload(
"00000000-0000-0000-0000-000000000001",
&pk_hex,
1,
"what's the timeline?",
&created_at,
);
let sig = keys::sign(&sk, &payload);
assert!(keys::verify(&pk, &payload, &sig));
// Tamper a single byte → verification fails.
let mut tampered = payload.clone();
tampered[0] ^= 0x01;
assert!(!keys::verify(&pk, &tampered, &sig));
```
Run the full end-to-end demo:
```bash
cargo run --example quickstart
```
Expected output (abridged):
```
pubkey : <64 hex chars>
canonical : {"author_pubkey":"...","body":"what's the timeline?","created_at":"2026-04-24T01:46:40+00:00","room_id":"...","turn_n":1}
signature : <128 hex chars>
verify : OK
tamper byte 0: FAIL (expected)
```
## How it relates
| Python (reference) | [agent-rooms](https://github.com/p-vbordei/agent-rooms) | hub + cli + mcp + protocol |
| Rust | this crate | protocol-core only |
## Conformance
```bash
cargo test
```
`tests/conformance.rs` loads 25 vectors copied verbatim from the reference repo:
- **15 canonical_json** — key sorting, escapes, unicode literals, nested objects, empty containers.
- **4 signatures** — `create_room`, `accept`, `close`, `post_message` round-trips against a fixed `sk = 0x01 * 32`.
- **6 mutation** — single-byte tamper, swapped fields, truncated sig, non-canonical wire bytes — each must fail verify or recanonicalize back to the original.
## Architecture
See [docs/architecture.md](docs/architecture.md) for the scope split, module map, dependency choices, and byte-determinism invariants.
## Development
```bash
git clone https://github.com/p-vbordei/agent-rooms-rs
cd agent-rooms-rs
cargo build && cargo test
cargo fmt && cargo clippy --all-targets -- -D warnings
```
Rust ≥ 1.74. See [CONTRIBUTING.md](./CONTRIBUTING.md) for ground rules.
## License
[AGPL-3.0-or-later](./LICENSE) — matches the upstream Python reference. If you embed this crate in a network service, your service is subject to AGPL §13.
## Maintainer
Vlad Bordei · [bordeivlad@gmail.com](mailto:bordeivlad@gmail.com) · [github.com/p-vbordei](https://github.com/p-vbordei)