8. Mesh federation — laptop + VPS, one team
Difficulty: advanced · Time: 20 minutes · Ends at: two machines running AgentX, sharing one agent roster, delegating tasks across the mesh
Scenario
Your laptop runs marketing and support agents — they handle Telegram traffic while you work. A VPS runs devops and qa-forensics — they handle CI webhooks, scheduled deploys, and production incidents 24/7. You want:
- One logical team across both machines
- Cross-machine delegation (
@devopsworks no matter which node you're chatting on) - Wiki syncing so both machines share the knowledge base
Why Tailscale / private network
Agent-to-agent traffic is un-TLS'd JSON over HTTP. You must not expose the mesh port to the public internet. Tailscale gives every machine a stable private IP (100.x.x.x) with WireGuard encryption. WireGuard, Nebula, or a VPN also work. We'll assume Tailscale.
Prerequisites
- Tailscale (or equivalent) installed on both machines, both machines online on the same tailnet
- AgentX installed on both (see install)
- A shared
MESH_TOKENsecret in both.envfiles — required for peer auth
Config — Machine A (laptop)
{
"node": {
"id": "laptop",
"bind": "0.0.0.0:18800"
},
"agents": {
"marketing": { "name": "Marketing", "workspace": "./agents/marketing", "tier": "claude-code", "model": "claude-sonnet-4-6", "mentions": ["@marketing"] },
"support": { "name": "Support", "workspace": "./agents/support", "tier": "claude-code", "model": "claude-sonnet-4-6", "mentions": ["@support"] }
},
"mesh": {
"enabled": true,
"peers": [
{ "name": "clawd-server", "url": "http://100.67.108.119:19900", "token": "${MESH_TOKEN}" }
],
"discovery": "static",
"healthCheck": { "interval": 60, "timeout": 10 }
}
}Config — Machine B (VPS, e.g. clawd-server)
{
"node": {
"id": "clawd-server",
"bind": "0.0.0.0:19900"
},
"agents": {
"devops": { "name": "DevOps", "workspace": "./agents/devops", "tier": "claude-code", "model": "claude-sonnet-4-6", "mentions": ["@devops"] },
"qa-forensics": { "name": "QA Forensics", "workspace": "./agents/qa-forensics", "tier": "claude-code", "model": "claude-sonnet-4-6", "mentions": ["@qa"] }
},
"mesh": {
"enabled": true,
"peers": [
{ "name": "laptop", "url": "http://100.x.x.x:18800", "token": "${MESH_TOKEN}" }
],
"discovery": "static",
"healthCheck": { "interval": 60, "timeout": 10 }
}
}Both .env files:
MESH_TOKEN=<long random string, same on both machines>Start both daemons
# Laptop
agentx daemon start
# VPS (over SSH, or via systemd)
agentx daemon start --detachOn startup each node fetches the other's agent card from GET /.well-known/agent-card.json:
{
"node": "clawd-server",
"agents": [
{ "id": "devops", "name": "DevOps", "mentions": ["@devops"], "skills": ["deploy", "incident"] },
{ "id": "qa-forensics", "name": "QA Forensics", "mentions": ["@qa"], "skills": ["trace", "root-cause"] }
]
}The router merges local agents + remote agents into one landscape. @devops on the laptop now routes over HTTP to the VPS.
Verify the mesh
agentx mesh listNAME URL STATUS AGENTS
clawd-server http://100.67.108.119:19900 ✓ ok devops, qa-forensicsSend a task across:
agentx daemon send devops "Check disk free on /var/log" --peer clawd-serverOr from inside a chat on the laptop, mention @devops — the router detects it's a remote agent and forwards via HTTP with SSE streaming of the response.
Cross-mesh messaging from anywhere
curl -X POST http://localhost:18800/mesh/task \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MESH_TOKEN" \
-d '{"peer":"clawd-server","agent":"devops","message":"Run health check"}'The response is a streamed SSE feed of the remote agent's reply.
Wiki federation
Each agent has its own wiki. With mesh enabled, you can sync raw entries from peers:
agentx wiki sync # pulls from all configured peers
agentx wiki sync --peer clawd-server
agentx wiki absorb # compile into articles locallyOr serve a federated view:
agentx wiki serve --port 4200 # auto-discovers peers from configOpen http://localhost:4200 to browse local + remote agent wikis in one Wikipedia-style UI.
Security notes
- Never expose the mesh port to the public internet. Bind to
100.x.x.x(Tailscale) or127.0.0.1with a reverse SSH tunnel. MESH_TOKENmust be long and random (≥32 bytes). Rotate by updating both.envfiles and restarting.- Tailscale ACLs can restrict which tailnet nodes may reach the mesh port.
Troubleshooting
✗ clawd-server — Connection refused→ daemon down on remote, firewall blocks the port, or Tailscale not connected✗ clawd-server — 401→MESH_TOKENmismatch between the two.envfiles- Remote agent mentions unknown → agent cards don't refresh instantly; wait one health-check interval (default 60s) or restart
What's next
- Add daily wiki absorb to both nodes → Journey 2 — Scheduled reports (same pattern,
prompt: "node dist/cli.js wiki absorb --max 20") - All mesh + wiki CLI flags → Reference — CLI