构建一个面向充电业务售后场景的企业 Agent 项目。用户描述问题后,Agent 能判断售后意图,检索售后政策,查询充电订单和充电记录,生成处理建议。低风险动作自动创建售后工单,高风险退款或补偿进入审批,审批后按冻结动作恢复执行,并记录全链路审计。
首版目标不是做普通聊天机器人,而是做一个受控的企业执行者:能查、能建议、能调用工具,但高风险动作必须可审批、可恢复、可追责。
首版采用双服务垂直切片:
zsElectric-boot:企业业务系统和 MCP Server,负责业务工具、审批、冻结动作、审计、售后政策和数据库。zsElectric-agent-service:独立兄弟服务,使用 FastAPI 作为服务框架,使用 OpenAI Agents SDK 作为 Agent 编排层,作为 MCP Client 调用 Java MCP Server。不在首版范围内:
用户
-> 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。
在 zsElectric-boot 中新增 platform.agent 模块:
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。
在兄弟目录创建 E:\wzq\workCode\zswl\zsElectric-agent-service:
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 接口:
POST /api/v1/agent/chat
POST /api/v1/agent/resume/{approval_id}
GET /api/v1/agent/runs/{trace_id}
GET /health
首版工具清单:
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)
风险等级:
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。
表按职责拆成两组:
agent_tool_registry、agent_approval、agent_pending_action、agent_audit_log、aftersales_work_order。首版按 MySQL 设计,跟 zsElectric-boot 当前业务库一致。aftersales_policy_doc、aftersales_policy_chunk。首版按 PostgreSQL + pgvector 设计。Python FastAPI Agent 可以直接检索该知识库;Java MCP Server 也可以通过 retrieve_aftersales_policy 工具封装同一套检索能力。核心关系:
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
记录 Java MCP Server 可暴露工具的治理信息。工具必须先注册到该表,再进入白名单判断。
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工具注册表';
首版工具注册示例:
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_pending_action。
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高风险动作审批表';
状态流转:
pending -> approved -> executed
pending -> rejected
pending -> expired
approved 只表示审批通过。真实退款或补偿必须由 resume_after_approval(approval_id) 根据冻结动作执行,执行成功后再把审批单标记为 executed。
记录审批通过后要恢复执行的冻结动作。审批前后的执行参数必须保持一致,不能让模型在审批后重新生成参数。
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审批后待恢复执行动作表';
恢复执行校验顺序:
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 全链路审计。审计表只追加,不更新业务含义,用于追踪、排障和责任回溯。
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 '风险等级',
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_status_time (status, create_time)
) COMMENT='Agent全链路审计日志表';
审计步骤包括用户输入、意图判断、RAG 命中文档、工具调用、审批创建、审批结果、恢复执行和最终回复。
记录低风险售后自动建单结果,也可以承接高风险审批后的售后处理记录。
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 保存分片文本、embedding 和元数据,用于 pgvector 检索。
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);
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 模型,必须同步迁移分片表维度并重建向量索引。
低风险流程:
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
高风险流程:
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:
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) 触发,保证“审批”和“执行恢复”边界清楚。
RAG 无命中:
返回“政策依据不足”,只允许生成建议,不允许自动退款或补偿。
订单不存在:
停止工具链路,写 audit_log,返回需要人工核查。
MCP 工具失败:
记录 trace_id、tool_name、input、error,不让 Agent 猜测执行结果。
审批过期:
pending_action 标记 expired,需要重新发起申请。
审批拒绝:
resume_after_approval 返回 rejected,Agent 生成拒绝后的客服回复。
参数被篡改:
params_hash 校验失败,拒绝执行并写高危审计。
重复恢复:
pending_action 已执行则返回历史结果,保证幂等。
Java 测试:
Python FastAPI 测试:
/chat 低风险自动建工单。/chat 高风险返回 approval_required。/resume/{approval_id} 审批后恢复执行。集成演示:
交付 MCP endpoint、tool registry、approval、pending_action、audit_log,以及基础售后政策表。
交付 FastAPI 服务、OpenAI Agents SDK agent、MCP client、基础 RAG 检索、/chat 和 /resume。
交付订单查询、充电记录查询、政策检索、工单创建、退款/补偿审批和审批恢复。
交付种子数据、Swagger/Postman 脚本、eval case、README 跑通文档。
approval_id 恢复执行。trace_id 查到完整审计链路。