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

# Setting up a chat Surface

Use a chat [Surface](/user-guide/products-surfaces/what-are-surfaces) to put your Product's Capabilities in an embeddable chat widget. When you finish this guide, the widget runs on your website and answers visitors with your Flow or Agent.

## Before you begin

* Create a [Product](/user-guide/products-surfaces/creating-a-product).
* In the workbench, add at least one Capability to the Product before you set up the Surface. A Capability is a Flow, Agent, or connected external Agent that answers messages from the Surface. For more information, see [Adding capabilities to a Product](/user-guide/products-surfaces/adding-capabilities-to-a-product). In the classic dashboard, if you create a Product with a chat Surface and no Capability, Runtype creates an Agent for the Surface.

The dashboard has two layouts, the workbench and the classic dashboard. Each layout has its own way to set up a chat Surface. To go back to the classic dashboard from the workbench, open the **Runtype menu** and select **Switch to the classic dashboard**.

## Set up a chat Surface in the workbench

To set up a chat Surface in the workbench, follow these steps:

1. Open a Product. Under **Surfaces**, select **Add a surface**, then select **Chat Widget**. The new Surface opens as a draft in the Surface editor.
2. In **Overview**, enter a **Name** and a **Welcome message**.
3. In **Answering capability**, choose the Flow or Agent that answers messages.
4. Open **Access & keys** and click **New token**. Enter a **Name**, select a **Mode** of **Test** or **Live**, enter the **Allowed origins** of your website, and click **Create token**. Runtype shows a live token value only once, so store it before you close the dialog.
5. Open **Appearance** and style the widget. The preview shows the widget on desktop and mobile.
6. Open **Embed**. In **Snippet**, select **Script tag** or **React**, then select your token in the token list. For a live token, paste the value that you stored in step 4 into **Saved live token**. Click **Copy**.
7. Click **Save**, then click **Test** to chat with the saved configuration. **Test** is available after the Surface has an enabled Flow or Agent.
8. Open **Overview** and click **Activate** in **Status**.

A new chat Surface starts as a draft, and the widget returns `Chat surface is not active` until you activate it. **Activate** is available after the Surface has an active client token linked to it. To stop new conversations later, turn off **Surface active** to pause the Surface. Conversations that are already open continue until they end.

### Route messages between Capabilities

By default, one Capability answers every message. To send each message to the Capability that fits it best, follow these steps:

1. Open **Capabilities** and set **Message handling** to **Route each message to a capability**.
2. In **Routing**, choose a **Router model** and, optionally, enter a **Routing prompt**.
3. Use **Add a capability** to add more of the Product's Capabilities to the Surface.
4. Under **Routable capabilities**, select the Capabilities that the router can choose. The entry point is always routable. To change it, click **Make entry point** on another Capability.
5. Expand each Capability and write an **Exposed name** and **Exposed description**. The router uses them to choose a Capability, so describe what each one handles.
6. Optionally, choose a **Fallback capability** for messages that match no Capability.

For more information, see [Surface orchestration modes](/user-guide/products-surfaces/surface-orchestration-modes).

### Other Surface editor settings

The following table lists other settings in the Surface editor:

| Section           | What you can do                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Overview**      | Set conversation titles. Click **Delete surface** to delete the Surface. Deleting it removes its client tokens, so every widget that uses them stops working. Its conversations are kept.                                                                                                                                                                                                                                                                                                                                                           |
| **Access & keys** | Regenerate, revoke, or edit tokens. Set the Surface's **Allowed origins**, **Logging policy**, and **PII redaction**. In **Token defaults**, set the **Release** and **Limits** that new tokens get. A token that follows a release alias runs whichever Agent version that alias points to. For limits, defaults, and release targets, see [Client tokens and domain restrictions](/user-guide/products-surfaces/client-tokens-and-domain-restrictions) and [Agent versioning and publishing](/user-guide/agents/agent-versioning-and-publishing). |
| **WebMCP**        | Choose which browser tools from your website the Surface accepts.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| **Embed**         | Copy the `initAgentWidget()` handle in **Control it from your code** to control the widget from your code. Set up [Identity proof](/developer-guides/guides/end-user-identity) so a visitor's history follows them across devices. Copy an **Integration prompt** for a coding agent. Review **Origins seen · last 7 days** and click **Allow** to add an origin to the selected token. Copy or open the **Chat endpoint**.                                                                                                                         |

To review conversations from this Surface, open **Sessions** in the activity panel. Select a conversation to see its transcript and trace. **Cost & latency** and **Evals** are in the lower panel.

## Set up a chat Surface in the classic dashboard

In the classic dashboard, you set up a chat Surface with a setup wizard and then refine it in the **Surface panel**.

### Use the setup wizard

When you create a chat Surface, Runtype opens the **Get Your Chat Live** setup wizard:

1. **Configure Agent**: set the system prompt, choose a model, and add tools. This step is required.
2. **Style Widget**: choose a theme preset or customize the widget's appearance. You can skip this step.
3. **Ship**: select a client token and copy the embed code. You can skip this step. If no token exists, the wizard creates a live token that accepts every origin and activates the Surface. Restrict the token's origins in the **Auth** tab before you publish the widget.

When the wizard finishes, select **View Full Config** to open the **Surface panel**, or select **Add Capability** to add another Capability.

### Add a chat Surface to an existing Product

1. Open **Products** in the sidebar, then select the Product.
2. In the **Product surfaces** section, click **Add Surface**.
3. Select **Chat Widget**. The dashboard opens the **Surface panel**.

### Configure the Surface panel

The following table describes the tabs in the **Surface panel**:

| Tab               | What you can do                                                                                                                                                                                                            |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Overview**      | Set the Surface status to **Draft**, **Active**, or **Paused**, edit its name, and set conversation titles and logging.                                                                                                    |
| **Endpoints**     | View the chat endpoint that the widget uses.                                                                                                                                                                               |
| **Orchestration** | Choose **Single Orchestrator** to send every message to one Capability, or **Router** to route each message to a Capability. The tab appears when the Surface has at least two Capabilities or a connected external Agent. |
| **WebMCP**        | Turn on **Accept WebMCP tools**, then choose **Allow all tools** or **Use an allow-list** to control which browser tools from your website the Surface accepts.                                                            |
| **Auth**          | Click **Create Token**, enter a **Token Name** and **Allowed Origins**, then click **Create Token** again. Delete a token to stop every widget that uses it.                                                               |
| **Ship**          | Style the widget and copy its embed code.                                                                                                                                                                                  |

### Get the embed code from Ship

The **Ship** tab shows your choices as sentences with dropdowns that you can change.

1. In the first sentence, choose your app goal and the tool that builds it.
2. To get a prompt for a coding agent, leave the tool set to **my coding agent** or select a named tool. Click **Copy prompt** and paste the prompt into your coding agent.
3. To copy code yourself, select **code it myself**, then choose an **Integration format** of **Script tag** or **React**. Paste a script-tag snippet before the closing `</body>` tag of your page.
4. In the **It should use** sentence, click the style, such as **Clean style**, to open the **Chat Style Editor**. You can adjust colors, typography, layout, and launcher position, or generate a theme from a website URL or a description.
5. In the same sentence, select a client token after **with**, or select **Create token**. If you keep **a placeholder**, replace `YOUR_CLIENT_TOKEN` with a real token before you publish the page.
6. In **Overview**, set the status to **Active**.

## Verify the widget

Open a page that has the embed code, open the widget, and send a message. The widget shows the reply from your Flow or Agent. In the workbench, the conversation also appears in **Sessions**.

## Design browser tools for your assistant

Use WebMCP page tools when an assistant needs browser-only state or UI. Keep
backend work in server-side tools. Register page tools on `document.modelContext`,
enable `webmcp` in Persona and on the chat Surface, and restrict the token's
origins and the Surface's origin-scoped tool allowlist before publishing.

Design a user journey before writing tools. Include the starting state,
ambiguous requests, and the point where the user must confirm an action.
For example, `get_cart` reads a cart and `open_checkout` opens a review screen.
Neither places an order. Keep a purchase behind authenticated, user-confirmed
checkout; a model-authored `confirmed: true` is not proof of consent.

Declare `readOnlyHint: true` only for tools that change neither application
state nor the UI. Use `consequentialHint: true` for significant real-world
actions, and `untrustedContentHint: true` for user-authored or third-party
results, even when your own database stores the text. These hints are advisory,
not authorization. Missing hints do not justify bypassing confirmation.

Validate arguments and resource access at execution time, honor cancellation,
protect unsaved work, and wait for visible updates before returning success.
Remove owned tool registrations when their page or component unmounts.

Keep Persona's approval defaults. Browser confirmation and `requireConfirmFor`
do not replace server authorization. Use `webmcp.autoApprove` only with a
host-owned safe-read policy, not arbitrary page-authored hints.

Start with the [typed Persona tool example](https://github.com/runtypelabs/persona/tree/main/examples/webmcp-typed-tools).
It includes deterministic safety tests and opt-in model evaluations. Run both:
schema-only model tests do not prove approval enforcement or injection safety.
Google's [WebMCP authoring skill](https://github.com/GoogleChromeLabs/webmcp-tools/tree/main/webmcp-skills)
provides additional journey-design workflows. Its authoring budgets do not
change Runtype's limits, security policy, or supported compatibility paths.

## Troubleshooting

The following table lists common problems and how to fix them:

| Problem                                          | Fix                                                                                                                                                                                                                                                                      |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| The widget returns `Chat surface is not active`. | Activate the Surface. A paused Surface also returns this error for new conversations.                                                                                                                                                                                    |
| The widget returns `Origin not allowed`.         | Add the page's origin to the token's allowed origins. If the Surface also sets **Allowed origins**, add it there too. In the workbench, you can open **Embed** and click **Allow** next to the origin in **Origins seen · last 7 days** to add it to the selected token. |
| The widget returns `APPROVAL_MODE_UNSUPPORTED`.  | The Agent has a tool only its owner can approve. If the chat visitor should approve it, set `tools.approval.approver` to `end-user` on the Agent. Otherwise remove the approval requirement, or run it from a surface that supports approvals.                           |
| You lost the value of a live token.              | Regenerate the token and update your embed code. Runtype can't show a live token value again.                                                                                                                                                                            |

For other errors, such as `Session message limit reached`, see [Troubleshoot rejected requests](/user-guide/products-surfaces/client-tokens-and-domain-restrictions#troubleshoot-rejected-requests).

> **Tip**
>
> To set up a chat Surface without the dashboard, use the [Runtype MCP server](/developer-guides/integrations/runtype-mcp-server). Call `create_surface`, then `create_client_token` with the Surface's `product_surface_id`, then `generate_persona_embed_code`. To create an Agent, a client token, and a snippet from a terminal instead, run `runtype persona init`.

## Next steps

* [Embedding the chat widget (script tag)](/user-guide/products-surfaces/embedding-the-chat-widget-script-tag): add the widget to an HTML page
* [Embedding the chat widget (React)](/user-guide/products-surfaces/embedding-the-chat-widget-react): add the widget to a React application
* [Widget theming and customization](/user-guide/products-surfaces/widget-theming-and-customization): customize the widget's appearance
* [Client tokens and domain restrictions](/user-guide/products-surfaces/client-tokens-and-domain-restrictions): set token origins, limits, and release targets
* [Client conversation history](/developer-guides/guides/client-conversation-history): keep a visitor's history across sessions and devices