# Customize appearance (/en/docs/developers/agent/embed/appearance)



Match chat colors, starter text, and the input area to your website. iframe and Hosted share appearance saved in the Dashboard. A Kit component uses options supplied by your page.

## Prepare the integration [#prepare]

Start with a working service agent and embed policy. The Kit example requires your website to provide `POST /api/praxis-token`, check the login session, and return `{ token }`. This is your same-origin route; see [Embed tokens and users](/en/docs/developers/agent/embed/tokens). The example uses Develop addresses, and your page origin must be allowed.

| Integration     | Where to configure appearance                                                               |
| --------------- | ------------------------------------------------------------------------------------------- |
| iframe / Hosted | Save in the Dashboard; both share it, with changes applied on page refresh                  |
| Kit component   | Page-side `setOptions`; the Dashboard Kit editor previews and generates code without saving |

## Save hosted appearance [#saved-appearance]

Persistent iframe / Hosted appearance **can currently only be configured in the Dashboard**. Open **服务智能体 → your agent → 接入与配置 → 接入方式与外观 → iframe** (Service agents → your agent → Integration and configuration → Integration methods and appearance → iframe).

1. Under **主题** (Theme), select the color scheme, accent, grayscale, radius, and density.
2. Under **开场** (Start screen), enter the greeting and prompts. Use **输入区** (Input area) for the placeholder and footer.
3. Click **保存** (Save). &#x2A;*Expected:** a message says the changes apply after the embed page refreshes. Refresh the iframe or reopen Hosted to check the same text and colors.

The **配置 → 开场与外观** entry is currently an information page. The public appearance API supports reading only; it has no public save operation.

## Configure Kit appearance [#kit-options]

Serve this HTML from your website. It sets the theme, start screen, and composer, with a button to verify updates during a conversation.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8" />
<title>Order assistant</title>
<button id="dark">Switch to dark</button>
<praxis-agent style="display:block;height:600px"></praxis-agent>
<script type="module">
  import "https://kit-develop.praxisusercontent.com/v1/praxis-kit.js";
  await customElements.whenDefined("praxis-agent");
  const chat = document.querySelector("praxis-agent");
  chat.setOptions({
    api: {
      url: "https://api-develop.deepraxis.com",
      getToken: async () => {
        const response = await fetch("/api/praxis-token", {
          method: "POST", credentials: "same-origin",
        });
        if (!response.ok) throw new Error(`Token request failed: ${response.status}`);
        const { token } = await response.json();
        if (typeof token !== "string" || !token) throw new Error("Missing token");
        return token;
      },
    },
    agent: { name: "Order assistant" },
    theme: {
      colorScheme: "light", accent: "#2563eb", grayscale: "cool",
      radius: "lg", density: "normal", fontFamily: "system-ui, sans-serif",
      fontSize: 16,
    },
    header: { title: "Order support", subtitle: "Delivery and returns" },
    startScreen: {
      greeting: "What would you like to know?",
      prompts: [{ label: "Delivery rules", prompt: "Explain the delivery rules." }],
    },
    composer: { placeholder: "Ask about an order", attachments: { enabled: false } },
    history: { enabled: true },
    footer: "Confirm order details with the merchant.",
  });
  document.querySelector("#dark").addEventListener("click", () => {
    chat.setOptions({ theme: { colorScheme: "dark" } });
  });
</script>
</html>
```

**Expected result:** a blue accent, greeting, and **Delivery rules** button appear. The composer has no attachment button. Click **Switch to dark** to change the colors while keeping the current session and messages.

Subsequent `setOptions` calls merge nested groups and replace arrays. Updating `theme.colorScheme` does not require resending the token callback. To change starter prompts, supply the complete `startScreen.prompts` array.

## Adjust colors and text [#options]

| Option                                         | Values or purpose                                                                                           |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `theme.colorScheme`                            | `light`, `dark`, `system`; omitted means light, while `system` follows the system scheme                    |
| `theme.accent` / `theme.surface`               | Accent / background; use explicit opaque CSS colors such as `#2563eb`, not `var(...)` or transparent colors |
| `theme.grayscale`                              | `neutral`, `warm`, `cool`                                                                                   |
| `theme.radius`                                 | `none`, `sm`, `md`, `lg`, `full`                                                                            |
| `theme.density`                                | `compact`, `normal`, `spacious`                                                                             |
| `theme.fontFamily` / `theme.fontSize`          | Font stack / positive pixel size; load fonts in your own page                                               |
| `startScreen.greeting` / `startScreen.prompts` | Greeting / at most 4 visible prompts; `label` is button text, clicking sends `prompt`                       |
| `composer.placeholder`                         | Input placeholder                                                                                           |
| `composer.attachments.enabled`                 | Kit attachment button, enabled by default; unavailable in saved iframe / Hosted appearance                  |
| `locale`                                       | `zh` or `en`; if omitted, Kit uses the host page language, then the browser language                        |

Saved appearance JSON is limited to 8192 UTF-8 bytes. Greetings allow 200 characters; at most 4 prompts each allow 40 characters for `label` and 200 for `prompt`. Input placeholders allow 80 characters. Avatar and header images require HTTPS URLs. See the [component reference](/en/docs/developers/agent/embed/component-reference) for component-specific boundaries.

## Verify and continue [#verify]

Check starter text in a new session. Click a prompt and confirm the sent text matches `prompt`. Switch an ongoing conversation to dark and check that messages remain. Open another page to verify saved Dashboard appearance instead of mistaking local Kit options for saved settings.

Appearance changes do not change agent instructions or tool authorization. If saving fails, follow the field error: shorten text, reduce prompt count, or correct image URLs before retrying.

[Component reference](/en/docs/developers/agent/embed/component-reference) · [Secure your integration](/en/docs/developers/agent/embed/security) · [Agent API](/en/docs/api/native/agent).
