关于 ai-agent
用于通过 API 或仪表板配置 Zavu AI Agent 的技能,适合以命令式方式创建和更新 Agent。涵盖消息渠道、对话流程、工具、知识库及语音通话;新集成通常推荐使用 functions 技能。
主要功能
- 01通过 API 创建和更新 Agent
- 02配置提供方、模型和提示词
- 03管理消息发送方及渠道连接
- 04设置对话流程、工具和知识库
- 05启用语音并管理电话通话
适用场景
- 01从后台脚本创建客服 Agent
- 02通过仪表板更新 Agent 配置
- 03为消息渠道配置关键词触发流程
- 04设置可接听或拨出电话的 Agent
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zavudev/ zavu-skills --skill ai-agent安装后在 Claude Code 中输入/ai-agent确认已加载。
详细介绍
AI Agent
使用时机
当用户希望通过API 调用配置 AI Agent(无需源文件,也无需部署步骤)时,请使用此技能——通常是在控制面板或后端脚本中以命令式方式创建或更新 Agent。
如果用户希望使用 TypeScript 编写以代码为先、带自定义工具处理程序的 Agent,并通过 zavu CLI 部署,请引导他们使用 functions 技能。该方式更便捷、支持版本控制,并内置部署和调试功能。
快速判断:
| 用户说…… | 使用 |
|---|---|
“我希望 Agent 的工具能查询我的数据库” / “我想用代码编写工具处理程序” / defineTool / npx zavudev deploy | functions 技能 |
| “设置一个能调用我服务器上 webhook 的 Agent” / “从控制面板配置” / “通过 API 创建 Agent” | 此技能 |
| “我从零开始,希望选择最简单的方式” | functions 技能(默认推荐) |
此处介绍的命令式 API 完全受支持,不会弃用,但对于大多数新的集成,我们推荐使用 Functions。
发送方与账户(一段说明)
**发送方(Sender)**是你作为 Zavu-Sender 传入的 API 标识;账户(WhatsApp Business Account、Facebook Page、Telegram 机器人、电话号码)则是它路由到的连接,也是产生费用的对象。发送方免费。在控制面板中连接账户时,会自动创建其发送方;使用 GET /v1/senders 查找,并依据其 channels 数组判断它能发送哪些内容。完整说明请参阅 channel-setup 技能。
架构
Inbound message -> Flow check (keyword match, or an `always` flow?)
-> YES: Execute flow steps
-> NO: LLM call with system prompt + context + KB
-> Agent generates response -> Send reply
创建 Agent 的两种方式
以代码方式使用 defineAgent。 Agent 位于 Zavu Function 中,与它调用的工具并列,由 npx zavudev deploy 进行同步。若 Agent 带有工具、需要在拉取请求中接受审查,或属于你已部署的应用,请优先选择此方式。完整结构请参阅 functions 技能。
import { defineAgent, defineTool } from "@zavudev/functions"
export const support = defineAgent({
name: "Customer Support",
senderId: process.env.SENDER_ID!,
provider: "zavu",
model: "openai/gpt-5.6-luna",
// `prompt` here, `systemPrompt` over the REST API. The two paths name this
// field differently and only `prompt` compiles against @zavudev/functions.
prompt: "You are a helpful support agent for Acme Corp. Be concise.",
tools: [orderStatus],
})
使用 npx zavudev deploy 部署。同步输出会列出创建或更新的每个 Agent 和工具,因此请仔细阅读,不要想当然:即使声明未能同步,部署也可能成功;发生这种情况时,输出会明确说明。
通过 API,如下所示。若用于一次性设置、由你正在构建的控制面板管理的 Agent,或没有可附加 Agent 的 Function,请优先选择此方式。
无论选择哪种方式,创建的 Agent 默认都处于禁用状态。启用之前,它不会回复任何消息。
创建 Agent
每个发送方只能有一个 Agent。如果某个发送方已有 Agent 回复消息(在该发送方上创建,或通过 POST /v1/agents/{agentId}/senders 连接到该发送方),再创建第二个 Agent 会返回 409 conflict:
const result = await zavu.senders.agent.create({
senderId: "snd_abc123",
name: "Customer Support",
provider: "openai",
model: "gpt-4o-mini",
systemPrompt: "You are a helpful customer support agent for Acme Corp. Be friendly, concise, and helpful. If you don't know the answer, say so.",
apiKey: process.env.PROVIDER_API_KEY,
contextWindowMessages: 10,
includeContactMetadata: true,
triggerOnChannels: ["*"],
triggerOnMessageTypes: ["text"],
});
console.log(result.agent.id); // agent_xxx
Python:
result = zavu.senders.agent.create(
sender_id="snd_abc123",
name="Customer Support",
provider="openai",
model="gpt-4o-mini",
system_prompt="You are a helpful customer support agent...",
api_key=os.environ["PROVIDER_API_KEY"],
)
Go:
result, err := client.Senders.Agent.Create(context.TODO(), zavudev.AgentCreateParams{
SenderID: zavudev.String("snd_abc123"),
Name: zavudev.String("Customer Support"),
Provider: zavudev.String("openai"),
Model: zavudev.String("gpt-4o-mini"),
SystemPrompt: zavudev.String("You are a helpful customer support agent..."),
APIKey: zavudev.String(os.Getenv("PROVIDER_API_KEY")),
})
Ruby:
result = client.senders.agent.create(
sender_id: "snd_abc123",
name: "Customer Support",
provider: "openai",
model: "gpt-4o-mini",
system_prompt: "You are a helpful customer support agent...",
api_key: ENV["PROVIDER_API_KEY"],
)
PHP:
$result = $client->senders->agent->create([
'senderId' => 'snd_abc123',
'name' => 'Customer Support',
'provider' => 'openai',
'model' => 'gpt-4o-mini',
'systemPrompt' => 'You are a helpful customer support agent...',
'apiKey' => getenv('PROVIDER_API_KEY'),
]);
提供商与模型选择
| 提供商 | 模型 | 是否需要 API 密钥 |
|---|---|---|
openai | gpt-4o、gpt-4o-mini、gpt-4-turbo | 是 |
anthropic | claude-3-5-sonnet-latest、claude-3-5-haiku-latest | 是 |
google | gemini-2.5-pro、gemini-2.5-flash、gemini-2.5-flash-lite | 是 |
mistral | mistral-large、mistral-small | 是 |
zavu | Zavu 托管的模型 | 否(已包含) |
更新与切换 Agent
// Update configuration
await zavu.senders.agent.update({
senderId: "snd_abc123",
systemPrompt: "Updated prompt...",
temperature: 0.7,
maxTokens: 500,
});
// Enable/disable
await zavu.senders.agent.update({
senderId: "snd_abc123",
enabled: false,
});
切换提供商时,需要提供新提供商的密钥。 已存储的提供商密钥仅属于一个提供商。如果 Agent 当前持有的密钥属于其他提供商,而更新操作要将 provider 切换为 openai、anthropic、google 或 mistral,请求会被拒绝并返回 400 invalid_request(“This API key is for anthropic, but the agent uses openai.”),而不会保存一个在收到第一条消息时就会失败的 Agent。在同一个请求中同时发送 provider 和 apiKey;PATCH /v1/senders/{senderId}/agent 和 PATCH /v1/agents/{agentId} 都接受 apiKey。切换到 zavu 无需密钥。
语音
Agent 还可以通过 Zavu 的集成语音网络(语音识别、Agent 的 LLM、语音合成以及实时打断处理)接听和拨打电话。通话中同样适用 systemPrompt、工具和知识库——语音只是在此基础上增加了一个语音渠道。如需用 TypeScript 声明以代码为先的语音 Agent,请改用 functions 技能。
要求
- Agent 必须设置
voice.enabled: true。 - 发送方必须启用语音渠道。 如果发送方无法接听电话,即使 Agent 已启用语音,也会显得配置正常,却始终不会响铃。发送方需要一个由项目所有的电话号码,并设置
enableVoice:
运行npx zavudev senders update snd_abc123 --enable-voicenpx zavudev senders get snd_abc123确认:channels中必须包含voice。该数组根据发送方的实际配置计算得出,因此应以它为准,而不是某个存储的标志。 - 测试模式密钥不可用——请使用正式环境密钥(
zv_live_...)。 - 通话费用按接通分钟数和电信费用计费,并从预付余额中扣除。
在 Agent 上启用语音
语音配置位于 POST/PATCH /v1/senders/{senderId}/agent 的 Agent voice 对象中。SDK 目前尚未为 voice 字段提供类型定义,因此请通过 REST 设置:
curl -X PATCH https://api.zavu.dev/v1/senders/snd_abc123/agent \
-H "Authorization: Bearer $ZAVU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"voice": {
"enabled": true,
"greeting": "Hi, thanks for calling Acme. How can I help you today?",
"language": "en",
"ttsVoiceId": "aura-2-thalia-en",
"interruptible": true,
"maxCallDurationMinutes": 15,
"maxIdleSeconds": 30,
"voicemailAction": "hangup",
"transferPhoneNumber": "+14155551234"
}
}'
| 字段 | 描述 |
|---|---|
enabled | Agent 是否处理电话。必填。设为 false 时,不会接听拨打到其号码的电话,且会拒绝外拨电话。 |
greeting | 接通时说出的开场白(最多 1000 个字符)。省略时,Agent 会等待来电者先说话。 |
language | 用于识别和合成的 BCP-47 代码(例如 en、es、pt-BR)。省略时会根据接收方自动检测。 |
ttsVoiceId | 用于合成的语音。使用 npx zavudev agents voices(或 GET /v1/agents/voices)列出 ID;不在列表中的名称会被忽略。省略时使用默认中性语音。 |
interruptible | 来电者可以在 Agent 说话时插话。默认值为 true。 |
maxCallDurationMinutes | 通话时长上限,范围为 1-120 分钟。默认值为 15。 |
maxIdleSeconds | Agent 结束通话前的静音时长,范围为 5-300 秒。默认值为 30。 |
voicemailAction | 遇到应答机时(外拨):hangup 或 leave_message。默认值为 hangup。 |
voicemailMessage | 当 voicemailAction 为 leave_message 时播放(最多 1000 个字符)。未设置时使用 greeting。 |
transferPhoneNumber | Agent 可以将通话转接到的 E.164 号码。设置后,Agent 会获得一个转接工具。 |
启用后,发送方的号码会自动接听来电。
拨打外拨电话
从 @zavudev/sdk 0.56.0 开始,SDK 提供 calls 资源。to 是唯一必填字段;senderId 默认使用项目的默认发送方(其 Agent 必须已启用语音)。
const { call } = await zavu.calls.create({
to: "+56912345678",
senderId: "snd_abc123",
greeting: "Hi, this is Acme calling about your appointment.",
maxDurationMinutes: 10,
metadata: { campaign: "appointment_reminders" },
})
使用 REST(或较旧版本的 SDK):
curl -X POST https://api.zavu.dev/v1/calls \
-H "Authorization: Bearer $ZAVU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+56912345678",
"senderId": "snd_abc123",
"greeting": "Hi, this is Acme calling about your appointment.",
"maxDurationMinutes": 10,
"metadata": { "campaign": "appointment_reminders" }
}'
开始拨号时会返回包含通话对象的 202 响应。greeting 和 maxDurationMinutes 仅对本次通话覆盖 Agent 的配置。
获取通话及其转录文本
SDK:zavu.calls.retrieve(callId)(包含转录文本)、zavu.calls.list({ status, direction })(自动分页)、zavu.calls.hangup(callId)。使用 REST:
# Single call, including the ordered transcript
curl https://api.zavu.dev/v1/calls/call_abc123 \
-H "Authorization: Bearer $ZAVU_API_KEY"
# List recent calls (filter by status / direction)
curl "https://api.zavu.dev/v1/calls?direction=outbound&status=completed&limit=50" \
-H "Authorization: Bearer $ZAVU_API_KEY"
# Hang up an active (queued, ringing or in-progress) call; an ended call answers 409
curl -X POST https://api.zavu.dev/v1/calls/call_abc123/hangup \
-H "Authorization: Bearer $ZAVU_API_KEY"
转录文本是由多轮对话组成的列表,每轮格式为 { seq, role, text },其中 role 为 user、assistant 或 tool。获取单个通话时会包含转录文本,列表中则不包含。通话结束后会填充 durationSeconds、endReason、turnCount 和 cost。
寻址 Agent
工具、流程和知识库可以通过两种方式访问,它们指向同一个 资源:
/v1/senders/{senderId}/agent/tools via the sender that answers with it
/v1/agents/{agentId}/tools via the agent itself
当 Agent 还没有发送方时,请使用 Agent 作用域形式,这是
POST /v1/agents 创建的状态。使用
POST /v1/agents/{agentId}/senders 将发送方连接到 Agent 后,也可以通过
发送方作用域路由访问它。POST /v1/agents 和发送方作用域的创建接口一样接受 apiKey,因此独立
Agent 也可以使用 openai、anthropic、google 或 mistral,而不只是 zavu。发送方作用域形式无法寻址该 Agent,因此,过去无法组装被要求独立组装的 Agent。
AGENT=$(curl -s -X POST https://api.zavu.dev/v1/agents \
-H "Authorization: Bearer $ZAVUDEV_API_KEY" \
-d '{"name":"Ada","provider":"zavu","model":"openai/gpt-5.6-luna","systemPrompt":"..."}' \
| jq -r .agent.id)
curl -X POST https://api.zavu.dev/v1/agents/$AGENT/tools -d '{...}'
curl -X POST https://api.zavu.dev/v1/agents/$AGENT/knowledge-bases -d '{...}'
curl -X POST https://api.zavu.dev/v1/agents/$AGENT/senders -d "{\"senderId\":\"$SENDER_ID\"}"
curl -X PATCH https://api.zavu.dev/v1/agents/$AGENT -d '{"enabled":true}'
对话流程
流程用于处理结构化对话(关键词触发、数据收集):
const result = await zavu.senders.agent.flows.create({
senderId: "snd_abc123",
name: "Lead Capture",
description: "Capture lead information from interested prospects",
trigger: {
type: "keyword",
keywords: ["info", "pricing", "demo"],
},
steps: [
{
id: "welcome",
type: "message",
config: { text: "Thanks for your interest! Let me get some info." },
nextStepId: "ask_name",
},
{
id: "ask_name",
type: "collect",
config: { variable: "name", prompt: "What's your name?" },
nextStepId: "ask_email",
},
{
id: "ask_email",
type: "collect",
config: { variable: "email", prompt: "What's your email?" },
nextStepId: "confirm",
},
{
id: "confirm",
type: "message",
config: { text: "Thanks {{name}}! We'll reach out at {{email}}." },
},
],
enabled: true,
priority: 10,
});
除非请求中发送 enabled: true,否则创建的流程默认禁用。对于流程和工具的列表端点,?enabled= 只接受 true 或 false;
其他任何值都会返回 400。
触发类型
| 类型 | 描述 |
|---|---|
keyword | 匹配消息中的特定关键词(不区分大小写的子字符串) |
intent | 消息表达了 trigger.intent 中描述的意图,按含义而非字面用词判断 |
always | 对每条尚未进入某个流程的入站消息运行 |
对于 intent,用一句简单的话描述联系人想要什么,语言不限:{ type: "intent", intent: "asks where their order is" }。决定启动哪个流程的规则:
- 优先级更高的
keyword或always流程会直接胜出,不考虑意图。为意图流程设置更高的优先级数值;否则,优先级高于它们的always流程会导致它们永远不会启动。 - 意图流程只有在明确匹配时才会启动。否则,按优先级顺序启动下一个
keyword或always流程;如果没有,则由 Agent 回复。 - 每条消息最多考虑 12 个意图流程(优先级最高的 12 个)。意图内容会截断至 300 个字符。
- 如果分类器不可用,系统会按没有匹配意图处理:联系人仍会收到回复,但流程不会启动。
- “STOP” 或订单号等精确匹配的词项不代表意图。请使用
keyword。
流程未发送回复时。 如果流程在启动它的消息上结束,且没有回复,就会将该消息交给 Agent,由 Agent 回复。以下三种情况是有意保持静默:transfer 步骤(即使 message 为空)、选择不回复的 llm 步骤,以及此前已向联系人发送过内容的流程。
- 要在有人处理联系人期间让 Agent 保持安静,请以
transfer步骤结束流程。该步骤会让 Agent 对该联系人保持静默,直到有人通过收件箱或 API 向其发送消息。 - 会发送回复的
always流程会接管每条消息,因此其后的 Agent 永远不会回复。仅当机器人完全由流程组成时才使用它,不要将其用作 Agent 前面的拦截环节。 - 除非
condition有defaultGoto,否则不能将它作为第一步:API 会返回400 invalid_request。此时还没有收集任何内容,因此每条消息的条件结果都会相同。 {{ }}只读取同一流程中先前收集的变量(通过collect,或工具步骤的storeResultAs)。无法读取联系人字段和元数据:{{contact.plan}}不会被替换,条件也永远不会匹配。变量名不能包含点,因此{{lead.status}}也无法读取已存储对象中的字段。请在返回简单值(字符串、数字或布尔值)的tool步骤中查询该值,然后再进行比较。
API 接受 manual 并将其存储在流程中,但不会启动它:使用此触发类型创建的流程永远不会触发,也不会报告任何相关信息。
transfer 步骤会发送其消息、将会话标记为已转接,并让 Agent 对该联系人保持静默,直到有人回复。联系人的消息仍会收到并显示在收件箱中,只是 Agent 不再回复。向联系人发送任何出站消息都会结束转接,Agent 随后恢复回复。不过,系统不会替你通知任何人:notifyWebhook 和 reason 虽然会被接受,但不会被读取;如果团队需要收到提醒,请在转接前添加一个 tool 步骤。
collect 步骤的 date 验证接受任何文本,包括 tomorrow。请使用 choice 限定日期,或在自己的工具中验证。
流程会话不会过期。联系人如果中途不再回复,下次发消息时会从同一步骤继续,并保留已有变量。
步骤类型
| 类型 | 描述 |
|---|---|
message | 发送消息 |
collect | 将用户输入收集到变量中 |
condition | 根据条件分支 |
tool | 调用 webhook 工具 |
llm | 发起 LLM 调用 |
transfer | 转接给人工 Agent |
tool 步骤,以及那个看起来像 ID 的字段
{
id: "save_lead",
type: "tool",
config: {
toolName: "create_lead", // the tool's name, or its id
action: "call",
params: { email: "{{email}}", source: "whatsapp" },
storeResultAs: "lead",
},
nextStepId: "confirm",
}
config.toolId 是原始写法,仍然有效。两个字段都可用,且都可以填写工具的名称或 ID:长期以来,toolId 一直被当作名称读取,但仪表板会将真正的 ID 写入其中,因此实际使用中这两种形式都存在,也都能正确解析。
用 {{ }} 包裹的值会被之前流程中收集的数据替换;其他内容则按原样传递。对于不需要参数的工具,请省略 params。流程运行前,该工具必须已添加到 Agent。
如果某个步骤指向 Agent 不具备的工具,会话会以 abandoned 状态结束,并记录配置错误。该会话不会计为已完成的流程。如果流程此前还没有说过任何内容,普通 Agent 会回答这条消息;否则,它会在用户发送下一条消息时继续对话。
流程操作
// List flows
const flows = await zavu.senders.agent.flows.list({ senderId: "snd_abc123" });
// Update flow
await zavu.senders.agent.flows.update({
senderId: "snd_abc123",
flowId: "flow_abc123",
enabled: false,
});
// Duplicate flow
await zavu.senders.agent.flows.duplicate({
senderId: "snd_abc123",
flowId: "flow_abc123",
newName: "Lead Capture (Copy)",
});
// Delete flow
await zavu.senders.agent.flows.delete({
senderId: "snd_abc123",
flowId: "flow_abc123",
});
无需自行构建的预约技能
check_availability 和 book_meeting 由 Zavu 托管:无需端点、托管服务或密钥。它们会读取和写入每个项目的一个日历(Cal.com 或 Google Calendar),在通话和聊天线程中的表现完全相同。
可在仪表板中通过 Agent 的 Tools 标签页下的 Library 添加这些技能,并在此处连接日历。目前它们尚无 REST 或 SDK 接口,因此不要告知用户通过 API 添加。
预约 Agent 使用这些技能时,需注意:只有日历接受预约后,book_meeting 才会报告预约成功。需要确认的 Cal.com 活动类型会返回 pending,技能会告知 Agent,时间已暂时保留,但尚未确认。绝不要在提示词中指示 Agent 在工具结果确认之前就宣布预约已确认。
Webhook 工具
工具可让 Agent 在对话过程中调用你的后端。
哪些渠道会调用工具:全部渠道。 在语音、纯文本(WhatsApp、SMS、Telegram、电子邮件)以及流程的
tool步骤中,工具都会提供给模型。三者都通过同一个执行器分发,因此工具无法因渠道不同而表现不同。模型在一次回复中最多可以连续执行五轮工具调用,而你需要为整个循环所用的 Token 付费。只有在必须确保执行顺序时才使用流程,不要因为认为文本对话无法调用工具而使用流程。它可以调用。
请逐次执行进行验证,而不要想当然:如果 Agent 已配置工具,但
toolCalls: 0,说明它没有调用任何工具。这种情况下,回复会说“我来查一下”,但实际上什么也没发生。
const result = await zavu.senders.agent.tools.create({
senderId: "snd_abc123",
name: "get_order_status",
description: "Get the current status of a customer order",
webhookUrl: "https://api.example.com/webhooks/order-status",
webhookSecret: process.env.WEBHOOK_SECRET,
parameters: {
type: "object",
properties: {
order_id: { type: "string", description: "The order ID to look up" },
},
required: ["order_id"],
},
});
// Test tool
await zavu.senders.agent.tools.test({
senderId: "snd_abc123",
toolId: "tool_abc123",
testParams: { order_id: "ORD-12345" },
});
知识库(RAG)
如果没有附加文档,提示词即使要求“只陈述文档返回的内容”,Agent 也不会拒答,而是会编造内容。请先附加文档,然后使用 agents test 验证;该命令会报告实际检索到的分块数量。
从命令行运行:
npx zavudev agents knowledge-bases create --sender snd_abc123 --name "Product docs"
npx zavudev agents knowledge-bases documents add --sender snd_abc123 --kb <kbId> \
--title "Pricing" --content-file ./pricing.md
npx zavudev agents knowledge-bases documents list --sender snd_abc123 --kb <kbId>
处理需要几秒钟;isProcessed 会变为 true,chunkCount 会填入数量。
添加文档,供 Agent 通过检索增强生成进行参考:
// Create knowledge base
const kb = await zavu.senders.agent.knowledgeBases.create({
senderId: "snd_abc123",
name: "Product FAQ",
description: "Frequently asked questions about our products",
});
// Add document
await zavu.senders.agent.knowledgeBases.documents.create({
senderId: "snd_abc123",
kbId: kb.knowledgeBase.id,
title: "Return Policy",
content: "Our return policy allows returns within 30 days of purchase...",
});
// List documents
const docs = await zavu.senders.agent.knowledgeBases.documents.list({
senderId: "snd_abc123",
kbId: kb.knowledgeBase.id,
});
监控
// Get agent stats
const stats = await zavu.senders.agent.stats({ senderId: "snd_abc123" });
console.log(`Invocations: ${stats.totalInvocations}`);
console.log(`Tokens: ${stats.totalTokensUsed}`);
console.log(`Cost: $${stats.totalCost}`);
// successCount, errorCount and avgLatencyMs cover the 100 most recent
// executions, `filtered` ones excluded. avgLatencyMs is null when there are none.
console.log(stats.successCount, stats.errorCount, stats.avgLatencyMs);
// List executions
const executions = await zavu.senders.agent.executions.list({
senderId: "snd_abc123",
status: "error",
limit: 20,
});
for (const exec of executions.items) {
console.log(exec.id, exec.status, exec.errorMessage);
}
执行状态
| 状态 | 描述 |
|---|---|
success | Agent 成功生成了回复 |
error | 执行失败(大模型错误、工具错误等) |
filtered | 在 Agent 回复前,消息被丢弃(渠道或类型不在其触发条件内、群组回复达到上限),或者 Agent 回复了 NO_REPLY,因此没有发送任何内容。errorMessage 会说明原因。 |
rate_limited | 超出提供商的速率限制 |
balance_insufficient | 账户余额过低,无法处理 |
Agent 使用自身 ID 寻址
Agent 是独立对象。它可以通过多个发送方作答,并且在构建期间也可以不存在任何发送方。
npx zavudev agents list # every agent in the project, with ids
npx zavudev agents list --json
id name kind enabled senders model
qd75detym58c6has4sfrye3vws8b6ygt Atlas voice yes 1 openai/gpt-5.6-luna
qd7ck28evcskdc3xx4wzevtmeh8b6bcm Pizza Desk text no 0 gpt-4o-mini
通过 REST:
GET /v1/agents | 列出 Agent,包括没有发送方的 Agent |
POST /v1/agents | 创建独立 Agent——无需发送方 |
GET /v1/agents/{agentId} | 获取一个 Agent |
PATCH /v1/agents/{agentId} | 更新 |
DELETE /v1/agents/{agentId} | 删除 |
POST /v1/agents/{agentId}/test | 运行 Agent,返回回复,不发送任何内容 |
旧版 /v1/senders/{senderId}/agent 路由仍然可用。它们会将发送方解析为在该发送方上作答的唯一一个 Agent:在该发送方上创建的 Agent,否则就是通过 POST /v1/agents/{agentId}/senders 与其关联的 Agent。它们无法访问没有发送方的 Agent。对于没有 Agent 的发送方,GET /v1/senders/{senderId}/agent 会返回 404。
要测试单个工具,而不是整个 Agent:
POST /v1/senders/{senderId}/agent/tools/{toolId}/test | 使用你的参数调用工具,并返回它的响应 |
GET /v1/senders/{senderId}/agent/tools/{toolId}/test-runs | 最近的运行记录,按时间从新到旧排列 |
通过命令行:
npx zavudev agents tools test <toolId> --sender <senderId> --params '{"orderId":"ORD-4417"}'
npx zavudev agents tools test-runs <toolId> --sender <senderId>
测试会同步运行并返回工具的状态、正文和耗时,因此有结果就能证明工具已运行。工具若返回错误,则结果中会显示 run.success: false,但端点仍会返回 200——请查看该字段,而不是状态码。测试会触发真实 Webhook,因此会产生该工具本身具有的任何副作用。
test-runs 仅包含手动测试。Agent 在真实对话中调用的工具不会列在其中;要查看这类调用,请使用 agents executions 查看每条回复调用了多少个工具。
连接发送方
npx zavudev agents senders connect --agent <agentId> --sender <senderId>
npx zavudev agents senders disconnect --agent <agentId> --sender <senderId>
使用 {"senderId": "..."} 调用 POST /v1/agents/{agentId}/senders,并调用 DELETE /v1/agents/{agentId}/senders/{senderId}。
一个发送方最多只能由一个 Agent 作答。 如果连接的发送方已被使用,操作会返回 400,并指出占用它的 Agent——否则 Agent 看起来已经连接,却永远收不到消息。
测试 Agent,但不发送任何内容
npx zavudev agents test --agent <agentId> --message "where is order ORD-001?"
运行真实的提示词、模型和知识库,并打印 Agent 本会给出的回复,以及令牌数、延迟和使用的知识片段数。不会发送任何内容,也不会记录执行。
测试运行的计费方式与实时回复相同。 对于使用 zavu 提供方的 Agent,费用会按相同的每令牌价格(响应中的 cost)从余额中扣除;余额为零时会返回 402 insufficient_balance。对于使用自带密钥的 Agent,费用由你的提供方收取。每个项目的运行次数都有限制(429)。测试模式的密钥也按相同方式计费;使用此类密钥调用 executeTools 仍会触达你的真实处理程序,并写入真实记忆。
模型可以使用 Agent 的工具,但不会运行任何工具:如果它选择了某个工具,回复就会在此处停止,而 plannedToolCalls 会列出选择的工具及其参数。传入 executeTools 即可实际运行这些工具——这会触达你的处理程序。
它还会提示干跑无法验证的内容:已禁用的 Agent、没有 Agent 所触发渠道的发送方,以及仅在实时场景中才会存在的联系人元数据。请将这些警告视为结果的一部分。
多轮测试,以及将提示词与检索隔离:
npx zavudev agents test --agent <agentId> \
--turn "I need to change my booking" --turn "Sure — which one?" \
--message "the one on Friday"
npx zavudev agents test --agent <agentId> --message "what do you cost?" --no-knowledge
删除 Agent
await zavu.senders.agent.delete({ senderId: "snd_abc123" });
Agent 回复的渠道
triggerOnChannels 是一个白名单,也是最常见的导致 Agent 看起来配置完成却不回复的原因。若入站消息的渠道不在列表中,该消息会在 Agent 运行前被丢弃:既没有回复,也没有错误;而控制面板中的 Playground 仍会正常回复,因为它会绕过此筛选器。可在 GET /v1/senders/{senderId}/agent/executions 中查看,丢弃的消息会显示为 status: "filtered",且 errorMessage 会指出收到的渠道以及 Agent 监听的渠道。
["*"] 表示发送方承载的所有渠道,是合适的默认值。只有在有意排除某个渠道时才缩小范围;并且请记住,之后向发送方添加渠道不会将其自动添加到此处。系统会接受未知字符串,但它们不会匹配任何渠道,因此拼写错误的效果与有意排除某个渠道完全相同。
保持静默:NO_REPLY
如果 Agent 的完整回复去除首尾空白后恰好为 NO_REPLY,则不会发送任何内容。此规则适用于所有渠道,也适用于工作流的 llm 步骤。执行记录会显示为 status: "filtered",且 errorMessage 会说明 Agent 选择不回复;使用的令牌仍会计费并计数。
可在提示词中告诉 Agent 何时回复 NO_REPLY(“如果消息是在表示感谢,或不需要回复,请回复 NO_REPLY”)。由模型决定;对话中的其他内容不会因此改变。
约束
- 每个发送方只能有一个 Agent。 当发送方已由 Agent 回复时,
POST /v1/senders/{senderId}/agent会返回409 conflict;连接正在使用中的发送方则会返回400。每次读取都会将发送方解析为唯一一个 Agent。 - 每个 Agent 的工具名称必须唯一。 创建同名的第二个工具会返回
409 conflict。 - 系统提示词:最多 10,000 个字符
- 上下文窗口:1–50 条消息
- 温度:0–2
- 最大令牌数:1–4,096
- 工具名称:最多 100 个字符
- 工具描述:最多 500 个字符
- 文档内容:最多 100,000 个字符
- 知识库名称:最多 100 个字符
- 提供商
zavu无需 API 密钥(使用 Zavu 托管的模型) - 其他所有提供商均需要你自己的 API 密钥