[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6MMCZ4DCKDXDXJ2JGK6M5MB":3,"skill-same:01M6MMCZ4DCKDXDXJ2JGK6M5MB":76},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":52,"ownerHtmlUrl":53,"ownerBlogUrl":54,"ownerDescription":55,"updatedAt":56,"install":57,"resources":69},"01M6MMCZ4DCKDXDXJ2JGK6M5MB","runtype-persona",null,"Embed, theme, or debug a Runtype Persona chat widget on a website: client tokens, embed snippets, fullscreen assistant layouts, WebMCP page tools, and browser-side chat integrations.","hashgraph-online\u002Fawesome-codex-plugins","hashgraph-online","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F160371962?v=4","01M6CNB6NRJVNNGN14TR01Q6D3","HOL (Hashgraph Online)","01M6JT1HSKKG9V68KQAQGBA7XP",1559,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Fruntype-persona\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"runtype","runtype persona","persona","chat","webmcp","true","chat ui","embed","theme","tokens","widget","snippets","assistant","task","page","integrations","Tools","ui","website","browser","debug","2026-11-10 10:12:30",false,"---\nname: runtype-persona\ndescription: 'Embed, theme, or debug a Runtype Persona chat widget on a website: client tokens, embed snippets, fullscreen assistant layouts, WebMCP page tools, and browser-side chat integrations.'\nuser-invocable: true\nargument-hint: '[Persona widget or chat UI task]'\n---\n\n# Runtype Persona\n\nPersona (`@runtypelabs\u002Fpersona`) is an open-source chat widget that works with any\nbackend. It is a themeable chat UI with no framework dependency, and it streams from any\nbackend that sends server-sent events. It has first-party Runtype support, so the\nrecommended production path is a Runtype agent with a browser-safe `clientToken`. Use this\nskill for website widgets, assistant layouts, deployment snippets, theming, artifacts,\nWebMCP page tools, and local browser tools.\n\n## Where to Deploy\n\nDefault to Runtype. Embed with a browser-safe `clientToken`, and the widget talks to\n`api.runtype.com` directly. You need no proxy and no server code. This is the recommended\npath, and it is what `generate_persona_embed_code` produces.\n\nIf MCP is unavailable and the user wants a starter deploy, run `runtype persona init`. It\ncreates an agent, a client token, and a snippet you can paste. Without flags, the token is\na `test` token that allows every origin (`*`). For production, pass\n`--origins https:\u002F\u002Fyour-site.example` and `--environment live`.\n\nPersona also runs on other streaming backends through the Persona SSE protocol. Adapter\nexamples cover the Vercel AI SDK, OpenAI Agents, LangGraph, and the Anthropic Claude Agent\nSDK, among others. Use a self-hosted backend or `@runtypelabs\u002Fpersona-proxy` only when you\nmust hide a secret API key or front a non-Runtype agent. Otherwise, use the hosted\n`clientToken` embed, which needs no server code.\n\n## Required First Calls\n\nWhen MCP is available:\n\n- Use `get_platform_documentation(topic=\"persona-embed\")` for current embed docs.\n- Use `get_platform_documentation(topic=\"persona-fullscreen-assistant\")` for fullscreen\n  split-pane assistant layouts.\n- Use `get_platform_documentation(topic=\"types-surface-configs\")` when surface behavior\n  config details matter.\n- Use `get_persona_theme_reference` before custom themes.\n- Use `generate_persona_embed_code` for final snippets whenever possible.\n\nDo not hand-write embed code unless the MCP tools are unavailable. For details not listed\nhere, fetch one of the documentation topics above.\n\n## Critical Constants\n\n- Package: `@runtypelabs\u002Fpersona`.\n- CDN base: `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest`.\n- Installer script: `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest\u002Finstall.global.js`.\n- Self-contained browser bundle: `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest\u002Findex.global.js` (exposes `window.AgentWidget`).\n- Do not load `\u002Findex.js` (the ESM build) directly in a browser. It keeps bare import specifiers such as `marked`, fails with `Failed to resolve module specifier \"marked\"`, and leaves an empty mount. The ESM build is for bundlers (npm) only.\n- CSS for npm usage: `@runtypelabs\u002Fpersona\u002Fwidget.css`. For a manual CDN install, use `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest\u002Fwidget.css`.\n- Init function: `initAgentWidget()`.\n- Script installer lifecycle callbacks: `onScriptLoad`, `onLauncherShown`,\n  `onChatReady(handle)`, and `onError`.\n- Ready event: `persona:chat-ready`.\n- Direct `initAgentWidget()` returns the handle. Its `onChatReady` option is a fire-only\n  callback, not the primary way to get the handle.\n- Controller events include `user:message` and `assistant:complete`.\n\nCommon wrong answers: `@runtype\u002Fpersona`, `Persona.mount()`, `window.Persona`,\n`index.umd.js`, missing `widget.css`, `persona:ready`, `onReady`, `widget:ready`,\n`message:sent`, or `message:received`.\n\n### Load from cdn.runtype.com\n\nWhen you load Persona from a CDN, use `cdn.runtype.com`. Pages published with the\n`publish_page` tool load scripts only from `cdn.runtype.com`, and scripts from other CDNs\nfail without an error. On a page that\nRuntype deploys, replace `latest` with the current published version, for example\n`https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002FPERSONA_VERSION\u002Finstall.global.js`, so a new release does\nnot change the widget under your deployed page. Pin the version in the script URL, never\nas a `version` or `cdn` key in `data-config`.\n\n## Build Pattern\n\n1. Create or identify the agent or flow. A `chat` surface is optional for a basic embed:\n   a token that names the agent in `agentIds` is enough. You need a `chat` surface to use\n   WebMCP page tools, because the surface holds the `behavior.webmcp` policy.\n2. Create a scoped client token with `create_client_token`, or with\n   `Runtype.clientTokens.ensure({ name, agentIds, allowedOrigins })` from `@runtypelabs\u002Fsdk`\n   in code. Without a surface, pass `agentId` to the widget (`data-agent-id` or\n   `config.agentId`).\n   - `create_client_token` defaults to `environment: \"live\"` and `allowed_origins: [\"*\"]`,\n     so an unqualified call creates a live token that any origin can use. Pass\n     `environment: \"test\"` while you build, and for production list the exact site\n     origins in `allowed_origins`.\n   - Use a `test` token (`ct_test_`) only while you build. Test tokens allow localhost\n     automatically.\n   - A live token (`ct_live_`) created in the dashboard is shown once. Save its value\n     when you create it.\n3. For a production widget, set a release target on the token so an agent edit does not\n   change the live widget at once. Set `target_alias` (for example `live`) and deploy the\n   agent to that alias, or set `target_version_id` to pin one exact version. A pinned\n   version requires exactly one agent in `agentIds`. A token with no target resolves like\n   any run that names no version, so depending on your organization's live-default setting,\n   a saved agent edit can reach the widget immediately.\n4. Generate embed code with `generate_persona_embed_code`.\n5. For consumer-facing widgets, hide tool calls and reasoning by default.\n6. For internal or debug widgets, expose useful traces intentionally.\n7. For custom themes, set explicit high-contrast component tokens and verify header,\n   launcher, user message, primary button, tool call, and reasoning bubble contrast.\n8. Keep Persona's default HTML sanitization enabled unless all rendered content is\n   trusted.\n9. If the assistant should ask structured follow-up questions or suggest replies, set\n   `features.askUserQuestion.expose: true` or `suggestions.followUps.expose: true` in the\n   widget config instead of hand-writing duplicate local tools.\n\nIf a token value leaks, run `regenerate_client_token` and update the embed. The old value\nstops working immediately.\n\n## Signed-in and Returning Visitors\n\n- To pass a verified signed-in user to the agent and its tools, set `identityProvider` (the\n  Identity Exchange integration's provider value, such as `clerk` or `workos`) and\n  `getIdentityProof` in the widget config (Persona 4.24.0 or later). The widget then sends\n  `identityProof: { provider, token }` on every chat turn and stops the turn when the proof\n  is `null`. Without `identityProvider`, the proof goes only on init, so an agent whose\n  `tenancyStrategy` requires a tenant or end user rejects widget chat. See\n  [End-user identity](https:\u002F\u002Fdocs.runtype.com\u002Fdeveloper-guides\u002Fguides\u002Fend-user-identity).\n- To give each visitor a conversation list that persists, set\n  `features.history: { enabled: true }` in the widget config and configure\n  `behavior.conversationHistory` on the chat surface. See\n  [Client conversation history](https:\u002F\u002Fdocs.runtype.com\u002Fdeveloper-guides\u002Fguides\u002Fclient-conversation-history).\n\n## Fullscreen Assistant Layouts\n\nFor ChatGPT-style or Claude-style layouts, read the fullscreen assistant resource first.\nThe default launcher embed is not enough. Fullscreen layouts usually need full-height\nmode, panel chrome changes, a persistent shell, an artifact pane, composer customization,\nand layout-specific token choices.\n\n## Local Tools\n\nUse browser-side local tools when the assistant needs to read page state or trigger UI\nactions that are only available in the front end. For Persona widgets, these are WebMCP\npage tools registered on `document.modelContext` and admitted by the chat surface's\n`behavior.webmcp` policy. Pair local tools with hidden parameters when authenticated\ncontext should not enter model context.\n\nFor server-side tools that need the signed-in visitor's identity, pass an Identity\nExchange proof as `identityProof` on `\u002Fv1\u002Fclient\u002Finit` and `\u002Fv1\u002Fclient\u002Fchat` (in Persona,\nset `identityProvider` with `getIdentityProof`), then\nreference `{{_tenant.id}}` or `{{_endUser.id}}` in the tool's header (or send\n`{{_identity.token}}` for a signed assertion your API verifies). The model cannot set\nthese values, and the call fails closed when the execution has no identity. Docs:\nhttps:\u002F\u002Fdocs.runtype.com\u002Fdeveloper-guides\u002Fguides\u002Ftool-template-variables\n\nGood local tool examples:\n\n- Read current page HTML or selected DOM regions.\n- Navigate to a record detail page.\n- Open a modal or fill a safe form.\n- Read browser-only state that has no server API.\n\nRequired WebMCP setup:\n\n- Register page tools on `document.modelContext` in the host page, for example with\n  `registerTool(...)`. Persona collects them on each turn and runs returned\n  `webmcp:\u003Cname>` calls in the browser.\n- Create the client token with `product_surface_id` set to the `chat` surface, and include\n  the embedding page origin in `allowed_origins`. A token that is not bound to the surface\n  drops every page tool. `product_surface_id` is fixed at creation, so recreate an\n  existing unbound token.\n- Enable page tools in the widget config with `webmcp: { enabled: true }`. Persona asks\n  for approval before every page-tool call. Use `webmcp.autoApprove = (info) => ...` to\n  skip approval only for safe read-only tools, and `webmcp.onConfirm` only when the host\n  page needs custom confirmation UI. The widget-side `webmcp.allowlist` is a convenience\n  filter, not a security boundary.\n- Set the `chat` surface `behavior.webmcp.enabled` to `true`.\n- Add origin-scoped `behavior.webmcp.allowlist` rules for page tools that should be\n  callable, for example `{ origin: \"https:\u002F\u002Fstore.example.com\", tools: [\"search_*\"] }`.\n  The server enforces only `enabled` and `allowlist`. `behavior.webmcp.requireConfirmFor`\n  (for example `[\"checkout_*\"]`) forces Persona's confirmation and is not a security\n  boundary: chat dispatch does not enforce it, and the voice direct route never picks a\n  listed tool.\n- After real traffic, open the surface's **WebMCP** section in the dashboard to review\n  discovered tools and observed origins. Discovery records the offered page tools before\n  allowlist filtering.\n- Do not confuse WebMCP page tools with an `mcp` surface. WebMCP runs inside the browser\n  page. An `mcp` surface exposes Runtype capabilities to external AI clients.\n\n## Custom Chat UIs Without Persona\n\nA custom browser chat UI that uses a client token calls `\u002Fv1\u002Fclient\u002Fchat` and resumes\nwith `\u002Fv1\u002Fclient\u002Fresume`. That path follows the same surface `behavior.webmcp` policy as\nPersona. For an `approval_start` on a gate with `tools.approval.approver: \"end-user\"`,\nPOST `{ sessionId, executionId, approvalId, decision }` to `\u002Fv1\u002Fclient\u002Fapprove` and read\nthe continued SSE stream as you would from `\u002Fv1\u002Fclient\u002Fresume`. Never send `remember`.\nOwner gates never reach a client-token chat; it refuses them with 501.\n\nA trusted server or SDK process can send local tools directly to `\u002Fv1\u002Fdispatch` as\ntop-level `clientTools[]` and resume with `\u002Fv1\u002Fdispatch\u002Fresume`. This path requires a\nsecret API key, so never run it in a browser. It uses the optional\n`clientToolsPolicy.allowlist` and does not use `behavior.webmcp`, client-token origins, or\ndashboard discovery.\n\n## Verify and Troubleshoot\n\n1. Load the page and send a message in the widget.\n2. Confirm that the turn reached Runtype with\n   `list_conversations(source=\"client_token\", client_token_id=\"ct_...\")` or `list_logs`.\n\nIf the widget loads but does not respond, check the response body in the browser's\nNetwork tab:\n\n| Status | Error                           | Fix                                                                                     |\n| ------ | ------------------------------- | --------------------------------------------------------------------------------------- |\n| `401`  | `Invalid client token`          | Install the current token value. A regenerated token invalidates the old value.         |\n| `403`  | `Origin not allowed`            | Add the exact page origin to the token's list, and to the surface's list if it has one. |\n| `403`  | `Chat surface is not active`    | Activate the chat surface.                                                              |\n| `429`  | `Session message limit reached` | Start a new session, or raise `max_messages_per_session` with `update_client_token`.    |\n\nIf page tools never run, confirm that the token is bound to the chat surface, that\n`behavior.webmcp.enabled` is `true`. If the surface has a `behavior.webmcp.allowlist`,\nconfirm that a rule matches the page origin and the tool name. For the full error list and token limits, see\n[Client tokens and domain restrictions](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fclient-tokens-and-domain-restrictions).\n\n## Related Docs\n\n- [Quickstart: From Agent to Chat Widget](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fgetting-started\u002Fquickstart-from-agent-to-chat-widget)\n- [Embedding the chat widget (script tag)](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fembedding-the-chat-widget-script-tag)\n- [Embedding the chat widget (React)](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fembedding-the-chat-widget-react)\n- [Client tokens and domain restrictions](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fclient-tokens-and-domain-restrictions)\n","# Runtype Persona\n\nPersona (`@runtypelabs\u002Fpersona`) is an open-source chat widget that works with any\nbackend. It is a themeable chat UI with no framework dependency, and it streams from any\nbackend that sends server-sent events. It has first-party Runtype support, so the\nrecommended production path is a Runtype agent with a browser-safe `clientToken`. Use this\nskill for website widgets, assistant layouts, deployment snippets, theming, artifacts,\nWebMCP page tools, and local browser tools.\n\n## Where to Deploy\n\nDefault to Runtype. Embed with a browser-safe `clientToken`, and the widget talks to\n`api.runtype.com` directly. You need no proxy and no server code. This is the recommended\npath, and it is what `generate_persona_embed_code` produces.\n\nIf MCP is unavailable and the user wants a starter deploy, run `runtype persona init`. It\ncreates an agent, a client token, and a snippet you can paste. Without flags, the token is\na `test` token that allows every origin (`*`). For production, pass\n`--origins https:\u002F\u002Fyour-site.example` and `--environment live`.\n\nPersona also runs on other streaming backends through the Persona SSE protocol. Adapter\nexamples cover the Vercel AI SDK, OpenAI Agents, LangGraph, and the Anthropic Claude Agent\nSDK, among others. Use a self-hosted backend or `@runtypelabs\u002Fpersona-proxy` only when you\nmust hide a secret API key or front a non-Runtype agent. Otherwise, use the hosted\n`clientToken` embed, which needs no server code.\n\n## Required First Calls\n\nWhen MCP is available:\n\n- Use `get_platform_documentation(topic=\"persona-embed\")` for current embed docs.\n- Use `get_platform_documentation(topic=\"persona-fullscreen-assistant\")` for fullscreen\n  split-pane assistant layouts.\n- Use `get_platform_documentation(topic=\"types-surface-configs\")` when surface behavior\n  config details matter.\n- Use `get_persona_theme_reference` before custom themes.\n- Use `generate_persona_embed_code` for final snippets whenever possible.\n\nDo not hand-write embed code unless the MCP tools are unavailable. For details not listed\nhere, fetch one of the documentation topics above.\n\n## Critical Constants\n\n- Package: `@runtypelabs\u002Fpersona`.\n- CDN base: `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest`.\n- Installer script: `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest\u002Finstall.global.js`.\n- Self-contained browser bundle: `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest\u002Findex.global.js` (exposes `window.AgentWidget`).\n- Do not load `\u002Findex.js` (the ESM build) directly in a browser. It keeps bare import specifiers such as `marked`, fails with `Failed to resolve module specifier \"marked\"`, and leaves an empty mount. The ESM build is for bundlers (npm) only.\n- CSS for npm usage: `@runtypelabs\u002Fpersona\u002Fwidget.css`. For a manual CDN install, use `https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002Flatest\u002Fwidget.css`.\n- Init function: `initAgentWidget()`.\n- Script installer lifecycle callbacks: `onScriptLoad`, `onLauncherShown`,\n  `onChatReady(handle)`, and `onError`.\n- Ready event: `persona:chat-ready`.\n- Direct `initAgentWidget()` returns the handle. Its `onChatReady` option is a fire-only\n  callback, not the primary way to get the handle.\n- Controller events include `user:message` and `assistant:complete`.\n\nCommon wrong answers: `@runtype\u002Fpersona`, `Persona.mount()`, `window.Persona`,\n`index.umd.js`, missing `widget.css`, `persona:ready`, `onReady`, `widget:ready`,\n`message:sent`, or `message:received`.\n\n### Load from cdn.runtype.com\n\nWhen you load Persona from a CDN, use `cdn.runtype.com`. Pages published with the\n`publish_page` tool load scripts only from `cdn.runtype.com`, and scripts from other CDNs\nfail without an error. On a page that\nRuntype deploys, replace `latest` with the current published version, for example\n`https:\u002F\u002Fcdn.runtype.com\u002Fpersona\u002FPERSONA_VERSION\u002Finstall.global.js`, so a new release does\nnot change the widget under your deployed page. Pin the version in the script URL, never\nas a `version` or `cdn` key in `data-config`.\n\n## Build Pattern\n\n1. Create or identify the agent or flow. A `chat` surface is optional for a basic embed:\n   a token that names the agent in `agentIds` is enough. You need a `chat` surface to use\n   WebMCP page tools, because the surface holds the `behavior.webmcp` policy.\n2. Create a scoped client token with `create_client_token`, or with\n   `Runtype.clientTokens.ensure({ name, agentIds, allowedOrigins })` from `@runtypelabs\u002Fsdk`\n   in code. Without a surface, pass `agentId` to the widget (`data-agent-id` or\n   `config.agentId`).\n   - `create_client_token` defaults to `environment: \"live\"` and `allowed_origins: [\"*\"]`,\n     so an unqualified call creates a live token that any origin can use. Pass\n     `environment: \"test\"` while you build, and for production list the exact site\n     origins in `allowed_origins`.\n   - Use a `test` token (`ct_test_`) only while you build. Test tokens allow localhost\n     automatically.\n   - A live token (`ct_live_`) created in the dashboard is shown once. Save its value\n     when you create it.\n3. For a production widget, set a release target on the token so an agent edit does not\n   change the live widget at once. Set `target_alias` (for example `live`) and deploy the\n   agent to that alias, or set `target_version_id` to pin one exact version. A pinned\n   version requires exactly one agent in `agentIds`. A token with no target resolves like\n   any run that names no version, so depending on your organization's live-default setting,\n   a saved agent edit can reach the widget immediately.\n4. Generate embed code with `generate_persona_embed_code`.\n5. For consumer-facing widgets, hide tool calls and reasoning by default.\n6. For internal or debug widgets, expose useful traces intentionally.\n7. For custom themes, set explicit high-contrast component tokens and verify header,\n   launcher, user message, primary button, tool call, and reasoning bubble contrast.\n8. Keep Persona's default HTML sanitization enabled unless all rendered content is\n   trusted.\n9. If the assistant should ask structured follow-up questions or suggest replies, set\n   `features.askUserQuestion.expose: true` or `suggestions.followUps.expose: true` in the\n   widget config instead of hand-writing duplicate local tools.\n\nIf a token value leaks, run `regenerate_client_token` and update the embed. The old value\nstops working immediately.\n\n## Signed-in and Returning Visitors\n\n- To pass a verified signed-in user to the agent and its tools, set `identityProvider` (the\n  Identity Exchange integration's provider value, such as `clerk` or `workos`) and\n  `getIdentityProof` in the widget config (Persona 4.24.0 or later). The widget then sends\n  `identityProof: { provider, token }` on every chat turn and stops the turn when the proof\n  is `null`. Without `identityProvider`, the proof goes only on init, so an agent whose\n  `tenancyStrategy` requires a tenant or end user rejects widget chat. See\n  [End-user identity](https:\u002F\u002Fdocs.runtype.com\u002Fdeveloper-guides\u002Fguides\u002Fend-user-identity).\n- To give each visitor a conversation list that persists, set\n  `features.history: { enabled: true }` in the widget config and configure\n  `behavior.conversationHistory` on the chat surface. See\n  [Client conversation history](https:\u002F\u002Fdocs.runtype.com\u002Fdeveloper-guides\u002Fguides\u002Fclient-conversation-history).\n\n## Fullscreen Assistant Layouts\n\nFor ChatGPT-style or Claude-style layouts, read the fullscreen assistant resource first.\nThe default launcher embed is not enough. Fullscreen layouts usually need full-height\nmode, panel chrome changes, a persistent shell, an artifact pane, composer customization,\nand layout-specific token choices.\n\n## Local Tools\n\nUse browser-side local tools when the assistant needs to read page state or trigger UI\nactions that are only available in the front end. For Persona widgets, these are WebMCP\npage tools registered on `document.modelContext` and admitted by the chat surface's\n`behavior.webmcp` policy. Pair local tools with hidden parameters when authenticated\ncontext should not enter model context.\n\nFor server-side tools that need the signed-in visitor's identity, pass an Identity\nExchange proof as `identityProof` on `\u002Fv1\u002Fclient\u002Finit` and `\u002Fv1\u002Fclient\u002Fchat` (in Persona,\nset `identityProvider` with `getIdentityProof`), then\nreference `{{_tenant.id}}` or `{{_endUser.id}}` in the tool's header (or send\n`{{_identity.token}}` for a signed assertion your API verifies). The model cannot set\nthese values, and the call fails closed when the execution has no identity. Docs:\nhttps:\u002F\u002Fdocs.runtype.com\u002Fdeveloper-guides\u002Fguides\u002Ftool-template-variables\n\nGood local tool examples:\n\n- Read current page HTML or selected DOM regions.\n- Navigate to a record detail page.\n- Open a modal or fill a safe form.\n- Read browser-only state that has no server API.\n\nRequired WebMCP setup:\n\n- Register page tools on `document.modelContext` in the host page, for example with\n  `registerTool(...)`. Persona collects them on each turn and runs returned\n  `webmcp:\u003Cname>` calls in the browser.\n- Create the client token with `product_surface_id` set to the `chat` surface, and include\n  the embedding page origin in `allowed_origins`. A token that is not bound to the surface\n  drops every page tool. `product_surface_id` is fixed at creation, so recreate an\n  existing unbound token.\n- Enable page tools in the widget config with `webmcp: { enabled: true }`. Persona asks\n  for approval before every page-tool call. Use `webmcp.autoApprove = (info) => ...` to\n  skip approval only for safe read-only tools, and `webmcp.onConfirm` only when the host\n  page needs custom confirmation UI. The widget-side `webmcp.allowlist` is a convenience\n  filter, not a security boundary.\n- Set the `chat` surface `behavior.webmcp.enabled` to `true`.\n- Add origin-scoped `behavior.webmcp.allowlist` rules for page tools that should be\n  callable, for example `{ origin: \"https:\u002F\u002Fstore.example.com\", tools: [\"search_*\"] }`.\n  The server enforces only `enabled` and `allowlist`. `behavior.webmcp.requireConfirmFor`\n  (for example `[\"checkout_*\"]`) forces Persona's confirmation and is not a security\n  boundary: chat dispatch does not enforce it, and the voice direct route never picks a\n  listed tool.\n- After real traffic, open the surface's **WebMCP** section in the dashboard to review\n  discovered tools and observed origins. Discovery records the offered page tools before\n  allowlist filtering.\n- Do not confuse WebMCP page tools with an `mcp` surface. WebMCP runs inside the browser\n  page. An `mcp` surface exposes Runtype capabilities to external AI clients.\n\n## Custom Chat UIs Without Persona\n\nA custom browser chat UI that uses a client token calls `\u002Fv1\u002Fclient\u002Fchat` and resumes\nwith `\u002Fv1\u002Fclient\u002Fresume`. That path follows the same surface `behavior.webmcp` policy as\nPersona. For an `approval_start` on a gate with `tools.approval.approver: \"end-user\"`,\nPOST `{ sessionId, executionId, approvalId, decision }` to `\u002Fv1\u002Fclient\u002Fapprove` and read\nthe continued SSE stream as you would from `\u002Fv1\u002Fclient\u002Fresume`. Never send `remember`.\nOwner gates never reach a client-token chat; it refuses them with 501.\n\nA trusted server or SDK process can send local tools directly to `\u002Fv1\u002Fdispatch` as\ntop-level `clientTools[]` and resume with `\u002Fv1\u002Fdispatch\u002Fresume`. This path requires a\nsecret API key, so never run it in a browser. It uses the optional\n`clientToolsPolicy.allowlist` and does not use `behavior.webmcp`, client-token origins, or\ndashboard discovery.\n\n## Verify and Troubleshoot\n\n1. Load the page and send a message in the widget.\n2. Confirm that the turn reached Runtype with\n   `list_conversations(source=\"client_token\", client_token_id=\"ct_...\")` or `list_logs`.\n\nIf the widget loads but does not respond, check the response body in the browser's\nNetwork tab:\n\n| Status | Error                           | Fix                                                                                     |\n| ------ | ------------------------------- | --------------------------------------------------------------------------------------- |\n| `401`  | `Invalid client token`          | Install the current token value. A regenerated token invalidates the old value.         |\n| `403`  | `Origin not allowed`            | Add the exact page origin to the token's list, and to the surface's list if it has one. |\n| `403`  | `Chat surface is not active`    | Activate the chat surface.                                                              |\n| `429`  | `Session message limit reached` | Start a new session, or raise `max_messages_per_session` with `update_client_token`.    |\n\nIf page tools never run, confirm that the token is bound to the chat surface, that\n`behavior.webmcp.enabled` is `true`. If the surface has a `behavior.webmcp.allowlist`,\nconfirm that a rule matches the page origin and the tool name. For the full error list and token limits, see\n[Client tokens and domain restrictions](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fclient-tokens-and-domain-restrictions).\n\n## Related Docs\n\n- [Quickstart: From Agent to Chat Widget](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fgetting-started\u002Fquickstart-from-agent-to-chat-widget)\n- [Embedding the chat widget (script tag)](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fembedding-the-chat-widget-script-tag)\n- [Embedding the chat widget (React)](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fembedding-the-chat-widget-react)\n- [Client tokens and domain restrictions](https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fproducts-surfaces\u002Fclient-tokens-and-domain-restrictions)\n",{"name":5,"description":7,"argument-hint":45,"user-invocable":46},"[Persona widget or chat UI task]",true,"main","2b63f856ce19c2a797929cacabd9e0fc936812fa","plugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Fruntype-persona",474,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins","https:\u002F\u002Fhol.org\u002Fplugins\u002Fbest-codex-plugins","https:\u002F\u002Fgithub.com\u002Fhashgraph-online","https:\u002F\u002Fhol.org","Open-source standards and developer tools for interoperable AI agents: discovery, identity, communication, payments, privacy and security.","2026-11-11 14:40:14",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":46},[59,62,65],{"tool":60,"command":61},"npx","npx skills add hashgraph-online\u002Fawesome-codex-plugins --skill runtype-persona",{"tool":63,"command":64},"bunx","bunx skills add hashgraph-online\u002Fawesome-codex-plugins --skill runtype-persona",{"tool":66,"command":67},"pnpm","pnpm dlx skills add hashgraph-online\u002Fawesome-codex-plugins --skill runtype-persona","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Fruntype-persona\u002FSKILL.md",[70],{"path":71,"resourceType":72,"resourceTypeDesc":73,"sizeBytes":74,"sourceHtmlUrl":75},"agents\u002Fopenai.yaml","REFERENCE","参考文档",527,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Fruntype-persona\u002Fagents\u002Fopenai.yaml",[77,85,92,99,126,151],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":84},"01M746ZWACVKMZ1BJXJZHYJSSX","migrate-to-e2e","Moves an existing Playwright, Cypress, Selenium, Appium, Detox, Maestro, or TesterArmy suite to e2e one slice at a time, with the old suite running beside the new one until each ported test is proven. Keeps a MIGRATION.md progress file so any later session resumes where the last stopped. Optionally plants a defect to show both suites catch it. Use for \u002Fmigrate-to-e2e, \"migrate our tests to e2e\", \"port these Maestro flows\", \"move our TesterArmy tests\", or when a project has an e2e config and an older suite still running.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fmigrate-to-e2e\u002FSKILL.md",[],[],"2026-11-11 15:11:14",{"skillNo":86,"name":87,"nameZh":6,"description":88,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":91,"publishedAt":84},"01M746ZPTAX1Q0FBKAB1CYND7E","e2e","Writes, runs, and debugs end-to-end tests for web and mobile apps with e2e, the agentic test runner, which mixes agent.act goals with exact locator assertions on a Playwright browser or an iOS or Android device. Also drives a project's running app live over the e2e MCP server to look at a screen, check a UI change, take a screenshot or record a video, and try a locator; and runs bug bashes, parallel e2e explore runs with each bug proven by a repro test. Use when a project depends on e2e or has an e2e.config.ts, when asked for end-to-end, browser, mobile, or agentic UI tests, to check a change in the running app, to QA or bug bash an app or branch, or when an e2e run fails.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fe2e\u002FSKILL.md",[],[],{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":98,"publishedAt":84},"01M746ZJN784HVHMDP9MQGCSGG","create-verification-skill","Generate a project-local verify-\u003Capp> skill on top of e2e, so any coding agent can launch the app, check it is worth driving, exercise a feature the way a user does, keep evidence, and bug bash it. Writes the skill, a feature map with one explore charter per feature, and proves it once. Use for \u002Fcreate-verification-skill, \"make a verification skill for this repo\", or when a project has no scripted way to prove UI behavior.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fcreate-verification-skill\u002FSKILL.md",[],[],{"skillNo":100,"name":101,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":40},"01M716A6ETNB9B1SQ3GXZC75VR","deja-search","deja-vu memory — search the user's past AI coding sessions with the deja CLI. Holds what they already settled and never wrote into the repo (naming rules, banned or already-tried tools, required checks before merge, preferred values, who owns what). Use before your first edit in a task, before you call a change done or ready to merge, before you recommend a tool, library, design or reviewer, before re-debugging an error that may already be solved, when they say 'didn't we fix this before', 'what did we decide about X' or 'I already have that', and before telling them something on this machine does not exist.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fvshulcz\u002Fdeja-vu\u002Fskills\u002Fdeja-search\u002FSKILL.md",[],[106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125],"search","deja search","never","error","ready","memory","re","decide","fix","design","debugging","when","you","done","reviewer","io","change","cli","merge","past",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":40},"01M716A3J2W5SENSE9VGMXB375","deja-reflect","End-of-session reflection and memory curation with deja-vu. Review what was decided, what commands broke and what repaired them, and record durable project rules or decisions with deja remember so the next session starts with them.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fvshulcz\u002Fdeja-vu\u002Fskills\u002Fdeja-reflect\u002FSKILL.md",[],[133,134,135,121,136,137,138,139,140,141,142,143,144,145,111,146,147,148,149,150],"deja reflect","reflect","review","with","record","github","next","https","node","Rules","decisions","brew","remember","project rules","project","session","end","reflection",{"skillNo":152,"name":153,"nameZh":6,"description":154,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":155,"categories":156,"keywords":168,"publishedAt":40},"01M715T3RR4BAYSR57HPPTJ0PF","revid","Make, edit, export and post AI videos with Revid (revid.ai) through the Revid MCP server. Use whenever the user wants a short-form or long-form video made (from an idea, a script, a URL, an article, a PDF, a tweet, a product page, their own clips, or a song), wants to find what is going viral on TikTok, YouTube, Instagram or X before making something, wants to edit or re-export an existing Revid project, generate a standalone AI image or clip, make a series episode, or publish and schedule a finished video to connected social accounts. Covers setup (hosted MCP with OAuth, or an API key), the 36 tools, credits, polling and the rules for publishing. Routes to the more specific revid-* skills when one fits.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftmakersas\u002Frevid-skills\u002Fskills\u002Frevid\u002FSKILL.md",[157,162,165],{"categoryNo":158,"categoryName":159,"taxonomyType":160,"taxonomyTypeDesc":161},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",{"categoryNo":163,"categoryName":164,"taxonomyType":160,"taxonomyTypeDesc":161},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":166,"categoryName":167,"taxonomyType":160,"taxonomyTypeDesc":161},"01JBSEEDCAT000000000000010","后端与接口",[153,169,170,171,172,173,174,147,175,112,176,177,178,179,117,180,181,182,183,184],"URL","Video","short-form","standalone","PDF","viral","tiktok","short","social","MCP","song","image","mcp server","schedule","api","publish"]