自定义函数
自定义函数可以让您的 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 中创建或更新记录
- 报价生成 - 机器人收集客户的需求,并从您的定价系统中生成个性化报价
- 预订 - 机器人会在您的外部预订系统中创建预约
- 折扣验证 - “这个优惠码有效吗?”机器人会进行检查并确认
- 账户查询 - 自动识别回头客并调出其账户详细信息
客户永远看不到幕后发生的事情。 他们体验到的只是一个能够用真实、最新的信息回答问题的机器人。
自定义函数的工作原理(简单版本)
以下是对话期间触发自定义函数时发生的情况:
- 客户询问某事,需要实时数据(例如:“我的订单在哪里?”)
- 机器人识别出需要使用自定义函数来回答
- 机器人收集客户缺失的信息(例如:“您的订单号是多少?”)
- 平台发送请求到您的系统(您的网站、CRM 或任何其他工具),并附带相关详细信息
- 您的系统响应数据(例如:订单状态、追踪号码、送达日期)
- 机器人读取响应并撰写自然回复:“您的订单 ORD-4582 已发货,预计周五送达!”
自定义函数调用的费用
每次自定义函数调用均按照您 Agent 的 AI 质量层级计费:
| AI 质量等级 | 每个自定义函数调用的积分 | 连接您自己的 Anthropic 密钥 (BYOK) |
|---|---|---|
| Pro | 1 积分 | 0 积分 — 使用您的密钥运行 |
| Economy (已弃用) | 0.5 积分 | 0 积分 — 使用您的密钥运行 |
| Max | 0.25 积分 | 仍为 0.25 积分,即使连接了您自己的密钥也会计费 |
| Mini | 0.15 积分 | 仍为 0.15 积分,即使连接了您自己的密钥也会计费 |
设置自定义函数(分步指南)
- 在主侧边栏的 AI Studio 下,点击 Custom Functions(自定义函数)。
- 点击右上角的绿色 + 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 |
携带密钥或密码的标头值(例如 Authorization 或 X-API-Key)在输入后会显示为圆点。点击值旁边的眼睛图标即可查看。
安全提示: 请使用权限受限的专用 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 |
标识处理该对话的 AI 智能体,格式为 agent:<agentId>(该字段保留了其旧名称) |
system.userId |
您的用户 ID |
system.channel |
消息渠道(例如 "whatsapp", "instagram") |
system.contact |
完整的联系人记录(姓名、电话、电子邮件、标签等) |
system.campaign |
处理该对话的 AI 智能体的设置(该字段保留了其旧名称) |
system.test |
如果这是“试用”测试,则为 true;如果是实时对话,则为 false |
system.callback_url |
仅在开启稍后获取结果时:发送结果的链接(请参阅 长时间运行的任务) |
system.callback_expires_at |
仅在开启稍后获取结果时:该链接的过期时间 |
如果您的系统需要识别联系人、检查是哪个智能体调用了该函数,或在测试期间表现出不同的行为,这将非常有用。
当后续检查调用您的函数时(请参阅 仅在检查通过时发送),该请求与对话中的调用不同:它没有输入参数,且
system字段仅携带system.contact(及其id)以及一个system.follow_up块(type、cycle_number、follow_up_number、reason、campaign_id、agent_id)。其中不包含campaign对象。跳过系统数据(Skip System Data)也适用于该调用。
不需要系统数据? 在函数构建器中打开 跳过系统数据 (Skip System Data) 开关。机器人将仅发送您定义的输入参数,而不包含联系人或智能体数据。如果您的端点拒绝意外字段,或者您只是想要更精简的有效载荷,请使用此选项。
第 5 步:测试它,然后让机器人读取响应
通常您根本不需要映射响应字段。一旦您的端点做出响应,机器人就会读取整个 JSON 响应,并使用您函数的 描述 (Description) 和 用途 (Purpose (AI Action))(以及每个参数自身的描述)来确定哪些内容重要,并以自然的方式呈现。函数本身清晰的描述(“检索客户订单的当前状态,包括物流信息和追踪”)比逐个字段映射更能发挥作用。
如果您的端点返回较大的响应,而您只想让机器人看到几个特定的值,请打开 响应映射 (Response mapping) 部分(默认折叠,位于“测试”上方)。每一行从响应中选取一个顶级字段:响应字段 (Response field) 是 API 的 JSON 回复中的字段名称,输出字段 (Output field) 是机器人接收该值时使用的名称。只要填写至少一行,机器人就只会获取您映射的值,而不是完整的响应体。将该部分留空以保持默认的完整响应行为。
在保存之前,请使用构建器底部的 测试 (Test) 部分,按照配置发送请求并查看真实响应,无需离开应用程序:
您在此处看到的响应是端点的原始回复。如果您在上方设置了响应映射,则实际聊天中的机器人只会接收那些已映射的字段——测试始终显示完整的原始响应,以便您查看可用于映射的内容。如果看起来有误(字段名称意外、嵌套过多),请在您的端点上进行修复或调整您的映射。
为智能体分配函数
创建自定义函数后,您需要告知每个智能体它可以使用哪些函数:
- 在 AI Studio → AI 智能体 (AI Agents) 下打开 智能体。
- 转到其 AI 能力 (AI Abilities) 选项卡。
- 您将看到您创建的每个自定义函数的列表。为您希望此智能体的机器人能够调用的每个函数开启开关。
- 点击底部的 保存更改 (Save changes)。选择仅在保存后生效。
只有已分配的函数才可供该智能体的机器人使用。这可以防止机器人意外使用不相关的函数。
测试您的自定义函数
在上线之前,请进行全面测试:
- 运行内置测试 - 使用函数构建器内的测试部分(见上文)进行快速检查,无需离开应用程序——填入实际值并点击“运行测试”。
- 直接测试您的系统端点 - 对于下方的完整检查清单,使用 Postman 等专用工具(或由您的开发人员)进行比单次“运行测试”更深入的检查。
- 在“试用”中测试 - 模拟一段对话,让客户询问应该触发该函数的问题。
- 检查响应 - 确保机器人能正确读取并呈现数据。
- 测试错误场景 - 如果客户提供了无效的订单号会怎样?如果您的系统暂时宕机了会怎样?
当测试返回 401 或 403 时
401 或 403 意味着您的端点收到了请求但拒绝了它。关键点在于您的日志中没有任何显示——大多数工具在启动工作流之前就会拒绝未经授权的调用,因此您这边什么也看不到,看起来就像请求从未到达一样。
这几乎总是身份验证不匹配导致的:您的端点需要一种凭据,而函数发送的是另一种。请检查您在 第 3 步 中添加的标头是否正是您的系统所期望的。
最常见的情况是 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 在对话期间调用自定义函数且调用失败时(例如由于凭据错误、端点宕机或超时),对话现在会显示此情况:在代理的试用选项卡和聊天中的真实对话线程中,会出现一个红色的 “(函数名) 失败” 标记。点击该标记可展开详细信息:显示您的端点返回的状态码及其响应正文,这通常足以让您准确判断需要修复的内容(401 伴随“未经授权”的消息意味着身份验证标头有问题;超时意味着您的端点耗时超过 30 秒;对于需要更长时间的任务,请参阅 长时间运行的任务)。
成功的调用也会显示一个标记——点击它即可查看您的端点实际返回的内容。这是端到端调试集成的最快方法:在“试用”中进行测试对话,然后点击函数标记即可查看真实的请求结果,无需离开当前页面。
当工具在实际对话中持续失败时
如果同一个自定义函数在您的 AI 智能体对话期间 24 小时内失败 3 次,您每天会收到一次相关提醒:通过电子邮件、通知铃铛以及您已启用的推送通知。该提醒会指明工具名称、显示最后一次错误并提供受影响对话的链接,因为智能体已告知这些联系人它遇到了技术问题。在“设置”中,该函数的行会显示一行 Failing(失败),并带有错误计数和最后一次错误信息,直到该工具恢复正常;一次成功的调用即可清除此状态。您可以在 Settings → Notifications → Tool errors(设置 → 通知 → 工具错误)下关闭这些提醒。
完整示例:订单状态查询
这是一个您可以作为模板使用的完整配置示例:
基本信息:
- 名称:
check_order_status - 描述: “检索客户订单的当前状态,包括物流信息和追踪”
- AI 动作: “当客户询问订单状态、包裹位置或预计到达时间时调用此函数。请务必先询问订单号。”
连接:
- URL:
https://api.mystore.com/orders/lookup - 方法: POST
请求头:
Authorization:Bearer sk_live_abc123Content-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 商店。)
首先,在 Shopify 中创建一个访问令牌。 Shopify 在 2026 年期间对此进行了更改:应用不再能在 Shopify 管理后台内创建,新的应用屏幕会提供 Client ID(客户端 ID)和 Client secret(客户端密钥),而不是现成的令牌。以下步骤将这些凭据转换为永久令牌。每个商店只需操作一次,大约需要十分钟。(如果商店已经通过旧方式创建了旧应用,其现有令牌将继续有效——请直接跳至下方的自定义函数部分。)
- 前往 Shopify 开发人员仪表板 dev.shopify.com,打开您的组织,然后点击 Apps → Create app。将其命名为类似
Order lookup的名称。 - 为该应用授予 read_orders 权限,发布一个版本,并将该应用安装到商店中。
- 打开应用的 Settings,将商店自己的网页地址(例如
https://www.yourstore.com/)添加到允许的重定向 URL 中。保存。 - 仍在 Settings 中,复制 Client ID 和 Client secret。
- 在已登录该商店 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=后跟一个长值 —— 请复制该值。它仅在几分钟内有效,因此请直接进行下一步。 - 将该代码交换为令牌,您可以在 Your AI Connector 中完成此操作。在自定义函数构建器中,将 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)。这是正确构建的函数无法触发的最常见原因。
提示: 机器人还内置了 更新联系人电子邮件 工具,可将地址保存到平台内的联系人记录中。这与此功能是分开的,并且可以与此功能配合使用——内置工具可保持您自己的联系人记录完整,而自定义功能则将地址推送到您的 CRM。
实现可靠自定义函数的技巧
-
确保重复请求是安全的。 如果同一个请求被意外发送了两次,它不应创建重复的记录。网络故障偶尔会导致这种情况发生。
-
返回清晰的错误消息。 如果您的系统端出现问题,请返回一条人类可读的错误信息。机器人会优雅地将其转达给客户。
-
保持响应时间在 10 秒以内。 如果您的系统处理时间较长,请考虑先返回一个快速确认信息。
-
处理过期或无效的凭据。 如果您的 API 密钥过期,请确保错误信息清晰明确,以便机器人知道应提醒人工处理,而不是盲目重试。
-
编写详细的描述。 AI 会利用您的描述来判断何时调用函数,以及如何从对话中提取正确的信息。模糊的描述会导致错误。
-
通过真实对话进行测试。 “试用”(Try Out) 功能非常适合初步测试,但请务必监控最初的几次实时对话,以确保一切都能在真实的客户查询中正常工作。
-
保留您端的日志。 请您的开发人员记录来自应用程序的请求,以便您可以快速调试任何问题。
-
如果您的防火墙需要 IP 白名单,每个自定义函数调用(以及每个后续检查)都将从一个固定的 IPv4 地址发送,该地址与我们 Webhook 使用的地址相同;没有地址范围,没有 IPv6,也不会轮换。请联系支持团队,我们将为您提供该地址。请开启请求签名并验证签名作为您真正的信任检查,将 IP 视为额外的辅助过滤手段。
-
使用公共最终 URL。 您的函数 URL 必须是公共 Web (HTTP/HTTPS) 地址。出于安全考虑,内部地址、localhost 和专用网络地址将被拒绝,且平台不会跟随重定向 —— 请直接将函数指向最终 URL,而不是指向会重定向到该 URL 的地址。
长时间运行的任务:稍后获取结果
通常,自定义函数必须在 30 秒内响应,而联系人则在等待回复。有些任务耗时较长:例如渲染视频、运行信用检查或等待您方人员审批。对于这些任务,请开启稍后获取结果(长时间运行)。此时,AI 的调用仅用于启动任务。您的服务会立即响应,AI 会告知联系人结果正在处理中并继续对话,待任务完成后,您的服务再将结果发送到回调链接。
何时使用
当您的服务无法在 30 秒内可靠地响应时,请使用此功能。对于快速查询(如订单状态、库存检查、价格),请保持关闭状态:这些情况作为普通调用更简单,因为 AI 会在同一次回复中直接给出结果。
编辑器中的设置
您可以在自定义函数编辑器中找到这些设置,位于跳过系统数据旁边。
| 设置 | 作用 |
|---|---|
| 稍后获取结果(长时间运行) | 将函数转换为启动信号。您的服务有 30 秒的时间来响应第一次调用(任何 2xx 状态码均可,正文会被忽略),然后有最多 等待时长 的时间来发送结果。 |
| 结果到达时 | AI 编写下一条消息(默认):AI 读取结果并以自己的口吻编写下一条消息,遵循函数的目的(AI 操作)。按原样发送文本:您发布的文本将逐字发送给联系人。 |
| 等待时长 | 回调链接的有效时长(以小时为单位),范围为 1 到 168(7 天)。默认值为 24。 |
您的服务接收到的内容
开启此开关后,除了上述所有内容(您的输入参数、system 块和签名标头)外,每次调用都会在三个地方携带回调链接:
| 位置 | 包含内容 |
|---|---|
标头 X-Callback-Url |
回调链接。 |
正文字段 callback_url |
同样的链接,适用于 POST、PUT、PATCH 和 DELETE。对于 GET 和 HEAD,它是一个名为 callback_url 的查询参数。 |
system.callback_url 和 system.callback_expires_at |
链接及其过期时间(ISO 8601 日期和时间)。当跳过系统数据开启时,此项会被省略。 |
该链接对每次调用都是唯一的,属于该联系人和该次对话,仅可使用一次,并在等待时长后过期。您不需要 API 密钥即可使用它:链接本身就是权限。请像对待密码一样保护它,切勿将其写入公共日志。
发送结果
任务完成后,向回调链接发送一个 POST 请求:
POST https://api.<your host>/v1/custom-functions/callback/d3f9...
Content-Type: application/json
{
"result": { "video_url": "https://cdn.example.com/spring-offer.mp4", "duration_seconds": 42 },
"message": "Your video is ready: https://cdn.example.com/spring-offer.mp4"
}
result是 AI 读取的内容。它可以是文本或 JSON 对象。message是可选的。使用 按原样发送文本 时,如果发送的是文本,联系人会收到message,否则收到result。media_url是可选的:一个指向文件的https链接(图像、视频、音频或文档),联系人会将其作为真正的附件而非链接接收。请参阅下方的 发送文件。- 您还可以使用
Content-Type: text/plain发送纯文本正文。它会被视为result。 - 正文最多可包含 64 KB。
回调链接的响应内容:
| 状态 | 正文 | 含义 |
|---|---|---|
202 |
{"ok":true,"received":true} |
已收到结果。 |
200 |
{"ok":true,"duplicate":true} |
此链接已收到过结果。第二次提交不会产生任何影响,因此重试始终是安全的。 |
400 |
正文无效。 | |
404 |
链接未知。请检查您是否使用了请求中提供的确切链接。 | |
410 |
链接已过期。AI 已被告知结果未送达。 | |
413 |
正文超过 64 KB。 | |
429 |
一分钟内向同一链接发送了超过 20 次请求。请稍后再试。 |
一个完整示例:耗时三分钟的视频
- AI 调用您的函数。您将收到(已缩短):
POST https://api.example.com/render
X-Callback-Url: https://api.<your host>/v1/custom-functions/callback/d3f9...
Content-Type: application/json
{
"video_title": "Spring offer",
"callback_url": "https://api.<your host>/v1/custom-functions/callback/d3f9...",
"system": {
"contactId": "...",
"callback_url": "https://api.<your host>/v1/custom-functions/callback/d3f9...",
"callback_expires_at": "2026-10-20T19:15:00.000Z"
}
}
- 您的服务开始渲染并立即响应:
{ "status": "started" }
- AI 告知联系人视频正在制作中,并继续聊天。
- 三分钟后,您的服务将结果发布到回调链接:
{ "result": { "video_url": "https://cdn.example.com/spring-offer.mp4", "duration_seconds": 42 } }
- AI 用自己的话编写下一条消息,例如“您的视频已准备好:https://cdn.example.com/spring-offer.mp4”。
正在使用 Zapier 或 Make? 让触发器 Webhook 接收调用,并将流程的最后一步设置为向触发器数据中的 callback_url 发送 POST 请求。
聊天中会发生什么
结果将作为函数条目保存在对话中,因此您可以在收件箱中像查看任何其他自定义函数调用一样看到它。然后,根据 结果到达时 的设置,AI 会编写并发送下一条消息(这会消耗一次 AI 回复,就像任何 AI 消息一样),或者您的文本将按原样发送。如果勾选了 按原样发送文本,则在包含 message 字段时发送该字段,否则在为纯文本时发送 result;如果您仅发布一个不含文本的对象,AI 将代为编写消息。
如果结果到达时该联系人的 AI 已关闭(团队成员接管、AI 已暂停、坐席下线或额度用尽),结果仍会保存在对话中,但不会发送任何消息。当 AI 重新开启时,它也不会补发。团队成员可以在聊天中看到该结果并进行处理。
在坐席的 试用 (Try Out) 选项卡中,整个流程同样有效:结果会出现在测试聊天中。
发送文件(视频、图像、PDF)
作为文件的结果(例如您的服务在后台渲染的视频)在两种模式下都会作为附件发送给联系人,他们可以在聊天中打开该附件。平台会通过以下方式在您的回调中找到该文件:
- 正文中的
media_url(如果您发送了正文)。 - 否则为
result对象上的文件字段:file_url、video_url、image_url、pdf_url、document_url、audio_url、attachment_url或download_url。 - 否则为文本中第一个以文件扩展名(如
.mp4、.jpg、.png或.pdf)结尾的https链接。
使用 AI 编写下一条消息 时,AI 会编写文本,文件会作为该消息的附件(AI 会被告知不要粘贴链接)。使用 按原样发送文本 时,您的 message 将作为附件的标题。
{
"result": { "status": "done", "title": "Spring offer" },
"message": "Your video is ready.",
"media_url": "https://cdn.example.com/spring-offer.mp4"
}
文件最大可达 16 MB,且必须可通过 https 访问。每个渠道支持的类型不同:例如,电子邮件和 WhatsApp 渠道支持视频、图像、音频和文档,而短信 (SMS) 不支持文件。当渠道无法接收文件或文件过大时,联系人仍会收到消息,并在末尾附上文件链接。
当结果从未到达时
如果在 等待时长 (Wait up to) 耗尽之前没有任何内容发布,AI 会被告知结果未送达,以便它可以通知联系人。在 设置 → 错误日志 下会出现代码为 APP-3103 的条目,并且您会收到工具错误通知。
限制概览
- 每个回调链接对应一个结果。后续发送到同一链接的内容将被视为重复项,且不会产生任何更改。
- 每个结果最多 64 KB。
- 每个结果一个文件,最大 16 MB,通过
https传输。 - 每个链接每分钟最多 20 次请求。
- 等待时间 从 1 到 168 小时不等。
- 您的服务仍有 30 秒的时间来响应首次调用。
验证调用确实来自我们
任何获知您函数 URL 的人都可以向其发送伪造请求。在身份验证标头中使用长密钥会有所帮助,但它在每次调用中都是相同的值,因此任何看到过一次请求(在日志或截图中)的人都可以重复使用它。请求签名解决了这个问题:每次调用都携带一个只有持有您密钥的人才能生成的签名,并且该签名会在几分钟后过期。
签名是可选的,默认处于关闭状态,并且它是针对您整个账户的一项设置:一个密钥即可为所有自定义函数签名。
开启签名
- 打开自定义函数(Custom Functions)。
- 在函数列表下方,找到请求签名(Request signing)卡片并点击开启签名(Turn on signing)。
- 点击显示(Show),复制密钥(它以
whsec_开头)并将其存储在接收调用的系统中。请像对待密码一样对待它。
您可以从同一张卡片中再次复制密钥、轮换(Rotate)密钥(旧密钥将立即停止工作)或关闭(Turn off)签名。
我们发送的内容
一旦开启签名,自定义函数发出的每次调用都会携带两个额外的标头:AI 在聊天期间的调用、后续发送条件以及编辑器中的运行测试(Run Test)按钮。
| 标头 | 含义 |
|---|---|
X-Webhook-Signature |
签名,格式为 v1=<hex>。 |
X-Webhook-Timestamp |
我们发送的时间,以秒为单位的 Unix 时间戳。 |
除非您设置了自己的 User-Agent 标头,否则每次调用(无论是否签名)都会携带 User-Agent: Custom-Function/1.0。
这些标头和签名的工作方式与已签名 Webhook 完全相同,因此如果您已经验证了我们的 Webhook,同样的代码在这里也适用。唯一的区别是密钥不同。
如何验证
签名是对字符串 <timestamp>.<raw request body> 进行 HMAC-SHA256 计算的结果,使用您的签名密钥作为密钥。请将其与原始(raw)正文进行比对,即您接收到的确切字节:解析 JSON 并将其转回文本可能会改变字节,导致签名无法匹配。
使用 GET(或没有内容发送的 POST)的函数没有正文,因此签名字符串只是带有空正文的 <timestamp>.。此时签名证明了调用确实来自我们且是最近发出的,但它不涵盖查询字符串。
Node.js 示例:
const crypto = require("crypto");
function verify(rawBody, headers, secret) {
const timestamp = headers["x-webhook-timestamp"];
const signature = headers["x-webhook-signature"] || ""; // "v1=<hex>"
// Reject anything older than 5 minutes so a captured request can't be replayed later.
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
const received = signature.replace("v1=", "");
return received.length === expected.length && crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
}
Python 示例:
import hashlib, hmac, time
def verify(raw_body: bytes, headers, secret: str) -> bool:
timestamp = headers.get("X-Webhook-Timestamp", "")
signature = headers.get("X-Webhook-Signature", "").replace("v1=", "")
if not timestamp or abs(time.time() - int(timestamp)) > 300:
return False
expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(signature, expected)
使用编辑器中的运行测试(Run Test)进行测试:一旦开启签名,测试调用会像实时调用一样进行签名,因此通过测试的函数在真实聊天期间也能通过您的检查。
正在使用 API? 可以通过
/v1/custom-functions/signing-secret上的GET、POST和DELETE来读取、生成、轮换和删除同一个密钥。
执行限制
每个自定义函数在编辑器底部都有一个可选的 执行限制 部分。它控制 AI 运行该函数的频率,以及是否可以重用之前的结果。这里的所有内容都是可选的——全部留空,函数将表现得与之前完全一致。
只读函数。 如果您的函数仅读取数据(例如股票查询、价格检查、订单状态搜索),且从不创建或更改任何内容,请开启此选项。当临时的网络故障中断了 AI 的回复时,平台可以安全地重试该对话轮次,而不会让客户收不到回复。仅在函数确实从不执行任何写入操作时才启用此选项:创建记录的函数必须保持关闭状态,以防止重试操作意外导致函数运行两次。使用 GET 方法的函数会自动被视为只读,因为 GET 请求旨在仅获取数据;POST、PUT、PATCH 和 DELETE 函数则需要此开关。 在重复调用时提供缓存结果。 当 AI 使用相同的输入再次调用该函数时(例如,客户两次询问相同的问题),将重用之前的结果,而不是再次调用您的端点。缓存结果最多保留 24 小时,而使用 不同 输入的调用总是会重新请求您的端点。
每次对话的最大运行次数。 对函数在一次对话中可以运行的次数设置硬性上限。对于仅应在每次聊天中触发一次的函数(例如生成报价、触发回调、启动自动化),请将其设置为 1。当达到上限时,AI 会被告知该函数已运行并获得最近一次的结果,因此它仍然可以回答客户,而不会保持沉默。
每个时间窗口的最大运行次数。 跨时间的速率限制:例如,60 分钟内最多运行 5 次。这对于调用付费第三方服务或触发较重自动化的函数非常有用。两个框必须同时填写(运行次数和以分钟为单位的时间窗口,最长可达 7 天)。
在 LinkedIn 上发送报价、合同或发票。 当 AI 在 LinkedIn 上回复时,它是从账户所有者自己的收件箱中发送的,因此除非所有者明确要求,否则不应代表所有者发送报价、合同、估价单、发票、付款链接或访问权限。使用 自动 (Automatic)(默认设置)时,名称或描述中包含发送上述内容功能的函数不会在 LinkedIn 上运行:AI 会被告知未发送任何内容,并告知对方所有者将处理此事。选择 允许 (Allowed) 可让该函数在 LinkedIn 上照常运行,或选择 不在 LinkedIn 上使用 (Never on LinkedIn) 以阻止自动检查漏掉的函数。其他渠道不受影响,并且与上述限制不同,此设置也适用于“试用 (Try Out)”功能。
需要注意的几点:
- 限制仅计算 成功 的运行次数。在您的端点侧失败的调用不会消耗配额。
- 当运行被限制阻止时,客户永远不会被晾在一边——AI 会被告知原因,并利用它已有的信息进行处理。
- 限制适用于函数运行的所有场景:每个渠道的常规聊天,以及由自动化管理的函数。“试用”中的测试对话不计入次数,也不受限制。
内置机器人工具
除了您自己构建的自定义函数外,平台还附带了一个预构建工具库,AI 机器人可以在对话期间使用这些工具。这些工具涵盖了机器人需要执行的最常见操作——提醒团队成员、预约、标记联系人、搜索您的网站、安排后续跟进等——因此您无需从零开始进行连接。
机器人会根据对话中发生的情况以及您的智能体配置方式来决定何时使用每种工具。大多数工具在相关功能启用时会自动开启(例如,预订工具仅在您连接日历并启用预订后才可用)。
积分成本: 每次工具调用均按照您 Agent 的 AI 质量层级计费,您自行构建的自定义函数也按相同方式计费:
| AI 质量等级 | 每个工具调用的积分 | 连接您自己的 Anthropic 密钥 (BYOK) |
|---|---|---|
| Pro | 1 积分 | 0 积分 — 使用您的密钥运行 |
| Economy (已弃用) | 0.5 积分 | 0 积分 — 使用您的密钥运行 |
| Max | 0.25 积分 | 仍为 0.25 积分,即使连接了您自己的密钥也会计费 |
| Mini | 0.15 积分 | 仍为 0.15 积分,即使连接了您自己的密钥也会计费 |
团队与任务工具
| 工具 | 功能 | 机器人使用时机 |
|---|---|---|
| 提醒团队成员 | 暂停该联系人的机器人对话,并通过电子邮件通知您的团队需要人工介入。聊天会被标记,以便团队成员接手。 | 当客户要求人工服务、感到沮丧,或询问机器人不允许或无法回答的问题时。 |
| 创建任务 | 在您的任务看板上创建一个新任务,并可选择将其链接到联系人和对话。机器人会继续正常回复——任务仅作为提醒团队后续跟进的备注。 | 针对非紧急事项,如功能请求、追加销售机会或团队稍后应处理的回电。 |
| 建议更新常见问题解答 (FAQ) | 当机器人遇到无法很好回答的问题时,它会创建一个任务,要求您的团队在知识库中添加答案。 | 当联系人询问现有 FAQ 未涵盖的内容时——以便下次修复该知识缺口。 |
| 为 FAQ 建议添加上下文 | 如果后续有其他联系人以不同角度询问类似问题,机器人会将该上下文附加到现有的 FAQ 建议中,而不是创建重复的任务。 | 自动执行——当多人提出相同的知识缺口时,保持您的任务列表整洁。 |
联系人工具
| 工具 | 功能 | 机器人使用时机 |
|---|---|---|
| 标记 | 在每次机器人回复后自动运行——这不是面向客户的机器人决定调用的工具。系统会审查最近的对话并应用相关标签,尽可能重用您现有的标签(仅在需要时创建新标签)。 | 自动执行——每当对话揭示了值得细分的内容时,例如兴趣、意图、潜在客户质量或语言。 |
| 更新联系人姓名 | 当客户分享姓名时,保存其名字和/或姓氏。 | 当客户进行自我介绍或更正姓名时。 |
| 更新联系人电子邮件 | 当客户分享电子邮件地址时,保存该地址。 | 当客户提供电子邮件时——用于新闻通讯、收据、账户查询等。 |
预约与预订工具
这些工具仅在您的智能体上启用了预订功能并配置了日历事件类型时才可用。
| 工具 | 功能 | 机器人使用时机 |
|---|---|---|
| 检查可用时段 | 为给定的日期或日期范围查找您已连接的日历中哪些时间段是空闲的。 | 当客户想要预订且机器人需要提供真实的可用时间时。 |
| 预约 | 在您的日历中创建预约,并向客户确认预订。 | 在客户确认特定日期和时间后。 |
| 更改预约 | 将现有预约重新安排到新的日期和时间。 | 当客户要求重新安排时。 |
| 取消预约 | 取消现有预约。 | 当客户要求取消时。 |
| 查询预约 | 拉取联系人的现有预约,以便机器人了解已预订的内容。 | 当客户询问“我的预约是什么时候?”时,或在提议重新安排之前。 |
知识与 Web 工具
| 工具 | 功能 | 机器人使用时机 |
|---|---|---|
| 搜索您的网站 | 扫描您添加到智能体动态 URL 列表中的 URL,以查找回答客户问题的产品页面、文章或其他内容。仅在 AI 网页搜索 开启且您至少添加了一个动态 URL 时可用。如果 AI 网页搜索关闭,机器人将无法读取页面或链接,即使是客户粘贴到聊天中的链接也无法读取。 | 当客户询问的内容可能存在于您的网站上时(如产品、定价、地点、政策)。 |
| 检查链接 | 读取特定 URL 的内容,以便机器人能够回答有关该页面的问题。仅在 AI 网页搜索 开启且您至少添加了一个动态 URL 时可用。如果 AI 网页搜索关闭,机器人将无法读取页面或链接,即使是客户粘贴到聊天中的链接也无法读取。 | 当客户分享链接或询问您网站上的特定页面时。 |
| 搜索网页 | 运行公开的 Google 搜索并返回前几条结果,以便机器人能够回答您内容之外的问题。 | 当客户询问某些通用信息(例如方向、公共信息)且这些信息不在您的知识库中时。仅在启用网页搜索时使用。 |
跟进工具
这些工具需要启用智能体的后续跟进功能。
| 工具 | 功能描述 | 机器人使用场景 |
|---|---|---|
| 安排智能跟进 | 使用您的跟进序列安排智能跟进消息 — 根据对话选择合适的模板和时机。 | 当客户保持沉默或要求机器人“稍后再联系”时。 |
| 安排跟进 | 在特定时间安排基础跟进。 | 当机器人需要在特定时刻推动对话进展时。 |
自定义函数运行器
| 工具 | 功能描述 | 机器人使用场景 |
|---|---|---|
| 运行自定义函数 | 执行您构建并分配给 Agent 的自定义函数(请参阅本页其余部分)。 | 当客户的请求与您某个自定义函数的目标相匹配时。 |
| 发送工具结果中的文件 | 将自定义函数或 MCP 服务器返回的图片、视频、音频文件或文档链接作为真实附件发送,而不是直接粘贴链接。当 Agent 至少拥有一个自定义函数或 MCP 服务器时可用。 | 当工具结果中包含联系人要求查看的文件时。请参阅 来自您自有工具的文件。 |
餐厅预订工具(Zenchef 和 Formitable)
这些工具仅在连接了 Zenchef 或 Formitable 集成时可用。它们允许机器人端到端地管理餐厅预订。
| 工具 | 功能描述 | 机器人使用场景 |
|---|---|---|
| 查询餐厅空位 | 查找指定日期、人数和(可选)用餐区域的空余预订时段。 | 当客人要求预订餐位时。 |
| 创建餐厅预订 | 创建新的预订。 | 在客人确认特定时段后。 |
| 更新餐厅预订 | 更改现有预订的日期、时间、人数或备注。 | 当客人要求修改其预订时。 |
| 取消或更改预订状态 | 取消预订或更新其状态(例如:已确认、未到场)。 | 当客人取消预订,或机器人需要标记状态变更时。 |
| 搜索预订 | 查找符合姓名、电子邮件或日期等条件的现有预订。 | 当回头客询问现有预订信息时。 |
| 更新客人资料 | 在餐厅系统中更新客人的资料(偏好、备注、联系信息)。 | 当客人分享饮食偏好、新电话号码或其他个人资料级信息时。 |
| 列出餐厅产品 | 拉取可供预订的菜单、套餐或附加项目列表。 | 当客人询问“你们有什么套餐?”或机器人需要将菜单附加到预订时。 |
启用和禁用工具
大多数工具都在智能体的 AI 能力 (AI Abilities) 选项卡上进行控制:
- 预订工具:在同一 AI 能力 选项卡上的 预订 (Bookings) 卡片中启用预订并连接日历后开启
- 后续跟进工具:在您启用后续跟进时开启
- 餐厅工具:在您连接 Zenchef 或 Formitable 账户时开启
- 网页搜索:在 常见问题与知识 (FAQs & Knowledge) 选项卡上有其独立的开关
- 任务工具:可以通过 允许 AI 创建任务 (Allow AI to create tasks) 开关针对每个智能体进行关闭(默认开启;在 设置 → 个人资料 → 功能 (Settings → Profile → Features) 中的账户级任务开关会关闭所有地方的任务系统)
- 联系人更新工具:在同一 AI 能力 选项卡上控制,决定 AI 是否可以重命名联系人或将额外收集的信息保存到联系人中
- 提醒工具:始终可用;标签 (tagging) 在每次机器人回复后自动运行(这不是机器人选择调用的工具)
如果您希望机器人停止使用某个特定的内置工具,最彻底的方法是禁用其底层功能(例如,关闭预订功能以禁用所有预订工具)。
由自动化管理的函数
“自定义函数”页面上的某些条目可能带有由自动化管理徽章。这些条目并非在此处创建,而是来自具有AI 智能体函数触发器的自动化。该触发器赋予了您的智能体一项能力,其步骤是在自动化画布上以可视化方式构建的,而不是指向外部网址。
托管函数由系统为您代管:其名称、描述和字段始终遵循自动化触发器中的设置,因此无法在此页面上进行编辑或删除——请使用其 打开自动化 链接并直接修改自动化本身。不过,您仍然可以像往常一样选择哪些智能体拥有该函数:在智能体的 AI 能力 选项卡中,它会与其他能力一起显示,并配有常规的开/关切换开关(如果其自动化已暂停,该行会显示相应提示——当自动化开启时,该能力即会生效)。关于它的其他一切行为都与其他自定义函数相同:AI 会决定何时调用它、收集您定义的详细信息,并可以在同一对话中使用自动化的回复。
如果您正在两者之间进行选择:将常规自定义函数指向一个已有调用地址的系统;当工作内容是您希望通过步骤组合完成时(例如在电子表格或数据库中查找内容、根据条件分支、创建记录),且无需运行自己的服务器,请构建一个带有 AI Agent 函数触发器的自动化。请参阅 自动化。
套餐要求
自定义函数功能适用于包含该功能的套餐。请检查您的订阅以确认可用性。
后续步骤
- 将 MCP 服务器连接到您的机器人 — 一组现成的工具包,而不是一次一个函数。
- AI Agents — 自定义函数所属的 AI Studio 组的主页面,也是将自定义函数分配给机器人的地方。