# 企业售后 Agent 实战项目设计 ## 目标 构建一个面向充电业务售后场景的企业 Agent 项目。用户描述问题后,Agent 能判断售后意图,检索售后政策,查询充电订单和充电记录,生成处理建议。低风险动作自动创建售后工单,高风险退款或补偿进入审批,审批后按冻结动作恢复执行,并记录全链路审计。 首版目标不是做普通聊天机器人,而是做一个受控的企业执行者:能查、能建议、能调用工具,但高风险动作必须可审批、可恢复、可追责。 ## 范围 首版采用双服务垂直切片: - Java `zsElectric-boot`:企业业务系统和 MCP Server,负责业务工具、审批、冻结动作、审计、售后政策和数据库。 - Python `zsElectric-agent-service`:独立兄弟服务,使用 FastAPI 作为服务框架,使用 OpenAI Agents SDK 作为 Agent 编排层,作为 MCP Client 调用 Java MCP Server。 - PostgreSQL + pgvector:作为售后政策 RAG 知识库。 - Swagger 或 Postman:用于审批演示,不开发审批管理页面。 不在首版范围内: - 不把所有 Java REST Controller 自动暴露为工具。 - Python 不直连 Java 业务数据库。 - 不做完整前端审批后台。 - 不接入 MCP 之外的泛化工具网关。 ## 架构 ```text 用户 -> Python zsElectric-agent-service (FastAPI) -> OpenAI Agents SDK -> RAG Retriever (PostgreSQL + pgvector) -> MCP Client -> Java zsElectric-boot MCP Server -> tool registry / whitelist / risk policy -> approval / pending action / audit log -> existing service / mapper / DB ``` Python 只负责 Agent 编排:意图判断、对话状态、工具选择、RAG 上下文组装、最终建议生成。 Java 负责企业能力暴露:通过 MCP tools 暴露受控业务动作,内部仍然走现有 service 层,保留鉴权、参数校验、风险分级、审批、审计和幂等保护。 HTTP 可以作为 MCP 的传输方式存在,但对 Python 来说,调用边界是 MCP tool,不是普通业务 REST API。 ## Java 模块 在 `zsElectric-boot` 中新增 `platform.agent` 模块: ```text platform.agent ├─ mcp # MCP endpoint 和 tool 暴露层 ├─ tool # 工具注册、白名单、风险等级、schema ├─ approval # 审批和 pending_action ├─ audit # Agent 全链路审计 ├─ policy # 售后政策文档和 RAG 元数据 └─ aftersales # 售后工单、退款、补偿业务适配 ``` Java MCP Server 暴露的工具必须来自白名单,并带明确参数 schema、风险等级、trace_id、operator/user 上下文。模型不能直接访问 Mapper、数据库或内部通用 Controller。 ## Python 模块 在兄弟目录创建 `E:\wzq\workCode\zswl\zsElectric-agent-service`: ```text app ├─ main.py # FastAPI app ├─ agents # OpenAI Agents SDK agent 定义 ├─ mcp_client # 连接 Java MCP Server ├─ rag # pgvector 检索和上下文组装 ├─ schemas # 请求、响应、工具结果结构 ├─ api # chat、resume、trace、health 路由 └─ evals # 测试问题集和期望结果 ``` FastAPI 接口: ```text POST /api/v1/agent/chat POST /api/v1/agent/resume/{approval_id} GET /api/v1/agent/runs/{trace_id} GET /health ``` ## LLM 配置 LLM 运行配置归属 Python `zsElectric-agent-service`。Java `zsElectric-boot` 不直接调用大模型,Java 只作为 MCP Server 暴露受控企业工具。这样模型供应商、模型版本、prompt、RAG 参数和工具调用上限都集中在 Agent 编排层管理。 首版使用显式模型配置,不依赖 SDK 默认值。默认建议: ```text 主 Agent 模型: gpt-5.5 快速分类/意图模型: gpt-5.4-mini Embedding 模型: text-embedding-3-small Embedding 维度: 1536 ``` `gpt-5.5` 用于最终建议生成、复杂售后判断和审批前说明;`gpt-5.4-mini` 用于意图分类、轻量改写、简单摘要等低成本步骤。后续如果模型升级,只改配置和评估基线,不改业务工具协议。 Python `.env` 示例: ```dotenv OPENAI_API_KEY= OPENAI_BASE_URL=https://api.openai.com/v1 OPENAI_DEFAULT_MODEL=gpt-5.5 AGENT_MAIN_MODEL=gpt-5.5 AGENT_FAST_MODEL=gpt-5.4-mini AGENT_TEMPERATURE=0.2 AGENT_REASONING_EFFORT=medium AGENT_MAX_TURNS=8 AGENT_TIMEOUT_SECONDS=60 AGENT_TOOL_TIMEOUT_SECONDS=15 EMBEDDING_MODEL=text-embedding-3-small EMBEDDING_DIMENSIONS=1536 RAG_TOP_K=5 RAG_MIN_SCORE=0.75 RAG_MAX_CONTEXT_TOKENS=3000 MCP_SERVER_URL=http://localhost:8080/api/v1/agent/mcp MCP_CONNECT_TIMEOUT_SECONDS=5 MCP_READ_TIMEOUT_SECONDS=30 ``` Python `settings.yaml` 示例: ```yaml llm: provider: openai base_url: ${OPENAI_BASE_URL} default_model: ${OPENAI_DEFAULT_MODEL} agents: aftersales_main: model: ${AGENT_MAIN_MODEL} temperature: ${AGENT_TEMPERATURE} reasoning_effort: ${AGENT_REASONING_EFFORT} max_turns: ${AGENT_MAX_TURNS} timeout_seconds: ${AGENT_TIMEOUT_SECONDS} intent_classifier: model: ${AGENT_FAST_MODEL} temperature: 0 timeout_seconds: 20 embedding: model: ${EMBEDDING_MODEL} dimensions: ${EMBEDDING_DIMENSIONS} rag: top_k: ${RAG_TOP_K} min_score: ${RAG_MIN_SCORE} max_context_tokens: ${RAG_MAX_CONTEXT_TOKENS} mcp: server_url: ${MCP_SERVER_URL} connect_timeout_seconds: ${MCP_CONNECT_TIMEOUT_SECONDS} read_timeout_seconds: ${MCP_READ_TIMEOUT_SECONDS} ``` 配置边界: - API Key 只允许放在环境变量或密钥管理系统,不写入仓库。 - `AGENT_MAIN_MODEL`、`AGENT_FAST_MODEL`、`EMBEDDING_MODEL` 必须在启动日志中打印脱敏后的配置摘要,便于排查环境差异。 - 每次 Agent run 要把 `model_provider`、`model_name`、`prompt_version`、`rag_top_k`、`rag_min_score`、`token_usage` 写入审计日志。 - `EMBEDDING_DIMENSIONS` 必须与 `aftersales_policy_chunk.embedding VECTOR(...)` 一致,不一致时服务启动失败。 - 高风险工具不允许仅靠 prompt 约束,必须由 Java MCP Server 的风险等级和审批逻辑兜底。 - 生产环境模型变更必须跑 eval 数据集,确保意图判断、风险分级、审批触发和最终回复没有回归。 ## MCP 工具 首版工具清单: ```text query_charge_order(order_no | user_id | phone) query_charge_session(order_no) retrieve_aftersales_policy(issue_type, keywords) create_aftersales_work_order(order_no, issue_type, suggestion, evidence) request_refund(order_no, amount, reason, evidence) request_compensation(order_no, compensation_type, amount, reason) get_approval_status(approval_id) resume_after_approval(approval_id) write_agent_audit(trace_id, step, input, output, status) ``` 风险等级: ```text LOW: query_charge_order query_charge_session retrieve_aftersales_policy create_aftersales_work_order write_agent_audit HIGH: request_refund request_compensation resume_after_approval ``` 低风险工具可以直接执行。高风险工具不直接退款或补偿,而是由 Java 创建审批单和冻结动作,返回 `approval_required`。 ## 数据表 表按职责拆成两组: - Java 业务库:`agent_tool_registry`、`agent_approval`、`agent_pending_action`、`agent_audit_log`、`aftersales_work_order`。首版按 MySQL 设计,跟 `zsElectric-boot` 当前业务库一致。 - RAG 知识库:`aftersales_policy_doc`、`aftersales_policy_chunk`。首版按 PostgreSQL + pgvector 设计。Python FastAPI Agent 可以直接检索该知识库;Java MCP Server 也可以通过 `retrieve_aftersales_policy` 工具封装同一套检索能力。 核心关系: ```text agent_approval 1 -> 1 agent_pending_action agent_approval 1 -> n agent_audit_log agent_pending_action 1 -> n agent_audit_log aftersales_policy_doc 1 -> n aftersales_policy_chunk trace_id 贯穿 agent_approval、agent_pending_action、agent_audit_log、aftersales_work_order ``` ### agent_tool_registry 记录 Java MCP Server 可暴露工具的治理信息。工具必须先注册到该表,再进入白名单判断。 ```sql CREATE TABLE agent_tool_registry ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', tool_name VARCHAR(128) NOT NULL COMMENT 'MCP工具名', tool_version VARCHAR(32) NOT NULL DEFAULT 'v1' COMMENT '工具版本', description VARCHAR(512) NOT NULL COMMENT '工具说明', transport VARCHAR(32) NOT NULL DEFAULT 'mcp' COMMENT '工具传输协议', handler_bean VARCHAR(192) NOT NULL COMMENT 'Java处理器Bean或路由标识', risk_level VARCHAR(16) NOT NULL COMMENT '风险等级: LOW, MEDIUM, HIGH', enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用', require_approval TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否需要审批', idempotent TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否支持幂等', input_schema_json JSON NOT NULL COMMENT '输入参数JSON Schema', output_schema_json JSON NULL COMMENT '输出结果JSON Schema', allowed_roles JSON NULL COMMENT '允许调用的角色列表', sensitive_fields JSON NULL COMMENT '需要脱敏的字段列表', rate_limit_per_minute INT NOT NULL DEFAULT 60 COMMENT '单工具分钟限流', timeout_ms INT NOT NULL DEFAULT 10000 COMMENT '工具超时时间', remark VARCHAR(512) NULL COMMENT '备注', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', UNIQUE KEY uk_agent_tool_name_version (tool_name, tool_version), KEY idx_agent_tool_enabled_risk (enabled, risk_level), KEY idx_agent_tool_handler (handler_bean) ) COMMENT='Agent MCP工具注册表'; ``` 首版工具注册示例: ```text query_charge_order: LOW, require_approval=false query_charge_session: LOW, require_approval=false retrieve_aftersales_policy: LOW, require_approval=false create_aftersales_work_order: LOW, require_approval=false request_refund: HIGH, require_approval=true request_compensation: HIGH, require_approval=true resume_after_approval: HIGH, require_approval=false write_agent_audit: LOW, require_approval=false ``` ### agent_approval 记录高风险动作审批单。审批单只表达“是否允许执行”,不直接保存完整执行参数;完整执行参数保存在 `agent_pending_action`。 ```sql CREATE TABLE agent_approval ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', approval_id VARCHAR(64) NOT NULL COMMENT '审批ID,外部展示和恢复执行使用', trace_id VARCHAR(64) NOT NULL COMMENT 'Agent运行链路ID', pending_action_id BIGINT NULL COMMENT '关联冻结动作ID', biz_type VARCHAR(64) NOT NULL COMMENT '业务类型: refund, compensation', biz_no VARCHAR(128) NOT NULL COMMENT '业务编号,通常为订单号', risk_level VARCHAR(16) NOT NULL COMMENT '风险等级: HIGH', status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '状态: pending, approved, rejected, expired, executed', request_user_id BIGINT NULL COMMENT '发起用户ID', request_username VARCHAR(128) NULL COMMENT '发起用户名', request_reason VARCHAR(1024) NOT NULL COMMENT '申请原因', risk_reason VARCHAR(1024) NULL COMMENT '命中高风险的原因', policy_evidence_json JSON NULL COMMENT '政策依据和RAG命中证据', requested_amount DECIMAL(10,2) NULL COMMENT '申请退款或补偿金额', approver_id BIGINT NULL COMMENT '审批人ID', approver_username VARCHAR(128) NULL COMMENT '审批人名称', decision_comment VARCHAR(1024) NULL COMMENT '审批意见', decision_time DATETIME NULL COMMENT '审批时间', expires_at DATETIME NOT NULL COMMENT '审批过期时间', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本', deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', UNIQUE KEY uk_agent_approval_id (approval_id), KEY idx_agent_approval_trace (trace_id), KEY idx_agent_approval_status_time (status, create_time), KEY idx_agent_approval_request_user (request_user_id, status), KEY idx_agent_approval_biz (biz_type, biz_no) ) COMMENT='Agent高风险动作审批表'; ``` 状态流转: ```text pending -> approved -> executed pending -> rejected pending -> expired ``` `approved` 只表示审批通过。真实退款或补偿必须由 `resume_after_approval(approval_id)` 根据冻结动作执行,执行成功后再把审批单标记为 `executed`。 ### agent_pending_action 记录审批通过后要恢复执行的冻结动作。审批前后的执行参数必须保持一致,不能让模型在审批后重新生成参数。 ```sql CREATE TABLE agent_pending_action ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', action_id VARCHAR(64) NOT NULL COMMENT '冻结动作ID', approval_id VARCHAR(64) NOT NULL COMMENT '关联审批ID', trace_id VARCHAR(64) NOT NULL COMMENT 'Agent运行链路ID', tool_name VARCHAR(128) NOT NULL COMMENT '待执行MCP工具名', tool_version VARCHAR(32) NOT NULL DEFAULT 'v1' COMMENT '工具版本', risk_level VARCHAR(16) NOT NULL COMMENT '风险等级', params_json JSON NOT NULL COMMENT '冻结后的工具参数', params_hash CHAR(64) NOT NULL COMMENT '参数SHA-256摘要,防篡改', idempotency_key VARCHAR(128) NOT NULL COMMENT '幂等键', execute_status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '执行状态: pending, executing, executed, failed, expired, rejected', execute_result_json JSON NULL COMMENT '执行结果', error_message TEXT NULL COMMENT '失败原因', retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数', executed_at DATETIME NULL COMMENT '执行完成时间', expires_at DATETIME NOT NULL COMMENT '冻结动作过期时间', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本', deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', UNIQUE KEY uk_agent_action_id (action_id), UNIQUE KEY uk_agent_action_idempotency (idempotency_key), KEY idx_agent_action_approval (approval_id), KEY idx_agent_action_trace (trace_id), KEY idx_agent_action_status_time (execute_status, create_time), KEY idx_agent_action_tool (tool_name, tool_version) ) COMMENT='Agent审批后待恢复执行动作表'; ``` 恢复执行校验顺序: ```text approval_id 存在 -> approval.status = approved -> pending_action.execute_status = pending -> 当前时间未超过 expires_at -> tool_name 仍在 agent_tool_registry 白名单且启用 -> params_hash 与 params_json 重算结果一致 -> idempotency_key 未执行过 -> 执行业务工具 -> 更新 execute_status、execute_result_json、agent_approval.status -> 写 agent_audit_log ``` ### agent_audit_log 记录 Agent 全链路审计。审计表只追加,不更新业务含义,用于追踪、排障和责任回溯。 ```sql CREATE TABLE agent_audit_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', trace_id VARCHAR(64) NOT NULL COMMENT 'Agent运行链路ID', span_id VARCHAR(64) NULL COMMENT '步骤Span ID', parent_span_id VARCHAR(64) NULL COMMENT '父级Span ID', approval_id VARCHAR(64) NULL COMMENT '关联审批ID', pending_action_id VARCHAR(64) NULL COMMENT '关联冻结动作ID', actor_type VARCHAR(32) NOT NULL COMMENT '操作者类型: user, agent, system, approver', actor_id VARCHAR(64) NULL COMMENT '操作者ID', actor_name VARCHAR(128) NULL COMMENT '操作者名称', step VARCHAR(64) NOT NULL COMMENT '步骤: user_input, intent_detected, rag_retrieved, tool_called, approval_created, approval_decided, action_resumed, final_answer', event_type VARCHAR(64) NOT NULL COMMENT '事件类型', tool_name VARCHAR(128) NULL COMMENT '工具名', risk_level VARCHAR(16) NULL COMMENT '风险等级', model_provider VARCHAR(64) NULL COMMENT '模型供应商,如openai', model_name VARCHAR(128) NULL COMMENT '实际调用模型名', prompt_version VARCHAR(64) NULL COMMENT 'Prompt版本', token_usage_json JSON NULL COMMENT 'Token用量', input_json JSON NULL COMMENT '输入快照,敏感字段脱敏后保存', output_json JSON NULL COMMENT '输出快照,敏感字段脱敏后保存', status VARCHAR(32) NOT NULL COMMENT '状态: success, failed, pending, skipped', error_message TEXT NULL COMMENT '错误信息', duration_ms BIGINT NULL COMMENT '步骤耗时毫秒', ip_address VARCHAR(64) NULL COMMENT '客户端IP', user_agent VARCHAR(512) NULL COMMENT '客户端User-Agent', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', KEY idx_agent_audit_trace_time (trace_id, create_time), KEY idx_agent_audit_approval (approval_id), KEY idx_agent_audit_action (pending_action_id), KEY idx_agent_audit_tool_time (tool_name, create_time), KEY idx_agent_audit_model_time (model_name, create_time), KEY idx_agent_audit_status_time (status, create_time) ) COMMENT='Agent全链路审计日志表'; ``` 审计步骤包括用户输入、LLM 配置快照、意图判断、RAG 命中文档、工具调用、审批创建、审批结果、恢复执行和最终回复。 ### aftersales_work_order 记录低风险售后自动建单结果,也可以承接高风险审批后的售后处理记录。 ```sql CREATE TABLE aftersales_work_order ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', work_order_no VARCHAR(64) NOT NULL COMMENT '售后工单号', trace_id VARCHAR(64) NOT NULL COMMENT 'Agent运行链路ID', order_no VARCHAR(128) NOT NULL COMMENT '充电订单号', charge_record_id BIGINT NULL COMMENT '充电记录ID', user_id BIGINT NULL COMMENT '用户ID', phone_masked VARCHAR(64) NULL COMMENT '脱敏手机号', issue_type VARCHAR(64) NOT NULL COMMENT '问题类型: charge_failed, payment_issue, refund_request, compensation_request', issue_level VARCHAR(16) NOT NULL DEFAULT 'normal' COMMENT '问题等级: normal, urgent', source VARCHAR(32) NOT NULL DEFAULT 'agent' COMMENT '来源: agent, manual, third_party', suggestion TEXT NOT NULL COMMENT 'Agent处理建议', policy_evidence_json JSON NULL COMMENT '政策依据和RAG命中证据', order_snapshot_json JSON NULL COMMENT '订单和充电记录快照', status VARCHAR(32) NOT NULL DEFAULT 'created' COMMENT '状态: created, processing, resolved, closed, canceled', created_by_agent TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否Agent创建', created_by VARCHAR(64) NULL COMMENT '创建人', assigned_to VARCHAR(64) NULL COMMENT '处理人', resolve_result TEXT NULL COMMENT '处理结果', closed_at DATETIME NULL COMMENT '关闭时间', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', UNIQUE KEY uk_aftersales_work_order_no (work_order_no), KEY idx_aftersales_order_no (order_no), KEY idx_aftersales_trace (trace_id), KEY idx_aftersales_status_time (status, create_time), KEY idx_aftersales_issue_type (issue_type, create_time) ) COMMENT='售后工单表'; ``` ### aftersales_policy_doc / aftersales_policy_chunk `aftersales_policy_doc` 保存政策原文和版本,`aftersales_policy_chunk` 保存分片文本、embedding 和元数据,用于 pgvector 检索。 ```sql CREATE TABLE aftersales_policy_doc ( id BIGSERIAL PRIMARY KEY, doc_code VARCHAR(64) NOT NULL, title VARCHAR(256) NOT NULL, category VARCHAR(64) NOT NULL, issue_type VARCHAR(64) NOT NULL, version VARCHAR(32) NOT NULL, content TEXT NOT NULL, content_hash CHAR(64) NOT NULL, source_type VARCHAR(32) NOT NULL DEFAULT 'manual', source_uri VARCHAR(512), effective_at TIMESTAMPTZ, expired_at TIMESTAMPTZ, enabled BOOLEAN NOT NULL DEFAULT TRUE, metadata JSONB, create_time TIMESTAMPTZ NOT NULL DEFAULT now(), update_time TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (doc_code, version) ); CREATE INDEX idx_policy_doc_issue_enabled ON aftersales_policy_doc (issue_type, enabled); CREATE INDEX idx_policy_doc_category ON aftersales_policy_doc (category); ``` ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE aftersales_policy_chunk ( id BIGSERIAL PRIMARY KEY, doc_id BIGINT NOT NULL REFERENCES aftersales_policy_doc(id), chunk_no INT NOT NULL, chunk_text TEXT NOT NULL, token_count INT, embedding VECTOR(1536) NOT NULL, content_hash CHAR(64) NOT NULL, issue_type VARCHAR(64) NOT NULL, metadata JSONB, enabled BOOLEAN NOT NULL DEFAULT TRUE, create_time TIMESTAMPTZ NOT NULL DEFAULT now(), update_time TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (doc_id, chunk_no) ); CREATE INDEX idx_policy_chunk_doc ON aftersales_policy_chunk (doc_id); CREATE INDEX idx_policy_chunk_issue_enabled ON aftersales_policy_chunk (issue_type, enabled); CREATE INDEX idx_policy_chunk_metadata ON aftersales_policy_chunk USING GIN (metadata); CREATE INDEX idx_policy_chunk_embedding ON aftersales_policy_chunk USING hnsw (embedding vector_cosine_ops); ``` `VECTOR(1536)` 是首版 embedding 维度约定,后续如果更换 embedding 模型,必须同步迁移分片表维度并重建向量索引。 ## 主流程 低风险流程: ```text 1. FastAPI /chat 接收用户问题,生成 trace_id 2. Agent 判断意图,例如“充电失败咨询” 3. Agent 通过 RAG 检索售后政策 4. Agent 通过 MCP 调 query_charge_order 和 query_charge_session 5. Agent 生成处理建议 6. Agent 通过 MCP 调 create_aftersales_work_order 7. Java 创建工单并写 audit_log 8. FastAPI 返回建议、工单号、trace_id ``` 高风险流程: ```text 1. FastAPI /chat 接收用户问题,生成 trace_id 2. Agent 判断意图,例如“充电失败要求退款” 3. Agent 检索政策并查询订单、充电记录 4. Agent 判断需要退款或补偿 5. Agent 通过 MCP 调 request_refund 或 request_compensation 6. Java 判断为 HIGH 风险,创建 agent_approval 7. Java 创建 agent_pending_action,冻结 tool_name 和 params_json 8. Java 返回 approval_required、approval_id、建议说明 9. 人在 Swagger/Postman 调 Java 审批接口 approve 或 reject 10. FastAPI /resume/{approval_id} 调 MCP resume_after_approval 11. Java 校验审批和 pending_action,执行真实退款或补偿 12. Java 写 audit_log 并返回工具结果 13. Agent 生成最终客服回复 ``` ## Java 审批接口 审批演示接口放在 Java: ```text GET /api/v1/agent/approvals GET /api/v1/agent/approvals/{approval_id} POST /api/v1/agent/approvals/{approval_id}/approve POST /api/v1/agent/approvals/{approval_id}/reject ``` 审批通过只改变审批状态,不直接执行退款或补偿。真实执行由 `resume_after_approval(approval_id)` 触发,保证“审批”和“执行恢复”边界清楚。 ## 错误处理 ```text RAG 无命中: 返回“政策依据不足”,只允许生成建议,不允许自动退款或补偿。 订单不存在: 停止工具链路,写 audit_log,返回需要人工核查。 MCP 工具失败: 记录 trace_id、tool_name、input、error,不让 Agent 猜测执行结果。 审批过期: pending_action 标记 expired,需要重新发起申请。 审批拒绝: resume_after_approval 返回 rejected,Agent 生成拒绝后的客服回复。 参数被篡改: params_hash 校验失败,拒绝执行并写高危审计。 重复恢复: pending_action 已执行则返回历史结果,保证幂等。 ``` ## 测试 Java 测试: - 工具白名单测试。 - 高低风险分级测试。 - approval 和 pending_action 落库测试。 - approve/reject 状态流转测试。 - resume_after_approval 幂等测试。 - params_hash 篡改保护测试。 - audit_log 写入测试。 Python FastAPI 测试: - `/chat` 低风险自动建工单。 - `/chat` 高风险返回 `approval_required`。 - `/resume/{approval_id}` 审批后恢复执行。 - MCP client 工具调用失败。 - RAG 无命中降级。 - LLM 配置加载、默认模型、快速模型、embedding 维度一致性测试。 - 模型变更后的 eval 数据集回归测试。 集成演示: - 充电失败但只需普通售后处理,自动建工单。 - 充电失败要求退款,进入审批。 - 审批通过,resume 后执行退款或补偿。 - 审批拒绝,Agent 生成拒绝说明。 - 通过 trace_id 查询完整审计链路。 ## 里程碑 ### M1 Java MCP Server 与治理表 交付 MCP endpoint、tool registry、approval、pending_action、audit_log,以及基础售后政策表。 ### M2 Python FastAPI Agent 交付 FastAPI 服务、OpenAI Agents SDK agent、LLM 配置管理、MCP client、基础 RAG 检索、`/chat` 和 `/resume`。 ### M3 售后业务闭环 交付订单查询、充电记录查询、政策检索、工单创建、退款/补偿审批和审批恢复。 ### M4 验证与演示 交付种子数据、Swagger/Postman 脚本、eval case、README 跑通文档。 ## 验收标准 - Python 服务不直连 Java 业务数据库。 - Java 只暴露白名单 MCP tools,不把全部业务接口自动暴露给模型。 - 低风险售后问题可以自动创建工单。 - 高风险退款或补偿必须产生审批单和冻结动作。 - 审批通过后可以按 `approval_id` 恢复执行。 - 审批拒绝、审批过期、重复恢复、参数篡改都有确定结果。 - 每次 Agent 运行都能通过 `trace_id` 查到完整审计链路。 - 每次 Agent 运行都能在审计日志中看到实际模型、prompt 版本、RAG 参数和 token 用量。 - Embedding 模型维度与 pgvector 表结构不一致时,Python 服务启动失败。 - 项目文档能解释 RAG、MCP Tool Calling、权限、审批、状态恢复、审计和测试案例。