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

# Custom AI Actions

> Let the AI call your own HTTP APIs during conversations to look up data or take action

Custom AI Actions let the AI call your own API during a conversation -- to look up an order status, check an account balance, or trigger a workflow -- instead of only answering from your knowledge base. The AI decides when to call an action based on the conversation, sends the arguments your API expects, and can read the response back to the visitor.

> **Plan requirement:** Custom AI Actions are available on the Business plan.

***

## How it works

1. You define an action: an HTTP endpoint, its method, and the parameters the AI needs to supply (e.g. `order_id`).
2. The AI sees the action as a tool it can call, with your description telling it what the action does and when to use it.
3. During a conversation, if the AI decides the action is relevant, it calls your endpoint with the arguments it inferred from the conversation.
4. Your API responds, and the AI uses that response to answer the visitor -- or, for actions marked to require confirmation, the visitor is shown a card to approve or cancel first.

```text theme={null}
Visitor                    ReplyBubble AI                  Your API
   |                             |                             |
   |-- "What's the status of    |                             |
   |    order #4821?" --------->|                             |
   |                             |-- GET /orders/4821 -------->|
   |                             |<---- { status: "shipped" } -|
   |<-- "Your order shipped!" --|                             |
```

***

## Creating an action

Go to **Dashboard > Actions > New action**. Each action has:

| Field                                           | Description                                                                                                                                                                                                                                        |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Display name**                                | Human-readable label shown in the dashboard (e.g. "Look up order status"). Typing this auto-derives the slug below until you edit it manually.                                                                                                     |
| **Name**                                        | The tool name the AI sees -- a slug of lowercase letters, digits, and underscores (2-64 chars). Must be unique per workspace and can't reuse a reserved name (`transfer_to_human`, `collect_contact_info`, `close_conversation`, `offer_booking`). |
| **Description**                                 | What the AI reads to decide when to call this action. Be specific about what it does and when to use it -- this is the only thing steering the AI's judgment.                                                                                      |
| **Method**                                      | `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`.                                                                                                                                                                                                        |
| **URL**                                         | Your endpoint. Use `{parameter}` placeholders for path segments, e.g. `https://api.example.com/orders/{order_id}`. HTTPS only in production.                                                                                                       |
| **Timeout**                                     | 1,000-30,000 ms (default 10,000). The request is aborted if your API doesn't respond in time.                                                                                                                                                      |
| **Ask the visitor to confirm before executing** | When on, the AI proposes the call but doesn't run it until the visitor approves in the widget. See [Visitor confirmation](#visitor-confirmation) below.                                                                                            |
| **Enabled**                                     | Disabled actions are hidden from the AI entirely without deleting the configuration.                                                                                                                                                               |

You can have up to **20 actions per workspace**.

### Parameters

Each action can declare up to **12 parameters** -- the inputs the AI must supply when calling it. For each parameter you set:

* **Name** -- lowercase letters, digits, underscores (matches the placeholder name if used in the URL).
* **Type** -- `string`, `number`, or `boolean`.
* **Description** -- shown to the AI so it knows what to pass.
* **Required** -- whether the AI must supply a value.
* **Enum values** (string parameters only) -- an optional comma-separated allow-list (e.g. `open, closed, pending`), constraining the AI to one of those values.

Parameters that appear as a `{name}` placeholder in the URL are substituted into the path (URL-encoded); any remaining parameters are sent as query-string params on `GET`/`DELETE` requests, or as a JSON body on `POST`/`PUT`/`PATCH`.

### Headers

* **Headers** -- static, non-sensitive headers sent with every request (e.g. `Accept: application/json`).
* **Secret headers** -- for API keys and tokens. Values are encrypted at rest and **write-only**: once saved, the dashboard only ever shows the header *names* you've configured, never the values. To change a secret, re-enter it under its name; to keep it, leave it blank. An update is a per-key merge -- keys you don't re-type are kept as-is, so partial edits never wipe secrets you didn't touch. A **"Remove all secrets"** checkbox clears every secret header at once.

***

## Visitor confirmation

For actions that change state (placing an order, cancelling a booking, updating a record), turn on **"Ask the visitor to confirm before executing."** Instead of running the call immediately, the AI:

1. Shows a confirmation card in the widget with the action's display name and the arguments it plans to send.
2. Tells the visitor to confirm or dismiss it, without claiming the action already happened.

In the widget, the visitor sees **Confirm** or **Not now** buttons. Confirming runs the call and shows a "Working on it..." status, followed by a success or failure message (a failed call offers a **Dismiss** button); a successful card clears itself automatically after a few seconds. Only one confirmation card can be open at a time -- if the AI tries to propose a second action while one is still pending, the call is refused and the AI is told to have the visitor resolve the first one.

Confirmation requests that are never acted on (e.g. the visitor closes the tab) are automatically cancelled after 15 minutes; execution requests that are confirmed but never complete are marked failed after the same window, so nothing lingers in a pending state indefinitely.

***

## Execution log

Every time an action runs -- whether triggered directly by the AI or via visitor confirmation -- it's recorded to that conversation's execution log, visible to agents in the **inbox sidebar** under "AI Actions." Each entry shows the action's display name, how long ago it ran, its duration, and a status badge: `success`, `failed`, `pending`, `executing`, or `cancelled`. The log only surfaces status metadata -- the actual request arguments and response body are never shown in this view, since they may contain third-party data your team hasn't reviewed for the dashboard.

***

## Test runs

Before relying on an action in production, use **Test run** from the action's menu on the Actions page. It renders one input per declared parameter (a checkbox for booleans, a dropdown for enums, a text/number field otherwise), then fires the real HTTP call with the arguments you provide. The result shows the response status, duration, and a preview of the response body -- without creating an entry in any conversation's execution log.

***

## Security guarantees

Because custom actions let the AI reach out to arbitrary URLs you configure, ReplyBubble applies several protections automatically:

* **Public HTTPS endpoints only in production.** Action URLs are validated (and, at execution time, re-validated against the resolved IP addresses) to block requests to private networks, loopback addresses, link-local ranges, and cloud metadata endpoints -- so an action can't be pointed at your own infrastructure or another tenant's. HTTP and private/internal addresses are only permitted outside production, for local testing.
* **No redirects.** Responses in the 300-399 range are treated as failures rather than followed, so an action can't be redirected to an unintended destination after validation.
* **Response size cap.** Response bodies are streamed and capped at 256 KB; anything beyond that is discarded rather than buffered in full.
* **Errors never leak raw details.** If a request fails (bad TLS, malformed response, a secret with a stray character breaking the HTTP client), the AI and the execution log only ever see a generic message like "Request timed out" or "Request failed to send or complete" -- never the underlying exception text, which could otherwise expose configured secrets.
* **Per-turn invocation cap.** The AI can call actions at most **5 times** while composing a single reply, capping runaway tool use and API spend.

***

## Limits summary

| Limit                                   | Value           |
| --------------------------------------- | --------------- |
| Actions per workspace                   | 20              |
| Parameters per action                   | 12              |
| Timeout range                           | 1,000-30,000 ms |
| Action invocations per AI reply         | 5               |
| Response size cap                       | 256 KB          |
| Stale pending/executing execution sweep | 15 minutes      |
| Plan requirement                        | Business        |

***

## Troubleshooting

| Symptom                                                 | Cause                                                                                                                                                                                   | Fix                                                                                                            |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Action never gets called                                | Description doesn't clearly signal when to use it, or the action is disabled                                                                                                            | Rewrite the description to state explicitly what the action does and when to call it; check the Enabled toggle |
| "Invalid action URL" on save                            | URL is not a public HTTPS endpoint (or resolves to a private/internal address)                                                                                                          | Use a public HTTPS URL; private/internal addresses are only allowed outside production                         |
| Test run returns a generic failure with no detail       | By design -- raw error text (which could include secrets) is never surfaced                                                                                                             | Check your own API's logs, or verify the endpoint independently outside ReplyBubble                            |
| Secret header stops working after an unrelated edit     | A previous update sent a `secretHeaders` map without including that key while `clearSecretHeaders` wasn't set -- this is a merge, so unrelated keys are preserved, not silently dropped | Re-enter the header value to confirm it's current, or check the saved header names shown in the dialog         |
| Confirmation card disappears without the action running | The visitor dismissed it, or a second action's proposal replaced it before they acted                                                                                                   | Ask the visitor to retry the request so the AI proposes it again                                               |
| 402 error creating or editing an action                 | Workspace is on Free or Pro                                                                                                                                                             | Upgrade to Business                                                                                            |
