19 KiB
TH Hotel SuperAgent 与 AgentBus 项目接入记录
1. 文档定位
本文保存 TH Hotel 项目中已经验证过的 SuperAgent 与 AgentBus 接入经验、项目路径、表名和 验证记录。
本文是当前项目专属记录,不应整份复制到其他项目。可复用的通用接入规则应沉淀到
docs/import/reusable/integrations/superagent-agentbus-portable-integration-guide.md。
本文不是 SuperAgent 或 AgentBus 官方协议文档,也不记录任何真实 Token、API Key、 Session ID、Run ID、邮箱正文、附件 URL 或客户个人信息。其他项目接入时,应把本文作为 工程边界、配置清单和验证顺序参考;具体字段仍以提供方最新协议和真实测试响应为准。
相关本项目验证记录:
docs/superagent-integration-notes.mddocs/agentbus-integration-notes.mddocs/agentbus-production-flow.mddocs/architecture/ADR-003-ai-provider-boundary.md
2. 两条链路的职责边界
SuperAgent 和 AgentBus 不应被设计成同一个模块。
AgentBus
→ 接收 Email / LINE 等外部渠道消息
→ 保存 SourceMessage Inbox
→ 受控 Replay 为 MessageEvent / Evidence
→ 调用 AI 能力端口
→ SuperAgent Provider Adapter
→ 保存 AI Capability Invocation
→ 业务 Schema 校验
→ 人工确认
→ Case / Task / Operation / Receipt
| 能力 | 定位 | 负责什么 | 不负责什么 |
|---|---|---|---|
| AgentBus | 外部消息通道适配器 | WebSocket 连接、接收入站 frame、保存原始来源事实 | 不做 AI 抽取、不创建业务 Task、不回复客户、不调用业务写接口 |
| SuperAgent | 外部 AI / Agent 能力提供方 | 创建 Agent Session、发送消息、解析 SSE、返回建议或回答 | 不决定业务动作、不绕过人工确认、不直接写业务系统 |
| SourceMessage Inbox | 平台缓冲层 | 不可变保存来源消息和捕获状态 | 不表达 AI 结论或业务归属 |
| AiCapabilityPort | 平台能力端口 | 隔离业务层和具体 Provider SDK / HTTP 协议 | 不暴露 Provider DTO 给领域层 |
核心原则:
- 前端不直接调用 SuperAgent 或 AgentBus,不接触任何 Provider Secret。
- AgentBus 实时链路只落来源事实,不直接生成 Case、Task、Operation 或客户回复。
- SuperAgent 返回内容只能作为建议、证据或审计结果,不能直接改变业务最终状态。
- 业务写操作必须经过平台规则校验、权限控制、幂等控制和人工确认。
3. 推荐模块拆分
其他 Java / Spring Boot 项目接入时,建议按以下模块复制思路,而不是复制 TH Hotel 的 预订部业务代码。
platform
├── message
│ ├── SourceMessageInbox
│ ├── MessageEvent
│ └── Evidence
├── ai
│ ├── AgentCapabilityPort
│ ├── AgentCapabilityRequest
│ ├── AgentCapabilityResult
│ └── AiCapabilityInvocation
└── system
├── SuperAgentProbeController
├── AgentBusProbeStatusController
└── SourceMessageReplayController
integrations
├── ai
│ └── superagent
└── messaging
└── agentbus
TH Hotel 当前 M001 相关代码中的可参考文件:
| 目的 | 参考文件 |
|---|---|
| SourceMessage 查询与原文 API | server/src/main/java/cn/nianxx/thhotel/platform/message/control/SourceMessageController.java |
| SourceMessage 捕获服务 | server/src/main/java/cn/nianxx/thhotel/platform/message/service/impl/SourceMessageCaptureServiceImpl.java |
| SourceMessage 原文读取服务 | server/src/main/java/cn/nianxx/thhotel/platform/message/service/impl/SourceMessageOriginalServiceImpl.java |
| SourceMessage 持久化边界 | server/src/main/java/cn/nianxx/thhotel/platform/message/repository/MybatisSourceMessageInboxRepository.java |
| AgentBus WebSocket 客户端 | server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/adapter/AgentBusWebSocketClient.java |
| AgentBus frame 处理 | server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/adapter/AgentBusFrameProcessor.java |
| AgentBus 到 SourceMessage 适配 | server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/adapter/AgentBusSourceMessageAdapter.java |
| AgentBus 状态 API | server/src/main/java/cn/nianxx/thhotel/platform/system/control/AgentBusProbeStatusController.java |
| SourceMessage 表结构 | server/src/main/resources/db/migration/V1__create_source_message_inbox.sql |
| SourceMessage 原文读取审计表 | server/src/main/resources/db/migration/V2__create_source_message_original_access_audit.sql |
SourceMessage Replay 到 MessageEvent / Evidence 尚未实现,需等 MessageEvent、Evidence 字段模型确认后再进入后续 checkpoint。
4. SuperAgent 对接
4.1 运行时配置
最小配置建议:
AI_PROVIDER_ENABLED=false
DEERFLOW_BASE_URL=https://superagent.nianxx.cn
DEERFLOW_OPEN_API_KEY=
SUPERAGENT_PROBE_ENABLED=false
SUPERAGENT_PROBE_ACCESS_KEY=
SUPERAGENT_CONNECT_TIMEOUT=15s
SUPERAGENT_READ_TIMEOUT=180s
SUPERAGENT_MAX_MESSAGE_CHARS=4000
SUPERAGENT_EXTERNAL_SUBJECT_ID=your-project-superagent-probe
变量说明:
| 变量 | 是否 Secret | 说明 |
|---|---|---|
AI_PROVIDER_ENABLED |
否 | 是否启用真实 SuperAgent Provider Adapter。默认关闭。 |
DEERFLOW_BASE_URL |
否 | SuperAgent / DeerFlow Open API 地址。 |
DEERFLOW_OPEN_API_KEY |
是 | Open API Key,应只存在后端环境变量或 Secret Manager。 |
SUPERAGENT_PROBE_ENABLED |
否 | 是否开放本项目自己的探针接口。生产默认关闭。 |
SUPERAGENT_PROBE_ACCESS_KEY |
是 | 调用探针接口的本地访问密钥,不是 Provider API Key。 |
SUPERAGENT_CONNECT_TIMEOUT |
否 | 建立连接超时。 |
SUPERAGENT_READ_TIMEOUT |
否 | SSE 读取超时。 |
SUPERAGENT_MAX_MESSAGE_CHARS |
否 | 单次发送给 Provider 的消息长度上限。 |
SUPERAGENT_EXTERNAL_SUBJECT_ID |
否 | 创建 Agent Session 时使用的外部主体标识。 |
4.2 当前已验证的 Open API 调用形态
当前 TH Hotel 已验证的流程:
POST /api/open/agent-sessions
→ 获取 session_id
→ POST /api/open/agent-sessions/{sessionId}/messages/stream
→ 读取 text/event-stream
→ 解析最终 answer、run、profile、model、token usage
状态变更请求需要 CSRF double-submit:
X-CSRF-Token: <random-csrf-token>
Cookie: csrf_token=<same-random-csrf-token>
Authorization: Bearer <DEERFLOW_OPEN_API_KEY>
CSRF Token 由客户端实例临时生成,不需要写入配置,也不能当作 Secret 长期保存。
4.3 Session 请求示例
{
"external_subject_id": "your-project-superagent-probe",
"idempotency_key": "your-project-superagent-session-<correlation-id>",
"metadata": {
"source": "your-project",
"purpose": "provider-connectivity-test"
}
}
4.4 SSE 消息请求示例
{
"message": "请介绍一下你是谁。",
"idempotency_key": "your-project-superagent-message-<correlation-id>",
"metadata": {
"source": "your-project",
"purpose": "provider-flow-test"
}
}
4.5 SSE 解析口径
TH Hotel 当前观测并处理的事件类型:
| Event | 用途 |
|---|---|
metadata |
读取 Run、Thread、Profile 等调用元数据 |
messages |
流式消息增量或中间消息 |
values |
阶段性或最终聚合状态 |
end |
SSE 正常结束标志 |
解析最终答案时,不要简单拼接所有 messages。当前实现从后期 values.messages[] 中选择:
type = ai
response_metadata.finish_reason = stop
content 非空
并记录:
run_idresolved_profile_idresolved_profile_version_idresponse_metadata.model_nameusage_metadata.input_tokensusage_metadata.output_tokensusage_metadata.total_tokens- 已出现的 SSE event types
如果没有收到 end,或无法找到最终 AI 回答,应视为协议失败,不要伪造成成功结果。
4.6 平台能力端口
其他项目建议定义一个稳定端口,例如:
public interface AgentCapabilityPort {
AgentCapabilityResult invoke(AgentCapabilityRequest request);
}
领域层只依赖这个端口,不依赖 SuperAgent HTTP DTO、SSE event、Profile ID 或厂商 SDK。
建议 AgentCapabilityResult 至少包含:
providerCode
responseSchemaVersion
providerSessionId
providerRequestId
providerProfileId
providerProfileVersionId
providerModelId
outputText 或 outputReference
usageMetadata
4.7 调用审计
建议每次外部能力调用都写入不可变审计表。TH Hotel 当前表为
platform_ai_capability_invocation,参考:
server/src/main/resources/db/migration/V2__create_ai_capability_invocation.sqldocs/database/ai-capability-invocation-data-dictionary.md
审计表应记录成功与失败,不应记录:
- Provider API Key
- Cookie
- Authorization
- Chain of Thought
- Provider 内部 Plan / Memory
- 未脱敏的个人信息
5. AgentBus 对接
5.1 运行时配置
最小配置建议:
AGENTBUS_PROBE_ENABLED=false
AGENTBUS_WS_URL=wss://mesh.nianxx.cn/ws
AGENTBUS_WS_TOKEN=
AGENTBUS_BOT_ADDRESS=bot:external:listener
AGENTBUS_WS_RECONNECT_DELAY=5s
AGENTBUS_CONNECT_TIMEOUT=15s
AGENTBUS_SAMPLE_ENABLED=false
AGENTBUS_SAMPLE_DIR=var/agentbus-samples
AGENTBUS_MAX_FRAME_BYTES=1048576
AGENTBUS_MAX_SAMPLES=100
AGENTBUS_CAPTURE_ENABLED=true
AGENTBUS_DEFAULT_HOTEL_ID=HOTEL-TEST
AGENTBUS_REPLY_MODE=NONE
SOURCE_MESSAGE_DEV_ORIGINAL_READ_ACCESS_KEY=
SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY=
变量说明:
| 变量 | 是否 Secret | 说明 |
|---|---|---|
AGENTBUS_PROBE_ENABLED |
否 | 是否启用 AgentBus WebSocket 监听。默认关闭。 |
AGENTBUS_WS_URL |
否 | AgentBus WebSocket 地址。 |
AGENTBUS_WS_TOKEN |
是 | WebSocket 鉴权 Token。 |
AGENTBUS_BOT_ADDRESS |
否 | 当前 Bot / Listener 地址。 |
AGENTBUS_WS_RECONNECT_DELAY |
否 | 断线后的重连间隔。 |
AGENTBUS_CONNECT_TIMEOUT |
否 | WebSocket 连接超时。 |
AGENTBUS_SAMPLE_ENABLED |
否 | 是否保存本地原始 frame 样本。生产应默认关闭。 |
AGENTBUS_SAMPLE_DIR |
否 | 本地样本目录,可能含 PII,不得提交。 |
AGENTBUS_MAX_FRAME_BYTES |
否 | 单个入站 frame 最大字节数。 |
AGENTBUS_MAX_SAMPLES |
否 | 最多保留的本地样本数。 |
AGENTBUS_CAPTURE_ENABLED |
否 | 是否写入 SourceMessage Inbox。 |
AGENTBUS_DEFAULT_HOTEL_ID |
否 | AgentBus 未提供租户上下文时的默认业务上下文。 |
AGENTBUS_REPLY_MODE |
否 | 调试回复模式。真实客户渠道应保持 NONE。 |
SOURCE_MESSAGE_DEV_ORIGINAL_READ_ACCESS_KEY |
是 | dev 原文读取接口的临时受控访问 key,后续可替换为正式权限体系。 |
SOURCE_MESSAGE_TEST_ORIGINAL_READ_ACCESS_KEY |
是 | test 原文读取接口的临时受控访问 key。 |
SOURCE_MESSAGE_PROD_ORIGINAL_READ_ACCESS_KEY |
是 | prod 原文读取接口的临时受控访问 key,只能通过生产 Secret 注入。 |
SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY |
是 | 旧通用原文读取 key,仅作为兼容兜底。 |
5.2 WebSocket 连接
当前实现使用 JDK HttpClient 的 WebSocket:
Authorization: Bearer <AGENTBUS_WS_TOKEN>
GET <AGENTBUS_WS_URL>?ready=1
连接成功后应能收到 session.ready。
状态查询接口示例:
GET /api/system/agentbus-probe
响应只应返回连接状态、计数器和最近错误代码,不返回 Token 或原始消息。
5.3 入站 frame 处理边界
推荐处理顺序:
收到 raw WebSocket frame
→ 限制单帧大小
→ 可选本地采样
→ JSON 解析
→ 忽略 session.ready / task.progress / task.result 等控制事件
→ 将业务 payload 映射为 CaptureSourceMessageCommand
→ 写入 SourceMessage Inbox
实时链路禁止:
- 自动发送 ACK。
- 自动发送
task.result。 - 自动回复客户。
- 直接创建 MessageEvent、Evidence、AI Recognition、Case、Task、Operation 或 Receipt。
- 直接调用 OHIP、ERP、支付系统等业务写接口。
5.4 当前已确认的 Outlook Payload 关键字段
AgentBus 后续确认的 Outlook 邮件 payload 包括:
text
body.content_type
body.html
body.text
inline_images[]
attachments[]
source.channel
source.channel_account
source.external_message_id
source.external_conversation_id
source.sender
source.subject
source.web_link
reply_policy.mode
reply_policy.final_only
当前 SourceMessage 捕获只依赖少量稳定字段:
| AgentBus 字段 | 平台字段 |
|---|---|
source.channel |
channel,例如 EMAIL |
source.external_message_id |
externalMessageId,作为幂等键组成部分 |
source.external_conversation_id |
externalConversationId |
frame id |
agentbusFrameId |
frame session_id |
agentbusSessionId |
payload 规范 JSON |
payloadJson 与 payloadSha256 |
不要根据 envelope 的 from、to、conversation_id 猜测酒店、业务 Case 或下游 Task。
5.5 SourceMessage Inbox
建议单独建表保存 AgentBus 入站事实。TH Hotel 当前表为:
platform_source_message_inboxplatform_source_message_replay_attempt
参考:
server/src/main/resources/db/migration/V16__create_source_message_inbox.sqldocs/agentbus-production-flow.md
推荐幂等键:
hotel_id + provider + channel + external_message_id
重复投递时返回已有 Inbox,不覆盖原始 payload,不创建重复记录。
如果 payload 缺少必要字段或格式不符合预期,也应保存为 FAILED Inbox,并记录安全错误
摘要。错误摘要不得包含:
- 邮件正文
- HTML
- 附件 URL
- 完整邮箱地址
- Token / Cookie / Secret
5.6 Replay 到 MessageEvent / Evidence
SourceMessage Inbox 不应等同于正式业务消息。推荐增加受控 Replay:
POST /api/system/source-message-inbox/{inboxId}/replay
Header: X-TH-Hotel-Source-Replay-Key
Replay 负责:
- 从 Inbox payload 提取 MessageEvent 字段。
- 保存正文或正文引用。
- 保存 Evidence 摘要或附件引用。
- 记录 replay attempt。
- 返回 MessageEvent ID 和状态。
Replay 接口默认关闭,仅在本地、UAT 或受控生产运维场景开启。
6. 其他项目最小落地顺序
阶段 1:SuperAgent 连通性
目标:
后端探针
→ 创建 SuperAgent Session
→ 发送一条无 PII 测试消息
→ 解析 SSE 最终回答
→ 返回非敏感元数据
验收:
- HTTP 连接成功。
- SSE 收到
end。 - 最终回答非空。
- 日志不出现 API Key、Cookie、Session 原始值或客户信息。
阶段 2:AgentBus 连接
目标:
AgentBus WebSocket
→ session.ready
→ 状态接口可见 connected/sessionReady
验收:
- 连接成功。
- 可断线重连。
- 不发送客户回复。
- 不保存本地 raw sample,除非临时排障。
阶段 3:SourceMessage Inbox
目标:
AgentBus 入站业务 frame
→ SourceMessage Inbox
验收:
- 正常 payload 保存为
RECEIVED。 - 无效 payload 保存为
FAILED。 - 重复外部消息不重复入库。
- 查询接口只返回安全摘要。
阶段 4:手动 Replay
目标:
SourceMessage Inbox
→ MessageEvent / Evidence
验收:
- 同一 Inbox 可以按不同
replayRunId多次 replay。 - 相同
replayRunId幂等。 - Replay 失败有 attempt 记录。
- 响应不返回客户正文、HTML、附件 URL 或 Token。
阶段 5:业务接入 SuperAgent
目标:
MessageEvent
→ AgentCapabilityPort
→ SuperAgent Adapter
→ AiCapabilityInvocation
→ 业务 Schema 校验
验收:
- Provider 返回记录为审计,不直接触发业务写操作。
- 结构化输出必须通过 Schema 校验。
- 无法映射或不可信结果进入人工处理。
7. 安全与日志清单
必须放入 Secret 管理,不得提交仓库:
DEERFLOW_OPEN_API_KEYSUPERAGENT_PROBE_ACCESS_KEYAGENTBUS_WS_TOKENSOURCE_MESSAGE_DEV_ORIGINAL_READ_ACCESS_KEYSOURCE_MESSAGE_TEST_ORIGINAL_READ_ACCESS_KEYSOURCE_MESSAGE_PROD_ORIGINAL_READ_ACCESS_KEYSOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEYSOURCE_MESSAGE_REPLAY_ACCESS_KEY- 数据库密码
- 任何真实客户渠道 Token
普通日志和错误响应不得输出:
- Authorization
- Cookie
- CSRF Token
- Provider API Key
- AgentBus Token
- 邮件正文和 HTML
- 附件 URL
- 客人姓名、邮箱、电话、证件号
- 支付信息
本地采样要求:
AGENTBUS_SAMPLE_ENABLED默认false。- 只在隔离测试或排障时临时开启。
- 样本目录必须被
.gitignore忽略。 - 排障结束后删除样本。
8. 测试建议
SuperAgent 建议覆盖:
- 缺失 API Key 时启动或调用失败。
- CSRF Header / Cookie 不一致时转换为受控错误。
- 创建 Session 成功。
- SSE 正常结束并解析最终回答。
- SSE 缺少
end时失败。 - SSE 缺少最终回答时失败。
- HTTP 401 / 403 / 404 / 409 / 5xx 错误转换。
- 连接超时和读取超时。
AgentBus 建议覆盖:
session.ready只更新状态,不写 Inbox。- 控制事件不写 Inbox。
- 正常 Outlook payload 写入 Inbox。
captureEnabled=false时忽略业务 frame。- 无效 payload 写入
FAILEDInbox。 - 超大 frame 被拒绝并记录错误代码。
- 重复外部消息保持幂等。
- 查询接口不返回原始 payload。
- Replay 相同 run id 幂等。
9. 常见误区
9.1 把 AgentBus 当 AI Provider
AgentBus 是消息入口,不是抽取模型。它可以传递 Email / LINE 原始事实,但不应该直接产生 业务最终判断。
9.2 把 SuperAgent 返回当业务事实
SuperAgent 返回的是 Provider 输出。即使未来返回结构化 JSON,也必须经过平台 Schema、 业务规则、Case 匹配和人工确认。
9.3 让浏览器直接调用 Provider
浏览器不能持有 Provider Key、AgentBus Token 或 replay access key。前端只调用本项目后端。
9.4 实时入口直接生成 Task
实时 AgentBus 链路如果直接创建 Task,会导致重复投递、字段不完整、后续协议变化和人工 回溯都难处理。先落 Inbox,再 Replay,是更稳的路线。
9.5 在文档或测试里保存真实邮件
真实邮件、附件 URL、客户姓名和联系方式都可能是敏感数据。测试夹具应使用合成数据。
10. 接入前检查清单
接入 SuperAgent 前确认:
- 已获得 Open API Key 和允许访问的 Base URL。
- 已确认是否需要 CSRF double-submit。
- 已确认 Session、Message、Run 的生命周期。
- 已确认 SSE 最终答案或结构化结果所在字段。
- 已定义
AgentCapabilityPort和调用审计表。 - 已确认 Provider 输出不会直接触发业务写操作。
接入 AgentBus 前确认:
- 已获得 WebSocket URL、Token 和 Bot Address。
- 已确认真实渠道 payload 字段。
- 已确认外部消息稳定幂等键。
- 已确认断线重连和重复投递语义。
- 已确认是否允许 ACK 或客户回复;默认按禁止处理。
- 已建立 SourceMessage Inbox 和 Replay attempt。
- 已定义原始 payload 的保存、访问、保留和删除策略。
进入生产前确认:
- 所有 Secret 均通过环境变量或 Secret Manager 注入。
.env.example只有占位值。- 日志脱敏已验证。
- 自动回复保持关闭。
- 自动业务写操作保持关闭,除非经过单独评审。
- 监控至少覆盖连接状态、失败次数、Replay 失败和 Provider 调用失败。