跳转到内容

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。

使用 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 设置保留,但不会启动输入或投递。用当前权限保存修改或轮换机密,以设置新调用人并清除该标记。旧的未知发送不会以新调用人的身份重放。

机器人只为组织的成员工作。当一个还没有关联的人给机器人写消息时,什么都不会运行。机器人会改为给他发一个关联码(link code)。它把关联码发到只有这个人能看到的地方:私聊中,或者在平台支持时,作为群里的私密消息。关联码 15 分钟内有效。

设置了 linkPath 时,机器人会发一个链接,比如 https://api.example.com/link?code=ocl_...。你在这个路径上的客户端先让这个人登录,然后调用:

  1. GET /v1/channel-links/:code,显示这个关联码属于谁。
  2. 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 解除一个人的关联。


平台上的每个聊天都是一个 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 为已关联的发言人工作。保存的执行身份分别记录发言人、Chat 所有者和配置 Channel 的调用人。配置时使用的 token 在重启后仍保留限制。核心的 author 字段用于输入分组,不是用户 ID。

  • 发言人的权限限制 Bot 可以做什么。
  • Channel 工作中的工具和计划步骤检查 Channel 使用权限,不会给发言人直接访问所有者所存 Chat 的权限。App 和 Computer 调用仍检查各自资源的权限。
  • 配置调用人的限制也生效。所有者必须仍有使用 Bot 的权限。
  • Requests 发给发言人。
  • Bot 根据保存的发言人身份使用记忆。

恢复工作和开始外部调用前,OpenBot 会检查当前成员、token、Channel 和账户关联。删除关联会阻止该发言人的新动作。已保存的批准不能绕过这些检查。


当一个 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 可以连接任何其他聊天系统。用 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 现在无法访问它的存储或平台。