# Build with AI agents

> Machine-readable entry points to these docs, a skill for coding agents, and the rules an agent should follow when integrating Relay and Switchboard.

URL: https://www.caprid.com/docs/agents/

Everything in these docs is available in a form a model reads well, from the same sources as the
pages you're reading. Point your agent at one of the entry points below, or install the skill.

## Entry points

| URL | What it is |
|---|---|
| [`/llms.txt`](https://www.caprid.com/llms.txt) | The index: every page, as a link to its Markdown, with a one-line summary. Start here. |
| [`/llms-small.txt`](https://www.caprid.com/llms-small.txt) | What it takes to build an integration, in one Markdown file: getting started, these rules, the Switchboard guides, both SDK guides and the Account API. |
| [`/llms-full.txt`](https://www.caprid.com/llms-full.txt) | Everything except the TypeScript symbol pages in one file, adding the SDK specification, the Python reference and changelogs. Large; prefer fetching pages from `llms.txt`. |
| `<page>.md` | Any page as Markdown: drop the trailing slash and add `.md`, so `/docs/guides/credentials/` is [`/docs/guides/credentials.md`](https://www.caprid.com/docs/guides/credentials.md). Every page links to it with `<link rel="alternate" type="text/markdown">`. |
| [`/reference/http/account.md`](https://www.caprid.com/docs/reference/http/account.md) | The Account API as Markdown: every operation, parameter and schema. Also [`relay.md`](https://www.caprid.com/docs/reference/http/relay.md). |
| [`/openapi/account.yaml`](https://www.caprid.com/openapi/account.yaml) | The Account API's OpenAPI 3.1 spec, unchanged from its source. Also as [JSON](https://www.caprid.com/openapi/account.json), and the [Relay plane API](https://www.caprid.com/openapi/relay.yaml). Use these to generate a client. |
| [`/raw/spec/protocol.json`](https://www.caprid.com/raw/spec/protocol.json) | The SDKs' machine-readable protocol pins: MOQT draft, default endpoint, authentication convention, object size limit. |
| [`/docs/agents/SKILL.md`](https://www.caprid.com/docs/agents/SKILL.md) | A skill for coding agents: the rules below, and where to look things up. |
| [`/sources.json`](https://www.caprid.com/sources.json) | The exact commits of the source repositories this build of the docs came from. |

Every page also has **Copy as Markdown**, **Open in Claude** and **Open in ChatGPT** under its title.

## Give your coding agent the docs

**Claude Code, and agents that read skills.** Install the skill in your project:

```bash
mkdir -p .claude/skills/caprid
curl -fsSL https://www.caprid.com/docs/agents/SKILL.md -o .claude/skills/caprid/SKILL.md
```

**Any agent that reads `AGENTS.md` or `CLAUDE.md`.** Add a pointer:

```markdown
## Caprid (Relay and Switchboard)

Docs index: https://www.caprid.com/llms.txt. Fetch the `.md` pages it links to before writing
code against Relay, Switchboard, `@caprid/relay` or `caprid-relay`, and follow the integration
rules in https://www.caprid.com/docs/agents.md.
```

**Cursor, and editors with a docs index.** Add `https://www.caprid.com/llms-small.txt` as a docs
source.

**Letting an agent sign itself up.** An agent doesn't need you to create an API key first. Point it
at `https://www.caprid.com/auth.md` (the same steps are at `https://app.caprid.com/auth.md`): it
registers through WorkOS AuthKit and starts a Trial Organization with one Namespace, for 7 days.
Claim the agent to keep what it built. [AI agents](https://www.caprid.com/docs/guides/agents/) walks through it.

**Generating an API client.** Feed [`/openapi/account.yaml`](https://www.caprid.com/openapi/account.yaml) to your OpenAPI
generator. Every operation has a stable `operationId`, like `mintClientToken`.

## Integration rules

These are the facts an agent most often gets wrong. Each links to where it's specified.

1. **Only a Client token goes to a browser or app.** API keys (`sb_...`) and Signing keys stay on
   the server. A leaked API key or Signing key lets anyone mint tokens. ([Credentials](https://www.caprid.com/docs/guides/credentials/))
2. **Mint tokens on the backend, per Client, short-lived.** Grant the least you can: a viewer gets
   `subscribe` (`get`) only, under its own room. There is no way to revoke a single Client token;
   deleting the Signing key revokes every token it signed. ([Client tokens](https://www.caprid.com/docs/guides/credentials/#client-tokens))
3. **Sign tokens yourself in production.** A Client token is an HS256 JWT with the Signing key's
   `kid` in its header and `root`, `put`, `get` and `exp` claims. `root` is the full path, starting
   with the Namespace. The API's `path` is relative to the Namespace; a token's `root` is not.
   ([Sign your own](https://www.caprid.com/docs/guides/credentials/#sign-your-own))
4. **A token's grants must fit the Signing key's scope**, or a relay refuses it when a Client uses it.
   Check one with `POST /v1/namespaces/{namespace}/tokens/verify`.
   ([`verifyClientToken`](https://www.caprid.com/docs/reference/http/account/operations/verifyclienttoken/))
5. **The token travels as `?jwt=` on the relay URL.** Browsers can log that URL on a failed handshake,
   so scrub `jwt` values from diagnostics and error reports.
   ([Browser token exposure](https://www.caprid.com/docs/sdks/typescript/guide/#browser-token-exposure))
6. **Root the endpoint at the token's root.** Use `roomEndpoint(root)` (`room_endpoint(root)` in
   Python), which roots the hosted Relay, `DEFAULT_ENDPOINT`. Name namespaces relative to it. ([Room-rooted endpoints](https://www.caprid.com/docs/spec/behavior/#room-rooted-endpoints))
7. **Retry request error 16 on a fresh namespace.** A subscription can be rejected with `unroutable`
   for about a round trip while the publisher's announce propagates; a publisher's `announced` says
   its announce reached the wire. ([Subscription lifecycle](https://www.caprid.com/docs/sdks/typescript/guide/#subscription-lifecycle))
8. **A write waits for demand.** `write` doesn't send until a subscriber wants the track, and a
   completed write means the transport accepted it, not that anyone received it.
   ([Publishing lifecycle](https://www.caprid.com/docs/sdks/typescript/guide/#publishing-lifecycle))
9. **Never replay a failed write automatically.** Delivery may have been partial; decide on fresh data
   or an explicit replay policy. ([Errors and recovery](https://www.caprid.com/docs/sdks/typescript/guide/#errors-and-recovery))
10. **Plain connections never reconnect.** For anything long-lived use `connectSupervisedPublisher` /
    `connectSupervisedSubscriber` (`connect_supervised_*` in Python), which also rotate before the
    credential expires. ([Supervised connections](https://www.caprid.com/docs/sdks/typescript/guide/#stay-connected-supervised-connections))
11. **Branch on `RelayError` codes, not messages.** Codes and phases are stable.
    ([Error identities](https://www.caprid.com/docs/spec/behavior/#error-identities-and-operation-phases))
12. **An API key can't manage Members or Invitations, or delete a Namespace.** Those need a person
    signed in to the dashboard. ([Members and Owners](https://www.caprid.com/docs/guides/organizations/#members-and-owners))
13. **Install matching versions.** The packages are `@caprid/relay` on npm (add `@caprid/relay-quic`
    for Node) and `caprid-relay` on PyPI. Each SDK's packages release together, so pin them to one
    version. Before 1.0, a minor version can break the API.
    ([TypeScript](https://www.caprid.com/docs/sdks/typescript/#install), [Python](https://www.caprid.com/docs/sdks/python/guide/#use-the-local-packages-in-your-application))

## Where things are specified

These docs are generated from two repositories, which stay the source of truth. Every page made
from one has a **Source** link under its title.

- **Switchboard** (`docs/public/`, `openapi/`): the guides and both HTTP APIs.
- **Relay SDKs** (`ts/`, `python/`, `spec/`): the SDK guides, the package READMEs, the API reference
  (generated from the code's doc comments and docstrings) and the SDK specification.

When a guide and the [behavior contract](https://www.caprid.com/docs/spec/behavior/) seem to disagree, the behavior contract
says what an SDK must do.
