Skip to content

2026-07-15 已接入方迁移指南

适用对象:已经接入知办AI /api/external/v1/*、ZAP Runtime、A2A、Python / Go SDK 或应用单点登录的研发团队。
生效日期:2026-07-15。当前接口仍处于开发联调阶段,本次直接切换,不设置旧字段兼容期。
使用方式:可以把本文完整交给项目内的 Codex、Claude Code 或其他代码助手,让它先盘点调用点,再按文末验收清单修改和测试。

一、先看结论

本次迁移包含三部分:

  1. 资源标识字段统一:知办AI资源使用 id / <resource>_id,对方系统资源使用 third_<resource>_id
  2. SDK 和 ZAP/A2A 公共 API 同步改名:Python 属性、关键字参数以及 Go 结构体字段、方法参数都同步切换,不保留旧名称。
  3. 同日接入契约补齐:增加按数字员工检索关联知识库的入口、ZAP 标准健康检查,并补齐应用单点登录的 Token 与 ID Token 说明。

这是破坏性切换

  • 请求只接受新字段,响应只返回新字段。
  • 旧字段不再标记 deprecated,也不做 alias、双读、双写或回填。
  • 请求携带旧字段或其他未知字段时,服务端返回 HTTP 400
  • 服务端和调用方必须约定同一联调窗口完成切换;错开部署时旧请求会失败。

这次只修改线缆字段和 SDK 公共接口名称。资源 ID 的实际值、URL 层级、鉴权方式、权限 Scope 和数据库历史列名没有因为改名而变化。

二、影响范围判断

你的项目使用了什么是否要改重点章节
原生 HTTP 调用通知、主动聊天、组织、知识库第三节
runtime_access 换取 Session Token第三节“Runtime Access Token”
Python SDK第四节
Go SDK第五节
自建 ZAP Runtime第六节
A2A discover / invoke / edge第三节“A2A”及第四、五节
应用栏 H5 单点登录需要核对第七节
只使用 OAuth 标准字段或 Runtime 自己的本地 ID通常不改第八节

三、HTTP / JSON 字段替换表

3.1 通用规则

含义新字段不再使用
当前资源自身的稳定标识iduuid
引用知办AI数字员工agent_idagent_uuid / digital_employee_uuid
引用知办AI用户user_id 或领域明确的 account_iduser_uuid / account_uuid
引用知办AI会话conversation_idconversation_uuid
引用知办AI房间room_idroom_uuid
引用知识库knowledge_base_idkb_uuid
引用文件file_idfile_uuid / drive_file_uuid
对方系统自己的资源third_<resource>_idexternal_id / external_code / employee_id

所有知办AI资源 ID 都按不透明字符串处理。不得解析 UUID 版本、长度、前缀或生成算法,也不得由调用方自行生成。

3.2 通知与主动聊天

位置新字段删除字段
通知 / 主动聊天目标user_idagent_idaccount_uuiduser_uuidagent_uuid
通知的对方业务标识third_notification_idexternal_id
主动消息的对方业务标识third_message_idexternal_id
通知响应notification_idconversation_idroom_idnotification_uuidconversation_uuidroom_uuid
主动消息响应message_idconversation_idroom_idmessage_uuidconversation_uuidroom_uuid

请求示例:

json
{
  "user_id": "<知办用户ID>",
  "agent_id": "<知办数字员工ID>",
  "title": "审批待处理",
  "description": "请确认处理方案",
  "third_notification_id": "ticket-1024"
}

third_notification_id / third_message_id 是调用方系统生成的业务标识,不是知办AI资源 ID。它们的唯一范围至少应包含“租户 + 接入来源”。

3.3 组织与人员

位置新字段删除字段
部门对象idparent_iduuidparent_uuid
部门的对方标识third_department_idexternal_code
成员对象account_iddepartment_idaccount_uuiddepartment_uuid
成员的对方标识third_user_idemployee_id
职位对象iduuid
职位的对方标识third_position_idexternal_code
组织 Webhooktenant_identity_idtenant_uuidentity_uuid

成员没有独立的成员 UUID,account_id 承载知办账号的稳定标识。对方 HR / IAM / OA 中的员工编号应放在 third_user_id,不能放在 account_id

路径参数名同步改为 {department_id}{account_id}{position_id}。URL 层级和值本身不变。

3.4 知识库

位置新字段删除字段
知识库对象iduuid
文档对象idknowledge_base_iduuidkb_uuid
单库检索响应knowledge_base_iddocument_idkb_uuiddocument_uuid
路径参数名{knowledge_base_id}{document_id}{user_id}{uuid}{doc_uuid}{user_uuid}

指定数字员工检索其已关联知识库,新增统一入口:

http
POST /api/external/v1/knowledge/retrieve
Authorization: Bearer <runtime_access 换出的 st_>
Content-Type: application/json

{
  "agent_id": "<知办数字员工ID>",
  "query": "年假如何折算?"
}

返回结果使用 knowledge_base_iddocument_id。调用方不需要先获取知识库 ID 列表;Agent Bus 会在 token 的租户和 Runtime 边界内解析该数字员工的知识库绑定。

指定某一个知识库检索仍使用:

http
POST /api/external/v1/knowledge-bases/{knowledge_base_id}/retrieve

两者用途不同,不要把“按数字员工聚合检索”改回“由调用方遍历多个知识库”。

3.5 Runtime Access Token

位置新字段删除字段
换令牌请求的 Agent 绑定agent_idagent_uuid
换令牌请求的用户绑定account_idaccount_uuid
换令牌响应session_token_idbound_agent_idbound_account_idsession_token_uuidbound_agent_uuidbound_account_uuid

请求示例:

json
{
  "grant_type": "runtime_access",
  "client_id": "agentsdk_xxx",
  "client_secret": "***",
  "tenant_id": "<租户范围>",
  "agent_id": "<发起方数字员工ID>",
  "account_id": "<可选的知办用户ID>"
}

agent_id 仅在需要 Agent-bound token(例如 A2A)时传;account_id 仅在需要用户实例绑定时传。普通知识库、通知或记忆 backchannel 不要为了“字段齐全”盲目增加这两个字段。

3.6 ZAP 会话与身份

对象 / 位置新字段删除字段
usertenant_iduser_idtenant_uuidaccount_uuid
agentagent_iddigital_employee_uuid / agent_uuid
conversation_context_hinttenant_iduser_idconversation_idaccount_idconversation_uuid
调试上下文debug_session_iddebug_session_uuid
A2A 会话上下文a2a_edge_ida2a_edge_uuid
identity useruser_idmembership_idaccount_uuidmembership_uuid
identity 路径参数{tenant_id}{user_id}{tenant_uuid}{account_uuid}

标准会话请求应类似:

json
{
  "agent_key": "main",
  "agent": { "agent_id": "<知办数字员工ID>" },
  "user": {
    "tenant_id": "<知办租户ID>",
    "user_id": "<知办用户ID>"
  },
  "session_kind": "single",
  "conversation_context_hint": {
    "tenant_id": "<知办租户ID>",
    "user_id": "<知办用户ID>",
    "conversation_id": "<知办会话ID>",
    "purpose": "production"
  }
}

ZAP SDK 现在严格拒绝未知 JSON 字段。继续发送旧的 tenant_uuidaccount_uuidagent_uuid 等字段会直接失败,不会被静默忽略。

3.7 A2A

位置新字段删除字段
discover 候选agent_idagent_uuid
invoke 目标to_agent_idto_agent_uuid
invoke 上下文room_idparent_edge_idroom_uuidparent_edge_uuid
invoke 回执edge_idapproval_request_idedge_uuidapproval_request_uuid
edgeedge_idfrom_agent_idto_agent_idedge_uuidfrom_agent_uuidto_agent_uuid
SSE eventedge_idedge_uuid
可调用白名单agent_idsagent_uuids
ZAP 编排orchestration_idstep_idworker_agent_idcall_edge_idtrigger_message_idorchestration_uuidstep_uuidworker_agent_uuidcall_edge_uuidtrigger_msg_uuid

edge_created_at 仍是 edge 分区查询的一部分,调用方必须把 invoke 返回的值原样传给 get / cancel / stream,不能截断小数秒。

3.8 EMP 消息与文件引用

新字段删除字段说明
message_idmessage_uuid知办消息稳定标识
source_message_idsource_message_uuid引用的来源消息
file_id / file_idsfile_uuid / file_uuids / drive_file_uuid文件与附件引用

如果接入方会解析或回传 EMP file / image / 表单上传结果,必须同步修改本地 DTO、模板、日志字段和测试 fixture。

四、Python SDK 迁移

必须使用包含本次字段切换代码的发布 commit/tag。当前源码包版本字符串可能与之前相同,不能只看 0.5.0 就判断是否已经升级。

4.1 公共 API 改名

旧 Python 用法新 Python 用法
kb.uuidkb.id
chunk.document_uuidchunk.document_id
result.kb_uuidresult.knowledge_base_id
client.kb.get(uuid)client.kb.get(knowledge_base_id)
client.kb.list_documents(kb_uuid)client.kb.list_documents(knowledge_base_id)
client.kb.retrieve(uuid, ...)client.kb.retrieve(knowledge_base_id, ...)
client.kb.list_user_private(user_uuid)client.kb.list_user_private(user_id)
for_runtime_access(..., agent_uuid=..., account_uuid=...)for_runtime_access(..., agent_id=..., account_id=...)
provider.bound_agent_uuidprovider.bound_agent_id
provider.bound_account_uuidprovider.bound_account_id
notifications.agent_conversation(..., external_id=...)notifications.agent_conversation(..., third_notification_id=...)
chat.send_message(..., external_id=...)chat.send_message(..., third_message_id=...)
Department.uuid / parent_uuid / external_codeDepartment.id / parent_id / third_department_id
Member.account_uuid / department_uuid / employee_idMember.account_id / department_id / third_user_id
Position.uuid / external_codePosition.id / third_position_id
DiscoveredAgent.agent_uuidDiscoveredAgent.agent_id
InvokeAck.edge_uuidInvokeAck.edge_id
invoke(to_agent_uuid=..., room_uuid=..., parent_edge_uuid=...)invoke(to_agent_id=..., room_id=..., parent_edge_id=...)
get_edge(edge_uuid, ...)get_edge(edge_id, ...)

新增按数字员工聚合检索:

python
result = client.kb.retrieve_associated(
    agent_id="<知办数字员工ID>",
    query="年假如何折算?",
)
for item in result.items:
    print(item.knowledge_base_id, item.document_id, item.content)

4.2 Python ZAP handler 上下文

旧属性新属性
ctx.tenant_uuidctx.tenant_id
ctx.account_uuidctx.user_id
ctx.agent_uuidctx.agent_id
ctx.conversation_uuidctx.conversation_id
ctx.a2a_edge_uuidctx.a2a_edge_id
session.tenant_uuidsession.tenant_id
session.account_uuidsession.user_id
session.agent_uuidsession.agent_id

推荐继续使用 SDK router:

python
from fastapi import FastAPI
from zhiban_agent_sdk.zap.fastapi import build_router

app = FastAPI()
app.include_router(build_router(runtime), prefix="/zap/v1")

新版 router 自动提供带 Runtime bearer 鉴权的 GET /zap/v1/healthz,并对 ZAP 请求执行严格 JSON 字段校验。不要在业务项目里复制一套旧 router。

五、Go SDK 迁移

必须使用包含本次字段切换代码的发布 commit/tag。Go module 没有内嵌版本常量,不能继续沿用旧 tag 后只修改业务代码。

5.1 公共结构体与方法

旧 Go 用法新 Go 用法
KnowledgeBase.UUIDKnowledgeBase.ID
Document.UUID / KBUUIDDocument.ID / KnowledgeBaseID
RetrieveChunk.DocumentUUIDRetrieveChunk.DocumentID
RetrieveResponse.KBUUIDRetrieveResponse.KnowledgeBaseID
NewWithRuntimeAccess(..., agentUUID)NewWithRuntimeAccess(..., agentID)
NewWithRuntimeAccessContext(..., agentUUID, accountUUID)NewWithRuntimeAccessContext(..., agentID, accountID)
Client.BoundAgentUUID()Client.BoundAgentID()
Client.BoundAccountUUID()Client.BoundAccountID()
ExternalIDThirdNotificationIDThirdMessageID
MessageUUID / ConversationUUID / RoomUUIDMessageID / ConversationID / RoomID
DiscoveredAgent.AgentUUIDDiscoveredAgent.AgentID
InvokeRequest.ToAgentUUIDInvokeRequest.ToAgentID
InvokeRequest.RoomUUID / ParentEdgeUUIDInvokeRequest.RoomID / ParentEdgeID
InvokeAck.EdgeUUIDInvokeAck.EdgeID
Edge.EdgeUUIDEdge.EdgeID

新增按数字员工聚合检索:

go
result, err := client.KB().RetrieveAssociated(ctx, agentID, "年假如何折算?")
if err != nil {
    return err
}
for _, item := range result.Items {
    fmt.Println(item.KnowledgeBaseID, item.DocumentID, item.Content)
}

5.2 Go ZAP Runtime

旧字段新字段
MessageContext.TenantUUIDMessageContext.TenantID
MessageContext.AccountUUIDMessageContext.UserID
MessageContext.ConversationUUIDMessageContext.ConversationID
Session.TenantUUIDSession.TenantID
Session.AccountUUIDSession.UserID
Session.ConversationUUIDSession.ConversationID
IdentityTenant.TenantUUIDIdentityTenant.TenantID
IdentityUser.AccountUUIDIdentityUser.UserID
IdentityAgentContext.DigitalEmployeeUUIDIdentityAgentContext.AgentID

runtime.Handler("/zap/v1") 现在自动暴露 GET /zap/v1/healthz,并使用严格 JSON 解码。业务项目不应继续维护旧版手写 ZAP endpoint。

六、自建 Runtime / agent-example 对齐项

如果同事的项目是从旧版 agent-example 复制出来的,应逐项同步:

  1. 用新版 Python 或 Go ZAP SDK router,不复制 RuntimeCard、bearer 校验、session 和 SSE 编码。
  2. handler 中统一读取 tenant_iduser_idagent_idconversation_ida2a_edge_id
  3. A2A 调用统一使用 to_agent_idedge_id,不要保留 *_uuid 回退。
  4. 附件和 EMP 文件统一读取、返回 file_id
  5. Runtime 必须提供低成本、无副作用的 GET /zap/v1/healthz;健康检查不得调用 LLM、知识库或对方业务系统。
  6. 如果需要查询当前数字员工关联的知识库,调用 POST /api/external/v1/knowledge/retrieve 或 SDK 的 retrieve_associated,不要让 Runtime 自己猜绑定关系。
  7. 本地数据库列名可以继续叫 easyo_tenant_uuideasyo_account_uuid;这是接入方内部存储,不属于线缆字段,不需要为了本次迁移改库。

runtime_identity.tenant_id/user_id/agent_instance_id 是接入方 Runtime 自己生成和管理的本地资源 ID,继续保持,不增加 third_ 前缀。

七、应用单点登录接入同步项

应用接入的产品名称统一叫“单点登录接入”,底层仍使用 Agent Bus 的 OAuth2 authorization_code 流程。它不依赖租户是否配置企业 OIDC。

7.1 Token 请求

正式请求格式改为标准表单:

http
POST /api/external/v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=...&client_id=...&client_secret=...

服务端当前继续兼容已有应用的 JSON 请求体,但新代码和 SDK 应使用 application/x-www-form-urlencoded。成功响应保持 OAuth/OIDC 顶层字段,不套 Bus 业务响应信封:

json
{
  "access_token": "...",
  "id_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "kb.read contacts.read"
}

7.2 ID Token Claim

应用后端完成 RS256、issaudexpiat 校验后,从 ID Token 读取:

  • 标准用户字段:subnameemailemail_verifiedphone_number
  • 当前租户:tenant.uuidtenant.name
  • 当前成员关系:membership.employee_nomembership.titlemembership.department
  • 可选会话上下文:zhiban_context.conversation_idconversation_kindpeer

本次明确:

  • 不新增 /oauth/userinfo 或“解码 ID Token”私有接口;
  • 不返回 auth_time
  • state / nonce 当前只用于请求关联和协议兼容,不能宣称已完成登录 CSRF / replay 防护;
  • Discovery 和 JWKS 应按 TTL 缓存,遇到未知 kid 时强制刷新一次;
  • tenant.uuidzhiban_context.peer.uuid 是本次应用 ID Token 契约中的现有扩展字段,不要因本指南其他资源改成 _id 就自行重命名。

应用浏览器端不得解析或保存 ID Token、client_secret、Access Token、Refresh Token。换码、验签和业务 Session 必须全部在应用后端完成。

八、这些字段不要机械修改

字段保持原因
OAuth client_idclient_secretid_tokenaccess_tokenrefresh_token标准协议字段
JWT subaudissjti标准 Claim
ZAP session_idagent_keyZAP 协议自身标识
request_idevent_idtrace_ididempotency_key请求、事件和幂等语义
wukong_message_id已命名 provider 标识
runtime_identity.tenant_id/user_id/agent_instance_id接入方 Runtime 本地身份
接入方内部数据库的 *_uuid 列名内部存储,不是 API 线缆
当前应用 ID Token 的 tenant.uuidzhiban_context.peer.uuidF04 应用 SSO 当前契约

不要执行全仓 uuid -> id 文本替换。应只修改 API DTO、序列化字段、SDK 公共属性、调用代码、fixture 和协议测试。

九、推荐迁移顺序

  1. 锁定版本:拿到包含本指南改动的 Agent Bus 环境和 SDK commit/tag。
  2. 盘点调用点:搜索旧 JSON 字段、SDK 属性、函数关键字参数和测试 fixture。
  3. 升级 SDK:先升级依赖,再处理编译错误、类型错误和测试失败。
  4. 修改原生 HTTP DTO:请求只发送新字段,响应只读取新字段。
  5. 修改 ZAP/A2A handler:更新上下文属性、invoke 入参、edge 回执和日志字段。
  6. 修改测试数据:fixture、mock response、快照、示例 curl 和 API schema 全部同步。
  7. 增加负向测试:至少验证一个旧字段会被服务端或 SDK router 以 HTTP 400 拒绝。
  8. 联合部署:在约定窗口同步上线调用方和服务端,完成真实环境 smoke test。

十、交给 Codex / Claude Code 的执行指令

可把下面内容连同本文一起交给代码助手:

text
请按照《2026-07-15 已接入方迁移指南》迁移当前项目。

要求:
1. 先只读扫描当前项目,列出使用知办AI External API、ZAP、A2A、Python/Go SDK 的文件和调用点。
2. 识别每个 ID 的归属:知办AI资源使用 id/<resource>_id;对方系统资源使用 third_<resource>_id;标准协议字段保持不变。
3. 升级到平台方提供的、包含本次迁移的 SDK commit/tag;不要只根据旧版本字符串判断已经升级。
4. 删除旧字段和旧 SDK 属性的读取/写入,不添加兼容 alias、双读、双写或 fallback。
5. 同步修改请求 DTO、响应 DTO、业务代码、fixture、mock、快照、日志字段、示例和测试。
6. 如果项目是 ZAP Runtime,使用新版 SDK router,确认 GET /zap/v1/healthz 可用并带 bearer 鉴权;handler 改用 tenant_id/user_id/agent_id/conversation_id/a2a_edge_id。
7. 如果项目使用 A2A,改用 to_agent_id/edge_id/parent_edge_id/room_id,并原样保存 edge_created_at。
8. 如果项目使用应用单点登录,Token 请求改为 application/x-www-form-urlencoded;后端验签 ID Token 后读取 tenant/membership/zhiban_context,不新增 userinfo 或 decode-token 接口。
9. 运行项目现有 lint、类型检查和测试;新增新字段成功与旧字段被拒绝的覆盖。
10. 最后输出:修改文件、字段替换表、验证命令与结果、仍需平台方提供的配置或版本信息。

禁止:
- 全仓机械替换 uuid;
- 修改内部数据库列名;
- 保留旧字段兼容层;
- 在日志或浏览器输出 client_secret、bearer、ID Token、Access Token、Refresh Token;
- 绕过 Agent Bus 直接调用其他 Agent Runtime。

十一、检索与验收清单

11.1 建议检索

在业务源码、测试和示例目录执行,排除依赖、构建产物和数据库 migration:

bash
rg -n 'tenant_uuid|account_uuid|user_uuid|agent_uuid|digital_employee_uuid|conversation_uuid|room_uuid|edge_uuid|parent_edge_uuid|kb_uuid|document_uuid|file_uuid|external_id|external_code|employee_id' \
  src app tests examples

搜索结果必须逐条分类:协议旧字段需要修改;内部数据库列名、历史 migration 或本文第八节列出的例外可以保留。

11.2 HTTP 验收

  • 新字段请求成功;
  • 任一已删除字段返回 HTTP 400
  • 响应不再包含旧字段;
  • 使用其他租户的资源 ID 仍按原有规则返回模糊的无权限 / 不存在错误;
  • API Key、Session Token 和 Scope 行为没有变化。

11.3 SDK 验收

  • Python 不再访问旧属性或传旧关键字参数;
  • Go 不再引用旧结构体字段和旧方法名;
  • Python / Go SDK 测试通过;
  • 原生 HTTP mock 与 SDK 模型字段一致。

11.4 ZAP / A2A 验收

  • 正确 bearer 请求 GET /zap/v1/healthz 返回 200,错误 bearer 返回 401
  • ZAP session 请求只使用新字段;
  • 旧 ZAP 字段被严格拒绝;
  • discover、invoke、get edge、cancel、stream 使用同一个 edge_id
  • edge_created_at 原样传递;
  • A2A 仍由 Agent Bus 治理和转发,不直连被调 Runtime。

11.5 应用单点登录验收

  • 授权码只能使用一次;
  • Token Endpoint 接受标准 form 请求并返回顶层 token 字段;
  • 后端完成 ID Token 验签后才能读取用户、租户和成员信息;
  • Discovery / JWKS 有 TTL 缓存,未知 kid 会刷新一次;
  • 浏览器端看不到任何服务端凭证或 Token。

十二、不受影响的内容

  • API 路径版本仍是 /api/external/v1
  • API Key、Session Token、OAuth2 换码和权限 Scope 不变;
  • tenant、用户、数字员工、知识库的授权和可见性判断不变;
  • 资源 ID 的实际值不因字段名变化而变化;
  • 数据库历史列名、repository / domain 内部精确类型名不做机械改名;
  • 应用 SSO 不要求租户配置企业 OIDC;
  • 不新增 UserInfo、decode-id-token、PKCE 或 A2A 直连能力。

十三、依据与完整文档

© 知办AI Team — 开发者公开文档. 平台运维 / 内部架构文档见内部 wiki.