Prerequisites for both:
- An agent and its Agent Token. See Create and connect an agent.
- A Cloudflare account. Both paths deploy with
wrangler. - Node 20 or newer.
Add Relay as a channel to a Think agent
Think builds a channel by wrapping a Chat SDK adapter inmessengerChannel().
That is how its own Telegram channel is built. Relay publishes a Chat SDK
adapter, so Relay is one more channel: your agent, its tools, and its memory
stay exactly as they are.
1
Install the adapter
0.2.1 or newer.2
Declare the channel
The channel id names the route. Called
relay, it serves
POST /messengers/relay/webhook.src/index.ts
3
Set the secrets and deploy
4
Set the webhook receiver
signing_secret from the response, then set it:5
Message your agent
Open Relay, find your agent, and send it a message. It replies.
An unsigned or forged delivery to the webhook route returns
401 before
Think parses anything.
Two Relay rules shape what arrives on the other end. One send is one message, so
the adapter buffers a streamed turn and posts the finished text once instead of
editing a draft bubble into place. In a group, the agent is an ordinary member:
it receives every message from the sequence it joined at, and each reply is an
ordinary send.
A runnable version of this is
examples/think-channel
in the starter repository.Deploy the starter
Deploy relay-agent-starter to answer Relay conversations from a Cloudflare Agent. Each conversation gets its own agent instance, its own SQLite ledger, and its own alarm, so a reply survives an evicted isolate. Replace one function with your model call and it is your agent.The starter is developed in the public
relaymessenger/relay-agent-starter
repository. It depends on Cloudflare’s agents
package and nothing of Relay’s own beyond the HTTPS API documented on this site.1
Scaffold or deploy the starter
Use the one-click deploy:Deploy to CloudflareOr scaffold locally, then deploy:Note the deployed URL. It looks like
https://relay-agent.<your-subdomain>.workers.dev.2
Set the Agent Token
The deploy button prompts for it. Locally:
3
Set the webhook receiver
Point Relay at Save
/webhooks/relay on the deployed Worker:signing_secret from the response. Relay never returns it again.4
Set the signing secret and redeploy
5
Message your agent
Open Relay, find your agent, and send it a message. It replies.
GET /healthz on the Worker returns {"ok":true} when it is up.What it uses from the Agents SDK
The starter is a normal Cloudflare Agents project.RelayConversationAgent
extends the SDK’s Agent class, and each row below is a stock part of the
agents package doing the job it was built for.
The instance name is a digest of
chat_id, so every event for one
thread reaches one object and one ledger.
What the starter handles for you
Each row is a contract from these docs that the starter implements.The ledger stores identifiers only. Message text is re-read from Relay at reply
time rather than parked in agent storage.
Write your agent
Everything you change lives in one function,generateReply at the bottom of
src/agent.ts:
src/agent.ts
text is the whole user turn, with the messages of a burst joined back in
order. mediaCount is how many media parts came with it, for a model that
cannot open them yet.
Call any model from there. A Workers AI example is commented directly above the
function and needs no extra secrets: add the ai binding to wrangler.jsonc,
uncomment AI in src/env.ts, and swap the return.
Secrets
RELAY_API_ORIGIN is a plain var, already set to https://api.relayapp.im.
Running it as a plain Worker
The starter needs the Agents SDK, because the ledger, the state, and the alarm are the SDK’s. If you want a Relay backend with none of that, answer the webhook from any HTTPS route you already run and send replies withPOST /v1/messages.
Webhooks has the verification steps. You then own the
redelivery, idempotency, and turn coalescing this page’s table lists.
Next steps
- Webhooks for registration, verification, and secret rotation
- Sending messages for every part type beyond text
- Group conversations for how an agent takes part in a group
- Integrations for every way to connect an agent

