> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.rydhm.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.rydhm.ai/_mcp/server.

# Agent to agent (A2A)

A live expert can describe itself to other AI agents with an [A2A](https://a2a-protocol.org) **Agent Card**. Other agents, and your own code, can then talk to it through the public routes, which need no API key.

## Make an expert discoverable

#### Make the expert live

Make it **Live** or **Live and listed** (`unlisted` or `public` in the API). A draft can't be discovered.

#### Turn on discovery

On the expert's **Share** tab, under **Let other AI find and use this expert**, turn on **Discoverable by other agents**.

#### Copy the URLs

The section now shows two URLs to copy: the **A2A Agent Card** and the **MCP manifest**.

Turn discovery off, or move the expert back to draft, and both URLs answer `404`.

## The Agent Card

```bash
curl https://api.rydhm.ai/v1/public/experts/ava-k8nzvywsyuhw/agent-card
```

```json
{
  "name": "Ava",
  "description": "Answers product questions and walks prospects through features.",
  "url": "https://app.rydhm.ai/e/ava-k8nzvywsyuhw",
  "version": "1.0.0",
  "capabilities": { "streaming": true },
  "defaultInputModes": ["text", "audio"],
  "defaultOutputModes": ["text", "audio"],
  "skills": [
    {
      "id": "talk",
      "name": "Talk to Ava",
      "description": "Answers product questions and walks prospects through features."
    }
  ]
}
```

* `url` is the expert's public page, where people can chat or talk to it.
* There is one skill, `talk`. The card never lists the workspace's tools or other private capabilities.

### The MCP manifest

`GET /v1/public/experts/{code}/mcp` describes the same expert as a tool list:

```json
{
  "server": "Ava",
  "protocol": "mcp",
  "tools": [
    { "name": "ask", "description": "Ask Ava a question. It answers from its own knowledge base." }
  ]
}
```

This manifest is a description, not a server you can call. To use an expert as a real MCP server, with an API key, see [MCP](/developers/mcp).

## Talk to a public expert

Any live expert, discoverable or not, answers on the public routes. They need no key, so other agents and your own frontend can call them directly. The expert answers from its knowledge only: anonymous callers never run your workspace's tools.

Replace `ava-k8nzvywsyuhw` with the expert's public link code: the part after `/e/` in its public link.

#### Start a chat

```bash
curl -X POST https://api.rydhm.ai/v1/public/experts/ava-k8nzvywsyuhw/chat \
  -H "Content-Type: application/json" \
  -d '{}'
```

```json
{ "conversationId": "10699545-14b2-4352-a060-e3710dd3c82b" }
```

The body can carry `variables` (values for the expert's `{{variables}}`) and `language` (a two-letter code the expert speaks).

#### Send a message

```bash
curl -X POST https://api.rydhm.ai/v1/public/chat/$CONVERSATION_ID/messages \
  -H "Content-Type: application/json" \
  -d '{"content":"What do you help with?"}'
```

`content` is required, up to 4,000 characters. Messages are screened before the expert sees them. A message that is refused comes back with `"blocked": true` and the expert's `reply`, and has no stream to read.

#### Read the reply

```bash
curl -N https://api.rydhm.ai/v1/public/chat/$CONVERSATION_ID/stream
```

The reply is a server-sent event stream with the same frames as an authenticated chat: `sources`, `delta`, `message`, `done`, or `error`. See [the reply stream](/developers/overview#stream-the-reply).

To keep the conversation going, send the next message and read the stream again.

### Voice

`POST /v1/public/experts/{code}/voice-session` starts a voice call with a live expert. It returns a token your frontend uses to join the call with the [LiveKit client SDK](https://docs.livekit.io/reference/client-sdk-js/):

```json
{
  "serverUrl": "wss://…",
  "roomName": "…",
  "participantToken": "eyJhbGciOi…"
}
```

Connect with `serverUrl` and `participantToken`. The body can carry `variables` and `language`, as for chat.

### Limits on public routes

Public routes are limited per visitor IP address and per expert, so one caller can't run up your workspace's costs:

| Route                            | Per IP address    | Per expert or conversation    |
| -------------------------------- | ----------------- | ----------------------------- |
| Start a chat                     | 10 per 10 minutes | 1,000 per day, per expert     |
| Send a message                   | 20 per minute     | 60 per hour, per conversation |
| Read the reply stream            | 30 per minute     |                               |
| Start a voice call               | 6 per 10 minutes  | 300 per day, per expert       |
| Profile, Agent Card and manifest | 120 per minute    |                               |

A refused request gets `429` with a `Retry-After` header. Public chats and calls use the expert's workspace's credits, and voice calls count toward its limit of calls at once.

If the expert has an [allowed websites](/developers/embed#choose-which-websites-can-embed-the-expert) list, browser requests from other sites get `403` with `error: "origin_not_allowed"`. Server-to-server requests, which send no `Origin` or `Referer` header, are allowed and still count against the limits above.

## Experts consulting other experts

Your own experts can hand a live conversation to a specialist: another live Rydhm expert, added by its Agent Card URL on the expert's **Tools** tab. See [Specialists](/experts/specialists).

> **Note**
>
> You can save the Agent Card URL of an agent outside Rydhm, but today only live Rydhm experts can take a hand-off.