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

# External Agents

> Keep your own AI agent. Use ThinnestAI for the WhatsApp side — the number, the inbox, templates and opt-outs.

**Workspace → WhatsApp → your number's agent picker → External Agents.**

You already have an agent — your own prompts, your own voice and chat stack —
and you want it on WhatsApp without building a WhatsApp integration. Choose
**External Agents** as who answers a number and ThinnestAI stops answering it. Every
message a customer sends is passed to your platform, and your agent's replies
go back to the customer through us.

What stays with ThinnestAI: the connected number, the shared
[inbox](/workspace/inbox) where your team sees every thread and can take one
over, [templates](/whatsapp/templates), [forms](/whatsapp/templates#forms), opt-outs
("STOP") and Meta's 24-hour rule.

## How a message travels

1. A customer writes to your WhatsApp number.
2. We store it in the inbox and send it to your webhook as `message.received`.
3. Your agent decides what to say.
4. Your platform calls `POST /api/v1/conversations/{conversationId}/reply`.
5. We send it on WhatsApp and add it to the thread as the agent's reply.

Your agent can take as long as it needs — nothing waits on it. A reply sent
after the customer's [24-hour window](/meta/windows-and-pricing) has closed
must be an approved template.

## Set it up

<Steps>
  <Step title="Connect your WhatsApp number">
    On **WhatsApp**, connect your own WhatsApp Business Account — a new one or
    one you already have. Then choose an agent for the number. The agent is
    where these conversations are filed, and its webhooks are where the
    messages go. Its own prompt is not used.
  </Step>

  <Step title="Choose External Agents">
    In the number's agent picker, choose **External Agents**. The agent you
    picked in the previous step stays behind it. The number then shows these
    same steps, with links. Only admins can change it; choosing an agent again
    hands the number back to ThinnestAI.
  </Step>

  <Step title="Create an API key">
    **Settings → API keys.** Send it on every call as
    `Authorization: Bearer ta_live_…`. See [authentication](/api-reference/authentication).
  </Step>

  <Step title="Add a webhook">
    On that agent's **Actions** page, add your platform's HTTPS address and
    tick **A customer sent a WhatsApp message**. Or create it through the
    [webhooks API](/api-reference/webhooks) with `"events": ["message.received"]`.
    It must be ticked by name — an endpoint set to receive every event does
    not get it, so your Slack or helpdesk webhooks are not flooded.
    Keep the signing secret — it is shown once.
  </Step>

  <Step title="Reply">
    Call [`POST /api/v1/conversations/{id}/reply`](/api-reference/reply-to-conversation)
    with the `conversationId` from the event.
  </Step>
</Steps>

<Warning>
  If External Agents is on and no webhook on that agent receives
  `message.received`, customer messages go nowhere and nobody answers. The
  WhatsApp page shows a red warning under the number when this is the case.
</Warning>

## What your webhook receives

```json theme={null}
{
  "event": "message.received",
  "sentAt": "2026-09-21T10:15:02Z",
  "data": {
    "conversationId": "conv_e0829641-…",
    "messageId": "msg_91c2…",
    "channel": "whatsapp",
    "from": "919876543210",
    "name": "Priya",
    "text": "Has my order shipped?",
    "media": null,
    "form": null,
    "receivedAt": "2026-09-21T10:15:01Z"
  }
}
```

* **`media`** — when the customer sent a photo, voice note, video or document:
  `{ "kind": "image" | "audio" | "video" | "file", "mimeType", "filename" }`.
  The file itself is not in the event — read the conversation's
  [messages](/api-reference/conversations) for a download link.
* **`form`** — when the customer submitted a WhatsApp form: `{ "answers": { "field": "value" } }`.
* **`text`** — the message, or a media message's caption.
* **`messageId`** — the same id the [messages API](/api-reference/conversations)
  returns, so you can tell a message you already handled from a new one.

Every delivery carries `x-thinnest-signature: sha256=…`, an HMAC-SHA256 of the
raw body under your signing secret. Check it before trusting the body.

Every message is sent, not just the last one in a burst. If a customer sends
three messages quickly, your platform gets three events.

## What your agent can send

| Send                              | When        | Body                                                                   |
| --------------------------------- | ----------- | ---------------------------------------------------------------------- |
| Text                              | Window open | `{ "text": "…" }`                                                      |
| A photo, video, audio or document | Window open | `{ "media": { "type": "image", "url": "https://…", "caption": "…" } }` |
| A WhatsApp form                   | Window open | `{ "form": "Delivery address" }` — its name on the Forms page          |
| An approved template              | Any time    | `{ "template": { "name": "…", "variables": ["…"] } }`                  |

One kind per call. The full reference, with every refusal, is on
[Reply to a conversation](/api-reference/reply-to-conversation).

## When a person takes over

If a teammate takes a conversation over in the inbox, your agent's replies to
it are refused, and its new messages are not sent to your webhook, until the
conversation is handed back. That way the customer never has two voices
answering at once. The teammate's exchange can be read through the
[conversations API](/api-reference/conversations).

"STOP" and other opt-outs are handled before anything reaches you. The
customer is unsubscribed from marketing whatever your agent does.

## Pricing

Meta bills your WhatsApp Business Account directly for its fee on each message,
at [Meta's rates](/meta/windows-and-pricing). ThinnestAI charges **10% of Meta's
rate** per message, from your wallet — pay as you go, with no monthly
subscription. A message Meta does not charge for costs nothing from us either.
Replies your teammates send from the inbox or a connected helpdesk on these
numbers are charged the same way.

There is no AI usage to pay for on these numbers, because your agent does the
answering.

## If your endpoint misses a message

Each event is sent once. An event your endpoint does not accept is not retried,
and after five failures in a row the webhook is switched off. Nothing is lost:
[read back what you missed](/api-reference/conversations#catching-up-after-a-missed-webhook)
with the conversations API, then switch the webhook back on.

## Not available yet

* **No typing indicator or read receipts** from your agent.
* **WhatsApp only.** Website chat, Telegram and voice are answered by
  ThinnestAI agents.
