Gateway architecture
Last updated: 2026-01-22
Overview
- A single long‑lived Gateway owns all messaging surfaces (WhatsApp via Baileys, Telegram via grammY, Slack, Discord, Signal, iMessage, WebChat).
- Control-plane clients (macOS app, CLI, web UI, automations) connect to the
Gateway over WebSocket on the configured bind host (default
127.0.0.1:18789). - Nodes (macOS/iOS/Android/headless) also connect over WebSocket, but
declare
role: nodewith explicit caps/commands. - One Gateway per host; it is the only place that opens a WhatsApp session.
- The canvas host is served by the Gateway HTTP server under:
/__mayros__/canvas/(agent-editable HTML/CSS/JS)/__mayros__/a2ui/(A2UI host) It uses the same port as the Gateway (default18789).
Components and flows
Gateway (daemon)
- Maintains provider connections.
- Exposes a typed WS API (requests, responses, server‑push events).
- Validates inbound frames against JSON Schema.
- Emits events like
agent,chat,presence,health,heartbeat,cron.
Clients (mac app / CLI / web admin)
- One WS connection per client.
- Send requests (
health,status,send,agent,system-presence). - Subscribe to events (
tick,agent,presence,shutdown).
Nodes (macOS / iOS / Android / headless)
- Connect to the same WS server with
role: node. - Provide a device identity in
connect; pairing is device‑based (rolenode) and approval lives in the device pairing store. - Expose commands like
canvas.*,camera.*,screen.record,location.get.
Protocol details:
WebChat
- Static UI that uses the Gateway WS API for chat history and sends.
- In remote setups, connects through the same SSH/Tailscale tunnel as other clients.
Connection lifecycle (single client)
mermaidsequenceDiagram participant Client participant Gateway Client->>Gateway: req:connect Gateway-->>Client: res (ok) Note right of Gateway: or res error + close Note left of Client: payload=hello-ok<br>snapshot: presence + health Gateway-->>Client: event:presence Gateway-->>Client: event:tick Client->>Gateway: req:agent Gateway-->>Client: res:agent<br>ack {runId, status:"accepted"} Gateway-->>Client: event:agent<br>(streaming) Gateway-->>Client: res:agent<br>final {runId, status, summary}
Wire protocol (summary)
- Transport: WebSocket, text frames with JSON payloads.
- First frame must be
connect. - After handshake:
- Requests:
{type:"req", id, method, params}→{type:"res", id, ok, payload|error} - Events:
{type:"event", event, payload, seq?, stateVersion?}
- Requests:
- If
MAYROS_GATEWAY_TOKEN(or--token) is set,connect.params.auth.tokenmust match or the socket closes. - Idempotency keys are required for side‑effecting methods (
send,agent) to safely retry; the server keeps a short‑lived dedupe cache. - Nodes must include
role: "node"plus caps/commands/permissions inconnect.
Pairing + local trust
- All WS clients (operators + nodes) include a device identity on
connect. - New device IDs require pairing approval; the Gateway issues a device token for subsequent connects.
- Local connects (loopback or the gateway host’s own tailnet address) can be auto‑approved to keep same‑host UX smooth.
- Non‑local connects must sign the
connect.challengenonce and require explicit approval. - Gateway auth (
gateway.auth.*) still applies to all connections, local or remote.
Details: Gateway protocol, Pairing, Security.
Protocol typing and codegen
- TypeBox schemas define the protocol.
- JSON Schema is generated from those schemas.
- Swift models are generated from the JSON Schema.
Remote access
-
Preferred: Tailscale or VPN.
-
Alternative: SSH tunnel
bashssh -N -L 18789:127.0.0.1:18789 user@host -
The same handshake + auth token apply over the tunnel.
-
TLS + optional pinning can be enabled for WS in remote setups.
Operations snapshot
- Start:
mayros gateway(foreground, logs to stdout). - Health:
healthover WS (also included inhello-ok). - Supervision: launchd/systemd for auto‑restart.
Extension subsystems
Beyond the core Gateway and client architecture, Mayros includes several extension subsystems that plug into the agent loop:
- Token Economy — per-session and daily budget tracking, model pricing catalog, prompt cache, and cost enforcement (soft warnings or hard tool-call blocking).
- Semantic Observability — structured tracing with 5 event types, Prometheus metrics export, and an aggregated query engine for debugging agent behavior.
- Decision Graph — causal chain analysis that builds directed graphs from trace events, enabling root cause analysis of agent decisions.
- LSP Bridge — bridges language servers with Cortex for persistent diagnostics, hover info, go-to-definition, and completions available to agents.
- IoT Bridge — REST bridge to
aingle_minimalIoT nodes with fleet management, polling, and automatic context injection. - Phone Control — temporary command group activation for iOS devices with timed auto-disarm.
- Semantic Skills — skill runtime with manifest parsing, sandbox execution, namespace isolation, and enrichment pipeline.
- Skill Security — 18-layer security architecture protecting against malicious skills.
Each subsystem registers its own tools, hooks, and CLI commands through the plugin system.
Invariants
- Exactly one Gateway controls a single Baileys session per host.
- Handshake is mandatory; any non‑JSON or non‑connect first frame is a hard close.
- Events are not replayed; clients must refresh on gaps.