# Ruflo Federation — User Guide > Cross-installation agent peering with built-in cost limits, circuit breaker, signed envelopes, and (as of alpha.14) opt-in WireGuard mesh layer governed by federation trust. This guide walks through what federation is, when to use it, and how to set it up. For the architectural backstory and per-phase release notes see the [companion gist](https://gist.github.com/ruvnet/3b5111a2ea7e450ff262ce96e88560bf). ## What federation does Federation lets two or more Ruflo installations — your mac, a server, a teammate's laptop — discover each other, exchange signed manifests, and send messages between them with bounded cost and per-peer trust gates. Key properties: - **Ed25519 identity** — each node holds a private key; peers exchange Ed25519-signed manifests. No central directory. - **Five-level trust ladder** — `UNTRUSTED → VERIFIED → ATTESTED → TRUSTED → PRIVILEGED`. Each level unlocks a wider set of operations (`discovery`, `send`, `share-context`, `remote-spawn`, …). - **Per-peer budget + circuit breaker** — bounded tokens/USD per peer. Sustained failures auto-SUSPEND; further failures EVICT. ADR-097. - **PII pipeline + audit trail** — every cross-peer envelope passes through PII detection. Every state transition is auditable. - **Real wire transport** — WSS with permessage-deflate compression, optional cert pinning, stream multiplexing. ADR-104. - **Optional WG mesh layer** — opt-in opaque packet-layer reachability that follows federation trust changes. Compromised peer auto-isolated at L3 when the breaker fires. ADR-111. ## When to use federation | Use case | Fit | |---|---| | Two laptops collaborating on a project, want bounded cost sharing + audit | ✅ | | Personal home server agent ↔ travel laptop | ✅ | | Team of 5 engineers sharing memory/skills across machines | ✅ | | Mobile / Windows / sub-50 peers with NAT issues | ✅ over Tailscale + federation | | Public-internet exposed agent endpoints | ✅ with TLS cert pinning (ADR-107) | | Internal HR/finance multi-agent workflow with strict access tiers | ✅ with PRIVILEGED gating + audit | | Replacing Slack/Discord — no | ❌ federation is for agent-to-agent, not human chat | | Untrusted-internet messaging without identity vetting | ❌ — trust ladder must be bootstrapped out-of-band | ## Quick start ### 1. Install the plugin ```bash npx ruflo@latest # if you don't have it yet npx ruflo plugins install @claude-flow/plugin-agent-federation ``` Or directly via npm: ```bash npm i @claude-flow/plugin-agent-federation@latest # currently 1.0.0-alpha.14 ``` ### 2. Initialize a node ```bash npx claude-flow@v3alpha agent spawn -t federation --name fed-1 ``` Or via the MCP tool `federation_init`: ```json { "tool": "federation_init", "params": { "nodeId": "my-mac", "endpoint": "ws://my-mac.tailnet:9100", "agentTypes": ["coder", "tester"] } } ``` This generates an Ed25519 keypair (persisted to `.claude-flow/federation/keys-.json`, mode 0600), publishes a signed manifest, and starts the discovery service. ### 3. Join a peer ```json { "tool": "federation_join", "params": { "endpoint": "ws://other-host.tailnet:9100" } } ``` The handshake exchanges manifests, verifies Ed25519 signatures, and establishes the initial trust level (`UNTRUSTED` until the trust-evaluator records enough successful interactions to promote). ### 4. Send a message ```json { "tool": "federation_send", "params": { "targetNodeId": "other-host", "messageType": "agent-handoff", "payload": { "task": "Investigate the failing integration test" } } } ``` Budget and trust gates apply: if the peer is below `ATTESTED`, only `discovery`/`status`/`ping` go through. If the breaker has the peer SUSPENDED, the send short-circuits with `PEER_SUSPENDED`. ## MCP tools at a glance | Tool | What it does | Trust gate | |---|---|---| | `federation_init` | Initialize this node | — | | `federation_join` | Join a peer by endpoint | — | | `federation_peers` | List discovered peers | — | | `federation_send` | Send a typed message to a peer | per-peer (varies) | | `federation_query` | Synchronous query → response | `ATTESTED+` | | `federation_status` | Current node + peer trust summary | — | | `federation_trust` | View / adjust trust levels | operator | | `federation_audit` | Read audit log | operator | | `federation_breaker_status` | Per-peer state, when changed, why | — | | `federation_evict` | Operator manual evict | operator | | `federation_reactivate` | Operator manual reactivate | operator | | `federation_report_spend` | Report cost of a completed call | integrator | | `federation_consensus` | Federated proposal across peers | varies | | **`federation_wg_status`** | (ADR-111) Per-peer mesh state | — | | **`federation_wg_attest`** | (ADR-111) Operator-signed witness entry | operator | | **`federation_wg_keyrotate`** | (ADR-111) Rotate WG keypair | operator + `confirm:true` | ## Trust levels — what each unlocks | Level | Capabilities (federation) | WG reachability (if ADR-111 active) | |---|---|---| | `UNTRUSTED` | `discovery` | Excluded from mesh — drop all | | `VERIFIED` | `+ status, ping` | Discovery port (9100) only | | `ATTESTED` | `+ send, receive, query-redacted` | + federation messaging (9101-9199) | | `TRUSTED` | `+ share-context, collaborative-task` | + ssh (22), services (80/443) | | `PRIVILEGED` | `+ full-memory, remote-spawn` | Full mesh | Trust is earned via repeated successful interactions (the `TrustEvaluator` tracks score + interaction count). Promotion thresholds are documented in `domain/entities/trust-level.ts`. ## Circuit breaker If a peer's failure ratio or cost spend exceeds the policy: ``` ACTIVE → SUSPENDED → EVICTED ↑ │ └─────────operator-only─────────┘ ``` - **SUSPEND**: peer's outbound sends short-circuit (`PEER_SUSPENDED`). Existing sessions continue; new sends rejected. Auto-eviction on continued failures. - **EVICT**: peer's outbound sends short-circuit (`PEER_EVICTED`). Session terminated. Operator must explicitly reactivate. - The breaker **does not auto-reactivate**. The integrator's health probe is responsible for confirming the peer is healthy and calling `federation_reactivate`. Policy is tunable; defaults are conservative (50+ samples needed before suspend, high failure ratio threshold). ## ADR-111 — WireGuard mesh (opt-in, since alpha.14) Federation today treats network connectivity as the integrator's problem (Tailscale, LAN, wss://+pinning). That works but trust changes don't propagate to the L3 layer — a peer EVICTED in federation stays in the tailnet until an admin manually removes it. ADR-111 closes that gap with an optional in-tree WG mesh: - WG keypair generated alongside the federation key - Mesh IP derived deterministically from `nodeId` (sha256 → `10.50.0.0/16` host portion, with collision-handling probe loop) - WG identity published inside the same Ed25519-signed manifest - Federation breaker SUSPEND → `wg set ... allowed-ips ""` (soft-block at L3) - Federation breaker EVICT → `wg set ... remove` (terminal) - Operator reactivate → AllowedIPs restored - Each mutation entered into an append-only Ed25519-signed witness chain **Phases shipped in alpha.14:** - Phase 1 — Manifest extension + key generation - Phase 2 — `WgMeshService` (no shell — emits configs + commands) - Phase 3 — Coordinator/breaker wiring - Phase 4 — Firewall projection (`nftables` / `pf`) — PR #1895 - Phase 5 — Witness attestation chain — PR #1895 - Phase 6 — Operator MCP tools — PR #1895 **Phase 7 — operator-mediated**: See [`docs/federation/phase7-mesh-bringup.md`](./phase7-mesh-bringup.md) for the cross-OS bringup procedure (mac ↔ ruvultra over Tailscale). ### Enabling ADR-111 Set `config.wgMesh: true` in your federation plugin config, then run the staging helper: ```bash node v3/@claude-flow/plugin-agent-federation/scripts/phase7-stage.mjs \ ``` The script generates `/tmp/adr-111-stage/`: - `wg-key-.json` (mode 0600 — your private WG key) - `ruflo-fed.conf` (the wg-quick interface config) - `ruflo-fed.nft` or `ruflo-fed.pf` (firewall projection) After review, the operator manually activates: ```bash sudo install -m 0600 /tmp/adr-111-stage/ruflo-fed.conf /etc/wireguard/ruflo-fed.conf # Linux: sudo nft -f /tmp/adr-111-stage/ruflo-fed.nft # macOS: sudo pfctl -a ruflo-fed -f /tmp/adr-111-stage/ruflo-fed.pf sudo wg-quick up ruflo-fed ``` ## Using `claude -p` headless mode `claude -p` (print/pipe mode) can drive federation MCP tools non-interactively. Each invocation processes its prompt and exits — for a persistent federation listener, run a long-lived MCP server instead. **On the originating host** (mac mini): ```bash claude -p --model haiku --max-budget-usd 0.20 --output-format text \ "Federation MCP tools to verify cross-machine peering health: name 3. One line." # → Three Federation MCP tools for peering health verification: # federation-init (keypair generation), federation-status (peers/trust/metrics), # federation-audit (compliance filtering). ``` **On the peer host (ruvultra)** — requires interactive `/login` first since `claude -p` reads stored credentials: ```bash # First time only — operator-mediated: claude # then /login # After that: claude -p --model haiku --max-budget-usd 0.20 \ "Run federation_status MCP and report peer count." ``` **Workflow for cross-machine task handoff:** ```bash # Host A — kick off a federated task: claude -p --model sonnet --output-format json --resume \ "Use federation_send to dispatch this task to ruvultra: analyze the failing test" # Host B (ruvultra) — receive + work: claude -p --resume "Continue handling the federated task" ``` The federation plugin handles signing, PII gating, breaker, and audit on every send. The two `claude -p` invocations don't share state directly — they communicate exclusively through the federation envelope channel. ## Anti-goals — when **NOT** to use federation - **Replacement for Slack/Discord.** Federation moves agent envelopes, not human chat. - **Public internet without identity vetting.** Trust ladder bootstrapping is your responsibility. - **NAT traversal magic.** Use Tailscale (or Headscale) for that; federation rides on top. - **A general-purpose RPC framework.** It's specifically for AI agents with cost-aware budgeting. ## Where things live | What | Path | |---|---| | Plugin source | `v3/@claude-flow/plugin-agent-federation/src/` | | Tests | `v3/@claude-flow/plugin-agent-federation/__tests__/` | | ADRs | `v3/docs/adr/ADR-{097,104,105,106,107,109,110,111}-*.md` | | Phase 7 staging script | `v3/@claude-flow/plugin-agent-federation/scripts/phase7-stage.mjs` | | Witness signing | `plugins/ruflo-core/scripts/witness/` | ## Releases | Version | What landed | |---|---| | `1.0.0-alpha.9` | First user-visible release — see [announcement gist](https://gist.github.com/ruvnet/3b5111a2ea7e450ff262ce96e88560bf) | | `1.0.0-alpha.10` | ADR-097 Phases 2.a-4 + ADR-104 transport + ADR-109 inbound dispatcher | | `1.0.0-alpha.11-12` | ADR-109 sig verify, ADR-104 compression, ADR-107 TLS cert pinning | | `1.0.0-alpha.13` | ADR-104 stream multiplexing + ADR-110 MemorySpendReporter | | **`1.0.0-alpha.14`** | **ADR-111 Phases 1-3 (WG mesh foundation)** | | `1.0.0-alpha.15` (in flight) | ADR-111 Phases 4-6 (firewall + witness + MCP tools) — PR #1895 | ## Related ADRs - [ADR-097](../../v3/docs/adr/ADR-097-federation-budget-circuit-breaker.md) — budget + circuit breaker - [ADR-104](../../v3/docs/adr/ADR-104-federation-wire-transport.md) — WSS transport + multiplexing - [ADR-105](../../v3/docs/adr/ADR-105-federation-v1-state-snapshot.md) — state snapshot/replay - [ADR-106](../../v3/docs/adr/ADR-106-peer-discovery.md) — discovery mechanisms - [ADR-107](../../v3/docs/adr/ADR-107-federation-tls.md) — TLS + cert pinning - [ADR-109](../../v3/docs/adr/ADR-109-federation-inbound-dispatcher.md) — inbound dispatch + sig verify - [ADR-110](../../v3/docs/adr/ADR-110-federation-memory-spend-reporter.md) — production SpendReporter - [**ADR-111**](../../v3/docs/adr/ADR-111-federation-wg-mesh.md) — **WG mesh layer** ## Support - Issues: https://github.com/ruvnet/ruflo/issues - Tracking issue (ADR-111): [#1879](https://github.com/ruvnet/ruflo/issues/1879) - Federation gist (current through alpha.14): https://gist.github.com/ruvnet/3b5111a2ea7e450ff262ce96e88560bf - ADR-111 deep-dive gist: https://gist.github.com/ruvnet/c640fc71c7a6ced37908e645d5db84c5