Runtype Persona
Persona (@runtypelabs/persona) is an open-source, backend-agnostic chat widget: a
themeable, zero-framework chat UI that streams from any SSE-capable backend. It ships
first-party Runtype support, so the easiest production path is a Runtype chat surface
with a browser-safe clientToken. Use this skill for website widgets, assistant
layouts, deployment snippets, theming, artifacts, WebMCP page tools, and local browser
tools.
Where to Deploy
Default to Runtype. Embed against a Runtype chat surface with a browser-safe
clientToken and the widget talks to api.runtype.com directly — no proxy and no
server code. This is the recommended path and what generate_persona_embed_code
produces. If MCP is unavailable and the user wants a starter deploy, runtype persona init creates a simple agent, origin-scoped client token, and paste-ready snippet.
Persona also runs on any other streaming backend via the Persona SSE protocol, with
adapter examples for the Vercel AI SDK, OpenAI Agents, LangGraph, and the Anthropic
Claude Agent SDK, among others. Reach for a self-hosted backend or
@runtypelabs/persona-proxy only when you must hide a secret API key or front a
non-Runtype agent — otherwise the hosted clientToken embed is simpler and has fewer
moving parts.
Required First Calls
When MCP is available:
- Use
get_platform_documentation(topic="persona-embed") for current embed docs.
- Use
get_platform_documentation(topic="persona-fullscreen-assistant") for fullscreen
split-pane assistant layouts.
- Use
get_persona_theme_reference before custom themes.
- Use
generate_persona_embed_code for final snippets whenever possible.
- Read
runtype://types/surface-configs directly when surface behavior config details
matter.
Do not hand-write embed code unless the MCP tools are unavailable.
If the task needs details not listed here, fetch persona-embed,
persona-fullscreen-assistant, or types-surface-configs rather than adding
more embed prose to this skill.
Critical Constants
- Package:
@runtypelabs/persona.
- CDN base (Runtype's first-party CDN):
https://cdn.runtype.com/persona/latest for
ordinary embeds. Use cdn.runtype.com everywhere — it is the recommended source on every
surface (first-party, immutable, no third-party trust), and it is required on
publish_page preview pages, whose strict CSP allows no other script source (third-party
CDNs are blocked there and fail silently). Deployed static apps allow scripts and styles
from any https origin by default (authors can re-tighten via the manifest csp field), so
third-party CDNs load — but the first-party CDN is still the right choice for Persona. On
a Runtype-deployed page, replace latest with a pinned version (e.g. /persona/4.6.0/)
so a new release can't shift the widget code under your immutable app bundle.
- Installer script:
https://cdn.runtype.com/persona/latest/install.global.js.
- Self-contained browser bundle:
https://cdn.runtype.com/persona/latest/index.global.js (exposes window.AgentWidget).
- Do NOT load
/index.js (the ESM build) directly in a browser — it keeps bare import specifiers (marked) and dies with Failed to resolve module specifier "marked", leaving an empty mount. ESM is for bundlers (npm) only.
- CSS for manual/npm usage:
@runtypelabs/persona/widget.css (or https://cdn.runtype.com/persona/latest/widget.css for manual CDN installs).
- Init function:
initAgentWidget().
- Script installer lifecycle callbacks:
onScriptLoad, onLauncherShown,
onChatReady(handle), and onError.
- Ready event:
persona:chat-ready; do not use the removed persona:ready event.
- Direct
initAgentWidget() returns the handle; its onChatReady option is a fire-only
callback, not the primary way to get the handle.
- Controller events include
user:message and assistant:complete.
Common wrong answers: @runtype/persona, Persona.mount(), window.Persona,
index.umd.js, missing widget.css, persona:ready, onReady, widget:ready,
message:sent, or message:received.
Build Pattern
- Create or identify the product, agent/flow capability, and
chat surface.
- Create a scoped client token with
create_client_token.
- Generate embed code with
generate_persona_embed_code.
- For consumer-facing widgets, hide tool calls and reasoning by default.
- For internal/debug widgets, expose useful traces intentionally.
- For custom themes, set explicit high-contrast component tokens and verify header,
launcher, user message, primary button, tool call, and reasoning bubble contrast.
- Keep Persona's default HTML sanitization enabled unless all rendered content is
trusted.
- If the assistant should ask structured follow-up questions or suggest replies, set
features.askUserQuestion.expose: true or features.suggestReplies.expose: true
in the widget config instead of hand-writing duplicate local tools.
Fullscreen Assistant Layouts
For ChatGPT/Claude-style layouts, read the fullscreen assistant resource first. The
default launcher embed is not enough. Fullscreen layouts usually need full-height mode,
panel chrome changes, a persistent shell, an artifact pane, composer customization, and
layout-specific token choices.
Local Tools
Use browser-side local tools when the assistant needs to read page state or trigger UI
actions that are only available in the front end. For Persona widgets these are WebMCP
page tools registered on document.modelContext and admitted by the chat surface's
behavior.webmcp policy. Pair local tools with hidden parameters when authenticated
context should not enter model context.
Good local tool examples:
- Read current page HTML or selected DOM regions.
- Navigate to a record detail page.
- Open a modal or fill a safe form.
- Read browser-only state that has no server API.
Required WebMCP setup:
- Register page tools on
document.modelContext (e.g. registerTool(...)) in the host
page. Persona snapshots them per turn into clientTools[] and runs returned
webmcp:<name> calls back in the browser.
- Create a client token whose
allowedOrigins includes the embedding page origin.
- Enable page-tool consumption in the widget config with
webmcp: { enabled: true }.
Persona shows native approval bubbles by default; use
webmcp.autoApprove = (info) => ... only for safe reads and webmcp.onConfirm only
when the host page needs custom confirmation UI. Widget-side webmcp.allowlist is a
convenience filter, not a security boundary.
- Set the
chat surface behavior.webmcp.enabled to true.
- Add origin-scoped
behavior.webmcp.allowlist rules for page tools that should be
callable, e.g. { origin: "https://store.example.com", tools: ["search_*"] }. Use
behavior.webmcp.requireConfirmFor (a Persona-side UX hint, e.g. ["checkout_*"]) to
force per-call confirmation; server-side enforcement is enabled + allowlist.
- Use the dashboard WebMCP tab to review discovered tools and observed origins after
real traffic. Discovery records the offered page tools before allow-list filtering.
- Do not confuse WebMCP page tools with an
mcp surface. WebMCP runs inside the
browser page; an mcp surface exposes Runtype capabilities to external AI clients.
- Advanced custom chat UIs or server proxies can bypass Persona and send WebMCP-style
local tools directly to API-key
/v1/dispatch as top-level clientTools[], then
resume via /v1/dispatch/resume. This is not the default browser embed path and
must run from a trusted server or SDK process because it requires a secret API key.
Raw dispatch uses optional clientToolsPolicy.allowlist; it does not use
behavior.webmcp, client-token allowedOrigins, or dashboard discovery telemetry.
Custom public-token browser UIs should use /v1/client/chat plus
/v1/client/resume instead; that path follows the same surface behavior.webmcp
policy as Persona.
If the umbrella runtype skill is installed alongside this focused skill, its durable
references provide fallback snippets and working-mode tradeoffs. This skill must still
work when installed by itself; prefer live MCP docs over local sibling files.
1---2name: runtype-persona3description: Use when embedding, deploying, configuring, styling, or debugging Runtype Persona chat widgets, fullscreen AI assistant layouts, chat surfaces, client-token installs, theme tokens, artifacts, tool/reasoning visibility, programmatic widget access, WebMCP page tools, or browser-side local tools. Prefer generate_persona_embed_code and get_persona_theme_reference over hand-written snippets.4---56# Runtype Persona78Persona (`@runtypelabs/persona`) is an open-source, backend-agnostic chat widget: a9themeable, zero-framework chat UI that streams from any SSE-capable backend. It ships10first-party Runtype support, so the easiest production path is a Runtype `chat` surface11with a browser-safe `clientToken`. Use this skill for website widgets, assistant12layouts, deployment snippets, theming, artifacts, WebMCP page tools, and local browser13tools.1415## Where to Deploy1617Default to Runtype. Embed against a Runtype `chat` surface with a browser-safe18`clientToken` and the widget talks to `api.runtype.com` directly — no proxy and no19server code. This is the recommended path and what `generate_persona_embed_code`20produces. If MCP is unavailable and the user wants a starter deploy, `runtype persona21init` creates a simple agent, origin-scoped client token, and paste-ready snippet.2223Persona also runs on any other streaming backend via the Persona SSE protocol, with24adapter examples for the Vercel AI SDK, OpenAI Agents, LangGraph, and the Anthropic25Claude Agent SDK, among others. Reach for a self-hosted backend or26`@runtypelabs/persona-proxy` only when you must hide a secret API key or front a27non-Runtype agent — otherwise the hosted `clientToken` embed is simpler and has fewer28moving parts.2930## Required First Calls3132When MCP is available:3334- Use `get_platform_documentation(topic="persona-embed")` for current embed docs.35- Use `get_platform_documentation(topic="persona-fullscreen-assistant")` for fullscreen36 split-pane assistant layouts.37- Use `get_persona_theme_reference` before custom themes.38- Use `generate_persona_embed_code` for final snippets whenever possible.39- Read `runtype://types/surface-configs` directly when surface behavior config details40 matter.4142Do not hand-write embed code unless the MCP tools are unavailable.43If the task needs details not listed here, fetch `persona-embed`,44`persona-fullscreen-assistant`, or `types-surface-configs` rather than adding45more embed prose to this skill.4647## Critical Constants4849- Package: `@runtypelabs/persona`.50- CDN base (Runtype's first-party CDN): `https://cdn.runtype.com/persona/latest` for51 ordinary embeds. Use `cdn.runtype.com` everywhere — it is the recommended source on every52 surface (first-party, immutable, no third-party trust), and it is **required** on53 `publish_page` preview pages, whose strict CSP allows no other script source (third-party54 CDNs are blocked there and fail silently). Deployed `static` apps allow scripts and styles55 from any https origin by default (authors can re-tighten via the manifest `csp` field), so56 third-party CDNs load — but the first-party CDN is still the right choice for Persona. On57 a Runtype-deployed page, replace `latest` with a pinned version (e.g. `/persona/4.6.0/`)58 so a new release can't shift the widget code under your immutable app bundle.59- Installer script: `https://cdn.runtype.com/persona/latest/install.global.js`.60- Self-contained browser bundle: `https://cdn.runtype.com/persona/latest/index.global.js` (exposes `window.AgentWidget`).61- Do NOT load `/index.js` (the ESM build) directly in a browser — it keeps bare import specifiers (`marked`) and dies with `Failed to resolve module specifier "marked"`, leaving an empty mount. ESM is for bundlers (npm) only.62- CSS for manual/npm usage: `@runtypelabs/persona/widget.css` (or `https://cdn.runtype.com/persona/latest/widget.css` for manual CDN installs).63- Init function: `initAgentWidget()`.64- Script installer lifecycle callbacks: `onScriptLoad`, `onLauncherShown`,65 `onChatReady(handle)`, and `onError`.66- Ready event: `persona:chat-ready`; do not use the removed `persona:ready` event.67- Direct `initAgentWidget()` returns the handle; its `onChatReady` option is a fire-only68 callback, not the primary way to get the handle.69- Controller events include `user:message` and `assistant:complete`.7071Common wrong answers: `@runtype/persona`, `Persona.mount()`, `window.Persona`,72`index.umd.js`, missing `widget.css`, `persona:ready`, `onReady`, `widget:ready`,73`message:sent`, or `message:received`.7475## Build Pattern76771. Create or identify the product, agent/flow capability, and `chat` surface.782. Create a scoped client token with `create_client_token`.793. Generate embed code with `generate_persona_embed_code`.804. For consumer-facing widgets, hide tool calls and reasoning by default.815. For internal/debug widgets, expose useful traces intentionally.826. For custom themes, set explicit high-contrast component tokens and verify header,83 launcher, user message, primary button, tool call, and reasoning bubble contrast.847. Keep Persona's default HTML sanitization enabled unless all rendered content is85 trusted.868. If the assistant should ask structured follow-up questions or suggest replies, set87 `features.askUserQuestion.expose: true` or `features.suggestReplies.expose: true`88 in the widget config instead of hand-writing duplicate local tools.8990## Fullscreen Assistant Layouts9192For ChatGPT/Claude-style layouts, read the fullscreen assistant resource first. The93default launcher embed is not enough. Fullscreen layouts usually need full-height mode,94panel chrome changes, a persistent shell, an artifact pane, composer customization, and95layout-specific token choices.9697## Local Tools9899Use browser-side local tools when the assistant needs to read page state or trigger UI100actions that are only available in the front end. For Persona widgets these are WebMCP101page tools registered on `document.modelContext` and admitted by the chat surface's102`behavior.webmcp` policy. Pair local tools with hidden parameters when authenticated103context should not enter model context.104105Good local tool examples:106107- Read current page HTML or selected DOM regions.108- Navigate to a record detail page.109- Open a modal or fill a safe form.110- Read browser-only state that has no server API.111112Required WebMCP setup:113114- Register page tools on `document.modelContext` (e.g. `registerTool(...)`) in the host115 page. Persona snapshots them per turn into `clientTools[]` and runs returned116 `webmcp:<name>` calls back in the browser.117- Create a client token whose `allowedOrigins` includes the embedding page origin.118- Enable page-tool consumption in the widget config with `webmcp: { enabled: true }`.119 Persona shows native approval bubbles by default; use120 `webmcp.autoApprove = (info) => ...` only for safe reads and `webmcp.onConfirm` only121 when the host page needs custom confirmation UI. Widget-side `webmcp.allowlist` is a122 convenience filter, not a security boundary.123- Set the `chat` surface `behavior.webmcp.enabled` to `true`.124- Add origin-scoped `behavior.webmcp.allowlist` rules for page tools that should be125 callable, e.g. `{ origin: "https://store.example.com", tools: ["search_*"] }`. Use126 `behavior.webmcp.requireConfirmFor` (a Persona-side UX hint, e.g. `["checkout_*"]`) to127 force per-call confirmation; server-side enforcement is `enabled` + `allowlist`.128- Use the dashboard WebMCP tab to review discovered tools and observed origins after129 real traffic. Discovery records the offered page tools before allow-list filtering.130- Do not confuse WebMCP page tools with an `mcp` surface. WebMCP runs inside the131 browser page; an `mcp` surface exposes Runtype capabilities to external AI clients.132- Advanced custom chat UIs or server proxies can bypass Persona and send WebMCP-style133 local tools directly to API-key `/v1/dispatch` as top-level `clientTools[]`, then134 resume via `/v1/dispatch/resume`. This is not the default browser embed path and135 must run from a trusted server or SDK process because it requires a secret API key.136 Raw dispatch uses optional `clientToolsPolicy.allowlist`; it does not use137 `behavior.webmcp`, client-token `allowedOrigins`, or dashboard discovery telemetry.138 Custom public-token browser UIs should use `/v1/client/chat` plus139 `/v1/client/resume` instead; that path follows the same surface `behavior.webmcp`140 policy as Persona.141142If the umbrella `runtype` skill is installed alongside this focused skill, its durable143references provide fallback snippets and working-mode tradeoffs. This skill must still144work when installed by itself; prefer live MCP docs over local sibling files.