``` sequenceDiagram participant User as 用户(前端) participant Gateway as 鉴权(可合并到智能体) participant Agent as Spring AI Agent(编排/工具执行) participant LLM as 大语言模型 participant DomainAPI as 域名列表接口(Tool,可选,举例后期多智能体多工具协作) participant DataAPI as 流量查询接口 query_traffic(Tool) autonumber User->>Gateway: 提问:“帮我查一下 a.com 昨天的流量” Gateway->>Gateway: 校验 Token,解析 TenantID Gateway->>Agent: 转发请求(带 TenantID 到 header 或 context) Agent->>Agent: 拦截器读取 header -> 写入 ThreadLocal(TenantID) Agent->>LLM: system prompt + 对话历史 + tools schema alt 参数充足(有 domain + timeRange) LLM-->>Agent: tool_call: query_traffic{domain=a.com,time=yesterday} Agent->>DataAPI: HTTP 调用或者调用 tool,取决于是否采用远程 mcp(拦截器从 ThreadLocal 注入 TenantID) DataAPI->>DataAPI: 横向鉴权(tenant 是否拥有 domain) alt 鉴权失败 DataAPI-->>Agent: 业务错误:无权访问该域名数据 Agent->>LLM: tool_result(错误信息/错误码) LLM-->>Agent: 生成答复(解释无权限 + 建议可查询域名/联系管理员) Agent-->>User: 返回最终结果 else 鉴权成功 DataAPI-->>Agent: 200 JSON{traffic=500GB} Agent->>LLM: tool_result(JSON 数据) LLM-->>Agent: 生成答复:“a.com 昨天的流量为 500GB...” Agent-->>User: 返回最终结果 end else 参数不全(例如只问“查 3 月流量”,缺 domain) LLM-->>Agent: 需要 domain,先澄清/或先发找可选域名 alt 仅澄清(没有域名查找工具) LLM-->>Agent: 追问:“要查询哪个域名的 3 月流量?” Agent-->>User: 返回追问 Note over User,Agent: 用户补充 domain 后进入下一轮对话,再走“参数充足”分支 else 有域名查找工具(显得比较智能) LLM-->>Agent: tool_call: list_domains{} Agent->>DomainAPI: 调用(注入 TenantID) DomainAPI-->>Agent: JSON{domains:[a.com,b.com,...]} Agent->>LLM: tool_result(JSON 域名列表) LLM-->>Agent: 追问/确认:“你要查哪个域名?a.com 还是 b.com?” Agent-->>User: 返回追问 Note over User,Agent: 用户选择后进入下一轮对话,再走“参数充足”分支 end end Agent->>Agent: finally 清理 ThreadLocal(线程复用问题) ```