``` sequenceDiagram participant User as 用户(前端) participant Gateway as 鉴权(可合并到智能体) participant Agent as Spring AI Agent(编排/工具执行) participant LLM as 大语言模型 participant DomainAPI as 域名列表接口(Tool,可选) participant DataAPI as 流量数据接口(Tool:query/export) participant OSS as 对象存储 autonumber User->>Gateway: 提问:“帮我把 a.com 1月到3月的流量数据导出来” Gateway->>Gateway: 校验 Token,解析 TenantID Gateway->>Agent: 转发请求(带 TenantID 到 header 或 context) Agent->>Agent: 拦截器读取 header -> 写入 ThreadLocal(TenantID) Agent->>LLM: system prompt + 对话历史 + tools schema(query_traffic/export_traffic/list_domains) alt 参数充足(domain + timeRange + intent=export) LLM-->>Agent: tool_call: export_traffic{domain=a.com,from=2025-01-01,to=2025-03-31,format=xlsx} Agent->>DataAPI: 调用 tool(拦截器从 ThreadLocal 注入 TenantID) DataAPI->>DataAPI: 横向鉴权(tenant 是否拥有 domain) alt 鉴权失败 DataAPI-->>Agent: 业务错误:无权访问该域名数据 Agent->>LLM: tool_result(错误信息/错误码) LLM-->>Agent: 生成答复(无权限 + 建议/下一步) Agent-->>User: 返回最终结果 alt 同步导出(小数据) DataAPI->>DataAPI: 查询明细/聚合数据 DataAPI->>DataAPI: EasyExcel 生成临时 .xlsx DataAPI->>OSS: 上传文件流 OSS-->>DataAPI: 返回预签名下载链接(过期时间) DataAPI-->>Agent: 200 JSON{url,expireAt,fileName} Agent->>LLM: tool_result(JSON:url/expireAt...) LLM-->>Agent: 生成答复(Markdown 链接 + 过期提示) Agent-->>User: 返回最终结果 DataAPI-->>Agent: 202 JSON{jobId,status=PROCESSING} Agent->>LLM: tool_result(jobId + 引导用户等待/可查询进度) LLM-->>Agent: 生成答复:“已开始导出,任务号xxx…” Agent-->>User: 返回任务已创建 Note over User, Agent: 用户稍后追问“导出好了没?”或前端轮询(模型能力弱我感觉最好别轮训,可以在对话框提示询问) User->>Gateway: “查询导出进度 jobId=xxx” Gateway->>Agent: 转发(TenantID) Agent->>Agent: 写 ThreadLocal(TenantID) Agent->>LLM: tools schema(get_export_status / get_export_url) LLM-->>Agent: tool_call: get_export_status{jobId=xxx} Agent->>DataAPI: 注入 TenantID 调用 DataAPI-->>Agent: 200 JSON{status=FINISHED,url,expireAt} Agent->>LLM: tool_result(JSON) LLM-->>Agent: 生成答复(返回下载链接) Agent-->>User: 返回最终结果 end end LLM-->>Agent: 需要补齐参数(domain/timeRange/导出格式) alt 仅澄清(无域名工具) LLM-->>Agent: 追问:“要导出哪个域名?时间范围是?” Agent-->>User: 返回追问 else 有域名查找工具 LLM-->>Agent: tool_call: list_domains{} Agent->>DomainAPI: 调用(注入 TenantID) DomainAPI-->>Agent: JSON{domains:[a.com,b.com,...]} Agent->>LLM: tool_result(域名列表) LLM-->>Agent: 追问/确认(domain + timeRange) Agent-->>User: 返回追问 end end Agent->>Agent: finally 清理 ThreadLocal(线程复用问题) ```