Appearance
ZAP 消息协议
ZAP 是知办AI与接入方 Agent Runtime 之间的 HTTP + SSE 协议。它负责会话创建、消息投递、流式输出、工具过程、HITL 暂停与取消。
和服务端 API 的区别
- ZAP:知办AI服务器 → 接入方 Agent Runtime。用户向知办AI 数字员工发消息后,知办AI服务器把消息推给接入方 Runtime。
- 租户服务端 API:接入方 Agent 服务 → 知办AI服务器。接入方在处理过程中主动调用租户授权能力,比如知识库检索,见 租户服务端 API 总览。
术语边界
| 名称 | 指谁 | 在本协议里做什么 |
|---|---|---|
| 知办AI 数字员工 | 管理后台创建/发布、客户端展示的员工入口 | 提供名称、头像、运行环境、agent_key 等配置。 |
| 接入方 Agent Runtime | 接入方部署的 ZAP HTTP/SSE 服务 | 实现 /zap/v1/*,接收知办AI服务器调用并返回 SSE。 |
| 接入方 Agent 服务 | Runtime 背后的业务代码 | 做 LLM 推理、工具执行、记忆和本地用户映射。 |
| 接入方本地 Agent 实例 | 接入方系统可选的本地实例资源 | 如果按“租户 + 用户 + 知办AI 数字员工”创建实例,通过 runtime_identity.agent_instance_id 返回。 |
数据面端点
| Method | Path | 输入 | 输出 | 用途 |
|---|---|---|---|---|
GET | /zap/v1/runtime_card | 无 body | runtime 能力声明 | 接入测试、健康巡检、决定是否启用实例初始化。 |
PUT | /zap/v1/tenants/{tenant_id} | 租户资料 | runtime_identity.tenant_id | 租户注册、后台启用外部 ZAP runtime 时,同步/更新接入方本地租户。 |
POST | /zap/v1/agents | 知办AI 数字员工配置 | agent_key | 数字员工发布/更新后,同步接入方 Agent Runtime 内的业务入口。 |
POST | /zap/v1/instances | 租户、用户、身份事实、数字员工上下文 | runtime_identity、mapping_status | 初始化/解析接入方本地用户与当前数字员工实例。 |
POST | /zap/v1/sessions | agent_key、平台用户、上下文、runtime_identity | session_id、可选 session_token | 创建 runtime 会话。 |
POST | /zap/v1/sessions/{session_id}/messages | 用户消息 blocks | SSE 事件流 | 推送用户消息,接入方 Agent Runtime 返回思考、工具过程和最终 blocks。 |
POST | /zap/v1/sessions/{session_id}/cancel | 无 body | 取消结果 | 取消正在处理的消息。 |
DELETE | /zap/v1/sessions/{session_id} | 无 body | 删除结果 | 会话释放,幂等。 |
所有端点都必须校验:
http
Authorization: Bearer <runtime_api_key>完整调用顺序
从管理员保存 runtime 到终端用户完成一次聊天,完整链路如下:
1. 后台测试连通
知办AI ──GET /zap/v1/runtime_card──▶ runtime
◀─能力声明,含 default_agent_key / runtime_ui_components / tenant_synchronization / agent_instance_initialization
2. 租户注册、或后台给租户启用外部 ZAP runtime
知办AI ──PUT /zap/v1/tenants/{tenant_id}──▶ runtime
body 带 tenant_id/name/status
◀─runtime_identity: {tenant_id}
3. 知办AI 数字员工创建、发布或修改
知办AI ──POST /zap/v1/agents──▶ runtime
body 带 agent_key/name/model/tools
◀─agent_key
4. 终端用户登录后初始化可见的外部 ZAP 数字员工实例
知办AI ──POST /zap/v1/instances──▶ runtime
body 带 tenant、user、identity、agent、可选 metadata.runtime_environment.external_id
◀─runtime_identity: {tenant_id, user_id, agent_instance_id?}
5. 创建会话
知办AI ──POST /zap/v1/sessions──▶ runtime
body 带 agent_key、平台 tenant/account、conversation_context_hint、runtime_identity、可选 metadata.runtime_environment.external_id
◀─session_id
6. 推送消息并流式返回
知办AI ──POST /zap/v1/sessions/{id}/messages──▶ runtime
Accept: text/event-stream
◀─event: message.created / tool_call / block.delta / completed
7. 用户取消或会话结束
知办AI ──POST /cancel 或 DELETE /sessions/{id}──▶ runtime如果 PUT /tenants 不支持,知办AI服务器会记录同步失败并继续租户开通;后续 /instances 仍会携带完整租户信息作为兜底。如果 runtime_card.agent_instance_initialization 未声明,第 4 步跳过;知办AI仍会在 POST /sessions 里传平台 tenant_id/user_id 和 profile,供旧 runtime 兼容使用。
runtime_card:能力自描述
知办AI在接入和健康巡检时会拉取 GET /zap/v1/runtime_card,接入方 Agent Runtime 返回自身能力声明。单入口 runtime 的最小示例:
json
{
"protocol_version": "zap-1.1",
"schema_version": "zap-1.1",
"framework": "custom",
"version": "0.1.0",
"supports_multi_agent": false,
"default_agent_key": "main",
"max_agents": 1,
"runtime_ui_components": ["markdown", "error", "table", "chart", "form", "tool_call", "tool_result"],
"data_egress": "platform-only",
"multi_tenant_isolation": true,
"tenant_synchronization": {
"version": "zap-tenant-sync-1",
"supports_upsert": true
},
"agent_instance_initialization": {
"version": "zap-agent-instance-1",
"supports_initialize": true,
"returns_runtime_identity": true
}
}default_agent_key 只是接入方 runtime 给知办AI后台自动生成/补齐数字员工 agent_key 的建议值,不是知办AI服务器会话分发的兜底值。知办AI 创建或更新数字员工时会把最终 agent_key 保存到数字员工配置;运行时缺少该字段时,知办AI服务器必须 fail-closed,不得自动改用 runtime_card.default_agent_key。
runtime_ui_components至少包含markdown与error;可声明的组件见 EMP 组件清单。multi_tenant_isolation声明该 runtime 能按租户隔离会话与数据;平台级外部接入要求必须为true。tenant_synchronization表示支持PUT /tenants/{tenant_id}。官方 SDK 在配置 identity provider 后会自动声明并暴露该路由。agent_instance_initialization是可选能力。未声明时,知办AI只在创建 session 时传平台tenant_id/user_id;声明后,用户登录后的 runtime 预热会为相关外部 ZAP 数字员工调用实例初始化接口,拿到 runtime 自己的runtime_identity.tenant_id/user_id/agent_instance_id。是否调用该流程不是后台人工开关,而是由 runtime_card 能力声明决定。supports_initialize=true表示支持POST /instances。
租户同步
租户同步发生在用户聊天之前。两种场景会触发:
- 租户注册后,平台默认启用的外部 ZAP runtime 会收到租户同步。
- 后台管理在某个租户下启用自定义 Agent runtime,或平台管理启用对租户开放的外部 ZAP runtime 后,知办AI服务器会收到
tenant_runtime_enablements配置变更并调用接入方 runtime。
知办AI服务器调用:
http
PUT /zap/v1/tenants/tnt_xxx
Authorization: Bearer <runtime_api_key>
Content-Type: application/json请求体:
json
{
"tenant": {
"tenant_id": "tnt_xxx",
"name": "某某公司",
"status": "active"
},
"metadata": {
"source": "easyo",
"runtime_environment_id": 16
}
}响应体:
json
{
"ok": true,
"runtime_identity": {
"tenant_id": "tenant_123"
},
"mapping_status": "matched"
}处理要求:
- 请求必须幂等。同一个
tenant_id多次 upsert,应返回同一个本地tenant_id。 - 这一步只同步租户,不初始化用户、不创建会话。
- 如果 runtime 暂不支持该接口或调用失败,知办AI不会阻断租户开通;后续
/instances仍会带完整租户信息。
数字员工信息同步
当知办AI 数字员工绑定了外部 ZAP runtime,并且该 runtime 在 runtime_card.control_plane_capabilities 中声明 agent.create/update/delete/list 等能力后,知办AI服务器会通过 control-plane 同步数字员工信息。
典型调用:
http
POST /zap/v1/agents
Authorization: Bearer <runtime_api_key>
Content-Type: application/jsonjson
{
"agent_key": "main",
"name": "行政协同助手",
"model": {"primary": "gpt-5.4"},
"tools": {"allow": ["calendar.search"]}
}发布、修改数字员工配置或能力绑定变化后,知办AI服务器会写 runtime_resync_outbox;prewarm worker 读取后生成 agent_register 任务,再调用 /zap/v1/agents。这一步同步的是“知办AI 数字员工配置”,不是用户专属实例;用户专属实例仍由后续 /instances 处理。
Agent 实例初始化与用户映射
接入方 Agent Runtime 如果有自己的数据库、记忆、权限或工具副作用,建议实现 Agent 实例初始化端点。它不是让知办AI替你选唯一键,而是让知办AI在终端用户登录后把平台知道的租户、用户、身份事实和当前知办AI 数字员工上下文推给接入方,由 runtime 自己保存本地用户与本地 Agent 实例映射。
整体流程:
知办AI probe runtime_card,确认 agent_instance_initialization 能力
│
▼
终端用户登录后,知办AI服务器计算该用户可见的外部 ZAP 数字员工
│
▼
每个相关数字员工生成 agent_instance_init 预热任务
│
▼
知办AI服务器调 POST /instances 推送租户/用户/身份事实/agent 上下文
│
▼
runtime 自己绑定或创建本地用户/本地 Agent 实例
│
▼
POST /sessions 时附带 runtime_identity后台不配置“身份来源 / 唯一匹配字段 / 匹配策略”。知办AI只负责把平台租户、平台账号、成员关系、OIDC/LDAP 稳定主体、已验证联系方式、用户名、部门、当前知办AI 数字员工和 agent_key 等可用事实发送给 runtime。runtime 自行处理本地用户映射并返回 mapping_status;知办AI服务器不维护外部系统用户可用性的全局标记,只决定当前会话是否继续:matched/created 继续,pending/conflict 停止。
当 runtime card 未声明 agent_instance_initialization.supports_initialize=true 时,知办AI只走兼容模式:创建 session 时传平台 tenant_id/user_id、profile。声明支持后,知办AI服务器在登录预热中调用 POST /instances;如果会话创建前没有拿到可用 runtime_identity,知办AI服务器会幂等补调一次同一接口。任一调用失败或 runtime 返回 pending/conflict,本次会话不会继续发送给接入方 Agent Runtime;后台 agent_instance_init 预热任务按退避策略重试,达到上限后等待后续补偿或重放。
字段责任边界
| 字段 | 谁生成 | 是否必填 | 说明 |
|---|---|---|---|
tenant.tenant_id / user.user_id | 知办AI | 是 | 平台内稳定 ID;作为外部引用下发给 runtime。 |
agent.agent_id / agent.agent_key | 知办AI | 用户进入具体数字员工时必填 | 表示本次要初始化的是哪个知办AI 数字员工和 runtime 内哪个业务入口。 |
identity.provider_subjects.oidc | 知办AI | 有 SSO 时尽量提供 | OIDC 的稳定主体事实;通常应与 issuer 一起使用。 |
identity.provider_subjects.ldap | 知办AI | 有 LDAP 时尽量提供 | LDAP 稳定主体事实,例如 objectGUID / entryUUID。 |
user.email / user.phone | 知办AI | 有则提供 | 会带 *_verified;runtime 自己决定是否用于绑定。 |
metadata.runtime_environment.external_id | 知办AI | 后台配置后提供 | 接入方自定义的环境级外部引用;/instances 与新建 /sessions 使用同一个值。只用于关联接入方部署/项目,不是知办租户、用户或鉴权主体。 |
runtime_identity.tenant_id | runtime | identity 成功时必填 | runtime 自己数据库里的租户 ID。 |
runtime_identity.user_id | runtime | 用户 identity 成功时必填 | runtime 自己数据库里的用户 ID。 |
runtime_identity.agent_instance_id | runtime | 可选 | 如果接入方系统按“租户 + 用户 + agent”创建独立本地实例,这里返回实例 ID;没有这种实例时省略。 |
mapping_status | runtime | identity 响应必填 | 表示 runtime 这次绑定/创建/解析的结果。 |
mapping_status 取值:
| 值 | runtime 表达的意思 | 知办AI服务器行为 |
|---|---|---|
matched | 已找到并绑定本地用户 | 继续创建 session。 |
created | 已创建本地影子用户或用户专属本地实例 | 继续创建 session。 |
pending | 需要 runtime 管理员人工绑定或异步处理 | 本次会话停止,后续可重试。 |
conflict | 找到多个候选或安全策略不允许自动绑定 | 本次会话停止,提示处理。 |
POST /instances
推荐新 runtime 实现这个聚合接口。知办AI服务器调一次,你在 runtime 内部完成本地 tenant/user 解析或创建,并按“租户 + 用户 + 知办AI 数字员工”初始化或定位本地 Agent 实例。
http
POST /zap/v1/instances
Authorization: Bearer <runtime_api_key>
Content-Type: application/json请求体:
jsonc
{
"tenant": {"tenant_id": "tnt_xxx", "name": "某某公司", "status": "active"},
"user": {
"user_id": "acc_xxx",
"display_name": "张三",
"email": "zhangsan@example.com",
"email_verified": true
},
"agent": {
"agent_id": "de_xxx",
"agent_key": "main",
"name": "行政协同助手"
},
"identity": {
"source": "easyo",
"provider_issuer": "https://sso.company.com",
"provider_subject": "stable-sub",
"provider_subjects": {
"oidc": "stable-sub",
"ldap": "stable-objectguid"
}
},
"llm": {
"base_url": "https://aigc-gateway.example.com/v1",
"api_key": "sk_tenant_account_xxx",
"model": "gpt-5.4",
"source": "aigc_gateway",
"scope": "tenant_account"
},
"metadata": {
"runtime_environment": {
"external_id": "chuangye-prod"
}
}
}响应体:
jsonc
{
"ok": true,
"runtime_identity": {
"tenant_id": "tenant_123",
"user_id": "user_456",
"agent_instance_id": "agent_instance_789"
},
"mapping_status": "matched",
"message": ""
}处理要求:
- 请求必须幂等。同一个
tenant_id + user_id + agent_key多次调用,应返回同一个本地tenant_id/user_id/agent_instance_id。 metadata.runtime_environment.external_id是可选的 1-256 字符字符串。接入方可用它关联自己的部署、项目或业务环境,但不得用作知办身份、授权或租户隔离依据;不要把它当密钥。后台未配置时,知办AI省略整个runtime_environment。- 成功时必须返回
runtime_identity.user_id;如果 runtime 有用户或 agent 专属本地实例,同时返回agent_instance_id。 llm是知办AI给可信接入方 runtime 的服务端模型调用授权上下文。llm.api_key是当前“租户 + 用户”维度的 AIGC 网关 key,llm.base_url是 AIGC 网关 base URL;runtime 可用它调用模型,但不得下发给浏览器/客户端、不得写入日志、不得存入会话消息或conversation.metadata。- 知办AI在调用
/instances前必须拿到 per-(tenant, account) 的llm.api_key。如果 AIGC channel 创建、凭证落库或解密失败,本次/instances不会调用或会以失败任务重试;不得用平台全局 AIGC token 作为用户级 key 兜底。 - 不能在日志里记录 bearer token、Session Token、client secret、
llm.api_key或密码。
runtime 如何使用身份事实
知办AI会尽量提供以下事实,但不会替 runtime 选择唯一键:
| 场景 | 知办AI会传什么 | runtime 应做什么 |
|---|---|---|
| 租户已接 OIDC / SSO | provider_subjects.oidc、兼容 provider_issuer/provider_subject、profile claims | 可用 issuer + subject 绑定本地用户。 |
| 租户已接 LDAP | provider_subjects.ldap 或兼容 provider_subject | 可用 LDAP 稳定字段绑定本地用户,如 objectGUID / entryUUID。 |
| 没有统一 SSO | user_id、已验证邮箱/手机号、用户名、部门等 profile | 按外部系统自己的规则绑定/创建本地用户,必要时走人工绑定。 |
| 只有姓名 | display_name | 只能展示,不应作为唯一识别依据。 |
知办AI的 user_id 是平台内稳定 ID,会传给 runtime 作为外部引用;但是否拿它当本地主键由外部系统决定。最佳实践是:首次匹配成功后,runtime 在自己的数据库保存平台身份事实与本地 user_id 的映射,之后不再每次按姓名/邮箱猜测。
如果返回 mapping_status="conflict" 或 "pending",知办AI不应继续推正式用户消息,需要租户管理员处理绑定。
POST /sessions.agent_key 用于定位接入方 Agent Runtime 内的业务入口;如果接入方系统会按“租户 + 用户 + agent”创建独立本地实例,请在 POST /instances 响应的 runtime_identity.agent_instance_id 中返回,知办AI会继续把它放进 session 的 runtime_identity 中。
agent_key 和 agent_instance_id 的区别:
| 字段 | 含义 | 示例 |
|---|---|---|
agent_key | 接入方 Agent Runtime 内的业务入口,由知办AI后台按所选运行环境自动生成/补齐并保存;缺失时本次初始化/会话失败,不得用 runtime 默认值兜底 | main、finance、hr-assistant |
runtime_identity.agent_instance_id | 接入方系统给当前租户/用户/agent 创建的本地实例,由 runtime 返回 | agent_instance_789 |
没有用户或 agent 专属本地实例的 runtime 可以只返回 tenant_id/user_id,再用 agent_key + user_id + conversation_id 定位记忆和上下文。
创建会话
http
POST /zap/v1/sessions
Authorization: Bearer <runtime_api_key>
Content-Type: application/jsonjson
{
"agent_key": "main",
"user": {
"tenant_id": "tnt_9f2c1a8e",
"user_id": "acc_71d83b50"
},
"session_kind": "single",
"conversation_context_hint": {
"tenant_id": "tnt_9f2c1a8e",
"account_id": "acc_71d83b50",
"conversation_id": "cnv_3b6e92d4",
"purpose": "production"
},
"runtime_identity": {
"tenant_id": "tenant_123",
"user_id": "user_456",
"agent_instance_id": "agent_instance_789",
"mapping_status": "matched"
},
"metadata": {
"runtime_environment": {
"external_id": "chuangye-prod"
}
}
}响应(session_token 由你的 runtime 生成并仅在这里返回一次,知办AI用它校验后续反向调用;runtime 侧不要存明文):
json
{
"ok": true,
"session_id": "ses_Qy3KpW8NcTlV2mGa",
"session_token": "wN4tJq9X3hRbK7sUe2ZfYm8L",
"expires_at": "2026-06-11T09:30:00Z",
"agent_key": "main",
"metadata": { "purpose": "production", "session_kind": "single" }
}校验要求(fail-closed):conversation_context_hint.tenant_id 必须等于 user.tenant_id,account_id 必须等于 user.user_id,不一致直接拒绝。agent_key 必须是该 runtime 已注册的 key;单入口 runtime 通常使用 runtime_card.default_agent_key 作为后台配置建议,但知办AI服务器不会在缺失 agent_key 时自动兜底。metadata.runtime_environment.external_id 只能作为环境关联信息,不能覆盖上述身份字段;后台配置变化只影响新建 session,不会改写已存在 session。
推送消息与流式返回
http
POST /zap/v1/sessions/ses_Qy3KpW8NcTlV2mGa/messages
Authorization: Bearer <runtime_api_key>
Accept: text/event-stream
Content-Type: application/jsonjson
{
"role": "user",
"blocks": [
{ "type": "markdown", "text": "查一下差旅报销标准,顺便画个各部门费用柱状图" }
]
}接入方 Agent Runtime 通过同一 HTTP 响应以 SSE 返回处理过程和结果:
知办AI 接入方 Agent Runtime
│ POST /zap/v1/sessions/{id}/messages │
│ Accept: text/event-stream │
├──────────────────────────────────────────▶│
│ │
│ event: message.created │
│ event: message.reasoning │
│ event: message.tool_call │
│ event: message.tool_result │
│ event: message.block.delta │
│ event: message.completed │
◀──────────────────────────────────────────┤一次完整的 SSE 流(含推理、工具过程、增量文本、最终结果):
text
event: message.created
data: {"message_id":"msg_01","role":"assistant","status":"streaming"}
event: message.reasoning
data: {"message_id":"msg_01","reasoning":"先检索知识库拿报销标准,再汇总费用数据画图"}
event: message.tool_call
data: {"message_id":"msg_01","tool_call_id":"call_01","tool_name":"kb_retrieve","tool_status":"running","tool_args":"{\"query\":\"差旅报销标准\",\"top_k\":3}"}
event: message.tool_result
data: {"message_id":"msg_01","tool_call_id":"call_01","tool_name":"kb_retrieve","tool_status":"succeeded","tool_result":"命中 3 条:《差旅费管理办法》第 4 章……"}
event: message.block.delta
data: {"message_id":"msg_01","block_index":0,"block_delta":{"type":"markdown","text":"根据《差旅费管理办法》,"}}
event: message.block.delta
data: {"message_id":"msg_01","block_index":0,"block_delta":{"type":"markdown","text":"一线城市住宿上限 500 元/晚。"}}
event: message.completed
data: {"message_id":"msg_01","role":"assistant","blocks":[{"type":"markdown","text":"根据《差旅费管理办法》,一线城市住宿上限 500 元/晚。"},{"type":"chart","title":"各部门差旅费用(万元)","chart_kind":"bar","data":[{"label":"技术","value":12.4},{"label":"销售","value":21.9},{"label":"运营","value":8.7}]}],"usage":{"input_tokens":482,"output_tokens":156}}要点:
message.completed是权威终态,携带完整blocks;客户端最终以它为准,delta 只用于打字机效果。tool_args/tool_result是字符串(JSON 内容自行编码),不是嵌套对象。- 只输出
markdown也完全合法:created→ 若干block.delta→completed即最小实现。 - blocks 里可用的结构化组件(表格、图表、表单、文件等)见 EMP 组件清单。
事件列表
| event | 何时发送 | 关键字段 |
|---|---|---|
message.created | assistant 消息开始 | message_id、role、status |
message.block.delta | 文本或 block 增量 | message_id、block_index、block_delta |
message.reasoning | 思考/推理过程 | message_id、reasoning |
message.tool_call | 工具调用开始 | tool_call_id、tool_name、tool_status、tool_args |
message.tool_result | 工具调用结果 | tool_call_id、tool_status、tool_result |
message.awaiting_user | 等用户审批、确认、填表 | message_id、blocks、awaiting_block_id |
message.completed | 完成输出 | message_id、blocks、usage |
message.failed | 失败 | message_id、error_code、error_message |
message.cancelled | 已取消 | message_id |
ping | 心跳 | ts |
HITL 暂停与恢复
接入方 Agent Runtime 可以在流程中暂停,等待用户完成审批、确认或表单填写:
- 接入方 Agent Runtime 返回
approval、confirm或formblock。 - 接入方 Agent Runtime 发
message.awaiting_user,停止本次 SSE。 - 客户端渲染组件,用户提交。
- 知办AI把用户提交转换成
approval_response、form_response或action_callbackblock,作为下一条 user message 推回接入方 Agent Runtime。 - 接入方 Agent Runtime 从会话状态恢复,继续后续流程。
示例:表单暂停
接入方 Agent Runtime 需要用户补充信息时,发出 message.awaiting_user 并结束本次 SSE:
text
event: message.created
data: {"message_id":"msg_02","role":"assistant","status":"streaming"}
event: message.awaiting_user
data: {"message_id":"msg_02","blocks":[{"type":"form","title":"补充报销信息","description":"填写后提交,继续生成报销单。","submit_label":"提交报销信息","fields":[{"name":"subject","label":"主题","type":"text","required":true},{"name":"amount","label":"金额","type":"number","required":true}]}]}submit_label 是可选按钮文案,未提供时客户端显示"提交"。它只控制展示文案,不改变回灌的 form_response 结构。表单只有在 message.awaiting_user 原消息上才可编辑/提交;若通过 message.completed 返回同样的 form block,客户端按只读表单展示。
用户提交后,知办AI把结果作为下一条 user message 推到 POST /sessions/{id}/messages:
json
{
"role": "user",
"blocks": [
{
"type": "form_response",
"fields": { "subject": "上海出差", "amount": 1860 },
"in_reply_to_message_id": "msg_02"
}
]
}接入方 Agent Runtime 据此恢复流程,照常以 SSE 返回新一条 assistant 消息。
回灌 block 对照
用户在四类交互组件上的操作,分别转换成以下 user block(均带 in_reply_to_message_id 指向原 awaiting 消息):
| 用户操作 | 回灌 block type | 关键字段 |
|---|---|---|
| 审批(approval) | approval_response | decision: approve / reject,可选 reason |
| 确认(confirm) | approval_response | confirmed: true / false |
| 表单(form) | form_response | fields: 字段名 → 值 |
| 操作按钮(action) | action_callback | action_id、params |
注意确认与审批共用 approval_response,但 payload 不同:确认只有 confirmed 布尔字段,没有 decision。
取消与关闭
http
POST /zap/v1/sessions/ses_Qy3KpW8NcTlV2mGa/cancel
Authorization: Bearer <runtime_api_key>返回 200;正在进行的 SSE 流应尽快以 message.cancelled 收尾。会话结束后知办AI会调 DELETE /zap/v1/sessions/{session_id} 显式释放,删除是幂等的(不存在也返回成功)。
错误返回
非 2xx 时统一错误信封:
json
{
"error": {
"code": "zap.session_not_found",
"message": "session ses_Qy3K... 不存在或已过期",
"retryable": false
}
}常见错误码:zap.session_not_found / zap.session_expired / zap.agent_key_not_found / zap.context_missing / zap.tenant_mismatch / zap.upstream_failure。
与 SDK 的关系
第三方 runtime 可以直接手写 HTTP/SSE,也可以用官方 SDK。Python SDK 提供 FastAPI adapter;Go SDK 提供 net/http handler,二者都遵循同一条原则:SDK 拥有 /zap/v1/* 协议胶水,业务方只注册消息处理逻辑。
| SDK 模块 | 对应协议能力 |
|---|---|
zap.fastapi.build_router(runtime) | 生成 /zap/v1/runtime_card、/identity*、/agents、/sessions*,自动校验 runtime bearer、创建 session、包装 SSE |
zap.fastapi.require_runtime_bearer(runtime) | 给手写 router 复用 SDK 鉴权 dependency |
Go zap.Runtime.Handler("/zap/v1") | 生成 /zap/v1/runtime_card、/identity*、/agents、/sessions*,自动校验 runtime bearer、创建 session、包装 SSE |
zap.runtime.ZapRuntime | 注册 runtime、runtime 内业务入口 card、fallback handler 与按 agent_key 分发的 handler |
zap.runtime.ZapMessageContext | handler 入参上下文,包含 tenant、account、session、conversation、debug flags,以及可选 external_environment_id |
zap.events | 生成 SSE event payload 与 wire 编码 |
zap.emp | 构造 message.completed.blocks 或 message.awaiting_user.blocks |
zap.errors | 生成 ZAP 错误 envelope |
zap.session | 本地开发用 session store、TTL、token hash |
标准 handler 形态:
python
@runtime.on_message
async def handle(ctx, inbound):
tenant_id = ctx.tenant_id
account_id = ctx.user_id
session_id = ctx.session_id
conversation_id = ctx.conversation_id
external_environment_id = ctx.external_environment_id
text = inbound.text
...Go 标准 handler 形态:
go
runtime.OnMessage(func(ctx context.Context, inbound zap.InboundMessage, stream zap.Stream) error {
tenantID := inbound.Context.TenantID
accountID := inbound.Context.UserID
sessionID := inbound.Context.SessionID
conversationID := inbound.Context.ConversationID
externalEnvironmentID := inbound.Context.ExternalEnvironmentID
text := inbound.Text
_ = []string{tenantID, accountID, sessionID, conversationID, externalEnvironmentID, text}
return stream.Completed(zap.Markdown("收到,我来处理。"))
})ctx.to_log_dict() 可用于开发期日志和示例输出;它不会包含 bearer token、session token、header 或原始敏感入站 payload。
用 SDK 构造上面"完整 SSE 流"示例中的事件:
python
from zhiban_agent_sdk.zap import events, emp
yield events.message_created("msg_01")
yield events.message_tool_call(
"msg_01", tool_call_id="call_01", tool_name="kb_retrieve",
tool_args='{"query": "差旅报销标准", "top_k": 3}',
)
yield events.message_tool_result(
"msg_01", tool_call_id="call_01", tool_status="succeeded",
tool_result="命中 3 条:《差旅费管理办法》第 4 章……",
)
yield events.message_completed("msg_01", blocks=[
emp.markdown("根据《差旅费管理办法》,一线城市住宿上限 500 元/晚。"),
emp.chart(kind="bar", title="各部门差旅费用(万元)", data=[
{"label": "技术", "value": 12.4},
{"label": "销售", "value": 21.9},
]),
])agent-example 覆盖情况
apps/example/agent-example 当前覆盖:
| 能力 | 状态 |
|---|---|
runtime_card | 已实现 |
| Runtime 内业务入口管理 | 已实现 list/create/card/patch/delete |
| sessions 数据面 | 已实现 create/message/cancel/delete |
| 身份初始化 | 已实现 SQLite reference store + tenant/user upsert/resolve/status |
| SSE 流式输出 | 已实现 created、block.delta、completed |
| 工具/推理过程 | 已实现 tool_call、tool_result、reasoning |
| HITL | 已实现 message.awaiting_user + 表单/审批/确认恢复 |
| 多租户隔离声明 | runtime_card.multi_tenant_isolation=true,reference 级别校验 tenant/account/context |
相关链接
完整协议规范(含 RuntimeCard 全字段、多业务入口管理面、技能下发)可在知办AI管理后台「智能体托管环境」页在线查看与下载。