Channels
面向接入 OpenBot 客户端或扩展服务端的开发者。示例需要本页说明的访问权限。从开发者手册开始。
Channel 是你的组织在一个聊天平台上的一个机器人,比如一个 Slack 应用或一个 Telegram 机器人。人们在私聊和群聊中与这个 Channel 的 Bot 交谈。OpenBot 仍然是无界面的:Channel 是平台和 API 之间的连接,不是用户界面。
| 类型 | 平台 |
|---|---|
slack |
启用了 Events API 和交互功能的 Slack 应用。 |
lark |
启用了事件订阅和卡片回调的 Lark(飞书)应用。 |
telegram |
一个 Telegram 机器人。 |
custom |
任何其他使用 OpenBot Channel 协议 的系统。 |
每个平台都把它的事件发到一个 webhook(OpenBot 接收回调的地址)。OpenBot 会检查每个事件的签名,立即回答,然后再做工作。
添加 Channel
Section titled “添加 Channel”提供方设置参见设置 Channel。
使用 POST /v1/organization/channels 和 commandKey 创建。HTTP
201 返回已保存的 Channel; executionId 指向配置工作。修改使用
PATCH /v1/organization/channels/:channelId,带上 commandKey 和
expectedVersion,返回 Channel。回复丢失后复用相同键和正文。读取执行来确认远端注册结果。
删除使用 DELETE /v1/organization/channels/:channelId,JSON 正文为
{ "commandKey": "remove-channel-1" }。HTTP
202 返回执行回执。Channel 先停止接受新工作。移除等待已保存的工作释放资源,再删除 Channel 和账户关联。Chat 保留。
升级后的 Channel 可能有 needsAuthorization: true。数据和 enabled
设置保留,但不会启动输入或投递。用当前权限保存修改或轮换机密,以设置新调用人并清除该标记。旧的未知发送不会以新调用人的身份重放。
关联你的账户
Section titled “关联你的账户”机器人只为组织的成员工作。当一个还没有关联的人给机器人写消息时,什么都不会运行。机器人会改为给他发一个关联码(link code)。它把关联码发到只有这个人能看到的地方:私聊中,或者在平台支持时,作为群里的私密消息。关联码 15 分钟内有效。
设置了 linkPath 时,机器人会发一个链接,比如
https://api.example.com/link?code=ocl_...。你在这个路径上的客户端先让这个人登录,然后调用:
GET /v1/channel-links/:code,显示这个关联码属于谁。POST /v1/channel-links/:code/accept,把账户关联到调用者。一个关联码只能用一次。
关联需要一个 POST,所以没有人能只靠给别人发一个链接就关联账户。没有 linkPath
时,机器人只发送关联码,这个人用同样的调用来接受它。
GET /v1/user/channel-identities
列出你关联的账户。DELETE /v1/user/channel-identities/:channelId/:externalUserId
解除一个关联。管理员用 GET /v1/organization/channels/:channelId/identities
列出一个 Channel 的人,并对 .../identities/:externalUserId 使用 DELETE
解除一个人的关联。
Channel 的 Chat
Section titled “Channel 的 Chat”平台上的每个聊天都是一个 kind: "channel"
的长期 Chat:每个私聊一个 Chat,每个群聊一个 Chat。这个 Chat 把聊天的名字作为它的
title。以 actor 的身份用 GET /v1/chats?kind=channel 列出它们。
- 在私聊中,每条消息都会交给 Bot。
- 在群聊中,只有提到机器人的消息才会交给 Bot。每条消息都以写它的人的名字开头,这样 Bot 知道是谁在说话。
- Bot 正在为某个人工作时,这个人发来的消息会进入正在运行的 Turn。Bot 在下一步读取它。
- 另一个人发来的消息会在这个 Chat 的收件箱中等待。正在运行的 Turn 结束后,它作为单独的 Turn 运行。
- Turn 运行时,机器人会显示它的文本,并随着文本变长不断修改这条消息。很长的回答会分成几部分发出。
- 每个 Turn 的回答都会发到这个聊天。由通知启动的 Turn 也是这样,例如 Bot 交出去的工作的结果。所以 Bot 可以先说“我去看看”,之后再发出结果。
- 如果平台把同一个事件发了第二次,OpenBot 会丢弃它。
每个 Turn 为它的发言人工作
Section titled “每个 Turn 为它的发言人工作”Turn 为已关联的发言人工作。保存的执行身份分别记录发言人、Chat 所有者和配置 Channel 的调用人。配置时使用的 token 在重启后仍保留限制。核心的
author 字段用于输入分组,不是用户 ID。
- 发言人的权限限制 Bot 可以做什么。
- Channel 工作中的工具和计划步骤检查 Channel 使用权限,不会给发言人直接访问所有者所存 Chat 的权限。App 和 Computer 调用仍检查各自资源的权限。
- 配置调用人的限制也生效。所有者必须仍有使用 Bot 的权限。
- Requests 发给发言人。
- Bot 根据保存的发言人身份使用记忆。
恢复工作和开始外部调用前,OpenBot 会检查当前成员、token、Channel 和账户关联。删除关联会阻止该发言人的新动作。已保存的批准不能绕过这些检查。
聊天中的批准
Section titled “聊天中的批准”当一个 request 在等待某个人时,机器人会发送一张带三个按钮的卡片:Allow
once(允许一次)、Allow in this chat(在这个聊天中允许)和
Deny(拒绝)。Allow in this chat 会创建一个范围为 chat 的 Grant。见
Requests。在计划模式中等待批准的计划也会收到同样的卡片。如果这个人在这个 Channel 上关联了账户,卡片会发到他的私聊。否则,卡片会发到这项工作所在的聊天。对于 Bot 交出去的工作提出的请求,例如为这个聊天工作的 task
Chat 提出的请求,也是这样。
只有 request 在等待的那个人才能按按钮。当 request 发生变化时,卡片会显示这个决定。
Bot 也可以用工具 openbot_channel_send
向同一个 Channel 的另一个聊天发消息。每次发消息都是能力
channels.send,所以由决策者链来决定。
Channel 输入、回复、卡片和工具发送都使用共同执行系统。Webhook 事件 ID 用于去重。每条输入保存前一条执行的引用,使所有节点按同一会话顺序处理输入。消息和调用人保存在加密业务记录中。引擎消息只保存执行引用。
回复和卡片读取执行事件日志。重启后从游标继续,不再另外扫描遗漏的回复。每条文本事件都有步骤和 attempt。模型重试不会合并两次 attempt 的文本。
每个消息分段和编辑都有调用意图及结果记录。已知结果会被复用。如果平台可能已经接收发送,但结果未保存,OpenBot 会暂停该执行。通过执行事件和决策接口停止它或允许再次尝试。网络错误不代表消息一定没有发送。重复提交同一决策时使用相同的命令键。
openbot_channel_send 返回 queued 和
executionId,表示发送请求已被接受。观察该执行以取得发送结果。关闭事件流只关闭观察。
自定义 Channel
Section titled “自定义 Channel”自定义 Channel 可以连接任何其他聊天系统。用
credentials:{ "kind": "custom", "endpoint": "https://chat.example.com/openbot" }
创建它。然后用 PUT /v1/organization/channels/:channelId/secret
生成签名密钥。请求体需要 commandKey 和 Channel 的 expectedVersion。响应包含
secret 和
channel。使用相同键重试会返回已保存的结果。新的命令生成新密钥,并让旧密钥失效。
两个方向的签名方式相同。每个请求都有两个请求头:
X-OpenBot-Timestamp:以秒为单位的时间。X-OpenBot-Signature:sha256=,后面接用密钥对timestamp + "." + body计算出的十六进制 HMAC-SHA256。
你的系统把事件发到 webhookUrl:
{ "type": "message", "id": "evt_1", "conversation": { "id": "room-1", "kind": "group", "title": "Ops" }, "sender": { "id": "u_42", "name": "Ada" }, "text": "What broke last night?", "mentioned": true}id 在这个 Channel 中必须唯一。按下按钮的事件是
{ "type": "action", "id", "conversation", "sender", "value" }。
OpenBot 把消息发到 endpoint。一个 send 包含 markdown、可选的
buttons,以及 conversation、person
或两者都有。两者都有时,只有这个人应该在这个聊天中看到它。只有 person
时,它会发到私聊。用 { "ref": "<message id>" } 回答;如果 OpenBot 没有发送
conversation,就加上 conversation。一个 edit 包含 conversation、ref
和新的 markdown。OpenBot 只调用公开地址。
| 资源 | 操作 | 允许做什么 |
|---|---|---|
Channel |
read |
读取组织的 Channels,以及与它们关联的人。 |
Channel |
write |
创建、修改和删除 Channels,设置它们的密钥,并解除人的关联。 |
Channel |
use |
与 Channel 的 Bot 交谈,并让你的 Bots 向它发消息。 |
ChannelIdentity |
read |
读取你关联的账户。 |
ChannelIdentity |
write |
关联和解除关联你的账户。 |
Channel 的路径是
org / <org> / channel / <id>。管理员管理它们。每个成员都可以使用它们,并关联自己的账户。见
权限。
| 错误 | 状态 | 何时出现 |
|---|---|---|
ChannelInvalid |
400 | Bot 不是共享 Bot、类型被修改了,或者平台拒绝了这个 webhook。 |
ChannelNotFound |
404 | 没有这个 Channel。 |
ChannelLinkInvalid |
404 | 关联码未知、已经用过或已经过期。请再向机器人要一次。 |
ChannelIdentityNotFound |
404 | 没有这个关联的账户。 |
ChannelConflict |
409 | 你读取之后,这个 Channel 已经改变。 |
ChannelHookDenied |
401 | 签名错误或太旧,或者这个 Channel 已停用。 |
ChannelsUnavailable |
503 | OpenBot 现在无法访问它的存储或平台。 |