Capability Manifest 声明
Capability Manifest 是 Agent 自我声明 “我能做什么 / 我需要什么权限” 的 JSON 文档。Hashee 客户端用它生成”添加 Agent”的权限同意 UI、控制 tool call 流程、判断版本变更是否 breaking。
依据:Capability Manifest 规范 v1.0 (owner-approved,2026-04-23 frozen)。
完整结构
{ "schema_version": "1.0", "agent_version": "1.0.0", "tools": [ { "name": "fetch_web_page", "description_i18n_key": "agent.tools.fetch_web.desc", "input_schema": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" }, "method": { "enum": ["GET", "POST"], "default": "GET" } }, "required": ["url"], "additionalProperties": false }, "permission_scope": "network:http", "timeout_ms": 10000 } ], "permission_scopes": [ { "id": "network:http", "label_i18n_key": "agent.scopes.network_http.label", "sensitivity": "medium" } ], "capability_flags": { "supports_streaming": true, "supports_artifacts": true, "supports_voice": false, "supports_group_chat": true }}字段约束
schema_version
固定 "1.0",未来 schema 演进会改这一段。客户端按 schema_version 路由 parser。
agent_version
由 Agent 开发者维护的语义化版本号,仅供 Agent 自身参考——
Hashee 不会基于这个判断 breaking change(用 capability_manifest_version + diff 引擎)。
tools[]
每个工具一个对象,字段:
| 字段 | 必填 | 说明 |
|---|---|---|
name | 是 | 工具唯一名(snake_case,全 manifest 内不重复) |
description_i18n_key | 是 | 客户端 i18n 键,显示给用户的工具说明 |
input_schema | 是 | JSON Schema Draft 2020-12,仅 type: object,必须 additionalProperties: false |
permission_scope | 是 | 必须引用下面 permission_scopes[].id 之一 |
timeout_ms | 否 | 工具执行超时(默认 10000) |
permission_scopes[]
| 字段 | 必填 | 说明 |
|---|---|---|
id | 是 | scope 唯一 ID,建议格式 <domain>:<action>(如 filesystem:read) |
label_i18n_key | 是 | 客户端 i18n 键 |
sensitivity | 是 | low / medium / high(详见下表) |
Sensitivity 三级语义
| 级别 | UI 行为 | 用户超时 | 适合 |
|---|---|---|---|
low | 静默执行,无弹窗(信息已在 Agent 添加时 disclose) | — | 通知发送、数据查询、读公开数据 |
medium | 首次弹窗 + 同设备同会话 24 小时静默(滑动窗口) | — | 文件读、网络请求、剪贴板 |
high | 每次调用都弹窗,即使 scope 已授权 | 30 秒未确认 → denied: user_timeout | 文件写、shell 执行、删除操作、位置 |
V1 预置四个标准 scope(已在客户端 i18n 表):
| scope id | label | sensitivity |
|---|---|---|
notification:send | 发送通知 | low |
filesystem:read | 读取本地文件 | medium |
clipboard:read | 读取剪贴板 | medium |
location:read | 读取位置 | high |
非标准 scope 也允许,但客户端会显示 i18n key 原值(fallback 到 id)。
capability_flags
| flag | 说明 |
|---|---|
supports_streaming | Agent 支持流式输出(stream 类型消息) |
supports_artifacts | Agent 能发送 / 更新 Artifact |
supports_voice | Agent 能处理语音输入和发送语音输出(V1 暂未实装) |
supports_group_chat | Agent 可以加入群聊(H2G) |
客户端用这些 flag 决定是否在对话 UI 里显示对应入口(语音键、artifact 编辑面板)。
大小限制
- 整体序列化后 JSON ≤ 128 KB(hard cap,CI 强制,超过 →
MANIFEST_TOO_LARGE413)。 - ≥ 64 KB 后端写入 telemetry warning 推送到你的 Agent 详情页。
- 大 manifest 通常意味着 tool 设计太散——用更少的 tool + JSON Schema oneOf 表达。
提交方式
通过 System Agent Hashee 用对话方式:
更新 DemoBot 的 Capability ManifestHashee 会用 Artifact 表单卡片让你贴 JSON,自动 schema 校验 + diff 预览。
或者直接调 REST:
curl -X PATCH https://api.hashee.ai/agents/<agent_id> \ -H "Authorization: Bearer hsk_..." \ -H "Content-Type: application/json" \ -d @manifest.json成功响应:
{ "agent_id": "01906abc-...", "capability_manifest_version": 7, "capability_manifest_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "breaking_changes": []}Diff 引擎(服务端单一真源)
每次 PATCH 后,后端:
- 把 manifest JSON canonicalize(按 RFC 8785 JSON Canonicalization Scheme)。
- 计算
capability_manifest_hash = SHA-256(canonical_json)。 - 把
capability_manifest_version单调 +1(永不回退、永不跳号)。 - 跑 diff vs 前一版,分类 breaking / non-breaking。
Breaking change 触发条件
- 删除已存在的 tool。
- 修改 tool 的
input_schema(任何方式:去字段、改 type、加 required)。 - 把 tool 的
permission_scope提升到更高敏感度(如medium → high)。 - 删除
permission_scope(让它无法再被授权)。 capability_flags由true → false(撤销已宣告能力)。
Breaking change 触发后,所有已添加你 Agent 的用户客户端会收到一个 “Agent 能力变更,请重新审阅权限”通知卡片。
Non-breaking 范围
- 增加新 tool。
- 增加新 permission_scope(默认未授权,要单独申请 grant)。
- 修改
description_i18n_key/label_i18n_key(仅文案)。 capability_flags由false → true(新增能力)。- 修改
agent_version(开发者元信息)。
Tool Call 双向流程
Agent 调工具的完整链路:
Agent 进程 Hashee 后端 用户客户端 │ │ │ │ agent.sendArtifact({ │ │ │ subtype: "tool_call", │ │ │ call_id, tool_name, │ │ │ arguments │ │ │ }) │ │ ├──加密+签名+wrap──────────►│ │ │ │ 路由(盲管道) │ │ ├─────────────────────────►│ │ │ │ 解密+验签 │ │ │ 匹配 tool 到 Capability Manifest │ │ │ 按 sensitivity 决定 UI: │ │ │ low: 直接执行 │ │ │ medium: 首次弹窗 │ │ │ high: 每次弹窗 (30s timeout) │ │ │ 执行工具 (in-app 或代理) │ │ │ 生成 artifact_response: │ │ │ { call_id, status: "ok"|"denied"|"error", │ │ │ result?, reason? } │ │ ◄─加密+签名─────────── │ │ ◄────────────────────────│ │ │ agent.addEventHandler: │ │ │ artifact_response 解码 │ │ │ 匹配 call_id → 业务回调 │ │artifact_response.status 枚举
| status | 含义 |
|---|---|
ok | 用户授权或工具执行成功,result 字段有数据 |
denied | 用户拒绝;reason 给出 enum:user_rejected / user_timeout / tool_not_supported_in_group / permission_revoked |
error | 客户端执行 tool 时出错;reason 给文本错误码 |
接收 Tool Response 示例
agent.addEventHandler((event) => { if (event.type !== "artifact_response") return; if (event.artifact?.subtype !== "tool_response") return;
const { call_id, status, result, reason } = event.artifact; const handler = pendingCalls.get(call_id); pendingCalls.delete(call_id);
if (!handler) return; if (status === "ok") handler.resolve(result); else handler.reject(new Error(`tool ${status}: ${reason}`));});群聊里的 Tool Call
V1 禁用群聊(H2G)中的 tool call:响应永远是
status: "denied", reason: "tool_not_supported_in_group"。
原因:群聊里多人 broadcasting 工具 prompt 会破坏隐私语义。
V2 路线图允许 group-scoped tool call(管理员定义谁能 trigger,结果只可见 trigger 用户),但 V1 不支持。
下一步
- 接收第一条消息 — 端到端加密管道追踪
- 更新与撤销 — Capability 变更后的客户端通知机制
- SDK 章节 — Tool Call — SDK 层的封装 API