332 lines
18 KiB
Markdown
332 lines
18 KiB
Markdown
# 专题-05:AI 统一交互协议与外部 Agent Adapter 设计
|
||
|
||
- 版本:v0.2
|
||
- 更新日期:2026-07-20
|
||
- 目标读者:架构 / 后端 / 前端 / 运维 / 测试
|
||
- 边界说明:本文定义 Muse 后端到外部 Agent 运行时的统一交互协议与 adapter 层。它承接 `专题-03-AI编排上下文与质量评测实现规范.md`,不改变 Shadow -> Canonical、Runtime Permission Envelope、RAGFlow 检索和用户确认边界。
|
||
- 变更记录:v0.2(2026-07-20)§5.4 固化正文写手 adapter 的无工具、无会话持久化和超时失败关闭边界;v0.1(2026-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,当前实现使用 RAGFlow;Dify 内置知识库只能作为 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 BC;Muse 授权知识检索仍由 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 adapter,job/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 记录。
|