02 能力声明(buildCapabilities)契约


文档摘要

02 能力声明(buildCapabilities)契约 本节摘要:服务端有一件很重要的事——告诉客户端「我能做什么」。这不是让客户端瞎猜,而是通过一份「能力声明」契约,明确列出服务端支持哪些能力(技能/插件/MCP/命令的读写、审批模式、沙箱后端、令牌作用域等)。本节讲清这份契约:它声明什么、客户端怎么用它、为什么这种「自述能力」对多客户端协作至关重要。 一、为什么服务端要「自述能力」 考虑没有能力声明的场景:客户端(桌面、CLI、企业云)想用服务端的某个功能,但它不知道服务端支不支持、怎么调。结果: 客户端要么「假设支持」硬调,不支持就报错。 要么「瞎试」,效率低。 不同服务端版本能力不同,客户端没法适配。 能力声明解决这个——服务端主动告诉客户端「我支持什么」,客户端据此决定行为。

02 能力声明(buildCapabilities)契约

本节摘要:服务端有一件很重要的事——告诉客户端「我能做什么」。这不是让客户端瞎猜,而是通过一份「能力声明」契约,明确列出服务端支持哪些能力(技能/插件/MCP/命令的读写、审批模式、沙箱后端、令牌作用域等)。本节讲清这份契约:它声明什么、客户端怎么用它、为什么这种「自述能力」对多客户端协作至关重要。

一、为什么服务端要「自述能力」

考虑没有能力声明的场景:客户端(桌面、CLI、企业云)想用服务端的某个功能,但它不知道服务端支不支持、怎么调。结果:

  • 客户端要么「假设支持」硬调,不支持就报错。
  • 要么「瞎试」,效率低。
  • 不同服务端版本能力不同,客户端没法适配。

能力声明解决这个——服务端主动告诉客户端「我支持什么」,客户端据此决定行为。这就像餐厅的菜单:你不用问「有没有 X」,看菜单就知道。

二、能力声明声明什么

服务端的能力声明大致含这些:

声明项 内容
版本 服务端版本、底层引擎版本(让客户端知道运行环境)
能力资源读写 技能/插件/MCP/命令/配置 各自是否可读、可写
审批模式 是否支持审批、超时多久
沙箱后端 支持哪种沙箱
UI UI 相关能力
令牌作用域 是否启用作用域、有哪些 scope(owner/collaborator/viewer)
代理 是否代理引擎
工具提供者 浏览器、文件收发(inbox/outbox)等
能力声明(示例结构): { schemaVersion: 1, serverVersion: "...", opencodeVersion: "...", skills: { read: true, write: true }, // 技能可读写 plugins: { read: true, write: true }, mcp: { read: true, write: true }, commands: { read: true, write: true }, config: { read: true, write: true }, approvals: { mode: "manual", timeoutMs: ... }, tokens: { scoped: true, scopes: ["owner","collaborator","viewer"] }, proxy: { opencode: true }, toolProviders: { browser: ..., files: { inbox, outbox, ... } } }

注意「读写」的区分——有些服务端实例是只读模式(如 demo、受限环境),这时所有 write 都是 false。客户端看到只读,就不提供「编辑」按钮,避免用户尝试后失败。

三、客户端怎么用这份契约

客户端拿到能力声明后,用它来决定 UI 和行为:

  • 看到 skills.write = true → 提供「编辑技能」入口。
  • 看到 skills.write = false(只读)→ 隐藏编辑入口,只允许看。
  • 看到 tokens.scoped = true → 知道有权限作用域,按 scope 处理。
  • 看到 approvals.mode → 按模式决定要不要等审批。
客户端启动 │ ▼ 拉取服务端能力声明 │ ▼ 据此配置 UI(显示/隐藏功能)和行为(只读/可写) │ ▼ 用户操作时,只调服务端声明支持的能力

这让客户端「自适应」不同服务端——同一个客户端,连全功能服务端时啥都能干,连只读服务端时自动变成只读浏览器。

四、为什么这种「自述能力」重要

这套机制的重要性在多客户端协作里特别明显:

  • 多客户端一致:桌面、CLI、企业云看到同一服务端,能力声明一致,行为一致。
  • 版本适配:服务端升级加了新能力,客户端通过声明发现并支持;服务端降级或受限,客户端自动适配。
  • 避免无效调用:客户端只调声明支持的能力,不会「调了才发现不支持」。

💡 类比 OpenAPI:它和 OpenCode 的 OpenAPI(OpenCode 教程第 3 章)思想类似——都是「服务端主动描述自己」。区别是 OpenAPI 描述「接口形状」,能力声明描述「运行时能力」(可读可写、模式等)。

五、能力声明与「服务端消费优先」

这套机制和第 2 章「服务端消费优先」哲学呼应——客户端是服务端的客户端,所以客户端的「能干什么」由服务端决定。能力声明就是这个「决定」的载体:

服务端(声明能力)──► 客户端(按声明行为)

如果客户端「自作主张」做声明里没有的事(比如只读服务端里硬编辑),就违反了「服务端消费优先」——它会失败,因为服务端不支持。

六、schemaVersion:契约的演进

能力声明带一个 schemaVersion(当前是 1)。这个版本号让契约能演进——未来如果声明结构大改(加新字段、改语义),升 schemaVersion,客户端按版本解析。这是契约演进的标配做法。

七、本节要点回顾

  1. 能力声明 = 服务端自述:告诉客户端「我支持什么」,避免瞎猜。
  2. 声明内容:版本、能力资源读写、审批模式、沙箱、令牌作用域、代理、工具提供者。
  3. 读写区分:只读模式 write 全 false,客户端据此隐藏编辑入口。
  4. 客户端用它配 UI/行为:自适应不同服务端(全功能/只读)。
  5. 多客户端一致 + 版本适配 + 避免无效调用:三样红利。
  6. 呼应服务端消费优先:客户端能干什么由服务端声明决定。
  7. schemaVersion:契约演进版本号。

能力声明讲清了,下一节讲服务端如何「代理」底层引擎——透明反代。


发布者: 作者: 灏天文库 转发
评论区 (0)
U