doc_id: DDS-202606-004 feature_id: FEAT-202606-006-agent-semantic-interaction type: detailed-design title: Agent 语义交互与命令治理详细设计 status: reviewing owner: 医梦研发团队 created_at: 2026-06-29 updated_at: 2026-07-01 reviewers:
本设计描述后续实现所需的目标模块、领域对象、数据模型、状态机、接口、异常、安全和测试边界。 本轮只产出设计,不实施代码或数据库变更。
首个纵向样板仅覆盖挂号 Agent:
约束提取 → 号源查询 → 替代推荐 → 无状态展示
→ 候选选择 → 实时复核 → 临时锁号 → 最终挂号确认
{
"taskId": "task_001",
"taskType": "REGISTRATION",
"status": "ACTIVE",
"currentStage": "CANDIDATE_SELECTION",
"constraints": {
"departmentId": "respiratory",
"departmentName": "呼吸科",
"doctorTitle": "主任医师",
"visitDate": "2026-06-30",
"timeRange": null,
"campusId": null
},
"missingFields": ["candidateId"],
"activeResultRef": "result_001",
"activeCommandId": null,
"version": 5
}
约束:
ACTIVE 前台任务;其他任务为 SUSPENDED。{
"turnId": "turn_001",
"answer": "明天呼吸科有 3 位主任医师可预约。",
"task": {
"taskId": "task_001",
"taskType": "REGISTRATION",
"status": "ACTIVE",
"currentStage": "CANDIDATE_SELECTION",
"version": 5
},
"resultRefs": [
{
"resultRef": "result_001",
"version": 1,
"resultType": "APPOINTMENT_SLOT_CANDIDATES",
"expiresAt": "2026-06-30T09:35:00+08:00"
}
],
"availableActions": [
{
"actionType": "SELECT_CANDIDATE",
"riskLevel": "L1",
"confirmationRequired": false
}
]
}
SemanticResponse 是薄传输 DTO,不是持久化领域对象,也不是要求 FastGPT 一次性输出的模型 JSON。
仅 turnId 和 answer 必填;task、resultRefs、availableActions 按本轮结果可选。
风险和确认要求只存在于具体 Action/Command,Presentation 使用独立 SSE 事件。
ResultSnapshot 是只读 MCP 结果的最小化、短期、版本化引用。
必须包含:
result_ref、result_version、result_type;tenant_id、project_id、conversation_id、task_id;patient_binding_id;result_json;source_tool_call_id、trace_id;expires_at、created_at。禁止包含:
Presentation 是 ResultSnapshot 的无状态投影:
{
"presentationId": "prs_001",
"viewModelType": "AppointmentSlotCandidates",
"schemaVersion": "1.0",
"resultRef": "result_001",
"resultVersion": 1,
"payload": {
"groups": []
},
"interactions": [
{
"type": "SELECT_CANDIDATE",
"candidateId": "slot_001"
}
]
}
通用布局原语包括列表、分组、标签、摘要、按钮和确认区。
领域 ViewModel 包括 DoctorCandidate、AppointmentSlot、RegistrationConfirmation。
模板和策略不得包含:
nextCard;{
"commandId": "cmd_001",
"commandType": "REGISTER_APPOINTMENT",
"riskLevel": "L2",
"status": "AWAITING_CONFIRMATION",
"taskId": "task_001",
"taskVersion": 7,
"summary": {
"department": "呼吸科",
"doctor": "张明 主任医师",
"visitTime": "2026-06-30 09:00",
"feeYuan": "25.00"
},
"expiresAt": "2026-06-30T09:40:00+08:00"
}
命令参数由后端根据 TaskState、ResultSnapshot 和实时 MCP 结果准备。
终端不能提交或覆盖 commandType、HIS 参数、风险等级和金额。
| 字段 | 类型建议 | 约束 |
|---|---|---|
id |
bigint | 主键 |
result_ref |
varchar(96) | 全局唯一 |
result_version |
int | 同一引用递增 |
result_type |
varchar(64) | 领域结果类型 |
tenant_id |
varchar(64) | 必填、索引 |
project_id |
varchar(64) | 必填 |
conversation_id |
varchar(96) | 必填、索引 |
task_id |
varchar(96) | 必填、索引 |
patient_binding_id |
varchar(96) | 可空,不保存证件号 |
result_json |
json/text | 最小化结果 |
source_tool_call_id |
varchar(96) | 必填 |
trace_id |
varchar(96) | 必填、索引 |
expires_at |
datetime | 必填、索引 |
created_at |
datetime | 必填 |
唯一键:(result_ref, result_version)。
| 字段 | 类型建议 | 约束 |
|---|---|---|
id |
bigint | 主键 |
command_id |
varchar(96) | 全局唯一 |
command_type |
varchar(64) | 后端注册类型 |
risk_level |
varchar(8) | L1/L2/L3 |
status |
varchar(32) | 状态机字段 |
tenant_id/project_id |
varchar(64) | 权限边界 |
conversation_id/task_id/turn_id |
varchar(96) | 链路关联 |
task_version |
int | 防止旧任务确认 |
patient_binding_id |
varchar(96) | 确认主体 |
command_payload |
json/text | 后端生成,敏感字段最小化/加密 |
summary_json |
json/text | 面向确认的脱敏摘要 |
idempotency_key |
varchar(128) | 唯一或业务唯一 |
source_result_ref/version |
varchar/int | 可空 |
expires_at |
datetime | 必填 |
confirmed_at/executed_at |
datetime | 可空 |
trace_id |
varchar(96) | 必填、索引 |
created_at/updated_at |
datetime | 必填 |
| 字段 | 类型建议 | 说明 |
|---|---|---|
audit_id |
varchar(96) | 唯一 |
command_id |
varchar(96) | 命令关联 |
event_type |
varchar(32) | PREPARED/CONFIRMED/REJECTED/EXECUTING/SUCCEEDED/FAILED/UNKNOWN |
actor_type/actor_id |
varchar(32/96) | 患者、医护、系统 |
request_digest |
varchar(128) | 请求摘要,不保存密钥 |
result_digest |
varchar(128) | 结果摘要 |
tool_call_id |
varchar(96) | 可空 |
trace_id |
varchar(96) | 必填 |
occurred_at |
datetime | 必填 |
挂号纵向样板不创建 ai_presentation_template 或 ai_presentation_policy:
AppointmentSlotCandidatesV1、RegistrationConfirmationV1 Schema 随代码版本管理;只有出现三个以上可复用领域 ViewModel、且医院确有无代码换肤需求时,才另立需求评估模板表。
stateDiagram-v2
[*] --> ACTIVE
ACTIVE --> SUSPENDED: 切换业务任务
SUSPENDED --> ACTIVE: 恢复且上下文仍有效
ACTIVE --> COMPLETED: 业务目标完成
ACTIVE --> CANCELLED: 用户取消
ACTIVE --> EXPIRED: 任务超时
SUSPENDED --> EXPIRED: 上下文或资源过期
stateDiagram-v2
[*] --> PREPARED
PREPARED --> AWAITING_CONFIRMATION: L2/L3
PREPARED --> EXECUTING: L1 明确交互授权
AWAITING_CONFIRMATION --> EXECUTING: 确认通过
AWAITING_CONFIRMATION --> REJECTED: 用户拒绝
PREPARED --> EXPIRED: 到期
AWAITING_CONFIRMATION --> EXPIRED: 到期
EXECUTING --> SUCCEEDED
EXECUTING --> FAILED
EXECUTING --> UNKNOWN: 下游状态不明
UNKNOWN --> SUCCEEDED: 幂等状态查询确认
UNKNOWN --> FAILED: 幂等状态查询确认
禁止从 UNKNOWN 直接重新执行。
| 组件 | 职责 | 备注 |
|---|---|---|
FastGptAgentEngine |
文本流、只读工具调用和引擎元数据适配 | 首期唯一正式引擎 |
AgentApplicationService |
校验查询参数、更新查询上下文、保存结果引用、组装响应、解析 interaction | 保持薄应用层,不做通用 Workflow |
ResultSnapshotService |
最小化、版本化、过期与访问控制 | 可作为 AgentApplicationService 内部协作者 |
PresentationPolicy |
根据 ResultType 和终端能力选择代码内 ViewModel | 先用简单策略,不建设独立规则引擎 |
CommandRuntime |
固定命令策略、准备、确认、拒绝、执行、幂等和审计 | 命令类型与风险使用代码/配置白名单 |
McpToolService |
工具注册、权限过滤、ToolCatalog、调用和审计 | FastGPT 只获得只读集合 |
医梦后端是工具目录权威来源:
{
"name": "query_appointment_slots",
"description": "按科室、日期、职称等条件查询可预约号源",
"riskLevel": "READ_ONLY",
"timeoutMs": 5000,
"dataClassification": "INTERNAL",
"inputSchema": {
"type": "object",
"required": ["departmentId", "visitDate"],
"properties": {
"departmentId": {"type": "string"},
"visitDate": {"type": "string", "format": "date"},
"doctorTitle": {"type": "string"},
"timeRange": {"type": "string"}
},
"additionalProperties": false
}
}
生成步骤:
READ_ONLY;FastGPT 具体采用 MCP ToolSet、HTTP ToolSet 或 Workflow 工具节点,由实施前能力验证确定。 该差异只存在于 Adapter,不改变医梦工具权限模型。
取消单独的 propose_task_constraints 协议。FastGPT 调用只读工具时提交的参数即候选查询条件:
FastGPT 接收:
traceId/turnId;FastGPT 可产生:
用户的锁号或挂号意图由 AgentApplicationService 结合当前 TaskState 和明确交互识别; FastGPT 不输出可执行命令参数。
后端必须拒绝:
query_appointment_slots 只读工具。APPOINTMENT_SLOT_CANDIDATES ResultSnapshot。relaxedConstraint。LOCK_APPOINTMENT_SLOT。REGISTER_APPOINTMENT L2 命令。command_prepared 脱敏摘要。外部接口以 API-202606-004 和 OpenAPI v2 为准。
SSE 事件:
message_delta
semantic_result
presentation
task_updated
command_prepared
command_completed
error
completed
presentation 不保证出现,也不阻塞 completed 前的业务结果。
命令状态可通过独立查询接口恢复。
| 场景 | 处理 |
|---|---|
| FastGPT 文本流失败 | 返回明确错误或已有文本;不产生未验证状态 |
| Tool Call Schema 失败 | 拒绝该调用,可有限重试;文本可降级 |
| 查询超时 | 有限重试,说明无法获取实时数据,提供人工/传统入口 |
| ResultSnapshot 过期 | 返回 RESULT_EXPIRED,重新查询 |
| 选择版本冲突 | 返回 RESULT_VERSION_CONFLICT |
| 锁号失败 | 返回最新候选,不自动改选 |
| L2 命令过期 | 返回 COMMAND_EXPIRED,重新准备 |
| 写命令超时 | 进入 UNKNOWN,按幂等键查询下游状态 |
| 展示生成失败 | 记录指标,继续文本/语音 |
| 任务切换 | 暂停旧任务,不续锁;提示剩余有效期 |
平台级配置:
租户/医院可配置: