App
App(应用)是 Agent 可以使用的外部服务。每个 App 都通过 OpenBot App Protocol 发布在网上。本页介绍如何把 App 连接到你的账号、登录 App,以及在 Turn 中使用它。
所有示例都使用用户令牌。同样的调用也可以用 session cookie 完成。参见身份验证。
| 词语 | 含义 |
|---|---|
| Card URL | App 的 Server Card 的稳定 HTTPS 地址。它就是 App 的身份。 |
| Connection | 保存在你账号中的 App,带有你的设置和登录信息。你最多可以有 30 个。 |
| Connection draft | 保存下来的发现结果。你在创建连接前先审查它。它保留 24 小时。 |
| App operation | 从 Turn 到 App 的一次被记录的调用,带有它的状态和结果。 |
连接 App
找到 App
把 App 的地址交给 OpenBot。它可以是一个域名、一个 App 页面、一个 Catalog 链接或一个 Card 链接。二维码里存的也是同样的 HTTPS 链接。
curl -X POST https://api.example.com/v1/connection-drafts \ -H "Authorization: Bearer $OPENBOT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "input": "apps.example.com" }'响应是一个草稿,状态码为 201。请保留它的 id 和 revision。discovery 字段有两种:
Single有一个candidate。Multiple有一个candidates列表。请让用户选择一个。OpenBot 永远不会添加整个 Catalog。
每个候选项都有一个 cardUrl、card、一个 endpoints 列表,以及找到它的 sources。每个端点都有一个 index 和它需要的 requirements,比如一个 API 密钥请求头。
如果只想查看而不保存草稿,请把同样的请求体发送到 POST /v1/apps/discover。发现过程永远不会添加、登录或调用 App。
审查并创建连接
把 App 名称、来源和端点展示给用户。然后创建连接。你必须发送 "confirmed": true。
curl -X POST https://api.example.com/v1/connections \ -H "Authorization: Bearer $OPENBOT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "draftId": "<draft id>", "revision": 0, "cardUrl": "https://apps.example.com/mcp/server-card", "remoteIndex": 0, "name": "Work calendar", "values": { "header:X-API-Key": "<secret>" }, "confirmed": true }'values 中的键来自端点的 requirements。它们的形式是 variable:<name>、header:<name> 或 header:<name>:variable:<name>。OpenBot 会加密这些值。之后读取时只显示不是机密的值。
OpenBot 在保存之前会再次读取 Card。新连接使用草稿的 id 作为自己的 id。如果你再次发送同样的请求,会得到同一个连接。
检查它是否可用
curl -X POST https://api.example.com/v1/connections/<connection id>/verify \ -H "Authorization: Bearer $OPENBOT_TOKEN"Verified 返回实时的 protocolVersion、tools、resources、resourceTemplates 和 prompts。Unavailable 返回连接,它的 availability 说明原因。
连接时的错误
| 状态 | 错误 | 怎么做 |
|---|---|---|
| 409 | ConnectionConflict |
查看 reason:CandidateChanged、RevisionChanged、DraftExpired、AlreadyAdded 或 LimitReached。 |
| 422 | ConnectionConfigurationInvalid |
填写 keys 中列出的设置项。 |
| 422 | AppDiscoveryFailed |
检查地址。reason 和 issues 说明哪里失败了。 |
| 403 | AppRestricted |
本部署屏蔽了这个 App。参见 restriction.reason 和 restriction.appealUrl。 |
可用性
availability 字段告诉你 Agent 能否使用一个连接。
_tag |
含义 |
|---|---|
Unverified |
已保存,但还没有检查。 |
Available |
已检查,可以使用。 |
PendingAuthorization |
App 需要账号登录。scopes 列出它要求的访问权限。 |
AuthorizationExpired |
登录已失效。请刷新或重新登录。 |
ConnectionFailed |
上次检查失败。message 说明原因。 |
NeedsRevalidation |
App 改变了它的端点或登录要求。请重新审查。 |
CleanupPending |
移除没有完成。请再次尝试移除。 |
Restricted |
本部署屏蔽了这个 App。 |
PendingConfiguration |
连接需要更多设置。 |
登录 App 账号
有些 App 需要用户自己的账号。OpenBot 为此使用带 PKCE 的 OAuth。用户在 App 的提供方登录,而不是在 OpenBot 登录。
-
开始流程。发送连接的
revision。scopes留空表示使用 App 要求的范围。returnTo是一个同源路径。默认是/。Terminal window curl -X POST https://api.example.com/v1/connections/<connection id>/authorization \-H "Authorization: Bearer $OPENBOT_TOKEN" \-H "Content-Type: application/json" \-d '{ "revision": 0, "scopes": [], "returnTo": "/apps" }' -
读取响应:
AuthorizationStarted有一个flowId和一个authorizationUrl。在用户的浏览器中打开这个 URL。IssuerSelectionRequired列出issuers。请让用户选择一个,然后带上issuer重新开始。AuthorizationNotRequired表示 App 不需要登录。
-
用户登录。提供方把浏览器跳转到
https://api.example.com/auth/apps/callback。 -
OpenBot 把浏览器跳转到
returnTo?authorization=<flowId>。如果浏览器没有 OpenBot 会话,它会跳转到/?authorization=<flowId>。你的客户端先让用户登录(参见身份验证)。 -
你的客户端完成流程:
Terminal window curl -X POST https://api.example.com/v1/app-authorizations/<flow id>/complete \-H "Authorization: Bearer $OPENBOT_TOKEN"
要查看流程,请调用 GET /v1/app-authorizations/:flowId。它的 status 是 Waiting、Received、Processing、Succeeded、Cancelled 或 Failed。
OpenBot 的 OAuth 客户端 ID 是一个公开文档,地址是 https://api.example.com/v1/apps/client-metadata。提供方会读取它,所以你不需要在每个提供方那里注册 OpenBot。
要退出 App,请发送 DELETE /v1/connections/:connectionId/authorization。响应是 Revoked,或者在提供方无法撤销令牌时为 LocalOnly。两种情况下,OpenBot 都会删除它保存的令牌。
管理连接
| 任务 | 请求 |
|---|---|
| 列出或读取 | GET /v1/connections、GET /v1/connections/:connectionId |
| 重命名、关闭或打开 | PUT /v1/connections/:connectionId,带上 { "revision", "name", "enabled" } |
| 刷新登录 | POST /v1/connections/:connectionId/refresh |
| 审查有变化的 App | 从 Card URL 创建一个新草稿。然后 POST /v1/connections/:connectionId/revalidate。 |
| 移除 | DELETE /v1/connections/:connectionId |
刷新永远不会要求更多的访问权限。如果刷新失败,连接会变成 AuthorizationExpired。
当 App 改变了它的端点、私密设置、提供方或范围时,连接会变成 NeedsRevalidation。在你审查之前,Agent 不能使用它。把 { "revision", "draftId", "remoteIndex", "values", "confirmed": true } 发送到 revalidate。OpenBot 不会把旧令牌发送到新端点。需要登录的 App 这时需要重新登录。
移除返回 204。OpenBot 先关闭连接,再撤销并删除它的令牌。如果清理没有完成,你会得到 409 ConnectionCleanupPending。再次发送同样的 DELETE 来完成它。
手动连接
你也可以连接一个没有 Server Card 的 MCP 服务器。发送 POST /v1/connections/manual,带上一个新的 UUID id、一个 name、HTTPS url、"transport": "streamable-http" 和 headers。用 PUT /v1/connections/:connectionId/manual 修改它。把某个请求头设为 null 即可删除它。手动连接永远不会进入公开的 App Index。
Turn 中的 App
Turn 运行时,OpenBot 会为你可用连接的每项能力给模型一个工具。每个工具名称的形式是 openbot_<hash>。它的描述以 App 名称、连接名称和能力名称开头。
- 工具(tools)成为可调用的工具。
visibility不包含model的工具对模型隐藏。 - 资源(resources)、资源模板(resource templates)和提示词(prompts)成为读取工具。
每次 App 工具调用都要先经过能力检查。一个工具的第一次调用通常会产生一个请求,由决策者回答。之后的调用可以由一个 Grant 或 Rule 覆盖。读取资源和提示词不需要决定,组织在设置中标记为读取的工具也不需要。App 的说明永远不能决定这一点。每个 App 工具都有一个额外的 openbot_reason 参数,用来传 Agent 的理由。OpenBot 永远不会把它发给 App。
模型还会得到三个辅助工具。它们永远不会添加 App、登录或批准动作。
| 工具 | 作用 |
|---|---|
openbot_search_apps |
在公开的 App Index 中搜索缺少的能力。 |
openbot_app_details |
通过 Card URL 读取一个 App 的公开信息和来源。 |
openbot_app_access |
列出用户的连接,以及它们在设置或登录方面的需要。 |
Code Mode
当平台打开 Code Mode 时,模型还会得到 openbot_code_api 和 openbot_run_code。Agent 用它们写一段调用这些 App 工具的小程序。程序中的每次调用都和普通的 App 工具调用走同样的路径。
App 操作
OpenBot 把每次 App 调用记录为一个 App 操作(App operation)。用 GET /v1/sessions/:sessionId/app-operations 或 GET /v1/app-operations/:id 读取它们。
| 状态 | 含义 |
|---|---|
PendingApproval、Approved、Rejected |
关于这次调用的决定。 |
Sending |
调用正在进行。 |
InputRequired |
App 要求更多输入。见下文。 |
Completed、Failed |
调用已结束。result 包含详细信息。 |
OutcomeUnknown |
OpenBot 发送了调用,但没有得到明确的回答。 |
有些 App 会在调用中途提出问题。这时操作的状态为 InputRequired,带有一个 round 编号,App 的请求在 result.request 中。用同样的 round 发送回答:
curl -X POST https://api.example.com/v1/app-operations/<operation id>/inputs \ -H "Authorization: Bearer $OPENBOT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "round": 1, "responses": { "<input key>": { "action": "accept", "content": { "label": "Team sync" } } } }'responses 中的键必须和 App 输入请求的键一致。每个回答都使用该类请求的标准 MCP 结果。上面的示例回答的是一个表单请求。OpenBot 在发送回答之前会检查它们。
App 视图
有些 App 工具带有一个交互式视图。视图是来自 App 的 HTML 页面,由 MCP Apps 定义。OpenBot 没有用户界面,所以由你的客户端显示视图。你可以跳过这一部分。每个结果也都有文本。
- 为一个操作打开视图:
POST /v1/app-operations/:operationId/view,带上{ "sessionId", "itemId" }。响应包含视图的id、HTMLresource、视图的tools、调用的arguments和result。 - 在 iframe 中显示 HTML。
@openbot-build/protocol/McpApps模块有一个浏览器宿主可以做这件事。参见 Protocol。 - 把视图的请求转交给 OpenBot:
| 视图请求 | OpenBot 调用 |
|---|---|
| 列出工具、资源、模板 | POST /v1/app-views/:viewId/read |
| 调用工具或读取资源 | POST /v1/app-views/:viewId/actions(返回 202 和一个凭据) |
| 检查一个动作 | GET /v1/app-views/:viewId/actions/:requestId |
| 更新模型上下文 | PUT /v1/app-views/:viewId/context |
| 发送一条文本消息 | POST /v1/app-views/:viewId/messages |
| 关闭 | DELETE /v1/app-views/:viewId |
视图动作遵守同样的批准规则。消息会启动一个新的 Turn,而且只在 Session 空闲时才会。如果你用较旧的 Timeline version 打开视图,视图是只读的。如果视图无法打开,你会得到 409 AppViewUnavailable。文本结果仍然在。
导出、导入和重置
导出你的 App 列表。文件中没有机密信息,也没有登录信息。
curl https://api.example.com/v1/app-experience/export \ -H "Authorization: Bearer $OPENBOT_TOKEN"{ "format": "openbot-apps-v1", "apps": [ { "name": "Work calendar", "cardUrl": "https://apps.example.com/mcp/server-card", "remoteIndex": 0 } ]}把同样的 JSON 发送到 POST /v1/app-experience/import。一个文件最多可以包含 30 个 App。导入不会创建连接。对于每个 App,你会得到一个新的草稿或一个 error。草稿的 imported 字段保留名称和端点。请审查每个草稿,然后像平常一样创建连接。
POST /v1/app-experience/reset 移除你所有的连接和草稿。响应列出被移除的 ID(removed)和所有待完成的清理(pending)。
在 API 参考中查看完整的请求和响应结构。