Skip to main content
A relay transport lets a lightweight connector process own the Telegram/Discord/WhatsApp socket while a separate headless gateway handles all agent logic — enabling NAT-friendly hosting, one gateway fronting many connectors, and lossless scale-to-zero.
The user messages on a chat platform; the connector relays events to a private gateway that runs the agent.

Quick Start

1

In-Process (Default — No Change Needed)

Without a relay transport, the bot adapter runs in the same process as the gateway. This is the default and requires no extra config:
2

Out-of-Process via Relay Transport

Pass a transport= to the Bot constructor to use a remote connector. The transport= parameter is optional and backward-compatible:
The relay path opts out of Bot-level supervision automatically because the transport owns reconnect and scale-to-zero dormancy — you never need to set enable_supervision=False yourself. See Auto-reconnect on long-running-bots.
3

Implement a custom RelayTransport

4

Enable scale-to-zero

5

CLI Gateway with Relay


How It Works

At handshake time the connector attests a CapabilityDescriptor — the gateway uses this to adapt streaming, markdown, and message-length behaviour to the actual platform being fronted, even though it never touches the platform socket directly.

CapabilityDescriptor Fields

The connector attests these capabilities at handshake time:

RelayTransport Protocol

Implement these methods to create a custom transport:

When to Use a Relay


Scale-to-Zero with go_dormant()

When the gateway scales to zero, call go_dormant() to pause inbound dispatch:
The connector keeps the platform socket open and buffers inbound events while the gateway is dormant. When the gateway wakes, it drains the backlog losslessly — no messages are dropped during the idle period.

Best Practices

The relay transport authenticates with a token passed at connect() time. Use a long, random secret and rotate it with your other infrastructure credentials.
disconnect() tears down the connection and the connector stops buffering. go_dormant() keeps the connector alive and buffering, so events that arrive while the gateway is sleeping are drained on wake.
Always use the CapabilityDescriptor returned by connect() to configure your delivery layer. Never hard-code platform limits — the connector is the authority on what the actual platform supports.
Omit transport= entirely to keep the existing in-process behaviour. No existing code needs to change; just add the parameter when you need an out-of-process connector.

Gateway Overview

How the gateway connects agents to channels

Gateway Scale-to-Zero

Idle dormancy and wake-up behaviour

Durable Outbound Delivery

Retry and DLQ for all channels

Multi-Channel Bots

One gateway, many platforms