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

# Embedding the Agent

> Embed Char with the publishable-key auth contract in vanilla JS and modern frameworks

Use this guide for the canonical embed contract.

## Auth contract (current)

* `publishableKey`: **required**
* `idToken`: optional

<Info>
  `<char-agent>` handles ticket exchange internally through `POST /api/auth/pk-ticket`.
</Info>

## Install

<Tabs>
  <Tab title="npm">
    ```bash theme={null}
    npm install @mcp-b/char
    ```

    ```ts theme={null}
    import "@mcp-b/char/web-component";
    ```
  </Tab>

  <Tab title="Script tag">
    ```html theme={null}
    <script src="https://unpkg.com/@mcp-b/char/dist/web-component-standalone.iife.js" defer></script>
    ```
  </Tab>
</Tabs>

## Key-only embed

```html theme={null}
<char-agent publishable-key="pk_live_..."></char-agent>
```

This gives org-scoped access without per-user identity.

## Per-user identity embed

```ts theme={null}
import "@mcp-b/char/web-component";
import type { CharAgentElement } from "@mcp-b/char/web-component";

const agent = document.querySelector("char-agent") as CharAgentElement;
const idToken = await getIdTokenForCurrentUser();

agent.connect({
  publishableKey: "pk_live_...",
  idToken,
});
```

## React (`@mcp-b/char-react`)

```tsx theme={null}
import { CharAgent } from "@mcp-b/char-react";

export function SupportWidget({ idToken }: { idToken?: string }) {
  return (
    <CharAgent
      publishableKey="pk_live_..."
      idToken={idToken}
      style={{ width: 420, height: 640 }}
    />
  );
}
```

## Security notes

* Keep `idToken` out of DOM attributes; pass it via `connect()`/`setAuth()`.
* Treat publishable keys as public embed credentials and rotate if exposed unexpectedly.
* Restrict key usage with allowed origins in dashboard settings.

## Troubleshooting

* `MISSING_PUBLISHABLE_KEY`: provide `publishable-key` or `connect({ publishableKey })`
* `INVALID_KEY`: key is revoked/invalid
* `ORIGIN_NOT_ALLOWED`: add the origin to allowed origins/domains for that key
* `INVALID_TOKEN`/`TOKEN_EXPIRED`: refresh user session and pass a fresh `idToken`

<Snippet file="support-cta.mdx" />
