Back to docs
Tunnels and Relay

The tunnel is the bridge between Midfleet Control and live agent runtimes.

Cloudflare routes public console URLs to the runtime host, while the relay accepts authenticated spawn requests and starts local agent processes.

How a request reaches an agent

HopExamplePurpose
Midfleet app/APIhttps://midfleet.ai and https://app.midfleet.aiOperator UI, API calls, workflow state, and agent registry.
Cloudflare tunnel hostnamehttps://console-<workspace>.midfleet.io
https://console-<workspace>.midfleet.io/<workspace>/agents/<agent-id>/global/health
Public entrypoint for terminal/chat/health routes. The workspace slug selects the console host, for example workspace shahi uses https://console-shahi.midfleet.io. Confirm the exact value from consoleRouter.publicBaseUrl in runtime config.
Console router127.0.0.1:<listenPort>Routes workspace and agent path prefixes to serve-backed OpenCode sessions.
Agent serve port127.0.0.1:4341Per-agent route for chat, terminal, and health checks.
Relayhttps://relay-<workspace>.midfleet.io/spawn
http://127.0.0.1:8787/spawn
Receives authenticated spawn requests from the hub and starts safe midfleet start commands. The workspace slug selects the public relay host, for example workspace shahi uses https://relay-shahi.midfleet.io/spawn.

Use runtime config, not guessed hostnames

midfleet config pull-runtime
midfleet config show

# Values to mirror in Cloudflare and local processes:
# consoleRouter.publicBaseUrl, for example https://console-shahi.midfleet.io
# consoleRouter.bindHost
# consoleRouter.listenPort
# consoleRouter.routePrefix
# relay.bindHost
# relay.listenPort
# auth.relay_token, stored locally as MIDFLEET_RELAY_TOKEN

Configure Cloudflare tunnel ingress so the public console hostname forwards to the console router local bind address and port. Configure the relay hostname to forward to the local relay port and protect spawn requests with the relay token.

# Shape only; use your provisioned tunnel ID and hostname.
tunnel: <tunnel-id>
credentials-file: /etc/cloudflared/<tunnel-id>.json
ingress:
 - hostname: console-<workspace>.midfleet.io
 service: http://127.0.0.1:<consoleRouter.listenPort>
 - hostname: relay-<workspace>.midfleet.io
 service: http://127.0.0.1:<relay.listenPort>
 - service: http_status:404

Start and inspect relay

export MIDFLEET_RELAY_TOKEN=<relay-token-from-runtime-bundle>

midfleet internal relay start \
 --host 127.0.0.1 \
 --port 8787 \
 --daemon

midfleet internal relay status
midfleet internal relay health

The relay only accepts safe midfleet start ... or legacy agentmesh start ... spawn commands. If the hub cannot spawn agents, verify the hub uses https://relay-<workspace>.midfleet.io/spawn and the same relay token that the runtime host is using.

Relay endpointAuthUse
GET /healthzNone on localhost; protect public route with Cloudflare Access.Liveness check.
GET /readyzNone on localhost; protect public route with Cloudflare Access.Readiness check; fails when hub URL, workspace, or API key is missing.
GET /statusNone on localhost; protect public route with Cloudflare Access.Shows PID, host, port, and Node version.
POST /spawnx-midfleet-relay-token: <relay-token>Hub spawn path. Legacy x-agentmesh-relay-token is accepted during migration.
curl -i http://127.0.0.1:8787/healthz
curl -i http://127.0.0.1:8787/readyz

curl -X POST https://relay-<workspace>.midfleet.io/spawn \
 -H "x-midfleet-relay-token: $MIDFLEET_RELAY_TOKEN" \
 -H "content-type: application/json" \
 -d '{
 "name": "worker-a",
 "command": "midfleet start --name worker-a --worker --serve --serve-port 4341"
 }'

Expected checks

  • Public console health route returns a non-HTML API response.
  • Cloudflare Access policy allows the intended operator or service token.
  • Runtime config matches the currently deployed tunnel hostname and local listen ports.
  • Each serve-backed agent has a unique port and route.
  • Control can open chat or terminal without watching raw SSH sessions.