
# 自定义函数

自定义函数可以让您的 AI 机器人与实时对话中的其他系统进行连接。机器人无需再说“我查一下再回复您”，而是可以实时查询订单状态、检查库存或在您的 CRM（客户关系管理系统——您用于跟踪潜在客户和客户的软件，例如 HubSpot 或 Salesforce）中创建记录——所有这些都在客户等待时实时完成。


---

## 自定义函数与 Webhook 的区别

这是最容易混淆的地方，因此在构建任何内容之前，有必要先弄清楚这一点。

| | Webhook | 自定义函数 |
|---|----------|------------------|
| **方向** | 单向（触发即忘） | 双向（调用并等待） |
| **机器人行为** | 在发生某事时发送通知，然后继续执行。 | 发出调用，**暂停并等待响应**，然后利用返回的结果继续对话。 |
| **对对话的可见性** | 下游结果对机器人不可见——它永远不知道发生了什么。 | 响应直接反馈给 AI，因此机器人可以引用它、对其进行推理，并用它来回复客户。 |
| **适用场景** | 记录事件、将数据同步到 CRM、触发外部自动化（Zapier、Make、n8n）。 | 任何机器人需要在回复前获得**答案**的场景——实时查询、实时定价、即时内容生成。 |

**如何选择：** 如果您只需要*告诉*另一个系统发生了某事，请使用 Webhook——即发送给另一个系统的单向自动化消息（请参阅 **设置 → 集成 → Webhook**）。如果机器人需要在继续对话之前从另一个系统*获取*信息，请使用自定义函数。

---

## 自定义函数能实现的功能示例

由于响应会反馈到对话中，自定义函数可以实现 Webhook 无法做到的事情：

- **实时 Shopify 或 WooCommerce 库存查询** — 在向客户报价之前，机器人会实时检查库存并回答“是的，我们有 12 件 M 码”，而不是“让我查一下再回复您”。
- **来自 Google 表格的动态定价** — 您的销售团队在表格中更新价格；机器人会在对话中读取最新的一行，并在无需任何人触碰 AI 配置的情况下报出当前价格。
- **语音 AI 回呼代理** — 当机器人筛选出潜在客户时，它会触发一个语音代理（例如，由 ElevenLabs 驱动的呼叫器）在几分钟内回拨给该潜在客户，并向客户确认“太好了，请期待在接下来的 5 分钟内接到电话”。
- **自定义报价 PDF，在聊天中生成并发送电子邮件** — 机器人收集需求，调用您的报价生成器，获取 PDF URL，并告诉客户“我已经通过电子邮件发送了您的报价——请检查您的收件箱”。

---

## 自定义函数能做什么？

可以将自定义函数视为赋予您的机器人超越简单聊天的超能力。以下是实际应用示例：

- **订单跟踪** - 客户询问“我的订单在哪里？”，机器人会检查您的电子商务系统并回复运输状态和跟踪链接
- **库存检查** - “你们有 10 码的这个吗？”机器人会检查您的库存系统并给出实时答案
- **CRM 更新** - 当机器人筛选出潜在客户时，它会自动在 HubSpot、Salesforce 或任何其他 CRM 中创建或更新记录
- **报价生成** - 机器人收集客户的需求，并从您的定价系统中生成个性化报价
- **预订** - 机器人会在您的外部预订系统中创建预约
- **折扣验证** - “这个优惠码有效吗？”机器人会进行检查并确认
- **账户查询** - 自动识别回头客并调出其账户详细信息

**客户永远看不到幕后发生的事情。** 他们体验到的只是一个能够用真实、最新的信息回答问题的机器人。

---

## 自定义函数的工作原理（简单版本）

以下是对话期间触发自定义函数时发生的情况：

1. **客户询问某事**，需要实时数据（例如：“我的订单在哪里？”）
2. **机器人识别出**需要使用自定义函数来回答
3. **机器人收集**客户缺失的信息（例如：“您的订单号是多少？”）
4. **平台发送请求**到您的系统（您的网站、CRM 或任何其他工具），并附带相关详细信息
5. **您的系统响应**数据（例如：订单状态、追踪号码、送达日期）
6. **机器人读取响应**并撰写自然回复：“您的订单 ORD-4582 已发货，预计周五送达！”

### 自定义函数调用的费用

每次自定义函数调用均按照您 Agent 的 AI 质量层级计费：

| AI 质量层级 | 每次自定义函数调用的积分 | 连接您自己的 Anthropic 密钥 (BYOK) 时 |
|---|---|---|
| Pro | 1 积分 | 0 积分 — 在您的密钥上运行 |
| Economy (已弃用) | 0.5 积分 | 0 积分 — 在您的密钥上运行 |
| Max | 0.25 积分 | 仍为 0.25 积分，即使连接了您自己的密钥也会计费，因为 Max 在我们自己的模型上运行 |
| Mini | 0.15 积分 | 仍为 0.15 积分，即使连接了您自己的密钥也会计费，因为 Mini 在我们自己的模型上运行 |

---

## 设置自定义函数（分步指南）

1. 在主侧边栏的 **AI Studio** 下，点击 **Custom Functions**（自定义函数）。


2. 点击右上角的绿色 **+ Add Function**（或 **New function**）按钮。


自定义函数列表显示了一个包含以下列的表格：

| 列 | 显示内容 |
|--------|--------------|
| **Name** | 函数名称（例如 `check_order_status`） |
| **Description** | 函数功能的简短摘要（在表格中截断为 50 个字符） |
| **Method** | 使用的 HTTP 方法，显示为彩色徽章：GET（蓝色）、POST（绿色）、PUT（橙色）、DELETE（红色） |
| **Created** | 函数创建日期 |

这使您可以轻松地一目了然地浏览函数并找到所需的函数。

### 第 1 步：命名并添加描述


| 字段 | 输入内容 | 示例 |
|-------|--------------|---------|
| **Name** | 使用字母、数字和下划线的短名称 | `check_order_status` |
| **Description** | 解释此函数的功能（AI 读取此内容以决定何时使用它） | “使用订单号查询客户订单的当前状态” |
| **Purpose (AI Action)** | 明确告知 AI 何时以及如何使用此函数 | “当客户询问订单状态、发货或配送时使用此函数。请先询问他们的订单号。” |

**提示：** 在描述和用途中要非常具体。您对何时应使用该函数描述得越清晰，机器人就越能可靠地在正确的时间使用它。

### 第 2 步：设置连接

您需要告知应用将请求发送到何处：

| 字段 | 输入内容 | 示例 |
|-------|--------------|---------|
| **URL** | 您系统端点的网址（您系统中接收请求并回传数据的特定地址） | `https://api.yourstore.com/v1/orders/status` |
| **Method** | 要发送的请求类型 | 见下方选项 |

**如何选择方法：**

| 方法 | 使用场景 |
|--------|---------------|
| **GET** | 查询信息（订单状态、库存、账户详情） |
| **POST** | 创建新记录（支持工单、潜在客户、预订）或进行复杂查询 |
| **PUT** | 完全更新现有记录 |
| **PATCH** | 部分更新现有记录 |
| **DELETE** | 删除记录 |

如果您不确定该使用哪种方法，请咨询您的开发人员或查阅您所连接系统的文档。**GET**（用于查询）和 **POST**（用于创建记录）是最常用的方法。

### 第 3 步：添加身份验证标头

大多数系统需要身份验证才能接受请求。请添加任何必要的标头：

| 标头 | 示例值 |
|--------|--------------|
| `Authorization` | `Bearer your-api-key-here` |
| `Content-Type` | `application/json` |

**安全提示：** 请使用权限受限的专用 API 密钥。切勿使用管理员级别的凭据。

**在哪里查找 API 密钥：** 请检查您所连接系统的设置或开发者部分（例如，您的 CRM、电子商务平台或预订工具）。

### 第 4 步：定义输入（机器人发送的内容）

输入参数是机器人从对话中收集并发送到您系统的信息片段。

对于每个参数，您需要指定：

| 属性 | 含义 |
|----------|--------------|
| **Name** | 参数名称（必须与您系统预期的名称一致） |
| **Type** | 数据类型（文本、数字、真/假等） |
| **Description** | 告知 AI 此信息是什么以及在对话中何处查找 |
| **Required** | 如果设置为“是”，机器人将在继续之前向客户询问此信息 |

**可用的参数类型：**

| 类型 | 含义 |
|------|--------------|
| **string** | 文本（名称、订单号、地址） |
| **number** | 数值（数量、价格） |
| **boolean** | 真或假（是/否值） |
| **array** | 项目列表。作为真实的 JSON 列表发送 — 在 **Run Test** 中，您可以将其输入为 `[8624]`、`["a", "b"]` 或直接以逗号分隔（`8624, 8625`），系统会自动为您转换。如果您的 API 对列表内容有严格要求（例如仅限数字），请在类型旁边设置可选的 **Item type**，列表中的每个值都会被转换为该类型。 |
| **query_param** | 作为 URL 参数而非请求体发送的文本。当您的 API 需要在 URL 中获取数据时使用此类型（例如 `?order_id=123`）。 |

每个参数还有一个可选的 **请求体路径 (Request body path)** 字段。通常，参数作为请求体中的顶级字段（或对于 `query_param` 类型，作为查询字符串值）发送。如果您的端点要求将其嵌套（例如 `{"order": {"id": "ORD-123"}}`），请将路径设置为 `order.id`，平台将为您在该位置嵌套该值。


**示例：对于订单状态查询，您可以定义：**

- **order_number** (string, 必填): “客户的订单号。通常以 ORD- 开头，后跟数字。如果客户未提及，请向其询问。”
- **email** (string, 可选): “客户的电子邮件地址，用于额外验证。仅在仅凭订单号无法找到匹配项时才需要。”

### 您的系统自动接收的内容

除了您定义的输入参数外，平台还会随每个请求自动包含系统数据。您的端点会在 `system` 字段中接收此数据：

| 系统字段 | 包含内容 |
|-------------|----------------|
| `system.contactId` | 对话中联系人的平台 ID |
| `system.campaignId` | 对话所属的营销活动 ID |
| `system.userId` | 您的用户 ID |
| `system.channel` | 消息渠道（例如 `"whatsapp"`, `"instagram"`） |
| `system.contact` | 完整的联系人记录（姓名、电话、电子邮件、标签等） |
| `system.campaign` | 营销活动配置 |
| `system.test` | 如果这是“试用”测试，则为 `true`；如果是实时对话，则为 `false` |

如果您的系统需要识别联系人、检查触发该函数的营销活动或在测试期间执行不同行为，这将非常有用。

> **不需要系统数据？** 在函数构建器中打开 **跳过系统数据 (Skip System Data)** 开关。机器人将仅发送您定义的输入参数，而不发送任何联系人或营销活动数据。如果您的端点拒绝意外字段，或者您只是想要更精简的有效载荷，请使用此选项。

### 第 5 步：测试它，然后让机器人读取响应

通常您根本不需要映射响应字段。一旦您的端点做出响应，机器人就会读取整个 JSON 响应，并使用您函数的 **描述 (Description)** 和 **用途 (Purpose (AI Action))**（以及每个参数自身的描述）来确定哪些内容重要，并以自然的方式呈现。函数本身清晰的描述（“检索客户订单的当前状态，包括物流信息和追踪”）比逐个字段映射更能发挥作用。

如果您的端点返回较大的响应，而您只想让机器人看到几个特定的值，请打开 **响应映射 (Response mapping)** 部分（默认折叠，位于“测试”上方）。每一行从响应中选取一个顶级字段：**响应字段 (Response field)** 是 API 的 JSON 回复中的字段名称，**输出字段 (Output field)** 是机器人接收该值时使用的名称。只要填写至少一行，机器人就只会获取您映射的值，而不是完整的响应体。将该部分留空以保持默认的完整响应行为。


在保存之前，请使用构建器底部的 **测试 (Test)** 部分，按照配置发送请求并查看真实响应，无需离开应用程序：


您在此处看到的响应是端点的原始回复。如果您在上方设置了**响应映射**，则实际聊天中的机器人只会接收那些已映射的字段——测试始终显示完整的原始响应，以便您查看可用于映射的内容。如果看起来有误（字段名称意外、嵌套过多），请在您的端点上进行修复或调整您的映射。

---

## 为智能体分配函数

创建自定义函数后，您需要告知每个智能体它可以使用哪些函数：

1. 在 **AI Studio → AI 智能体**下打开[智能体](../ai-agents/ai-agents.md)。
2. 转到其 **AI 能力**选项卡。（对于仍直接保留其自身 AI 设置而非通过独立智能体管理的营销活动，相同的列表会出现在该营销活动自身的 **AI 能力**步骤中。）
3. 您将看到您创建的所有自定义函数的列表。为您希望此智能体的机器人能够调用的每个函数开启开关。
4. 点击底部的**保存更改**。选择仅在保存后生效。


只有已分配的函数才可供该智能体的机器人使用。这可以防止机器人意外使用不相关的函数。

---

## 测试您的自定义函数

在上线之前，请进行全面测试：

1. **运行内置测试** - 使用函数构建器内的**测试**部分（见上文）进行快速检查，无需离开应用程序——填入实际值并点击“运行测试”。
2. **直接测试您的系统端点** - 对于下方的完整检查清单，使用 Postman 等专用工具（或由您的开发人员）进行比单次“运行测试”更深入的检查。
3. **在“试用”中测试** - 模拟一段对话，让客户询问应该触发该函数的问题。
4. **检查响应** - 确保机器人能正确读取并呈现数据。
5. **测试错误场景** - 如果客户提供了无效的订单号会怎样？如果您的系统暂时宕机了会怎样？

### 当测试返回 401 或 403 时

401 或 403 意味着您的端点收到了请求但拒绝了它。关键点在于**您的日志中没有任何显示**——大多数工具在启动工作流之前就会拒绝未经授权的调用，因此您这边什么也看不到，看起来就像请求从未到达一样。

这几乎总是身份验证不匹配导致的：您的端点需要一种凭据，而函数发送的是另一种。请检查您在 [第 3 步](#step-3-add-authentication-headers) 中添加的标头是否正是您的系统所期望的。

最常见的情况是 Webhook 受 **Basic Auth**（n8n、Make 和大多数自托管工具在 Webhook 本身上提供此选项作为复选框）保护，而函数发送的是自定义密钥标头，例如 `X-My-Secret`。Basic Auth 仅接受 `Authorization` 标头，因此自定义标头会被忽略，调用也会被拒绝。您有两个选择：

- **关闭 Webhook 上的 Basic Auth**，并在工作流内部检查您的自定义标头。
- **保持 Basic Auth 开启**，并向函数添加一个 `Authorization` 标头，其值为单词 `Basic` 后跟您的 base64 编码的 `username:password`。

两种方法都有效——只需确保双方达成一致即可。

### 当测试返回 404 时

端点 URL 错误，或者工作流未发布。特别是在 n8n 中，每个 Webhook 都有一个单独的 **测试 (Test)** URL 和 **生产 (Production)** URL，且测试 URL 仅在您打开编辑器时才会监听。请复制生产 URL 并确保工作流处于激活状态。

### 在“试用”和“聊天”中查看失败情况

当 AI 在对话期间调用自定义函数但调用失败（例如凭据错误、端点宕机、超时）时，对话现在会显示该情况：在代理的**试用**选项卡和**聊天**中的真实对话线程里，会出现一个红色的 **“(函数名) 失败”** 标记。点击该标记可展开详细信息：查看您的端点返回的状态码及其响应正文，这通常足以让您明确需要修复的内容（例如，带有“unauthorized”消息的 `401` 表示身份验证标头有问题，超时则表示您的端点响应时间超过了 30 秒）。

成功的调用也会显示一个标记——点击它即可查看您的端点实际返回的内容。这是端到端调试集成的最快方法：在“试用”中进行测试对话，然后点击函数标记即可查看真实的请求结果，无需离开当前页面。

---

## 完整示例：订单状态查询

这是一个您可以作为模板使用的完整配置示例：

**基本信息：**
- **名称：** `check_order_status`
- **描述：** "检索客户订单的当前状态，包括物流信息和追踪"
- **AI 动作：** "当客户询问订单状态、包裹位置或预计到达时间时调用此函数。请务必先询问订单号。"

**连接：**
- **URL：** `https://api.mystore.com/orders/lookup`
- **方法：** POST

**请求头：**
- `Authorization`: `Bearer sk_live_abc123`
- `Content-Type`: `application/json`

**输入参数：**
- `order_number` (文本，必填)："客户提供的订单号"
- `customer_email` (文本，选填)："用于额外验证的客户电子邮件"

**无需响应映射** — 由于上方已设置清晰的描述和 AI 操作，机器人会自动读取您的端点返回的任何 JSON（状态、追踪号码、送达日期、商品），并确定如何进行表述。

**对话示例：**

> **客户：** 嘿，我的订单在哪里？
>
> **机器人：** 您好！我很乐意为您查询订单。请问可以提供一下您的订单号吗？
>
> **客户：** 是 ORD-78234
>
> **机器人：** 让我为您查询一下...
>
> 您的订单 ORD-78234 已发货，正在运输途中！预计送达日期为 3 月 10 日。您可以在此处追踪您的包裹：https://tracking.example.com/1Z999AA1
>
> 还有什么我可以帮您的吗？

---

## 完整示例：Shopify 订单状态

如果商店运行在 Shopify 上，您无需开发人员构建查询端点 —— Shopify 自身的系统可以直接回答订单问题。（对于 Shopify 商店的产品和库存问题，您根本不需要自定义函数：直接连接商店的内置服务器即可 —— 请参阅 [连接 Shopify 商店](mcp-servers.md#ready-made-example-connect-a-shopify-store)。）

**首先，在 Shopify 中创建一个访问令牌。** Shopify 在 2026 年期间对此进行了更改：应用不再能在 Shopify 管理后台内创建，新的应用屏幕会提供 **Client ID**（客户端 ID）和 **Client secret**（客户端密钥），而不是现成的令牌。以下步骤将这些凭据转换为永久令牌。每个商店只需操作一次，大约需要十分钟。（如果商店已经通过旧方式创建了旧应用，其现有令牌将继续有效——请直接跳至下方的自定义函数部分。）

1. 前往 Shopify 开发人员仪表板 [dev.shopify.com](https://dev.shopify.com)，打开您的组织，然后点击 **Apps → Create app**。将其命名为类似 `Order lookup` 的名称。
2. 为该应用授予 **read_orders** 权限，发布一个版本，并将该应用安装到商店中。
3. 打开应用的 **Settings**，将商店自己的网页地址（例如 `https://www.yourstore.com/`）添加到允许的重定向 URL 中。保存。
4. 仍在 **Settings** 中，复制 **Client ID** 和 **Client secret**。
5. 在已登录该商店 Shopify 管理后台的浏览器中，打开以下地址，并将商店名称、客户端 ID 和重定向地址替换为您自己的信息：
   `https://YOUR-STORE.myshopify.com/admin/oauth/authorize?client_id=YOUR-CLIENT-ID&scope=read_orders&redirect_uri=https://www.yourstore.com/&state=12345`
   批准出现的屏幕。浏览器将跳转到您的重定向地址，地址栏现在包含 `code=` 后跟一个长值 —— 请复制该值。它仅在几分钟内有效，因此请直接进行下一步。
6. 将该代码交换为令牌，您可以在 <span data-t="appName">Your AI Connector</span> 中完成此操作。在自定义函数构建器中，将 **Method** 设置为 POST，将 **URL** 设置为 `https://YOUR-STORE.myshopify.com/admin/oauth/access_token`，添加三个名为 `client_id`、`client_secret` 和 `code` 的文本输入参数，然后点击 **Test**，填入这三个值并运行。响应中包含 `access_token` —— 这就是您的永久令牌。将其复制到安全的地方，然后清除构建器并设置下方的真实函数。

**然后设置自定义函数：**

**基本信息：**
- **名称：** `check_shopify_order`
- **描述：** "在商店的 Shopify 系统中查找订单，并返回其状态、物流追踪和商品信息"
- **AI 操作：** "当客户询问订单状态或配送情况时调用此函数。请务必先询问订单号。"

**连接：**
- **URL：** `https://YOUR-STORE.myshopify.com/admin/api/2026-01/orders.json?status=any` — 将 `YOUR-STORE` 替换为商店的 `.myshopify.com` 名称（此地址使用 Shopify 的技术域名，而非商店的自定义域名）
- **方法：** GET

**请求头：**
- `X-Shopify-Access-Token`: `shpat_...`（上述令牌）

**输入参数：**
- `name` (query_param, 必填)："客户订单确认信息中显示的完整订单号，包括 # 符号 —— 例如 #1001。如果客户未提及，请向其询问。"

**无需响应映射** —— 机器人会读取返回的订单信息（付款状态、履行状态、物流追踪、商品）并自然地进行回答。

**温馨提示：** 通过这种方式创建的令牌可以查看 **过去 60 天** 内的订单 —— 这足以应对日常支持问题，但无法查看完整的订单历史记录。

---

## 完整示例：预约服务

**基本信息：**
- **名称：** `create_booking`
- **描述：** "在我们的预约系统中创建新预约"
- **AI 操作：** "在与客户确认日期、时间和联系方式后使用此功能。在客户明确确认要预约之前，请勿调用。"

**连接：**
- **URL：** `https://booking.mycompany.com/api/appointments`
- **方法：** POST

**输入参数：**
- `date` (文本，必填)："YYYY-MM-DD 格式的预约日期"
- `time` (文本，必填)："HH:MM 格式的预约时间"
- `name` (文本，必填)："客户全名"
- `phone` (文本，必填)："客户电话号码"
- `service_type` (文本，必填)："预约的服务类型"

---

## 完整示例：将时事通讯订阅者添加到您的 CRM

一个非常常见的模式是：机器人回答完毕后，提供订阅时事通讯的选项，联系人回复其电子邮件地址，该地址应立即存入您的电子邮件工具中。大多数 CRM（FluentCRM、ActiveCampaign、MailerLite、Brevo 等）都接受简单的 POST 请求来实现此目的，因此无需中间的自动化平台。

本示例使用 WordPress 上的 **FluentCRM**。对于任何为您提供“传入 Webhook”或“创建订阅者”端点的其他工具，其形式都是相同的。

**首先，从您的 CRM 获取 URL。** 在 WordPress 中，打开 **FluentCRM → 设置 → 传入 Webhook (Incoming Webhooks)** 并创建一个 Webhook。选择新联系人应获得的列表、标签和订阅状态，然后复制生成的 Webhook URL。您在此处设置的任何内容都会自动应用，因此机器人只需发送电子邮件地址即可。

**然后设置自定义函数：**

**基本信息：**
- **名称：** `add_newsletter_subscriber`
- **描述：** "使用联系人在聊天中提供的电子邮件地址将其添加到我们的时事通讯列表中"
- **AI 操作：** "在联系人同意订阅时事通讯并提供其电子邮件地址时使用此操作。在他们实际提供地址之前不要调用它，也不要对同一个人调用两次。"

**连接：**
- **URL：** 您从 CRM 复制的 Webhook URL
- **方法：** POST

**输入参数：**
- `email` (字符串，必填)："联系人在对话中提供的电子邮件地址"
- `first_name` (字符串，选填)："联系人的名字（如果他们提到了的话）"

**跳过系统数据：** 将此项**开启**。您的 CRM 只需要上述字段，更精简的有效负载可以避免因工具拒绝意外字段而导致的错误。

**响应映射：** 此处不需要。机器人继续运行无需返回任何内容。

**别忘了为您运行对话的 Agent 开启该函数**（请参阅 [将函数分配给 Agent](#assigning-functions-to-an-agent)）。这是正确构建的函数无法触发的最常见原因。

::: tip
**提示：** 机器人还内置了 **更新联系人电子邮件** 工具，可将地址保存到平台内的联系人记录中。这与此功能是分开的，并且可以与此功能配合使用——内置工具可保持您自己的联系人记录完整，而自定义功能则将地址推送到您的 CRM。
:::


---

## 实现可靠自定义函数的技巧

1. **确保重复请求是安全的。** 如果同一个请求被意外发送了两次，它不应创建重复的记录。网络故障偶尔会导致这种情况发生。

2. **返回清晰的错误消息。** 如果您的系统端出现问题，请返回一条人类可读的错误信息。机器人会优雅地将其转达给客户。

3. **保持响应时间在 10 秒以内。** 如果您的系统处理时间较长，请考虑先返回一个快速确认信息。

4. **处理过期或无效的凭据。** 如果您的 API 密钥过期，请确保错误信息清晰明确，以便机器人知道应提醒人工处理，而不是盲目重试。

5. **编写详细的描述。** AI 会利用您的描述来判断何时调用函数，以及如何从对话中提取正确的信息。模糊的描述会导致错误。

6. **通过真实对话进行测试。** “试用”(Try Out) 功能非常适合初步测试，但请务必监控最初的几次实时对话，以确保一切都能在真实的客户查询中正常工作。

7. **保留您端的日志。** 请您的开发人员记录来自应用程序的请求，以便您可以快速调试任何问题。

8. **使用公共最终 URL。** 您的函数 URL 必须是公共 Web (HTTP/HTTPS) 地址。出于安全考虑，内部地址、localhost 和私有网络地址将被拒绝，且平台不会跟踪重定向——请将函数直接指向最终 URL，而不是指向重定向到该 URL 的地址。

---

## 执行限制

每个自定义函数在编辑器底部都有一个可选的 **执行限制** 部分。它控制 AI 运行该函数的频率，以及是否可以重用之前的结果。这里的所有内容都是可选的——全部留空，函数将表现得与之前完全一致。


**只读函数。** 如果您的函数仅 *读取* 数据（例如股票查询、价格检查、订单状态搜索），且从不创建或更改任何内容，请开启此项。当临时的网络故障在 AI 回复过程中中断时，平台可以安全地重试对话轮次，而不会让客户收不到回复。仅在函数确实从不执行写入操作时才启用它：创建记录的函数必须保持关闭状态，以确保重试操作永远不会意外运行两次。

**在重复调用时提供缓存结果。** 当 AI 使用相同的输入再次调用该函数时（例如，客户两次询问相同的问题），将重用之前的结果，而不是再次调用您的端点。缓存结果最多保留 24 小时，而使用 *不同* 输入的调用总是会重新请求您的端点。

**每次对话的最大运行次数。** 对函数在一次对话中可以运行的次数设置硬性上限。对于仅应在每次聊天中触发一次的函数（例如生成报价、触发回调、启动自动化），请将其设置为 1。当达到上限时，AI 会被告知该函数已运行并获得最近一次的结果，因此它仍然可以回答客户，而不会保持沉默。

**每个时间窗口的最大运行次数。** 跨时间的速率限制：例如，60 分钟内最多运行 5 次。这对于调用付费第三方服务或触发较重自动化的函数非常有用。两个框必须同时填写（运行次数和以分钟为单位的时间窗口，最长可达 7 天）。

需要注意的几点：

- 限制仅计算 **成功** 的运行次数。在您的端点侧失败的调用不会消耗配额。
- 当运行被限制阻止时，客户永远不会被晾在一边——AI 会被告知原因，并利用它已有的信息进行处理。
- 限制适用于函数运行的所有场景：每个渠道的常规聊天，以及由自动化管理的函数。“试用”中的测试对话不计入次数，也不受限制。

---

## 内置机器人工具

除了您自己构建的自定义函数外，平台还附带了一个预构建工具库，AI 机器人可以在对话期间使用这些工具。这些工具涵盖了机器人需要执行的最常见操作——提醒团队成员、预约、标记联系人、搜索您的网站、安排后续跟进等——因此您无需从零开始进行连接。

**机器人会根据对话中发生的情况以及您的智能体（及其关联的营销活动）的配置，决定何时使用每种工具。** 大多数工具会在相关功能启用时自动开启（例如，预订工具仅在您连接日历并启用预订功能后才可用）。

**积分成本：** 每次工具调用均按照您 Agent 的 AI 质量层级计费，您自行构建的自定义函数也按相同方式计费：

| AI 质量层级 | 每次工具调用的积分 | 连接您自己的 Anthropic 密钥 (BYOK) 时 |
|---|---|---|
| Pro | 1 积分 | 0 积分 — 在您的密钥上运行 |
| Economy (已弃用) | 0.5 积分 | 0 积分 — 在您的密钥上运行 |
| Max | 0.25 积分 | 仍为 0.25 积分，即使连接了您自己的密钥也会计费，因为 Max 在我们自己的模型上运行 |
| Mini | 0.15 积分 | 仍为 0.15 积分，即使连接了您自己的密钥也会计费，因为 Mini 在我们自己的模型上运行 |

### 团队与任务工具

| 工具 | 功能 | 机器人使用时机 |
|------|--------------|----------------------|
| **提醒团队成员** | 暂停该联系人的机器人对话，并通过电子邮件通知您的团队需要人工介入。聊天会被标记，以便团队成员接手。 | 当客户要求人工服务、感到沮丧，或询问机器人不允许或无法回答的问题时。 |
| **创建任务** | 在您的任务看板上创建一个新任务，并可选择将其链接到联系人和对话。机器人会继续正常回复——任务仅作为提醒团队后续跟进的备注。 | 针对非紧急事项，如功能请求、追加销售机会或团队稍后应处理的回电。 |
| **建议更新常见问题解答 (FAQ)** | 当机器人遇到无法很好回答的问题时，它会创建一个任务，要求您的团队在知识库中添加答案。 | 当联系人询问现有 FAQ 未涵盖的内容时——以便下次修复该知识缺口。 |
| **为 FAQ 建议添加上下文** | 如果后续有其他联系人以不同角度询问类似问题，机器人会将该上下文附加到现有的 FAQ 建议中，而不是创建重复的任务。 | 自动执行——当多人提出相同的知识缺口时，保持您的任务列表整洁。 |

### 联系人工具

| 工具 | 功能 | 机器人使用时机 |
|------|--------------|----------------------|
| **标记** | 在每次机器人回复后自动运行——这不是面向客户的机器人决定调用的工具。系统会审查最近的对话并应用相关标签，尽可能重用您现有的标签（仅在需要时创建新标签）。 | 自动执行——每当对话揭示了值得细分的内容时，例如兴趣、意图、潜在客户质量或语言。 |
| **更新联系人姓名** | 当客户分享姓名时，保存其名字和/或姓氏。 | 当客户进行自我介绍或更正姓名时。 |
| **更新联系人电子邮件** | 当客户分享电子邮件地址时，保存该地址。 | 当客户提供电子邮件时——用于新闻通讯、收据、账户查询等。 |

### 预约与预订工具

这些工具仅在链接到您智能体的营销活动中启用了预订功能，并且配置了日历事件类型时才可用。

| 工具 | 功能 | 机器人使用时机 |
|------|--------------|----------------------|
| **检查可用时段** | 为给定的日期或日期范围查找您已连接的日历中哪些时间段是空闲的。 | 当客户想要预订且机器人需要提供真实的可用时间时。 |
| **预约** | 在您的日历中创建预约，并向客户确认预订。 | 在客户确认特定日期和时间后。 |
| **更改预约** | 将现有预约重新安排到新的日期和时间。 | 当客户要求重新安排时。 |
| **取消预约** | 取消现有预约。 | 当客户要求取消时。 |
| **查询预约** | 拉取联系人的现有预约，以便机器人了解已预订的内容。 | 当客户询问“我的预约是什么时候？”时，或在提议重新安排之前。 |

### 知识与 Web 工具

| 工具 | 功能 | 机器人使用时机 |
|------|--------------|----------------------|
| **搜索您的网站** | 扫描您添加到营销活动动态 URL 列表中的 URL，以查找回答客户问题的产品页面、文章或其他内容。仅在启用 **AI Web 搜索** 且您至少添加了一个动态 URL 时可用。如果 AI Web 搜索关闭，机器人将无法读取页面或链接——即使是客户粘贴到聊天中的链接。 | 当客户询问的内容可能存在于您的网站上时——如产品、定价、地点、政策。 |
| **检查链接** | 读取特定 URL 的内容，以便机器人回答有关该页面的问题。仅在启用 **AI Web 搜索** 且您至少添加了一个动态 URL 时可用。如果 AI Web 搜索关闭，机器人将无法读取页面或链接——即使是客户粘贴到聊天中的链接。 | 当客户分享链接或询问您网站上的特定页面时。 |
| **搜索网络** | 运行公共 Google 搜索并返回前几条结果，以便机器人回答您自身内容之外的问题。 | 当客户询问一般性问题（例如方向、公共信息）且该信息不在您的知识库中时。仅在启用 Web 搜索时使用。 |

### 跟进工具

这些工具要求在链接到您的智能体（Agent）的营销活动中启用跟进功能。

| 工具 | 功能描述 | 机器人使用场景 |
|------|--------------|----------------------|
| **安排智能跟进** | 使用您的跟进序列安排智能跟进消息 — 根据对话选择合适的模板和时机。 | 当客户保持沉默或要求机器人“稍后再联系”时。 |
| **安排跟进** | 在特定时间安排基础跟进。 | 当机器人需要在特定时刻推动对话进展时。 |

### 自定义函数运行器

| 工具 | 功能描述 | 机器人使用场景 |
|------|--------------|----------------------|
| **运行自定义函数** | 执行您构建并分配给智能体的一个自定义函数（请参阅本页其余部分）。 | 当客户的请求与您的某个自定义函数用途相匹配时。 |

### 餐厅预订工具（Zenchef 和 Formitable）

这些工具仅在连接了 Zenchef 或 Formitable 集成时可用。它们允许机器人端到端地管理餐厅预订。

| 工具 | 功能描述 | 机器人使用场景 |
|------|--------------|----------------------|
| **查询餐厅空位** | 查找指定日期、人数和（可选）用餐区域的空余预订时段。 | 当客人要求预订餐位时。 |
| **创建餐厅预订** | 创建新的预订。 | 在客人确认特定时段后。 |
| **更新餐厅预订** | 更改现有预订的日期、时间、人数或备注。 | 当客人要求修改其预订时。 |
| **取消或更改预订状态** | 取消预订或更新其状态（例如：已确认、未到场）。 | 当客人取消预订，或机器人需要标记状态变更时。 |
| **搜索预订** | 查找符合姓名、电子邮件或日期等条件的现有预订。 | 当回头客询问现有预订信息时。 |
| **更新客人资料** | 在餐厅系统中更新客人的资料（偏好、备注、联系信息）。 | 当客人分享饮食偏好、新电话号码或其他个人资料级信息时。 |
| **列出餐厅产品** | 拉取可供预订的菜单、套餐或附加项目列表。 | 当客人询问“你们有什么套餐？”或机器人需要将菜单附加到预订时。 |

### 启用和禁用工具

大多数工具都在智能体的 **AI 能力 (AI Abilities)** 选项卡中进行控制（如果您使用的是经典营销活动，则在营销活动的 **AI 能力** 步骤中）：

- **预订工具**：在您启用预订并连接日历时开启 — 目前这仍是按营销活动设置的，您可以从智能体的“AI 能力”选项卡直接跳转到该营销活动的设置步骤。
- **跟进工具**：在您启用跟进功能时开启。
- **餐厅工具**：在您连接 Zenchef 或 Formitable 账户时开启。
- **网页搜索**：在 **常见问题与知识库 (FAQs & Knowledge)** 选项卡中有其独立的开关。
- **任务工具**：可以通过 **允许 AI 创建任务 (Allow AI to create tasks)** 开关按智能体进行关闭（默认开启；在 **设置 (Settings) → 个人资料 (Profile) → 功能 (Features)** 中的账户级任务开关会关闭所有地方的任务系统）。
- **联系人更新工具**：在同一个 **AI 能力** 选项卡中控制 — 决定 AI 是否可以重命名联系人或保存额外收集的信息。
- **提醒工具**：始终可用；**标签 (tagging)** 在机器人每次回复后自动运行（这不是机器人选择调用的工具）。

如果您希望机器人停止使用某个特定的内置工具，最彻底的方法是禁用其底层功能（例如，关闭预订功能以禁用所有预订工具）。

---

## 由自动化管理的函数

“自定义函数”页面上的某些条目可能带有**由自动化管理**徽章。这些条目并非在此处创建，而是来自具有**AI 智能体函数**触发器的自动化。该触发器赋予了您的智能体一项能力，其步骤是在自动化画布上以可视化方式构建的，而不是指向外部网址。

托管函数由系统为您代管：其名称、描述和字段始终遵循自动化触发器中的设置，因此无法在此页面上进行编辑或删除——请使用其 **打开自动化** 链接并直接修改自动化本身。不过，您仍然可以像往常一样选择哪些智能体拥有该函数：在智能体的 **AI 能力** 选项卡中，它会与其他能力一起显示，并配有常规的开/关切换开关（如果其自动化已暂停，该行会显示相应提示——当自动化开启时，该能力即会生效）。关于它的其他一切行为都与其他自定义函数相同：AI 会决定何时调用它、收集您定义的详细信息，并可以在同一对话中使用自动化的回复。

如果您正在两者之间进行选择：将常规自定义函数指向一个已有调用地址的系统；当工作内容是您希望通过步骤组合完成时（例如在电子表格或数据库中查找内容、根据条件分支、创建记录），且无需运行自己的服务器，请构建一个带有 AI Agent 函数触发器的自动化。请参阅 [自动化](../automations/automations.md#letting-your-ai-agent-call-an-automation)。

---

## 套餐要求

自定义函数功能适用于包含该功能的套餐。请检查您的订阅以确认可用性。

---

## 后续步骤

- [将 MCP 服务器连接到您的机器人](mcp-servers.md) — 一组现成的工具包，而不是一次一个函数。
- [AI Agents](../ai-agents/ai-agents.md) — 自定义函数所属的 AI Studio 组的主页面，也是将自定义函数分配给机器人的地方。
