Skip to main content
hexgate serve takes the same module:attr spec as hexgate register. The CLI imports the agent, derives the manifest in one call, auto-registers on the platform (idempotent — content-hash short-circuits no-ops), fetches the operator’s policy from the cloud, and opens the WebSocket relay so the dashboard’s Playground can drive it. Policy edits in /policies take effect at the next chat-turn boundary.
The bridge works like Cloudflare Tunnel or ngrok — your local agent runtime is reachable from the dashboard without exposing a port.

Behaviour

  • Loads the agent object from the module:attr spec — same form as hexgate register. The agent’s name, tools, model, and system prompt come from the object directly (no flags duplicating what’s already in code).
  • Auto-registers the manifest on first run via POST /v1/agents (idempotent). Skip with --no-auto-register for CI / deliberate deployments.
  • Fetches the operator’s policy from GET /v1/agents/{name}. Local code is authoritative for code; the platform is authoritative for policy.
  • Connects wss://${HEXGATE_API_URL}/v1/serve with the bearer percent-encoded into the WebSocket subprotocol (the WS handshake grammar doesn’t allow = padding in plain headers). Server echoes hexgate.v1 to confirm the contract.
  • Sends a hello frame announcing the agent name (the dashboard’s “Serving” indicator reads this).
  • On each inbound chat message, refreshes the active policy before running. Refresh is an If-None-Match round-trip: a 304 reuses the cached WASM module, a 200 swaps in the new bundle. Dashboard edits take effect at turn boundaries without restarting the process or re-wrapping the tools.
  • Streams every StreamEvent (text deltas, tool start/end, run end) back as JSON.
  • Routes approval_required tool calls per --approval-mode (default ask): ask sends the request to the connected Playground for a human to decide; auto-approve / auto-deny skip the round-trip and apply the outcome directly (script / CI mode).
  • Reconnects with exponential backoff on socket drop.
There is no HEXGATE_AGENT_NAME env var, --agent flag, or --use flag on serve — the module:attr spec carries everything. The name lives in the agent’s .name attribute (or the name= kwarg you passed to create_react_agent / create_agent).

Env vars

See the platform overview for the full three-terminal local setup.