跳转到内容

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 链接。

Terminal window
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。

Terminal window
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。如果你再次发送同样的请求,会得到同一个连接。

检查它是否可用

Terminal window
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 登录。

  1. 开始流程。发送连接的 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" }'
  2. 读取响应:

    • AuthorizationStarted 有一个 flowId 和一个 authorizationUrl。在用户的浏览器中打开这个 URL。
    • IssuerSelectionRequired 列出 issuers。请让用户选择一个,然后带上 issuer 重新开始。
    • AuthorizationNotRequired 表示 App 不需要登录。
  3. 用户登录。提供方把浏览器跳转到 https://api.example.com/auth/apps/callback。

  4. OpenBot 把浏览器跳转到 returnTo?authorization=<flowId>。如果浏览器没有 OpenBot 会话,它会跳转到 /?authorization=<flowId>。你的客户端先让用户登录(参见身份验证)。

  5. 你的客户端完成流程:

    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 发送回答:

Terminal window
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 没有用户界面,所以由你的客户端显示视图。你可以跳过这一部分。每个结果也都有文本。

  1. 为一个操作打开视图:POST /v1/app-operations/:operationId/view,带上 { "sessionId", "itemId" }。响应包含视图的 id、HTML resource、视图的 tools、调用的 arguments 和 result。
  2. 在 iframe 中显示 HTML。@openbot-build/protocol/McpApps 模块有一个浏览器宿主可以做这件事。参见 Protocol。
  3. 把视图的请求转交给 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 列表。文件中没有机密信息,也没有登录信息。

Terminal window
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 参考中查看完整的请求和响应结构。