oh-my-muse/design-docs/专题-05-AI统一交互协议与外部AgentAdapter设计.md

332 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 专题-05AI 统一交互协议与外部 Agent Adapter 设计
- 版本v0.2
- 更新日期2026-07-20
- 目标读者:架构 / 后端 / 前端 / 运维 / 测试
- 边界说明:本文定义 Muse 后端到外部 Agent 运行时的统一交互协议与 adapter 层。它承接 `专题-03-AI编排上下文与质量评测实现规范.md`,不改变 Shadow -> Canonical、Runtime Permission Envelope、RAGFlow 检索和用户确认边界。
- 变更记录v0.22026-07-20§5.4 固化正文写手 adapter 的无工具、无会话持久化和超时失败关闭边界v0.12026-06-29建立外部 Agent 统一协议与 provider adapter 设计。
## 1. 背景与结论
现状中 Muse 已有本地 `MuseAiRuntimeClient` 抽象,并通过 New-API 执行非流式模型调用;系统 Agent 由 Muse 本地表 `muse_agent / muse_agent_version` 管理。这个形态能跑通最小生成链路,但不能清晰表达“系统 Agent 在 Dify / AgentScope 等外部平台配置、Muse 只引用并受控调用”的产品目标。
本设计的结论:
1. Muse 保留系统 Agent 的 owner、版本、槽位绑定、权限包、审计和 Shadow 写入边界。
2. 外部 Agent 平台只承载可替换的能力节点,例如 Dify agent / workflow 或未来 AgentScope graph。
3. Muse 后端新增统一交互协议 `MuseAgentRuntimeProtocol`,由 provider adapter 翻译为 Dify / AgentScope / New-API 等具体 HTTP 调用。
4. 管理端系统 Agent 配置页允许跳转到 Dify 控制台配置能力,并在 Muse 中保存 Dify app/workflow 引用;不保存 Dify API Key。
5. RAG 仍走 Knowledge BC 的检索 facade当前实现使用 RAGFlowDify 内置知识库只能作为 Dify app 内部受限能力,不成为 Muse 的知识事实源。Dify 内部知识参与输出时必须标记为 `untraceable_provider_context`
## 2. 目标与非目标
目标:
- 定义 Muse 到外部 Agent 的统一请求、响应、事件、错误、重试、超时和审计协议。
- 支持系统 Agent 版本引用 Dify agent / workflow并由 Muse runtime adapter 调用。
- 支持管理端从系统 Agent 配置跳转到 Dify 控制台,配置完成后回填或录入外部 app/workflow 引用。
- 保证外部 Agent 不能绕过 Runtime Permission Envelope、Tool Grant、Source Snapshot、Shadow 写入和用户确认。
- 为未来 AgentScope adapter 预留同一协议扩展点。
非目标:
- 不让 Dify / AgentScope 直接写 Muse 数据库、Content Canonical、Knowledge Canonical 或 Market 事实。
- 不把 Dify API Key、New-API token、RAGFlow token 写入 `muse_agent_version.config`、审计日志、前端响应或记忆。
- 不把 Dify 知识库替代 Muse Knowledge BCMuse 授权知识检索仍由 Knowledge facade / RAGFlow 负责。
- 不在第一阶段实现任意工具动态注册。工具和知识权限已经在 Dify 侧受限,但 Muse 仍只把它视为外部受控 runtime不信任其自报权限。
## 3. 架构位置
```text
Studio / Admin
-> Muse app/admin API
-> AI Orchestration / Agent BC
-> Runtime Permission Envelope + Source Snapshot + Context Assembly
-> MuseAgentRuntimeProtocol
-> Provider Adapter
-> New-API adapter
-> Dify adapter
-> AgentScope adapter预留
-> Runtime Result / Event
-> Muse Shadow Candidate / Job / Audit / Usage
```
关键原则:
- Muse 是业务事实源和权限裁判。
- Provider adapter 是外部调用翻译层,不拥有业务状态机。
- 外部 runtime 返回的是候选输出,不是可直接入库的事实。
- 任何 provider 成功都必须回到 Muse 的输出合规、静态检查、质量门控和 Shadow 写入流程。
## 4. 统一交互协议
### 4.1 Runtime Request
`MuseAgentRuntimeRequest` 是 provider 无关协议,最小字段:
| 字段 | 说明 | 是否可外发 |
|---|---|---|
| `commandId` | Muse 幂等命令 ID | 是 |
| `taskId` / `jobId` | Muse 任务与 job 标识 | 是 |
| `correlationId` | 链路追踪 ID | 是 |
| `actor` | 用户 / 管理员 / 系统服务摘要 | 脱敏后可外发 |
| `agentRef` | Muse agentId、agentVersionId、slotKey、providerRef | 是 |
| `scenario` | continuation / rewrite / full_parse / quality_eval 等 | 是 |
| `runtimePermissionEnvelopeId` | 运行权限包 ID | 是 |
| `sourceSnapshotId` | 上下文来源快照 ID | 是 |
| `inputEnvelope` | 用户指令、上下文摘要、知识片段、格式要求 | 仅按权限包裁剪后可外发 |
| `outputContract` | 输出格式、最大长度、是否要求结构化 JSON | 是 |
| `traceabilityPolicy` | 是否要求 Muse-compatible source refs | adapter 消费 |
| `timeoutPolicy` / `retryPolicy` | Muse 统一超时与重试预算 | adapter 消费 |
| `auditPolicy` | 审计等级、是否允许记录摘要 | adapter 消费 |
禁止字段:
- 明文 token / password / API Key。
- 未授权的作品正文、私有知识、原始 provider 响应。
- 前端自报的权限、工具、外发范围。
### 4.2 Runtime Response
`MuseAgentRuntimeResponse` 必须归一化为:
| 字段 | 说明 |
|---|---|
| `status` | `succeeded` / `failed` / `retryable_failed` / `cancelled` |
| `outputSummary` | 可展示摘要,不含完整 provider 原始响应 |
| `outputPayloadRef` | 可选,短生命周期正文载荷引用;正式入 Shadow 前由 Muse 消费 |
| `providerRequestId` | provider 请求 ID 或运行 ID |
| `provider` | `new-api` / `dify` / `agentscope` |
| `usage` | token、耗时、成本摘要无则为空 |
| `traceability` | `muse_source_refs` / `untraceable_provider_context` / `none` |
| `finishReason` | stop / length / tool_call / error 等归一化值 |
| `failure` | 失败类型、错误码、HTTP 状态、是否可重试、脱敏消息 |
失败分类必须归一化:
- `auth_failed`:凭据或 provider 权限失败,不重试。
- `permission_denied`Muse 权限包或外发门禁失败,不重试。
- `provider_bad_request`:配置或输入合同错误,不重试。
- `provider_bad_response`provider 成功响应无法解析,不重试。
- `network_timeout` / `connect_failed` / `rate_limited` / `provider_5xx`:按 retryPolicy 决定是否重试。
- `runtime_unavailable`adapter 未配置或 provider 不可用,不得伪造成成功。
### 4.3 Runtime Event
第一阶段允许 blocking 调用,但协议必须支持事件:
| 事件 | 说明 |
|---|---|
| `runtime.requested` | Muse 已记录外部调用意图 |
| `runtime.started` | provider 接受任务 |
| `runtime.delta` | streaming 增量输出,默认不长期保存正文 |
| `runtime.tool_call` | provider 触发受限工具调用摘要 |
| `runtime.completed` | provider 完成,进入 Muse 投影 |
| `runtime.failed` | provider 或协议失败 |
| `runtime.cancelled` | Muse 或用户取消 |
Dify chat/workflow 均支持 blocking 与 streaming。生产长任务应优先使用 streaming 或异步 job 模式blocking 只作为短任务和最小实现路径,必须受 total timeout 约束。
## 5. Adapter 设计
### 5.1 Java 侧接口
建议新增或演进现有 `MuseAiRuntimeClient` 为以下结构:
```java
interface MuseAgentRuntimeAdapter {
String provider();
boolean supports(MuseAgentProviderRef ref);
MuseAgentRuntimeResponse execute(MuseAgentRuntimeRequest request);
}
interface MuseAgentRuntimeRouter {
MuseAgentRuntimeResponse execute(MuseAgentRuntimeRequest request);
}
```
路由规则:
1. `agentVersion.config.runtimeProvider` 指定 provider。
2. 旧的已存在 active version 未指定时默认 `new-api`,保持历史链路兼容。
3. 新建、复制、发布系统 Agent 版本必须显式写 `runtimeProvider`;缺失或未知 provider 必须拒绝发布。
4. 指定 `dify` 时只允许 Dify adapter 执行Dify 未配置必须 fail-closed不能回退 New-API。
5. 指定未知 provider 必须拒绝发布或运行。
### 5.2 Dify Adapter
Dify adapter 职责:
-`MuseAgentRuntimeRequest` 翻译成 Dify Service API。
- 支持 Dify `agent/chat` 类应用和 `workflow` 类应用。
- 支持 blocking 最小实现,预留 streaming SSE 解析。
- 将 Dify 响应归一化为 Muse response / event。
- 只记录 Dify app/workflow 引用、providerRequestId、运行状态和脱敏摘要。
Dify 引用结构:
```json
{
"runtimeProvider": "dify",
"dify": {
"appType": "agent",
"appId": "dify-app-id",
"workflowId": null,
"credentialRef": "dify-writing-prod",
"consoleUrl": "https://dify.example/apps/xxx"
}
}
```
workflow 示例:
```json
{
"runtimeProvider": "dify",
"dify": {
"appType": "workflow",
"appId": null,
"workflowId": "dify-workflow-id",
"credentialRef": "dify-parse-prod",
"consoleUrl": "https://dify.example/workflow/yyy"
}
}
```
凭据解析:
- `credentialRef` 是 Muse 安全配置中的引用名,不是密钥。
- 真实 Dify API Key 只允许来自环境变量、Nacos 密文或同等级安全配置。
- Dify provider 发布时 `credentialRef` 必填;不允许空值使用隐式默认凭据。默认凭据也必须保存为显式命名的 `credentialRef`,并带 scope、环境、轮换和审计信息。
- adapter 日志、审计、响应、异常不得包含 Authorization header、API Key、原始响应体。
重试与幂等:
- Muse 只在连接失败且确认 provider 未接受请求时允许自动重试。
- 一旦拿到 Dify `message_id``task_id``workflow_run_id` 或同等 `providerRequestId`,后续只能轮询、恢复或归档该 provider 运行,不得重新提交同一命令。
- Dify workflow 若包含外部写操作、通知、Webhook 或其它副作用,默认不自动重试;只有 provider 明确支持 idempotency key 且 Muse 已传入 `commandId` 时才可重试。
- adapter 必须把 `commandId``correlationId` 和脱敏 Muse 上下文传给 provider作为排障和幂等线索不能把它们当作 provider 已保证幂等的证据。
### 5.3 AgentScope Adapter 预留
AgentScope adapter 以后按同一协议接入:
- `runtimeProvider=agentscope`
- `providerRef.graphId` / `providerRef.agentId` / `providerRef.version`
- 请求和响应仍走 `MuseAgentRuntimeRequest/Response`
- AgentScope 内部工具和知识权限即使受限Muse 仍按外部 runtime 处理,不授予直接写入权。
### 5.4 正文写手 adapter 隔离边界
正文写手 adapter 是开放能力节点,但采用比通用 provider 更窄的执行边界:
1. **无工具**:写手进程的工具集合必须为空,不得读取文件、搜索、访问数据库、调用网络工具或自行扩大检索范围。检索、授权、冻结与组装全部在可信的 Muse 层完成。
2. **无会话持久化**:每次 attempt 使用独立无状态进程,禁止恢复、续接或保存 provider 会话;旧 attempt 的隐式记忆不得进入新候选。
3. **单一输入**adapter 只接收 [专题-03 §4.5](专题-03-AI编排上下文与质量评测实现规范.md) 定义的冻结 `WriterContext v1`不得旁路追加未登记正文、卡片、Prompt 记忆或未来信息。
4. **严格输出**:只接受 `WriterOutput v1`;非 JSON、未知字段、缺字段、候选哈希或上下文哈希不匹配均视为协议失败不生成可接受候选。
5. **超时失败关闭**adapter 必须设置单次 deadline。超时、取消、非零退出、provider bad response 或进程失联时,当前 attempt 进入失败终态,取消下游 detector/judge丢弃迟到结果且不得回退到有工具写手、旧会话或其他 provider 伪装成功。
6. **接受资格不可伪造**`acceptanceEligible` 由可信上下文层派生;诊断/评测运行及任何 adapter 失败结果固定不可接受。provider 返回 true 不能覆盖可信层的 false。
该边界先在实验台验证,不新增或修改产品 API、数据库字段和正式 runtime 状态;产品化必须等待正文 Gate B 通过后另立计划。本节只拥有 adapter 隔离语义Writer 合同和接受链分别由专题-03、专题-01 定义。
## 6. 系统 Agent 配置体验
管理端系统 Agent 配置页新增“外部运行时”区域:
| 控件 | 说明 |
|---|---|
| Runtime Provider | `new-api` / `dify` / 预留 `agentscope` |
| Dify 控制台链接 | 跳转到受限 Dify 控制台配置 agent/workflow |
| Dify App Type | `agent` / `workflow` |
| Dify App ID | agent/chat 类应用引用 |
| Dify Workflow ID | workflow 类应用引用 |
| Credential Ref | 后端安全配置引用名,不显示真实密钥 |
| 输出合同 | 文本 / JSON schema / 章节列表 / 候选建议等 |
| 试运行 | 只允许合成或脱敏样本,不能直接读取真实私有正文 |
发布系统 Agent 版本时:
1. 前端提交 provider 引用、输出合同、Prompt/模型摘要和发布理由。
2. 后端校验 provider 类型、Dify 引用完整性、credentialRef 是否存在可用配置。
3. 后端写入新的 `muse_agent_version.config`
4. 当前版本切换仍由 Muse Agent BC 控制。
5. 版本生效后Studio 生成/试用/槽位绑定只消费 Muse agent version不直接调用 Dify。
6. `consoleUrl` 只能由后端根据 Dify baseUrl allowlist 和 app/workflow id 拼装;禁止前端提交任意跳转 URL禁止 URL query 携带 token/code跳转行为必须进入审计。
## 7. RAGFlow 与 Dify 知识边界
当前 Muse 已使用 RAGFlow
- Knowledge 上传、解析、dataset/document/chunk 管理由 Knowledge BC 对接 RAGFlow。
- AI 上下文组装通过 Knowledge facade 检索已授权 KB并把 chunk 摘要放入 runtime 输入。
- Market KB 物化通过 RAGFlow fork 公开副本,保证安装者不读发布者私有内容。
Dify 的知识能力边界:
- 如果 Dify app 内部绑定了知识库,该知识库必须已经在 Dify 侧受限Muse 仍不能把它当成 Muse Knowledge Canonical。
- Muse 传给 Dify 的上下文只来自 Muse Runtime Permission Envelope 允许的输入。
- Dify 返回引用或知识片段时,只作为 provider output summary 或候选来源线索,不能反向写入 Muse Knowledge Canonical。
- 允许 Dify 内部知识参与输出,但必须标记为 `untraceable_provider_context`;候选进入 Shadow 后仍需显示来源不可追溯风险。
- 需要 Muse 可追溯知识来源的生成链路,仍应优先使用 Muse Knowledge facade / RAGFlow 检索结果;若输出合同要求 Muse-compatible source refs而 Dify 不能返回可验证 source refs则必须 fail-closed。
## 8. 用量归属
Dify 模型调用的账户用量和配额 authority 仍归 Muse / New-API 归属链:
- Dify 侧模型调用应通过 Muse 可归属的 New-API 网关或回传可归属 request id。
- adapter 可以记录 Dify `usage` 摘要,但不能把它当成 New-API 成本账本或账户扣费 authority。
- 无法归属到 Muse/New-API 的 Dify 用量只能作为脱敏审计事实;不得伪造扣费成功、余额消耗或配额同步成功。
- runtime call 必须保留 `commandId``correlationId`、agentVersion、providerRequestId 和 attribution status便于后续 Account 归属或人工处理。
## 9. 安全与审计
必须满足:
1. 凭据不入库、不进日志、不进前端、不进 agent 返回。
2. provider 原始响应默认不长期保存;需要排障时只保存脱敏摘要和 providerRequestId。
3. 外部调用前必须已记录 `runtime.requested`,失败也要留下调用意图。
4. Muse 权限包、source snapshot、agent version、providerRef 必须进入 runtime call 脱敏摘要。
5. Dify/AgentScope 自带工具权限只作为外部平台内部限制,不替代 Muse Runtime Permission Envelope。
6. Dify 未配置、credentialRef 不存在、app/workflow 引用不完整时 fail-closed。
7. 所有外部交互必须处理超时、失败、重试、幂等和取消。
8. Dify 不得持有 Muse admin/app 写凭据;如未来需要 Dify 调用 Muse 能力,只能通过 Muse tool broker 或 adapter 受控回调,并重新校验 RPE 与 Tool Grant。
## 10. 实施计划
阶段 A设计与契约
- 新增本文并在 ADR、专题-03、产品-02B 中建立引用。
- 后端定义 provider-neutral DTO / interface。
- OpenAPI 增加系统 Agent providerRef 字段、响应脱敏和发布校验错误码,不暴露密钥。
- 后端-04 增加 `muse_agent_version.config` 的 providerRef schema、密钥禁入、用量归属和可审计字段约束。
阶段 B后端最小闭环
- 在 AI 模块新增 runtime router。
- 把现有 New-API adapter 包装为 `new-api` provider。
- 新增 Dify adapter先支持 blocking chat/workflow保留 streaming 扩展接口。
- Agent version config 支持 `runtimeProvider``dify` 引用。
- 创建/发布系统 Agent 版本时校验 providerRef。
阶段 C管理端接线
- 系统 Agent 配置页增加 Dify 控制台跳转和引用录入。
- 列表展示 provider、app/workflow 引用、credentialRef 摘要和最近运行状态。
- 试运行入口只允许合成或脱敏样本。
阶段 D真验证
- 单测router 分发、Dify 请求映射、响应归一化、失败分类、脱敏。
- 后端 IT系统 Agent 版本引用 Dify 后,试运行 / createAiTask 走 Dify adapterjob/task/suggestion/audit 落库;新系统 Agent 版本缺 runtimeProvider 拒绝发布。
- 外部 live使用受限 Dify app/workflow 真调用验证成功、超时、鉴权失败、workflow 输出解析。
- 前端Admin 系统 Agent 配置能跳转 Dify、保存引用、发布版本Studio 仍只引用 Muse agent。
## 11. Done 判据
- Muse 有 provider-neutral runtime contract不再把 New-API 当唯一运行时语义。
- Dify app/workflow 可作为系统 Agent 版本的外部 providerRef 被引用和调用。
- 管理端可跳转 Dify 控制台配置,并在 Muse 保存引用。
- Dify 凭据只来自安全配置,未出现在 DB、日志、前端响应、测试快照。
- 指定 Dify 但未配置时 fail-closed不回退 New-API。
- 真 Dify 调用能产出 Muse Shadow 候选或可解释失败,并被 job/runtime/audit/usage 记录。