# Create a custom action

> Wire your agent to your own API, an interactive widget, or both — with typed inputs, a test run, and an automatic-or-confirm run mode.

A **custom action** is the most flexible tool — it can call your API, show a widget, or do both. Create one from **Actions → Create action**.

## Pick a type

- **Call API** — fetch data from your endpoint and let the agent use it in its answer.
- **API + Widget** — call your API, then render the response as a widget in the chat.
- **Widget only** — show an interactive widget with no API call (the agent fills it from the conversation).
- **Run code (Client)** — run your JavaScript in the visitor’s browser to *do* something on your site (see below).

## General

- **Action name** — the function name the agent calls (letters, numbers, underscores), e.g. `get_order_status`.
- **When to use** — a clear description of when the agent should use this, with example questions it answers. This is how the agent decides to call it, so be specific.

## API request

For **Call API** and **API + Widget** actions, set the **method** and **URL**, plus optional **headers** and **body** (both JSON). Insert collected inputs anywhere with `{{input_name}}` tokens.

```text
Method: GET
URL:    https://api.example.com/orders/{{order_id}}
Headers: { "Authorization": "Bearer ..." }
```

> **INFO:** Requests are server-side and SSRF-guarded (no private/loopback/metadata hosts). Responses must be JSON.

## Data the agent collects

Declare the inputs the agent should gather from the customer — each has a **name**, **type** (string / number / boolean), a **description** (which helps the agent fill it correctly), and whether it's **required**. These become the action's parameters.

## Run code (Client) actions

A **Client** action runs your JavaScript in the **visitor’s own browser**, on your site — so it can *do* things the page can do: add an item to the cart, redirect to checkout, open a cart drawer, prefill a field, or fire an analytics/pixel event. The agent decides when to trigger it and passes along the inputs you defined.

Your code receives two things: `args` (the inputs the agent collected) and `bookbag` (the embed SDK). It runs as a **side effect** — it does not return a value back to the agent. If you need data back in the agent’s answer, use a **Call API** action instead.

```js
// Go to checkout
window.location.href = '/checkout';

// Add a variant to the Shopify cart
fetch('/cart/add.js', {
  method: 'POST', headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ id: args.variant_id, quantity: 1 }),
});

// Prefill a field, then fire an analytics event
document.querySelector('#email').value = args.email;
window.dataLayer?.push({ event: 'chat_action', name: args.name });
```

> **IT RUNS YOUR CODE ON YOUR SITE:** Client actions execute the JavaScript you write here on your storefront, in the visitor’s browser. Only the agent’s owner can set this code, and it’s delivered only by the Bookbag widget (origin-checked) — but treat it like any script you add to your site: keep it small and trusted.

> **INFO:** In the Playground the code runs in the dashboard so you can test it; on your live site it runs on the embedded page.

## Run mode

Choose **Run automatically** for read-only lookups, or **Ask the user to confirm first** for anything that changes data.

## Test it

Use the **Test** button on the action to run it with sample inputs and inspect the raw result before you rely on it in live chats. For confirm-mode actions the test approves the run for you so you can see the output.

## What's next

- [Widget-backed actions](/docs/actions/widgets) — Show interactive UI from an action.
- [Widgets](/docs/widgets/overview) — Build the UI an action renders.
- [Actions overview](/docs/actions/overview) — All action types and run modes.
