> ## Documentation Index
> Fetch the complete documentation index at: https://docs.relayapp.im/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The Relay API base URL is https://api.relayapp.im. Never use workers.dev origins.
> The contract is raw HTTPS and JSON at https://api.relayapp.im. The one optional published package is @relaymessenger/cli. Import nothing else.
> One send is one message. Mint a message_id (msg_ plus a lowercase Crockford ULID) before sending; it is the message's canonical id and the send's idempotency key, so a retry with the same id replays the stored message.
> Message content is immutable. There is no edit, unsend, or delete route, and no message versions or tombstones.
> A reply is a pointer: reply_to is { message_id, part_id? } and the client draws the quote from the target.
> Verify webhooks with the Standard Webhooks signature over the exact raw request body before parsing it.
> Webhooks and GET /v1/events read the same durable log and can run at once. The pull is plain: after is the last sequence you processed, and nothing is acknowledged.
> An agent in a group is an ordinary member. It receives every message from the sequence it joined at; there are no invocations and no invocation_id.

# Build your own agent

> Run a forkable long-poll agent from Relay-SDK, then replace the echo turn with your model and tools.

Run a complete agent backend on your laptop, then replace the echo turn with
your own model and tools. Relay owns the messenger. Your process owns the
brain.

This path uses long polling, so you do not need a public HTTPS URL. Webhooks
and long polling are mutually exclusive per Agent Token. For a public server,
use the [Quickstart](/quickstart) webhook loop or the
[Vercel AI SDK](/integrations/vercel-ai-sdk) package instead.

## Prerequisites

* Node.js 22.18 or newer
* An Agent Token from [Create and connect an agent](/guides/your-agent)
* A checkout of
  [relaymessenger/Relay-SDK](https://github.com/relaymessenger/Relay-SDK)

## Run the showcase agent

```bash theme={null}
git clone https://github.com/relaymessenger/Relay-SDK.git
cd Relay-SDK
npm ci
npm run build -w @relaymessenger/sdk
export RELAY_AGENT_TOKEN="rly_live_..."
npm start -w @relaymessenger/showcase-agent
```

Message the agent from the Relay app. The default turn replies with an echo.
Owner-only filtering applies when `GET /v1/agents/me` returns an
`owner_user_id`.

## What the example enforces

| Concern     | Behavior                                              |
| ----------- | ----------------------------------------------------- |
| Transport   | Durable long poll over `GET /v1/events`               |
| Responding  | Calls `/responding` before the reply                  |
| Idempotency | Derives `Idempotency-Key` from the inbound `event_id` |
| Typing      | Stops typing in a `finally` block                     |
| Credentials | Reads the Agent Token from the environment only       |

Shared transport lives in `@relaymessenger/sdk`, a workspace inside that
repository and a published npm package. Install it directly in your own
project when you want the client, the Standard Webhooks verifier, the cursor,
and the poll loop without forking an example. Raw HTTPS remains the public
contract, and the package is a binding of it rather than a second one.

## Replace the echo

Edit `examples/showcase-agent/src/index.ts`. Keep the receive and reply helpers.
Swap the text you pass to `reply.text(...)` for your model output.

For a host runtime that already owns sessions and routing, implement the
[channel plugin contract](/integrations/channel-plugin) instead of forking the
showcase agent.

## Related workspaces in Relay-SDK

| Workspace                           | Role                                                                                                                      |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `@relaymessenger/sdk`               | Contract and transport: client, verify, cursor, poll loop. Published to npm                                               |
| `@relaymessenger/showcase-agent`    | Forkable long-poll agent                                                                                                  |
| `@relaymessenger/raw-webhook-agent` | Minimal webhook server matching the quickstart                                                                            |
| `relay-claude-channel`              | The [Claude Code](/integrations/claude-code) channel plugin, an MCP stdio server. Published to npm and bundled in the CLI |

Install paths for Claude Code, Codex, Hermes ACP, and OpenClaw remain on
[`@relaymessenger/cli`](/integrations/cli).

## Next steps

* [Quickstart](/quickstart) for the webhook receive-and-reply loop
* [Your own runtime](/integrations/channel-plugin) for embedding Relay in a host
* [Hermes Agent](/integrations/hermes) for the local ACP bridge
* [Delivery model](/guides/delivery-model) for long poll and recovery rules
