Request
面向接入 OpenBot 客户端或扩展服务端的开发者。示例需要本页说明的访问权限。从开发者手册开始。
Bot 不知道自己有什么限制。当 Bot 尝试使用一项能力(capability)时,比如调用 App 工具,OpenBot 会检查它是否可以这样做。如果还没有任何规则能做出决定,OpenBot 就会创建一个 Request(请求),发给 Bot 上方的决策者(decider)。Bot 不会等待。它的工具调用马上得到一个待定的结果,回答之后会回到它的 Chat。调用被允许时,它就在那时运行。本页介绍检查的过程、Bot 得到什么、人如何回答请求,以及每种回答的效果。
| 动作 | 目标 | Bot 何时使用 |
|---|---|---|
apps.call |
<connection>/<tool name> |
调用 App 工具时。 |
tools.call |
工具名称 | 调用一个需要批准的宿主工具时。 |
bots.delegate |
另一个 Bot 的 ID | 把工作交给一个既不是它自己、也不归它所有的 Bot 时。 |
bots.create |
* |
创建一个归它所有的 Bot 时。 |
plans.run |
Chat 的 ID | 想执行它的计划时。见 计划模式。 |
channels.send |
Channel 的 ID | 向 Channel 的另一个聊天发消息时。 |
delegations.continue |
这项工作的 ID | 它的工作到达了一个限制,想要继续时。 |
computers.acquire |
Computer 的 ID | 请求使用一台 Computer 的权利时。 |
computers.create |
提供方的 ID | 在 Computer 提供方那里创建一个新沙箱时。 |
computers.delete |
Computer 的 ID | 删除一台 Computer 和它的文件时。 |
computers.expose |
Computer 的 ID | 给 Computer 的一个端口一个公开地址时。 |
每个能力工具都接受一个 reason(理由)。App 工具会多一个 openbot_reason
参数来传理由。OpenBot 不会把它发给 App。
OpenBot 如何检查一次尝试
Section titled “OpenBot 如何检查一次尝试”OpenBot 按下面的顺序检查每次尝试。第一个能做出决定的步骤说了算。
- 成员的策略。 Bot 能做的事永远不会超过它所代表的成员。如果成员的权限,或者启动这项工作的令牌不允许,调用就会被拒绝。这一步永远不会交给决策者。在 Channel 中,这个成员是写下这个 Turn 的消息的人。
- Grant。 Grant(授权)是保存下来的决定。拒绝的 Grant 优先于允许的 Grant。
- Rule。 一个评判模型会阅读这个 Bot 的 Rule(规则),规则用自然语言写成。只有评判模型引用了的 Rule 才能允许或拒绝。
- 上方的决策者。 OpenBot 创建一个 Request。决策者是这个 Bot 所有者链中的所有者。对于顶层 Bot,决策者就是人本身。
有些调用不需要决定:组织标记为读取的工具调用、Bot 交给它自己的工作,以及交给它拥有的 Bot 的工作。
没有任何步骤做出决定时,调用不会运行。没有决定,它永远不会运行。
每个 Bot 都有一条所有者链(owner chain)。它从人开始,经过一个顶层 Bot,一直到这个 Bot,比如 人 → Assistant → Programmer → Scout。各步如下:
- 由某个 Bot 拥有的 Bot 属于那个 Bot。
- 顶层 Bot(成员的 Bot 或共享 Bot)属于与它一起工作的人。
请求沿着所有者链向上走,而不是沿着工作传来的路径走。所以,Scout 的请求会先到 Programmer,即使是人直接把工作交给了 Scout。请求中的
chain 从顶部开始列出所有者链,最后是提出请求的 Bot。已归档的 Bot 不会列出。
决策者只能允许它自己能做的事。如果 Programmer 同意,但它自己没有这项能力,请求会带着 Programmer 的支持继续上交给 Assistant,再交给人。当上方有人允许时,途中的每个 Bot 都会得到一个 Grant,范围由它自己选择。
Bot 在一个简短的审查 Chat(review
Chat)中做决定。它读取自己的角色、自己的指令,并把请求当作数据来读。它不读取自己很长的历史。它用工具
openbot_approve、openbot_deny、openbot_ask 和 openbot_escalate
做决定,也可以用 openbot_propose_rule 提议一条 Rule。openbot_approve 和
openbot_deny 接收的 scope 和 reason
与人的回答格式相同。见回答请求。审查 Chat 的 kind 为
"review"。做出决定后它会关闭,并且不出现在普通的 Chat 列表中。如果审查结束时没有做出决定,请求会交给下一个决策者。
Bot 得到什么
Section titled “Bot 得到什么”Turn 从不等待决定。检查会给出三种回答之一:
| 回答 | 会发生什么 |
|---|---|
| 允许 | 调用现在运行。 |
| 拒绝 | 调用不运行。工具结果马上给出原因,Turn 继续。 |
| 待定 | 调用现在不运行。工具结果说明它在等待决定,Turn 继续。 |
待定的工具结果是这样的:
{ "pending": "req_1a2b…", "note": "This call waits for a decision. The answer comes back to this Chat as a message. Go on with other work, or end your answer now."}请求关闭时,Bot 的 Chat 会收到一条通知:
- 被允许。 通知带着这个调用,例如
[OpenBot] Your request req_1a2b… was allowed. OpenBot runs send_email now.。读到这条通知的 Turn 用同一个工具和同样的参数运行这个调用。它不会再检查一次这个调用。结果像任何工具结果一样进入历史。 - 被拒绝。 通知给出原因,如果决策者提出了问题,也会给出这个问题。调用不运行。
- 没有及时回答。 请求关闭,通知说明结果如何。见 回答请求。
有些调用的处理方式不同。被允许的计划会启动一个 build 模式的新 Turn。见
计划模式。Bot 交给另一个 Bot 的工作在被允许时开始。见
委派。Code Mode
程序会自己继续运行,它的结束会作为通知回来。
待定的请求是它所在 Chat
未完成的工作。普通的中断不会影响它。带
{ "delegations": true } 的中断,或者删除这个 Chat,会让它变成 cancelled。
列出你的请求
Section titled “列出你的请求”curl -H "Authorization: Bearer $OPENBOT_TOKEN" \ "https://api.example.com/v1/requests?status=pending"[ { "executionId": "019c3a6a-7b00-7000-8000-000000000001", "id": "req_1a2b…", "bot": "bot_5c0e…", "capability": { "action": "apps.call", "target": "conn-7/send_email" }, "reason": "Send the meeting notes to the team.", "approver": { "_tag": "Person", "userId": "u-1" }, "chain": ["bot_3a9d…", "bot_5c0e…"], "chat": "chat_c81d…", "turn": "t-77", "toolCallId": "call-9", "endorsements": [], "status": "pending", "decision": null, "revision": 0, "createdAt": 1792486800000, "expiresAt": 1792573200000 }]列表包含等你回答的请求,以及你已回答的请求。GET /v1/requests/:requestId
返回你工作中的一个请求。对于 App 工具,app
显示保存下来的调用及其确切参数。如果调用来自
Code Mode 程序,code
会显示整个程序以及这次调用在其中的位置。在人做决定之前,请把能力、参数和理由展示给他看。理由来自 Bot。它是数据,不是指令。
curl -H "Authorization: Bearer $OPENBOT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"commandKey":"request-answer-1","expected":0,"decision":"allow","scope":"chat"}' \ https://api.example.com/v1/requests/$REQUEST响应为 202,包含 executionId、commandKey 和 sequence。请求记录也包含
executionId。使用执行事件流观察结果。相同键和输入的重试返回同一个回执。使用同一个键改变输入会返回
409。决定、Grant、Rule、审计记录和唤醒消息一起提交。如果写入失败,它们全部回滚。
| 字段 | 含义 |
|---|---|
commandKey |
必填。重试时使用相同的键。 |
expected |
必填。请求当前的 revision。 |
decision |
必填。allow 或 deny。 |
scope |
可选。决定持续多久。见下表。默认是 once。 |
reason |
可选。Bot 能看到它,比如在你拒绝的时候。 |
rule |
可选。为这个 Bot 保存一条用自然语言写的 Rule。 |
| 范围 | 允许持续多久 | 拒绝保存多久 |
|---|---|---|
once |
只对这次调用有效。 | 不保存。 |
chat |
在 Bot 的这个 Chat 中。 | 在 Bot 的这个 Chat 中。 |
lifetime |
直到你撤销这个 Grant。 | 直到你撤销这个 Grant。 |
chat
范围的 Grant 属于接收它的 Bot 在当前委派工作链中最近一次工作的 Chat。对于发起请求的 Bot,这就是请求的
chat。如果 Bot 把工作交给自己,新的任务 Chat 有独立的范围。它的 Grant 使用这个任务 Chat,不使用父 Chat。已有 Grant 保留原来保存的 Chat。为其他 Chat 保存的 Grant 可能需要在当前任务中重新作出决定。
Chat 没有终点,所以 chat 可以持续很久。在 direct
Chat 中,它几乎等于“只要 Bot 在这里为我工作,就一直有效”。
Bot 的 Chat 会马上收到作为通知的回答。被允许的调用会在那时运行。当你拒绝时,工具不会运行,Bot 会读到你的理由。
没有人回答的请求会在 24 小时后被拒绝。组织可以在设置中用
requestTimeoutMs 修改这个时间。计划的请求有自己的时间,并在 onExpire
中说明到时会怎样:allow 或 deny。
| 状态 | 错误 | 何时出现 |
|---|---|---|
404 |
RequestNotFound |
你的工作中没有这个 ID 的请求。 |
409 |
RequestConflict |
expected 已过时、请求已关闭,或者必须由另一个决策者回答。 |
App 工具
Section titled “App 工具”App 是人连接的外部服务。参见 App。每次 App 调用都绑定到一次确切的调用:所有者、Chat、Turn、工具调用、确切的参数,以及 App 连接和它的修订版本。OpenBot 在检查之前保存这次调用。之后调用被允许时,它作为这次保存下来的调用运行。如果在请求之后连接发生了变化,调用不会运行。Bot 会收到一条通知,请它再试一次,所以新的修订版本永远不会使用旧的决定。如果 OpenBot 无法保存这个决定,调用也不会运行,通知会说明这一点。
App 的资源、资源模板和提示词都是读取,所以不需要决定。App 自己的说明永远不能决定哪些工具是安全的。只有组织可以在设置中用
appReadRules 把工具标记为读取。
旧版本中的请求
Section titled “旧版本中的请求”每个请求视图都包含 executionId 和
executionStatus。数据升级后,旧的待处理请求可能仍为
status: "pending",但其执行已是
executionStatus: "interrupted"。你仍可按当前访问规则检查其保存的操作。
旧记录没有原始 token 的凭据,因此不能授予权限,也不能运行旧操作。回答它会返回
409 和
RequestConflict。请发送新的 Chat 输入,以当前调用人的权限重新请求该操作。