Create a Botpress AI agent with the ADK using OpenClaw
Botpress ADK 开发指南
使用 Botpress 智能体开发套件(ADK)构建 AI 机器人的综合指南。
何时使用
- 用户要求构建 Botpress 机器人或聊天机器人
- 用户提及 ADK、Agent Development Kit 或 Botpress
- 用户想要创建操作、工具、工作流、对话、表格、触发器或知识库
- 用户需要帮助
adkCLI 命令(init, dev, deploy, link) - 用户遇到 ADK 相关错误或需要故障排除
- 用户询问机器人配置、状态管理或集成
快速参考
ADK 是一个基于约定的 TypeScript 框架其中文件结构直接映射到机器人行为。

你的角色:引导用户完成整个机器人开发生命周期——从项目设置到部署。使用本技能中的模式和代码示例来编写正确、可运行的 ADK 代码。
关键原则:在ADK中,文件的存放位置至关重要。每种组件类型都有特定的src/子目录,文件会根据位置自动被发现。
如何使用此技能
此技能是您构建Botpress机器人的主要参考。当用户要求您使用ADK构建某物时:
- 确定他们需要什么- 是新机器人、功能(动作、工具、工作流)、数据存储(表),还是事件处理(触发器)?
- 检查正确的目录- 每种组件类型都放在特定的
src/子目录中 - 使用以下模式- 严格遵循代码示例,它们代表了正确的ADK约定
- 运行
adk --help- 对于此处未涵盖的CLI命令,或adk <命令> --help获取具体帮助
决策指南 - 创建何种组件:
| 用户希望... | 创建此组件 | 位置 |
|---|---|---|
| 处理用户消息 | 对话 | src/conversations/ |
| 添加AI可以调用的函数 | 工具 | src/tools/ |
| 添加可复用的业务逻辑 | 操作 | src/actions/ |
| 运行后台/计划任务 | 工作流 | src/workflows/ |
| 存储结构化数据 | 数据表 | src/tables/ |
| 响应事件(例如用户创建等) | 触发器 | src/triggers/ |
| 授予AI访问文档/数据的权限 | 知识库 | src/knowledge/ |
| 连接外部服务(Slack等) | 集成 | adk add <名称> |
如果此技能中的信息不足,请获取相应的GitHub参考文件(每个部分都提供了链接)以获取更详细的规范。
重要提示:ADK是AI原生
ADK不使用传统的聊天机器人模式。不要创建意图、实体或对话流。
而不是:
- 定义意图(
问候、订购披萨、检查状态) - 训练实体提取(
@pizzaSize、@toppings) - 手动路由到意图处理器
ADK 使用:
execute()- AI 能够从指令中自然理解用户意图- 工具 - AI 自主决定何时调用您的函数
zai.extract()- 基于模式的结构化数据提取- 知识库 - 用于在您的文档中锚定响应的 RAG
文档: https://www.botpress.com/docs/adk/ GitHub: https://github.com/botpress/skills/tree/master/skills/adk
先决条件与安装
在使用 ADK 之前,请确保用户拥有:
- Botpress 账户- 在此创建:https://app.botpress.cloud
- Node.js v22.0.0+- 使用以下命令检查:
node --version - 包管理器- bun(推荐)、pnpm、yarn 或 npm
安装 ADK CLI:
macOS 和 Linux 系统:
curl -fsSL https://github.com/botpress/adk/releases/latest/download/install.sh | bash
Windows(PowerShell):
powershell -c "irm https://github.com/botpress/adk/releases/latest/download/install.ps1 | iex"
验证安装:
adk --version
如果安装失败,请查看https://github.com/botpress/adk/releases以获取手动下载选项。
文档: https://www.botpress.com/docs/adk/quickstart GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/cli.md
快速入门
安装 ADK CLI 后,创建一个新的机器人:
adk init my-bot # Create project (choose "Hello World" template for beginners)
cd my-bot
npm install # Or bun/pnpm/yarn
adk login # Authenticate with Botpress Cloud
adk add chat # Add the chat integration for testing
adk dev # Start dev server with hot reload
adk chat # Test in CLI (run in separate terminal)
adk deploy # Deploy to production when ready
位于http://localhost:3001/的可视化控制台,可让你配置集成并测试机器人。
文档: https://www.botpress.com/docs/adk/quickstart GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/cli.md
链接和部署你的机器人
重要提示:您的机器人必须链接到 Botpress Cloud 并部署后才能正常工作。ADK 在开发期间于本地运行,但机器人本身驻留在 Botpress Cloud 中。
正确的顺序是:链接 → 开发 → 部署
请遵循此顺序以使您的机器人正常工作:
# 1. LINK - Connect your project to Botpress Cloud (creates agent.json)
adk link
# 2. DEV - Start the development server (hot reload, testing)
adk dev
# 3. DEPLOY - Push to production when ready
adk deploy
逐步说明:
-
adk link- 将您的本地项目链接到 Botpress Cloud 中的一个机器人。这将创建agent.json文件,其中包含您的工作区和机器人ID。请在任何其他操作之前首先运行此命令。 -
adk dev- 启动支持热重载的本地开发服务器。在http://localhost:3001地址打开开发控制台,您可以在其中配置集成并测试您的机器人。在单独的终端中使用adk chat命令进行测试。 -
adk deploy- 将您的机器人部署到生产环境。当您的机器人准备就绪,需要通过生产渠道(Slack、WhatsApp、网络聊天等)访问时,请运行此命令。
错误排查
如果你在运行adk dev或adk deploy时遇到错误:
- 检查日志- 查看终端输出或开发控制台中的日志面板,地址为http://localhost:3001
- 复制错误信息- 从日志中选择并复制完整的错误信息
- 寻求帮助- 将错误信息粘贴回AI助手,并请它帮助修复问题
常见错误场景:
- 集成配置错误:通常意味着需要在 localhost:3001 的UI界面中配置集成
- 类型错误:通常由不正确的导入或模式不匹配引起
- 部署失败:可能表明缺少环境变量或配置无效
修复错误的示例工作流程:
1. Run `adk dev` or `adk deploy`
2. See error in terminal/logs
3. Copy the error message
4. Tell the AI: "I got this error when running adk dev: [paste error]"
5. The AI will help diagnose and fix the issue
文档: https://www.botpress.com/docs/adk/quickstart GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/cli.md
项目结构
关键规则:文件位置决定行为。请将组件放置在正确的src/子目录中,否则它们将无法被识别。
my-bot/
├── agent.config.ts # Bot configuration: name, models, state schemas, integrations
├── agent.json # Workspace/bot IDs (auto-generated by adk link/dev, add to .gitignore)
├── package.json # Node.js dependencies and scripts (dev, build, deploy)
├── tsconfig.json # TypeScript configuration
├── .env # API keys and secrets (never commit!)
├── .gitignore # Should include: agent.json, .env, node_modules/, .botpress/
├── src/
│ ├── conversations/ # Handle incoming messages → use execute() for AI responses
│ ├── workflows/ # Background processes → use step() for resumable operations
│ ├── actions/ # Reusable functions → call from anywhere with actions.name()
│ ├── tools/ # AI-callable functions → AI decides when to invoke these
│ ├── tables/ # Data storage → auto-synced to cloud, supports semantic search
│ ├── triggers/ # Event handlers → react to user.created, integration events, etc.
│ └── knowledge/ # RAG sources → index docs, websites, or tables for AI context
└── .botpress/ # Auto-generated types (never edit manually)
关键配置文件:
- agent.config.ts- 定义机器人元数据、AI模型、状态模式和集成的首要配置文件(由您编辑此文件)
- agent.json- 将智能体链接到工作区/机器人ID。由
adk link或adk dev命令自动生成。添加到 .gitignore- 包含特定于环境的ID,这些ID因开发人员而异 - package.json- Node.js配置文件,包含
@botpress/runtime依赖项和脚本用于开发、构建、部署 - tsconfig.json- 项目的 TypeScript 配置
- .env- 用于 API 密钥和密钥的环境变量(切勿提交!)
- .gitignore- 应包含:
agent.json、.env、node_modules/、.botpress/
文档: https://www.botpress.com/docs/adk/project-structure GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/agent-config.md
Agent Configuration
Theagent.config.ts文件定义了你的机器人的身份、AI模型、状态模式和集成。在设置新机器人时,请总是从这里开始。
import { defineConfig, z } from "@botpress/runtime";
export default defineConfig({
name: "my-support-bot",
description: "AI customer support assistant",
// AI models for different operations
defaultModels: {
autonomous: "openai:gpt-4o", // Used by execute() for conversations
zai: "openai:gpt-4o-mini" // Used by zai operations (cheaper, faster)
},
// Global bot state - shared across all conversations and users
bot: {
state: z.object({
maintenanceMode: z.boolean().default(false),
totalConversations: z.number().default(0)
})
},
// Per-user state - persists across all conversations for each user
user: {
state: z.object({
name: z.string().optional(),
tier: z.enum(["free", "pro"]).default("free"),
preferredLanguage: z.enum(["en", "es", "fr"]).default("en")
}),
tags: {
source: z.string(),
region: z.string().optional()
}
},
// Per-conversation state
conversation: {
state: z.object({
context: z.string().optional()
}),
tags: {
category: z.enum(["support", "sales", "general"]),
priority: z.enum(["low", "medium", "high"]).optional()
}
},
// Integrations your bot uses (ADK 1.9+ format)
dependencies: {
integrations: {
chat: { version: "chat@0.7.3", enabled: true },
slack: { version: "slack@2.5.5", enabled: true }
}
}
});
可用模型:
- OpenAI:
openai:gpt-4o、openai:gpt-4o-mini、openai:gpt-4-turbo - Anthropic:
anthropic:claude-3-5-sonnet、anthropic:claude-3-opus - Google:
google:gemini-1.5-pro、google:gemini-1.5-flash
文档: https://www.botpress.com/docs/adk/project-structure GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/agent-config.md
核心概念
1. 操作 - 可复用的业务逻辑
何时创建操作:
- 你需要可复用的逻辑,这些逻辑将从多个地方(工作流、对话、触发器)被调用
- 你正在封装一个外部 API 或数据库操作
- 你需要可测试、可组合的业务逻辑
- 你需要用自定义逻辑调用集成 API(如 Slack、Linear 等)
何时不应使用操作(应使用工具代替):
- 你希望 AI 能自主决定何时调用它
- 该函数应在
execute()
操作不能被 AI 直接调用 - 如果 AI 需要使用它们,请使用.asTool()将其转换为工具。
位置: src/actions/*.ts
import { Action, z } from "@botpress/runtime";
export const fetchUser = new Action({
name: "fetchUser",
description: "Retrieves user details from the database",
// Define input/output with Zod schemas for type safety
input: z.object({ userId: z.string() }),
output: z.object({ name: z.string(), email: z.string() }),
// IMPORTANT: Handler receives { input, client } - destructure input INSIDE the handler
async handler({ input, client }) {
const { user } = await client.getUser({ id: input.userId });
return { name: user.name, email: user.tags.email };
}
});
调用操作:
import { actions } from "@botpress/runtime";
const userData = await actions.fetchUser({ userId: "123" });
// To make an action callable by the AI, convert it to a tool:
tools: [actions.fetchUser.asTool()]
关键规则:
- 处理程序接收
{ 输入, 客户端 }- 必须进行解构输入在处理器内部 - 不能在参数中直接解构输入字段
- 可以调用其他动作、集成动作,访问状态
- 可以通过以下方式转换为工具
.asTool()
文档: https://www.botpress.com/docs/adk/concepts/actions GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/actions.md
2. 工具 - 可由 AI 调用的函数
何时创建工具:
- 您希望 AI 能自主决定何时使用此功能
- 该功能获取 AI 所需的信息(搜索、查找、获取)
- 该功能代表用户执行操作(创建工单、发送消息)
- 您正在构建 AI 在对话中应具备的能力
AI 根据以下情况决定何时使用工具:
- 该工具的
描述- 清晰且具体地说明何时使用它 - 输入模式的
.describe()字段 - 帮助AI理解参数含义 - 对话上下文和用户意图
与Actions的关键区别:工具可以直接解构输入;Actions不能。
位置: src/tools/*.ts
import { Autonomous, z } from "@botpress/runtime";
export const searchProducts = new Autonomous.Tool({
name: "searchProducts",
// This description is critical - it tells the AI when to use this tool
description: "Search the product catalog. Use when user asks about products, availability, pricing, or wants to browse items.",
input: z.object({
query: z.string().describe("Search keywords"),
category: z.string().optional().describe("Filter by category")
}),
output: z.object({
products: z.array(z.object({ id: z.string(), name: z.string(), price: z.number() }))
}),
// Unlike actions, tools CAN destructure input directly in the handler
handler: async ({ query, category }) => {
// Your search logic here
return { products: [] };
}
});
使用ThinkSignal:当工具无法完成但你想给AI提供上下文时:
import { Autonomous } from "@botpress/runtime";
// Inside handler - AI will see this message and can respond appropriately
throw new Autonomous.ThinkSignal(
"No results found",
"No products found matching that query. Ask user to try different search terms."
);
高级工具属性:
export const myTool = new Autonomous.Tool({
name: "myTool",
description: "Tool description",
input: z.object({...}),
output: z.object({...}),
aliases: ["searchDocs", "findDocs"], // Alternative names
handler: async (input, ctx) => {
console.log(`Call ID: ${ctx.callId}`); // Unique call identifier
// ...
},
retry: async ({ attempt, error }) => {
if (attempt < 3 && error?.code === 'RATE_LIMIT') {
await new Promise(r => setTimeout(r, 1000 * attempt));
return true; // Retry
}
return false; // Don't retry
}
});
文档: https://www.botpress.com/docs/adk/concepts/tools GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/tools.md
3. 对话 - 消息处理器
何时创建对话:
- 每个机器人至少需要一个对话处理器来响应用户
- 如果不同渠道需要不同行为,请为其创建独立的处理器
- 使用
channel: "*"可通过单一处理器处理所有渠道
构建对话时的关键决策:
- 选择哪些渠道?- 指定
"*"表示所有渠道,或指定具体渠道如"slack.dm" - AI需要哪些工具?- 通过
execute({ tools: [...] }) - 传递应以何种知识作为回答依据?
- 通过 - execute({ knowledge: [...] })传递
需要哪些指导AI的指令?- 定义个性特征、规则和上下文---- 它利用你的工具和知识运行自主AI逻辑。大多数对话处理器会调用execute()。
位置: src/conversations/*.ts
import { Conversation, z } from "@botpress/runtime";
export const Chat = new Conversation({
// Which channels this handler responds to
channel: "chat.channel", // Or "*" for all, or ["slack.dm", "webchat.channel"]
// Per-conversation state (optional)
state: z.object({
messageCount: z.number().default(0)
}),
async handler({ message, state, conversation, execute, user }) {
state.messageCount += 1;
// Handle commands
if (message?.payload?.text?.startsWith("/help")) {
await conversation.send({
type: "text",
payload: { text: "Available commands: /help, /status" }
});
return;
}
// Let the AI handle the response with your tools and knowledge
await execute({
// Instructions guide the AI's behavior and personality
instructions: `You are a helpful customer support agent for Acme Corp.
User's name: ${user.state.name || "there"}
User's tier: ${user.state.tier}
Be friendly, concise, and always offer to help further.`,
// Tools the AI can use during this conversation
tools: [searchProducts, actions.createTicket.asTool()],
// Knowledge bases for RAG - AI will search these to ground responses
knowledge: [DocsKnowledgeBase],
model: "openai:gpt-4o",
temperature: 0.7,
iterations: 10 // Max tool call iterations
});
}
});
处理器上下文:
message- 用户的消息数据execute- 运行自主AI逻辑conversation- 对话实例方法(发送、开始输入、停止输入)state- 可变状态(机器人、用户、对话)client- Botpress API客户端type- 事件分类(消息、工作流请求)
执行函数选项:
await execute({
instructions: string | async function, // Required
tools: Tool[], // AI-callable tools
knowledge: Knowledge[], // Knowledge bases for RAG
exits: Exit[], // Structured exit handlers
model: string, // AI model to use
temperature: number, // 0-1, default 0.7
iterations: number, // Max tool calls, default 10
hooks: {
onBeforeTool: async ({ tool, input }) => { ... },
onAfterTool: async ({ tool, output }) => { ... },
onTrace: async (trace) => { ... }
}
});
常见渠道: chat.channel、webchat.channelslack.dmslack.channeldiscord.channelwhatsapp.channel"*"(全部)文档:https://www.botpress.com/docs/adk/concepts/conversationsGitHub:https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/conversations.md4. 工作流 - 后台与多步骤流程
何时创建工作流: 操作耗时超过2分钟(默认超时时间) 需要能在崩溃/重启后继续执行的多步骤流程 定时/重复性任务(每日报告、定期同步)
后台处理(订单履行、数据迁移)
需要等待外部事件或用户输入的操作
- Operations that take longer than 2 minutes (the default timeout)
- Multi-step processes that need to survive crashes/restarts
- Scheduled/recurring tasks (daily reports, periodic syncs)
- Background processing (order fulfillment, data migration)
- Operations that need to wait for external events or user input
何时不应使用工作流(应通过对话处理):
- 可立即完成的快速操作
- 简单的请求-响应模式
- 无需持久化的操作
工作流核心概念:
- 步骤即检查点- 若工作流崩溃,将从最后完成的步骤恢复执行
- 状态持久化- 将进度存储于
状态以实现跨步骤追踪 - 始终传递会话ID- 当工作流需要向用户发送消息时
存放位置: src/workflows/*.ts
import { Workflow, z } from "@botpress/runtime";
export const ProcessOrderWorkflow = new Workflow({
name: "processOrder",
description: "Processes customer orders",
timeout: "6h", // Max duration
schedule: "0 9 * * *", // Optional: run daily at 9am (cron syntax)
input: z.object({
orderId: z.string(),
conversationId: z.string() // Include this to message the user back!
}),
state: z.object({
currentStep: z.number().default(0),
processedItems: z.array(z.string()).default([])
}),
output: z.object({
success: z.boolean(),
itemsProcessed: z.number()
}),
async handler({ input, state, step, client, execute }) {
// State is passed as parameter, auto-tracked
state.currentStep = 1;
// IMPORTANT: Each step needs a unique, stable name (no dynamic names!)
const orderData = await step("fetch-order", async () => {
return await fetchOrderData(input.orderId);
});
// Steps can have retry logic
await step("process-payment", async () => {
return await processPayment(orderData);
}, { maxAttempts: 3 });
// To message the user from a workflow, use client.createMessage (NOT conversation.send)
await step("notify-user", async () => {
await client.createMessage({
conversationId: input.conversationId,
type: "text",
payload: { text: "Your order has been processed!" }
});
});
return {
success: true,
itemsProcessed: state.processedItems.length
};
}
});
// Start a workflow from a conversation or trigger
await ProcessOrderWorkflow.start({
orderId: "123",
conversationId: conversation.id // Always pass this if you need to message back
});
// Get or create with deduplication
const instance = await ProcessOrderWorkflow.getOrCreate({
key: `order-${orderId}`, // Prevents duplicate workflows
input: { orderId, conversationId }
});
步骤方法:
| 方法 | 用途 |
|---|---|
step(name, fn) | 支持缓存的基础执行方法 |
step.sleep(name, ms) | 暂停指定毫秒时长 |
步骤.休眠直到(名称, 日期) | 暂停直到特定日期 |
步骤.监听() | 等待外部事件 |
步骤.进度(消息) | 更新进度消息 |
步骤.请求(名称, 提示) | 请求用户输入(阻塞式) |
步骤.执行工作流() | 启动并等待另一个工作流 |
步骤.等待工作流(标识符) | 等待现有工作流 |
步骤.映射(项目数组, 函数) | 并发处理数组 |
步骤.遍历(项目数组, 函数) | 无返回结果地执行项目 |
步骤.批处理(项目数组, 函数) | 分组处理 |
步骤.失败(原因) | 将工作流标记为失败 |
步骤.中止() | 立即停止,不视为失败 |
关键规则:
- 步骤名称必须唯一且稳定(避免在循环中使用动态命名)
- 状态作为参数传递,而非通过
this.state - 访问
始终为需要向用户发送消息的工作流传递conversationId - 默认超时时间为2分钟 - 对于耗时更长的流程请使用步骤
文档: https://www.botpress.com/docs/adk/concepts/workflows/overview GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/workflows.md
5. 表格 - 数据存储
何时创建表格:
- 您需要持久化结构化数据(用户、订单、工单、日志)
- 您希望通过字段查询/筛选数据
- 您需要对文本内容进行语义搜索(设置
searchable: true) - 您存储的数据需要在机器人重启后依然保留
何时不应使用表格(应改用状态):
- 每个用户/会话的简单键值数据 → 使用
user.state或conversation.state - 不需要持久化的临时数据
- 少量可以放入状态的数据
表格与知识库对比:
- 表格= 您进行CRUD(创建、读取、更新、删除)操作的结构化数据
- 知识库= 供AI搜索和参考的文档/内容
位置: src/tables/*.ts
关键规则(违反将导致错误):
- 请勿定义
id列 - 它会自动创建为数字类型 - 表格名称必须以"Table"结尾(例如,
OrdersTable不是订单)
import { Table, z } from "@botpress/runtime";
export const OrdersTable = new Table({
name: "OrdersTable", // Must end with "Table"
description: "Stores order information",
columns: {
// NO id column - it's automatic!
orderId: z.string(),
userId: z.string(),
status: z.enum(["pending", "completed", "cancelled"]),
total: z.number(),
createdAt: z.date(),
// Enable semantic search on a column:
notes: {
schema: z.string(),
searchable: true
}
}
});
CRUD 操作:
// Create - id is auto-assigned
await OrdersTable.createRows({
rows: [{ orderId: "ord-123", userId: "user-456", status: "pending", total: 99.99, createdAt: new Date() }]
});
// Read with filters
const { rows } = await OrdersTable.findRows({
filter: { userId: "user-456", status: "pending" },
orderBy: "createdAt",
orderDirection: "desc",
limit: 10
});
// Get single row by id
const row = await OrdersTable.getRow({ id: 123 });
// Semantic search (on searchable columns)
const { rows } = await OrdersTable.findRows({
search: "delivery issue",
limit: 5
});
// Update - must include the id
await OrdersTable.updateRows({
rows: [{ id: 1, status: "completed" }]
});
// Upsert - insert or update based on key column
await OrdersTable.upsertRows({
rows: [{ orderId: "ord-123", status: "shipped" }],
keyColumn: "orderId"
});
// Delete by filter
await OrdersTable.deleteRows({ status: "cancelled" });
// Delete by IDs
await OrdersTable.deleteRowIds([123, 456]);
高级:计算列:
columns: {
basePrice: z.number(),
taxRate: z.number(),
fullPrice: {
computed: true,
schema: z.number(),
dependencies: ["basePrice", "taxRate"],
value: async (row) => row.basePrice * (1 + row.taxRate)
}
}
文档: https://www.botpress.com/docs/adk/concepts/tables GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/tables.md
6. 知识库 - 用于 AI 上下文的 RAG
何时创建知识库:
- 您希望 AI 根据您的文档回答问题
- 您有 AI 应参考的常见问题解答、政策或产品信息
- 您希望 AI 的回复基于特定内容(而非凭空捏造)
- 您正在构建一个需要访问帮助文章的支持机器人
RAG 在 ADK 中的工作原理:
- 您定义知识源(网站、文件、表格)
- 内容被索引和嵌入以进行语义搜索
- 在
execute()AI自动搜索相关知识 - AI利用检索到的内容生成有依据的回应
选择数据源类型:
- 网站- 索引公共文档、帮助站点、博客
- 目录- 索引本地markdown/文本文件(仅限开发用途!)
- 表格- 索引来自您表格的结构化数据
位置: src/knowledge/*.ts
import { Knowledge, DataSource } from "@botpress/runtime";
// Website source - index via sitemap
const websiteSource = DataSource.Website.fromSitemap(
"https://docs.example.com/sitemap.xml",
{
id: "website-docs",
maxPages: 500,
maxDepth: 10,
filter: (ctx) => ctx.url.includes("/docs/") // Only index /docs/ pages
}
);
// Local files (development only - won't work in production)
const localSource = DataSource.Directory.fromPath("src/knowledge/docs", {
id: "local-docs",
filter: (path) => path.endsWith(".md")
});
// Table-based knowledge
const tableSource = DataSource.Table.fromTable(FAQTable, {
id: "faq-table",
transform: ({ row }) => `Question: ${row.question}\nAnswer: ${row.answer}`,
filter: ({ row }) => row.published === true
});
export const DocsKB = new Knowledge({
name: "docsKB",
description: "Product documentation and help articles",
sources: [websiteSource, localSource, tableSource]
});
// Use in conversations - AI will search this knowledge base
await execute({
instructions: "Answer based on the documentation",
knowledge: [DocsKB]
});
// Manually refresh knowledge base
await DocsKB.refresh(); // Smart refresh (only changed content)
await DocsKB.refresh({ force: true }); // Force full re-index
await DocsKB.refreshSource("website-docs", { force: true }); // Refresh specific source
网站源方法:
fromSitemap(url, options)- 解析XML站点地图fromWebsite(baseUrl, options)- 从基础URL开始爬取(需要浏览器集成)fromLlmsTxt(url, options)- 解析llms.txt文件fromUrls(urls, options)- 索引特定URL
文档: https://www.botpress.com/docs/adk/concepts/knowledge GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/knowledge-bases.md
7. 触发器 - 事件驱动自动化
何时创建触发器:
- 你需要对事件自动做出反应(用户注册、问题创建等)
- 你希望在特定事件发生时启动工作流
- 当外部系统发生变化时,你需要同步数据
- 你希望基于事件发送通知
常见的触发器模式:
- 用户入职- 触发条件:
user.created→ 启动入职工作流 - 集成同步- 触发条件:
linear:issueCreated→ 在表格中创建记录 - 通知- 触发条件:
workflow.completed→ 发送 Slack 消息
查找可用事件:
- 机器人事件:
用户创建、会话开始、工作流完成等。 - 集成事件:运行
adk info <integration> --events以查看可用事件
位置: src/triggers/*.ts
import { Trigger } from "@botpress/runtime";
export default new Trigger({
name: "onNewUser",
description: "Start onboarding when user created",
events: ["user.created"], // Can listen to multiple events
handler: async ({ event, client, actions }) => {
const { userId, email } = event.payload;
// Start an onboarding workflow
await OnboardingWorkflow.start({
userId,
email
});
}
});
// Integration events use format: integration:eventName
export const LinearTrigger = new Trigger({
name: "onLinearIssue",
description: "Handle Linear issue events",
events: ["linear:issueCreated", "linear:issueUpdated"],
handler: async ({ event, actions }) => {
if (event.type === "linear:issueCreated") {
await actions.slack.sendMessage({
channel: "#notifications",
text: `New issue: ${event.payload.title}`
});
}
}
});
常见机器人事件:
用户创建、用户更新、用户删除会话开始、会话结束、消息创建工作流开始,workflow.completed,workflow.failedbot.started,bot.stopped
常见集成事件:
- Slack:
slack:reactionAdded,slack:memberJoinedChannel - Linear:
linear:issueCreated,linear:issueUpdated - GitHub:
github:issueOpened,github:pullRequestOpened - Intercom:
intercom:conversationEvent,intercom:contactEvent
查找集成事件:运行adk info <integration> --events
文档: https://www.botpress.com/docs/adk/concepts/triggers GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/triggers.md
发送消息
重要提示:方法取决于您从何处发送:
| 上下文 | 方法 | 原因 |
|---|---|---|
| 在对话中 | conversation.send() | 拥有对话上下文 |
| 在工作流/操作中 | client.createMessage() | 需要明确指定conversationId |
常见错误:在对话中使用client.createMessage()。应始终使用conversation.send()替代。
方法取决于您从何处发送:
在对话中- 使用conversation.send():
await conversation.send({ type: "text", payload: { text: "Hello!" } });
await conversation.send({ type: "image", payload: { imageUrl: "https://..." } });
await conversation.send({
type: "choice",
payload: {
text: "Pick one:",
choices: [
{ title: "Option A", value: "a" },
{ title: "Option B", value: "b" }
]
}
});
在工作流或操作中- 使用client.createMessage()并附带conversationId:
await client.createMessage({
conversationId: input.conversationId, // Must have this!
type: "text",
payload: { text: "Workflow complete!" }
});
所有消息类型:
// Text
{ type: "text", payload: { text: "Hello!" } }
// Markdown
{ type: "markdown", payload: { text: "# Heading\n**Bold**" } }
// Image
{ type: "image", payload: { imageUrl: "https://..." } }
// Audio
{ type: "audio", payload: { audioUrl: "https://..." } }
// Video
{ type: "video", payload: { videoUrl: "https://..." } }
// File
{ type: "file", payload: { fileUrl: "https://...", title: "Document.pdf" } }
// Location
{ type: "location", payload: { latitude: 40.7128, longitude: -74.0060, address: "New York, NY" } }
// Card
{ type: "card", payload: {
title: "Product Name",
subtitle: "Description",
imageUrl: "https://...",
actions: [
{ action: "url", label: "View", value: "https://..." },
{ action: "postback", label: "Buy", value: "buy_123" }
]
}}
// Carousel
{ type: "carousel", payload: {
items: [
{ title: "Item 1", subtitle: "...", imageUrl: "...", actions: [...] },
{ title: "Item 2", subtitle: "...", imageUrl: "...", actions: [...] }
]
}}
// Choice (Quick Replies)
{ type: "choice", payload: {
text: "Select an option:",
choices: [
{ title: "Option 1", value: "opt1" },
{ title: "Option 2", value: "opt2" }
]
}}
// Dropdown
{ type: "dropdown", payload: {
text: "Select country:",
options: [
{ label: "United States", value: "us" },
{ label: "Canada", value: "ca" }
]
}}
GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/messages.md
Zai - LLM 实用操作
何时使用 Zai 与 execute():
- 使用
zai用于特定、结构化的 AI 操作(提取数据、分类、总结) - 使用
execute()用于自主、多轮的工具辅助 AI 对话
Zai 非常适合:
- 从用户消息中提取结构化数据(
zai.extract) - 对内容进行分类/标记 (
zai.check,zai.label) - 总结长篇内容 (
zai.summarize) - 根据文档回答问题 (
zai.answer) - 智能排序/筛选/分组数据 (
zai.sort,zai.filter,zai.group)
Zai 操作针对速度和成本进行了优化- 它们使用在zai模型中配置的agent.config.ts(通常是一个更快/更便宜的模型)。
import { adk, z } from "@botpress/runtime";
// Extract structured data from text
const contact = await adk.zai.extract(
"Contact John at john@example.com, phone 555-0100",
z.object({
name: z.string(),
email: z.string(),
phone: z.string()
})
);
// Returns: { name: "John", email: "john@example.com", phone: "555-0100" }
// Check if text matches a condition (returns boolean)
const isSpam = await adk.zai.check(messageText, "is spam or promotional");
// Label text with multiple criteria
const labels = await adk.zai.label(customerEmail, {
spam: "is spam",
urgent: "needs immediate response",
complaint: "expresses dissatisfaction"
});
// Returns: { spam: false, urgent: true, complaint: true }
// Summarize content
const summary = await adk.zai.summarize(longDocument, {
length: 200,
bulletPoints: true
});
// Answer questions from documents (with citations)
const result = await adk.zai.answer(docs, "What is the refund policy?");
if (result.type === "answer") {
console.log(result.answer);
console.log(result.citations);
}
// Response types: "answer", "ambiguous", "out_of_topic", "invalid_question", "missing_knowledge"
// Rate items on 1-5 scale
const scores = await adk.zai.rate(products, "quality score");
// Sort by criteria
const sorted = await adk.zai.sort(tickets, "by urgency, most urgent first");
// Group items semantically
const groups = await adk.zai.group(emails, {
instructions: "categorize by topic"
});
// Rewrite text
const professional = await adk.zai.rewrite("hey wassup", "make it professional and friendly");
// Filter arrays
const activeUsers = await adk.zai.filter(users, "have been active this month");
// Generate text
const blogPost = await adk.zai.text("Write about AI in healthcare", {
length: 1000,
temperature: 0.7
});
// Patch code files
const patched = await adk.zai.patch(files, "add JSDoc comments to all functions");
Zai配置:
// Create configured instance
const preciseZai = adk.zai.with({
modelId: "best", // "best" | "fast" | custom model ID
temperature: 0.1
});
// Enable active learning
const learningZai = adk.zai.learn("sentiment-analysis");
文档: https://www.botpress.com/docs/adk/zai/overview GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/zai-complete-guide.md
集成
何时添加集成:
- 您需要连接到外部服务(Slack、Linear、GitHub等)
- 您希望从某个渠道接收消息(网页聊天、WhatsApp、Discord)
- 您需要使用预构建的操作调用外部API
- 您希望对来自外部系统的事件做出反应
集成工作流程:
- 搜索- 使用以下命令查找集成
adk search <名称> - 添加- 使用以下命令安装
adk add <名称>@<版本> - 配置- 在用户界面中设置凭据,位于
http://localhost:3001/ - 使用- 通过以下方式调用操作
actions.<集成>.<操作>()
向AI提供集成操作:
// Convert any integration action to an AI-callable tool
tools: [actions.slack.sendMessage.asTool()]
CLI命令:
adk search slack # Find integrations
adk add slack@latest # Add to project
adk add slack --alias my-slack # Add with custom alias
adk info slack --events # See available events
adk list # List installed integrations
adk upgrade slack # Update to latest
adk remove slack # Remove integration
使用集成操作:
import { actions } from "@botpress/runtime";
// Slack
await actions.slack.sendMessage({ channel: "#general", text: "Hello!" });
await actions.slack.addReaction({ channel: "C123", timestamp: "123", name: "thumbsup" });
// Linear
await actions.linear.issueCreate({ teamId: "123", title: "Bug report", description: "Details" });
const { items } = await actions.linear.issueList({
first: 10,
filter: { state: { name: { eq: "In Progress" } } }
});
// GitHub
await actions.github.createIssue({ owner: "org", repo: "repo", title: "Issue" });
// Browser (web scraping)
const results = await actions.browser.webSearch({ query: "Botpress docs", maxResults: 5 });
// Make integration actions available to AI as tools
await execute({ tools: [actions.slack.sendMessage.asTool()] });
文档: https://www.botpress.com/docs/adk/managing-integrations GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/integration-actions.md
状态管理
理解状态层级 - 选择正确的级别:
| 状态级别 | 作用域 | 用于 |
|---|---|---|
bot.state | 全局,所有用户 | 功能开关、计数器、维护模式 |
user.state | 每个用户,其所有对话 | 用户偏好、个人资料、等级 |
对话状态 | 按对话 | 上下文、消息计数、活动工作流 |
工作流状态 | 按工作流实例 | 进度跟踪、中间结果 |
状态自动持久化- 只需修改即可保存。
可在机器人的任意位置访问和修改状态:
import { bot, user, conversation } from "@botpress/runtime";
// Bot state - global, shared across all users
bot.state.maintenanceMode = true;
bot.state.totalConversations += 1;
// User state - per user, persists across conversations
user.state.name = "Alice";
user.state.tier = "pro";
user.state.preferredLanguage = "es";
// In handlers, state is passed as a parameter
async handler({ state }) {
state.messageCount += 1; // Auto-persisted
}
// Tags - simple string key-value pairs for categorization
user.tags.source = "website";
user.tags.region = "north-america";
conversation.tags.category = "support";
conversation.tags.priority = "high";
状态类型:
- 机器人状态- 全局状态,在所有用户和对话间共享
- 用户状态- 按用户设置,在其所有对话中持续存在
- 对话状态- 按对话设置,在对话间隔离
- 工作流状态- 按工作流实例设置,在步骤间持续存在
标签与状态对比:
- 使用标签适用于:分类、简单字符串、筛选/查询
- 使用状态用于:复杂对象、数组、嵌套数据、业务逻辑
GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/tags.md
上下文 API
在任何处理程序中访问运行时服务:
import { context } from "@botpress/runtime";
// Always available
const client = context.get("client"); // Botpress API client
const citations = context.get("citations"); // Citation manager
const cognitive = context.get("cognitive"); // LLM client
const logger = context.get("logger"); // Structured logger
const botId = context.get("botId"); // Current bot ID
const configuration = context.get("configuration"); // Bot config
// Conditionally available (use { optional: true })
const user = context.get("user", { optional: true });
const conversation = context.get("conversation", { optional: true });
const message = context.get("message", { optional: true });
const workflow = context.get("workflow", { optional: true });
const chat = context.get("chat", { optional: true }); // Conversation transcript
if (user) {
console.log(`User: ${user.id}`);
}
GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/context-api.md
CLI 快速参考
# Project Lifecycle
adk init <name> # Create new project
adk login # Authenticate with Botpress
adk dev # Start dev server (hot reload)
adk dev --port 3000 # Custom port
adk chat # Test in CLI
adk build # Build for production
adk deploy # Deploy to Botpress Cloud
adk deploy --env production # Deploy to specific environment
# Integration Management
adk add <integration> # Add integration
adk add slack@2.5.5 # Add specific version
adk add slack --alias my-slack # Add with alias
adk remove <integration> # Remove integration
adk search <query> # Search integrations
adk list # List installed integrations
adk list --available # List all available
adk info <name> # Integration details
adk info <name> --events # Show available events
adk upgrade <name> # Update integration
adk upgrade # Interactive upgrade all
# Knowledge & Assets
adk kb sync --dev # Sync knowledge bases
adk kb sync --prod --force # Force re-sync production
adk assets sync # Sync static files
# Advanced
adk run <script.ts> # Run TypeScript script
adk mcp # Start MCP server
adk link --workspace ws_123 --bot bot_456 # Link to existing bot
# Utilities
adk self-upgrade # Update CLI
adk telemetry --disable # Disable telemetry
adk --help # Full CLI help
adk <command> --help # Help for specific command
文档: https://www.botpress.com/docs/adk/cli-reference GitHub: https://raw.githubusercontent.com/botpress/skills/master/skills/adk/references/cli.md
使用execute()
进行自主执行execute()函数是 ADK AI 能力的核心。它运行一个自主的 AI 智能体,能够:
- 理解自然语言中的用户意图
- 决定何时调用哪些工具
- 在知识库中搜索相关信息
- 生成上下文相关的响应
- 循环进行多次工具调用,直至任务完成
何时使用 execute():
- 在对话处理器中生成AI响应时
- 在工作流中需要AI决策时
- 任何需要自主、多步骤AI行为的地方
需要配置的关键参数:
指令- 告知AI其身份及行为准则工具- 赋予AI能力(搜索、创建、更新等)知识库- 让AI基于您的文档进行决策输出结构- 为特定结果定义结构化输出模式
execute()函数可实现自主AI代理行为:故障排除
import { Autonomous, z } from "@botpress/runtime";
// Define custom tool
const searchTool = new Autonomous.Tool({
name: "search",
description: "Search documentation",
input: z.object({ query: z.string() }),
output: z.string(),
handler: async ({ query }) => {
// Search implementation
return "results...";
}
});
// Define exit (structured response)
const AnswerExit = new Autonomous.Exit({
name: "Answer",
description: "Provide final answer to the user",
schema: z.object({
answer: z.string(),
confidence: z.number(),
sources: z.array(z.string())
})
});
// Execute AI with tools, knowledge, and exits
const result = await execute({
instructions: "Help the user with their request. Be helpful and concise.",
// Add tools
tools: [
searchTool,
actions.linear.issueCreate.asTool()
],
// Add knowledge bases
knowledge: [DocsKnowledgeBase, FAQKnowledgeBase],
// Define exits for structured outputs
exits: [AnswerExit],
// Model configuration
model: "openai:gpt-4o",
temperature: 0.7,
iterations: 10, // Max tool call iterations
// Hooks for monitoring
hooks: {
onBeforeTool: async ({ tool, input }) => {
console.log(`Calling ${tool.name}`, input);
return { input: { ...input, enhanced: true } }; // Modify input
},
onAfterTool: async ({ tool, output }) => {
console.log(`Result:`, output);
}
}
});
// Handle structured exit
if (result.is(AnswerExit)) {
console.log(result.output.answer);
console.log(result.output.sources);
}
Troubleshooting
| 错误 | 原因 | 解决方案 |
|---|---|---|
| Actions 中的 "Cannot destructure property" | 在 handler 参数中直接解构输入 | 使用async handler({ input, client })然后在内部使用const { field } = input |
| 表创建失败 | 无效的表名或id已定义 | 移除id列,确保名称以 "Table" 结尾 |
| 未找到集成操作 | 集成未安装或未配置 | 运行adk list,使用adk add添加,并在 localhost:3001 的 UI 中配置 |
| 知识库未更新 | 知识库未同步 | 运行adk kb sync --dev或adk kb sync --force |
| 工作流未恢复 | 动态步骤名称 | 使用稳定、唯一的步骤名称(避免使用step(\item-${i}`)`) |
| 类型已过时 | 生成的类型已陈旧 | 运行adk dev或adk build以重新生成 |
| 无法从工作流向用户发送消息 | 缺少 conversationId | 在启动工作流时传递conversationId,使用client.createMessage() |
| "user 未定义" | 在对话上下文之外访问对话信息 | 使用context.get("user", { optional: true }) |
| 状态更改未持久化 | 创建新对象而非修改现有对象 | 直接修改状态:state.user.name = "Alice" |
| AI未使用工具 | 描述不清晰 | 改进工具描述,添加详细说明.describe()到输入参数 |
如需更多帮助:运行adk --help或查看:
- 文档: https://www.botpress.com/docs/adk/
- GitHub: https://github.com/botpress/skills/tree/master/skills/adk/references
常见模式与最佳实践
1. 工作流始终传递conversationId参数
// In conversation - starting a workflow that needs to message back
await MyWorkflow.start({
conversationId: conversation.id, // Always include this!
data: "..."
});
// In workflow - messaging back to user
await client.createMessage({
conversationId: input.conversationId,
type: "text",
payload: { text: "Processing complete!" }
});
2. 使用环境变量存储密钥
// In .env (never commit!)
API_KEY=sk-...
SLACK_TOKEN=xoxb-...
// In code
config: { apiKey: process.env.API_KEY }
3. 保持工作流中步骤名称的稳定性
// GOOD - Single step for batch
await step("process-all-items", async () => {
for (const item of items) {
await processItem(item);
}
});
// BAD - Dynamic names break resume
for (let i = 0; i < items.length; i++) {
await step(`process-${i}`, async () => { ... }); // Don't do this!
}
4. 动作/工具中的错误处理
export default new Action({
handler: async ({ input }) => {
try {
// Action logic
return { success: true };
} catch (error) {
console.error("Action failed:", error);
throw new Error(`Failed to process: ${error.message}`);
}
}
});
5. 为工具边界情况使用ThinkSignal
handler: async ({ query }) => {
const results = await search(query);
if (!results.length) {
throw new Autonomous.ThinkSignal(
"No results",
"No results found. Ask the user to try different search terms."
);
}
return results;
}
6. 多通道处理
export default new Conversation({
channels: ["slack.channel", "webchat.channel"],
handler: async ({ conversation }) => {
const channel = conversation.channel;
if (channel === "slack.channel") {
// Slack-specific handling (threading, mentions, etc.)
} else if (channel === "webchat.channel") {
// Webchat-specific handling
}
}
});
完整参考文档
官方Botpress ADK文档
基础URL: https://www.botpress.com/docs/adk/
GitHub 仓库参考(AI优化)
基础 URL: https://github.com/botpress/skills/tree/master/skills/adk/references
如需获取本指南之外的详细规范,请获取相应的参考文件:
常见场景 - 构建什么
"我想构建一个能回答我们文档问题的支持机器人"
- 将您的文档作为来源创建一个知识库
- 创建一个使用以下功能的对话处理器
execute()结合该知识 - 添加
聊天集成以进行测试
"我希望机器人在用户报告问题时能在 Linear 中创建工单"
- 添加 Linear 集成:
adk add linear - 创建一个调用以下功能的工具
actions.linear.issueCreate() - 将工具传递给
execute()在你的对话中
"我需要运行一个每日同步任务"
- 创建一个工作流,其
schedule: "0 9 * * *"(cron语法) - 在步骤中实现同步逻辑
- 工作流将在预定时间自动运行
"我想存储用户偏好设置"
- 在
agent.config.ts中的user.state - 下定义模式
通过 - user.state.preferenceField = value
访问/修改
- 状态会自动持久化
"当新用户注册时我需要做出反应"创建一个监听 - 在处理程序中,启动用户引导流程或发送欢迎消息
"我想要存储订单数据并进行搜索"
- 创建一张表并定义其结构(注意:不要包含
id字段,表名应以"Table"结尾) - 对于需要支持搜索的文本列,请使用
searchable: true属性 - 使用以下CRUD操作方法:
createRows、findRows、updateRows和deleteRows
概述
本技能为使用ADK构建Botpress机器人提供了全面指导:
- 设置与初始化- ADK安装与项目创建
- 项目结构- 规范、文件与组织方式
- 核心概念- 操作、工具、工作流、对话、表格、知识库、触发器
- 状态管理- 机器人状态、用户状态、对话状态和工作流状态
- 集成管理- 添加和配置集成
- Zai(人工智能操作)- 提取、检查、标注、总结、回答、排序、分组、重写、筛选
- 命令行界面参考- 完整的命令指南
- 测试与部署- 本地测试和云端部署
- 常见模式- 最佳实践与故障排除
核心原则:ADK是一个基于约定的框架,其行为由文件位置决定。将组件放置在正确的src/子目录下,它们就会自动成为机器人的能力。
何时使用此技能:
- 用户想要创建一个新的Botpress机器人
- 用户询问如何添加动作、工具、工作流、对话、表格、知识库或触发器
- 用户需要集成方面的帮助(Slack、Linear、GitHub等)
- 用户想要了解ADK模式与最佳实践
- 用户遇到错误或需要故障排除
- 用户询问CLI命令、配置或部署相关问题
官方文档: https://www.botpress.com/docs/adk/ GitHub仓库: https://github.com/botpress/adk 技能库: https://github.com/botpress/skills


微信扫一扫,打赏作者吧~