---
title: "嵌入网页小组件"
description: "只需添加一个脚本标签，即可将语音智能体嵌入您的营销或支持网站——访客可直接在浏览器中与其对话，无需电话号码。"
---

网页小组件让您的网站访客通过浏览器的麦克风，与 AI 智能体进行点击通话。它是一个独立的
JavaScript / React SDK，拥有自己的 [SDK 参考](/zh/widget/overview)
——本指南重点介绍网页小组件所需的 ThunderPhone 端配置。

<Note>
  无需使用 cURL：控制台中的 **网页小组件** 页面
  （`/dashboard/web-widgets`）可创建小组件、设置其模式
  和智能体、管理允许的域名，并为您提供嵌入代码片段。
</Note>

## 前提条件

<Steps>
  <Step title="创建智能体">
    该智能体的提示词和语音将运行小组件会话。设置
    `widget_enabled: true`（默认值）。
  </Step>
  <Step title="确定路由模式">
    - `mode="agent"` —— 每个密钥对应一个静态智能体。最简单。
    - `mode="webhook"` —— 您的服务器通过
      [`web.incoming` webhook](/zh/webhooks/call-incoming) 为每位访客选择智能体。适用于
      已登录用户、A/B 测试或按页面路由。
  </Step>
  <Step title="列出允许的域名">
    列出将嵌入该小组件的所有主机名。浏览器会在每次会话请求中发送
    页面来源，因此该列表可防止他人将您的密钥复制到其他网站后继续使用。这并非
    身份验证：浏览器外的脚本可以发送任意 `Origin`
    标头。生产环境不会自动允许 `localhost`；如需针对生产 API 进行本地测试，请将 `localhost` 添加到
    列表中。
  </Step>
  <Step title="选择浏览器覆盖设置">
    确定您的页面可发送哪些会话设置。新密钥默认不接受任何设置；请参阅[浏览器覆盖设置](#browser-overrides)。
  </Step>
</Steps>

## 创建可发布密钥

<CodeGroup>
```bash Static agent
curl -X POST https://api.thunderphone.com/v1/publishable-key \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":            "Marketing site (prod)",
    "mode":            "agent",
    "agent_id":        12,
    "allowed_domains": ["example.com", "*.example.com"],
    "allowed_overrides": ["context"]
  }'
```

```bash Dynamic via webhook
curl -X POST https://api.thunderphone.com/v1/publishable-key \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":            "Support (dynamic)",
    "mode":            "webhook",
    "webhook_url":     "https://example.com/thunderphone/widget-hook",
    "allowed_domains": ["support.example.com"]
  }'
```
</CodeGroup>

响应中包含一个以 `pk_live_...` 开头的 `key`。**可发布
密钥按设计即为公开**——可安全地包含在您的前端包中。
有关所有字段，请参阅[可发布密钥参考](/api-reference/publishable-keys)。

<Warning>
  `allowed_domains` 必须至少包含一项。`*.example.com`
  匹配子域名（例如 `api.example.com`），但**不**匹配
  裸域名。不接受如 `*` 或 `*.*` 这样的裸通配符。
</Warning>

## 在您的网站上嵌入小组件

[小组件 SDK 文档](/zh/widget/overview)涵盖三种集成方式：

<CardGroup cols={3}>
  <Card title="React 组件" icon="react" href="/zh/widget/react">
    `<ThunderPhoneWidget publishableKey="pk_live_..." />`。
  </Card>
  <Card title="无头 Hook" icon="circle-nodes" href="/zh/widget/headless-hook">
    用于自定义 UI 的 `useThunderPhone()`。
  </Card>
  <Card title="CDN 脚本标签" icon="code" href="/zh/widget/cdn-script-tag">
    面向不使用打包工具的网站的 `ThunderPhone.mount({...})`。
  </Card>
</CardGroup>

三种方式都接受相同的 `publishableKey`，并渲染麦克风按钮
以及通话中音频元素。

## 浏览器覆盖设置

小组件可以从页面发送四项会话级设置：

| 设置 | 小组件属性 | 变更内容 |
|---------|-------------|-----------------|
| `context` | `context` | 来自页面的文本，作为参考附加到智能体提示词中 |
| `variables` | 无（仅原始 `POST /v1/widget/session`） | 提示词中 `{{variable}}` 占位符的值 |
| `voice` | `voice` | 此会话中智能体使用的语音 |
| `language` | `language` | 会话开始时使用的语言 |

您的可发布密钥是公开的，因此任何拥有该密钥的人都可以发送这些
设置，包括通过伪造您域名的脚本发送。除非您在密钥上允许，否则每项设置
默认关闭：在控制台中创建或编辑小组件时，在 **浏览器覆盖** 下勾选相应选项，或者通过
[可发布密钥 API](/api-reference/publishable-keys) 设置
`allowed_overrides`。仅允许您的页面实际发送的设置。

如果会话请求携带了该密钥不允许的设置，请求将以 `400` 失败，并指出该设置：

```json
{
  "error": "override_not_allowed",
  "fields": ["voice"],
  "message": "This publishable key does not allow the browser to set `voice`. ..."
}
```

此检查适用于两种模式。在 webhook 模式下，允许的设置还会转发到您的
`web.incoming` webhook（`context` 会以 `website_context` 形式到达）。
在此设置推出前创建的密钥允许全部四项设置，因此现有嵌入仍可继续运行；
请关闭您未使用的设置。

小组件的 `context` 会被截断为 12,000 个字符（约为 3,400 个典型英文文本的
token），并计入[提示词大小附加费](/zh/guides/billing-and-topups)。
系统会告知智能体将其视为页面内容，而非指令。

## 小组件模式 webhook

当 `mode="webhook"` 时，ThunderPhone 会在每次会话开始时调用您的
`webhook_url`，并发送 `web.incoming` 载荷。返回您希望为该访客
运行的智能体配置——其遵循与电话呼叫相同的
[响应架构](/zh/webhooks/call-incoming)：

```json
{
  "prompt":  "You are a VIP concierge for Jane Doe.",
  "voice":   "john",
  "product": "storm-base",
  "tools":   [ /* per-customer tools */ ]
}
```

您可以将自身会话中的上下文（例如浏览的是哪位客户、
他们所在的页面）混入提示词，并可针对不同发布阶段切换智能体。

## 查看会话

小组件会话会显示在
[`GET /v1/calls`](/api-reference/calls#list-calls) 中，并带有
`direction="widget"` ——与电话通话一样，包含相同的转录、录音、评分和
计费。按 `direction` 筛选，以构建仅限小组件的
控制台。

---

## 后续步骤

<CardGroup cols={2}>
  <Card title="小组件 SDK 参考" icon="window-maximize" href="/zh/widget/overview">
    React / Hook / CDN 集成详情。
  </Card>
  <Card title="动态单次通话配置" icon="bolt" href="/zh/guides/dynamic-call-config">
    端到端实现 `mode="webhook"` 流程。
  </Card>
  <Card title="可发布密钥参考" icon="key" href="/api-reference/publishable-keys">
    密钥资源上的每个字段。
  </Card>
  <Card title="麦克风会话 API" icon="microphone" href="/api-reference/mic-sessions">
    跳过小组件；直接驱动 LiveKit 以构建自定义 UI。
  </Card>
</CardGroup>
