怎样把企业售后 Agent 做成可验收的工单闭环

怎样把企业售后 Agent 做成可验收的工单闭环
Asaakii企业售后系统里的模型可以归类工单、检索政策、起草回复,也能把一句未执行的“已退款”写得像真的。后者不是语言问题,而是系统没有把事实、权限和业务动作分开。
一套能用于售后流程的 Agent,需要明确谁可以看数据、哪些知识仍然有效、什么情况必须停下来等人、发生问题后怎样还原过程。模型只负责其中一段:根据受限上下文给出建议。它不能凭生成的文字获得退款、外发消息或改订单的权限。
本文以 Wmengti/enterprise-ai-after-sales-service-platform 为样本,结合 pangmadee 对该系列的阶段复盘,梳理一套售后工单 AI 工作台的设计方法。仓库包含源码、合成夹具、任务书和阶段证据。下文说的“仓库实现”,都指当前 main 分支可读到的代码和文档,不表示我已在真实客户数据或公网环境中复验过它。仓库也明确把成果定为本地 L0 Demo,尚不是生产系统。
一、先界定第一版要处理什么
“做一个企业客服 Agent”不算完整需求。它可能是聊天机器人、工单分流、知识问答、退款审批、外呼、质检,也可能想成为 CRM 的总入口。第一版把这些全塞进去,往往只会得到一个展示效果不错、责任边界却说不清的页面。
仓库的第一版把问题压缩为“企业售后工单 AI 工作台”。它选择了一个很具体的闭环:
1 | 登录 |
它刻意不做真实退款、改订单、支付、对客户外发消息、自由注册、复杂多租户和“模型直接访问数据库”。这一点写在 D00 总任务书 里,也和源码中的合成数据边界一致。
第一版的重点是把责任链补齐。比起“接了多少模型”,更该先回答下面这些问题:
- 谁能看到这张工单?
- 模型看到了哪些数据,哪些数据没有给它?
- 它的每一个引用是否来自这一轮允许的知识?
- 它的草稿和客服最终发出的版本能否区分?
- 它说“已退款”“已补发”时,系统如何拒绝?
- 模型、Prompt 或知识库改动后,怎样发现一个原本正确的案例变差了?
这些问题没有答案时,生成得越快,未经证实的判断就越容易被带到客户面前。
二、先按责任拆系统,再决定是否需要多个 Agent
有些架构图把系统分成“协调 Agent、检索 Agent、回复 Agent、审核 Agent、执行 Agent”。名称很多不代表控制更严。权限判断、状态流转和写入条件原本可以由代码确定,交给模型猜反而增加了不确定性。
先按责任划分,模型角色放在最后考虑。
flowchart LR
U["客服 / 主管 / 管理员"] --> W["工单工作台"]
W --> A["服务端鉴权\n资源范围与写入规则"]
A --> T["工单与订单摘要"]
A --> R["知识检索\n有效版本、权限、白名单"]
R --> M["模型适配层\n结构化建议"]
M --> V["服务端校验\n引用、风险、完成性表述"]
V --> H{"需要人工确认?"}
H -->|"是"| P["编辑 / 确认 / 拒绝 / 转人工"]
H -->|"否"| D["受限保存"]
P --> D
D --> L["审计、追溯、固定评测"]
图中只有“模型适配层”需要调用模型。其余环节主要由普通程序和数据库约束:
| 责任 | 应由谁决定 | 失败时的正确行为 |
|---|---|---|
| 身份、角色和资源范围 | 服务端策略 | 拒绝,不透露资源是否存在 |
| 当前可用知识 | 知识版本状态和检索逻辑 | 无可靠来源时不给模型伪装答案 |
| 分类、草稿、下一步建议 | 模型在受限上下文中提出 | 结构不合法时进入降级或人工处理 |
| 退款、换货、外发等业务执行 | 明确授权的业务系统和人 | 模型不得声称已完成 |
| 风险升级、最终确认 | 服务端规则加人工责任 | 暂停、拒绝或转人工 |
| 审计与评测 | 不可随意改写的记录和固定案例 | 保留失败,不用“总分不错”掩盖退步 |
Human-in-the-loop 也不等于在结果旁放一个“确认”按钮。人工确认应是一条状态迁移:记录确认人、时间、AI 原稿、人工终稿、拒绝或转人工的理由,并关联工单版本与 AI 运行记录。少了这些信息,出现争议时很难还原最后的决定由谁作出。
三、先画工单状态,再写 Prompt
不少原型先写提示词,把客户问题和知识库交给模型,再要求它“专业地回答”。但模型输出只是一瞬间,售后处理有完整的前后状态。
仓库的 Prisma Schema 把两类状态分开:工单状态包括 OPEN、IN_PROGRESS、WAIT_CONFIRM、ESCALATED、COMPLETED;AI 运行状态则包括 RUNNING、WAIT_CONFIRM、FAILED、FALLBACK、HUMAN_HANDOFF、COMPLETED 等。数据模型 中还有 version 字段,用来处理写入冲突。
简化后,状态关系如下:
stateDiagram-v2 [*] --> OPEN OPEN --> IN_PROGRESS: 客服领取 / 开始处理 IN_PROGRESS --> AI_RUNNING: 请求建议 AI_RUNNING --> WAIT_CONFIRM: 有可靠建议且需审批 AI_RUNNING --> IN_PROGRESS: 无来源 / 校验失败 / 降级 WAIT_CONFIRM --> COMPLETED: 人工确认终稿 WAIT_CONFIRM --> IN_PROGRESS: 拒绝并补充信息 WAIT_CONFIRM --> ESCALATED: 转人工队列 IN_PROGRESS --> ESCALATED: 超出授权或风险升级 ESCALATED --> [*] COMPLETED --> [*]
状态名可以调整,边的守卫条件不能含糊。AI_RUNNING → WAIT_CONFIRM 不应只因为“模型返回了文字”就发生,至少还要满足:
- 输出能被解析为既定的结构;
- 所有引用都在本轮检索结果白名单中;
- 没有把未执行的操作说成已经完成;
- 风险等级经过服务端规则复核;
- 当前用户确实有权访问这张工单和相关知识。
权限不能只靠前端隐藏菜单。仓库的 授权测试 检查了未登录返回 401、不同角色得到 200/403/404、伪造 role=admin 或请求头不能提权,以及受保护资源对无权限用户不暴露。测试不能覆盖现实世界中的全部安全问题,但它把权限检查放在了正确的位置:服务端。
3.1 乐观并发不是“技术细节”
设想两个客服同时打开一张工单。A 依据旧信息确认了 AI 草稿;B 刚刚补充了客户的新地址和新描述。如果 A 的保存无条件覆盖 B,系统就制造了一个客服自己也未必发现的数据错误。
最小接口契约应带上期望版本:
1 | type ConfirmDraftRequest = { |
服务端在事务里做条件更新:只有数据库中的 version === expectedVersion 才写入,并将版本加一。若更新条数为 0,就返回冲突,让客服刷新后再处理。模型不该决定怎样合并冲突,这需要了解业务语义的人来判断。
四、RAG 的起点是“哪一版知识可以被引用”
售后系统常把 RAG 理解为“上传几个 PDF,再做向量检索”。问题是知识不是静态文件。
退换货规则会更新,特殊时期政策可能停用,型号故障说明也会更正。模型引用旧版本时,回复写得再流畅也会得出错误结论。知识对象至少要有这些字段:
1 | document_id 文档身份,例如退换货政策 |
仓库的夹具包含同一政策的停用版本和有效版本,任务书要求“停用知识不进入新的检索”。它的 selected-retrieval.ts 不只按向量分数排序,还计算词法覆盖、实体匹配、敏感凭据问题的规则加分、阈值过滤,并最多保留三条结果。实现代码 传达的原则很直接:检索策略可以变,但每个入选片段都要能追溯来源。
4.1 给引用设白名单
把检索结果放进 Prompt,再写一句“请引用资料”,不能保证模型只引用这些资料。它可能编造一个很像内部文档编号的来源,也可能按训练记忆补出并不存在的规则。
更可靠的做法是让代码先生成白名单:
1 | const retrieved = await retrieveAuthorizedKnowledge({ |
模型返回后,服务端直接做集合校验:
1 | const invalid = suggestion.sources.filter( |
仓库的 validateAiSuggestion 采用了这类校验:输出必须是固定 JSON,引用必须属于本轮允许来源;没有可靠来源会被拒绝;“已经退款到账”“已补发并寄出”一类完成性业务描述也会被拒绝。产品质量类工单或命中风险词时,服务端会把风险升为高风险并要求人工确认。
这不是防止模型胡说的万能办法。规则词表仍会漏判或误判,真实业务操作也要由后端系统确认。不过它把原本只能靠提示词约束的问题,变成了可以写进单元测试的规则。
4.2 不命中是正常结果,不要拿旧片段凑答案
检索系统不该无论问题是什么都返回 Top 3。排序总会给出前三条,但不代表这些内容足以回答。政策已停用、客户问的是新型号,或问题缺少订单信息时,正确结果可以是“没有可靠来源”。
这时系统可以做三件事:
- 告诉客服缺的是订单号、产品型号还是地区信息;
- 允许客服补充信息后再次检索;
- 转给有权限的人处理,并把“知识缺口”记录下来。
不要让模型用相邻知识拼出一个看似合理的确定答案。售后回复要能被政策、订单和操作记录支持。
五、模型返回的是建议对象
API 直接返回一段 Markdown 时,前端很好展示,系统却很难判断分类、风险、依据和是否需要人工确认。再从自然语言里抽取这些字段,可靠性只会更差。
更适合业务系统的方式是要求模型生成受约束的对象,例如:
1 | { |
结构化输出让前端可以分别展示草稿、引用、风险和下一步;服务端可以校验枚举值、长度、来源与风险规则;评测也能落到字段级,例如引用是否正确、是否漏判高风险,而不是凭印象评价整段文字。
仓库的 AI 校验器限制了来源、风险、下一步数组和草稿长度,解析失败时返回 STRUCTURE_INVALID。没有可靠来源时,它返回明确的人工核验建议,而不会编出一个“安全答案”。
模型供应商应被隔在适配层后。业务层只依赖 generateSuggestion(input),适配层才处理 DeepSeek 或其他供应商的请求格式、流式事件、超时、重试和错误码。更换模型、做 A/B 对比或冻结版本时,业务状态机不必重写。
六、人工确认要保留原稿与终稿
客服会补充客户刚提供的信息,删去过度承诺,调整语气,也可能发现模型分错了类。系统如果只保存最终发出的文本,后续就不知道 AI 当时建议了什么,也不知道人工为什么改动。
一个足够小但完整的确认记录可以是:
1 | confirmation_id |
这些字段用于回答维护中绕不开的问题:
- 某条不当回复来自模型原稿,还是人工编辑?
- 哪些知识片段最常被人工改写,是否过期或表达不清?
- 新 Prompt 让“确认率”上升,是质量真的提升,还是客服放松了审查?
- 一次投诉发生时,能否重建当时的模型、知识和人工决策上下文?
仓库的 D06/D08 文档和数据模型围绕原稿、终稿、确认动作与追溯关系组织。完整追溯记录 展示了合成工单上的运行记录、来源元数据、高风险确认、终稿、审计与评测如何关联。它没有接通真实外发或退款渠道,文章也不把这部分写成已实现能力。
6.1 哪些动作必须停下来等人?
不要指望一条很长的“高风险 Prompt”覆盖所有场景。业务和安全团队应维护清晰、可更新的风险清单。第一版可以从下表起步:
| 场景 | 模型能做什么 | 必须由谁确认 |
|---|---|---|
| 常见使用说明 | 给出有来源的草稿 | 客服确认后发送,或按制度自动化 |
| 退换货、补偿、发票 | 提示适用规则与所缺信息 | 有相应授权的客服或主管 |
| 产品冒烟、发烫、破损 | 给出安全提示与转交建议 | 主管 / 专项安全流程 |
| 要求验证码、密码、银行卡、身份证 | 拒绝索取并提示正规渠道 | 不应由模型继续推进 |
| 改地址、补发、退款、对外发送 | 只能提出待执行建议 | 已授权业务系统与人工 |
这不是通用合规清单。不同地区、行业和公司有不同政策,应由实际业务负责人维护。模型可以总结证据并提出建议,但不能凭一段生成文本获得更高权限。
七、审计记录要能还原一次处理
客服问“这条建议为什么出现”时,单独存一段请求日志不够。需要能串起谁读取了什么、系统检索到什么、模型用了什么版本、校验是否放行、人工做了什么,以及结果落在哪张工单上。
建议为每次请求生成 request_id,每次模型运行生成 run_id,并让它们贯穿:
1 | request_id |
审计不等于把所有数据写进日志。客户正文、联系方式、Cookie、口令和完整模型上下文都可能含有敏感信息。审计只应保留复核决策所需的最小元数据,对敏感字段脱敏、分级访问,并规定保留期限。仓库的授权测试检查了会话只保存哈希、审计同时覆盖允许与拒绝结果、审计摘要不含密码或 token 等敏感字段。真实企业仍要按自己的数据分类和法律义务评审。
八、固定评测用来发现回归
“这次模型回答感觉更好”不能作为发布依据。模型、Prompt、嵌入模型、分块方式、检索阈值或知识库版本任意改一项,都可能让某些历史场景变差。
售后 Agent 的最小评测集不必从几千题开始。先做 30 到 100 个覆盖关键路径的合成案例,更容易维护。每个案例最好包含:
1 | case_id |
不要只看一个总分。至少分成四层:
| 层 | 问题 | 例子 |
|---|---|---|
| 检索 | 找到的依据对吗 | 新政策是否压过已停用旧政策 |
| 结构 | 输出能消费吗 | JSON、枚举、来源格式是否合法 |
| 安全 | 是否越权或漏判风险 | 是否把退款承诺为已到账 |
| 业务 | 建议是否有用 | 分类、优先级、下一步是否合理 |
仓库的 D07 运行比较 记录了一个很实际的结果:候选版本的总通过数更高,却有一个原本通过的案例退步。界面因此要显示 improved、regressed 和案例级失败原因,安全案例还要单独设门槛。只看百分比会掩盖这类退步。
发布门可以很简单:任一关键安全案例失败,就不自动通过;非关键业务案例可以保留待审查项,但要写清责任人和修复计划。模型有随机性不等于可以忽略失败。它要求记录模型参数、Prompt、知识快照和运行次数。
九、开发过程也要有验收关口
仓库没有让 AI 从一页需求直接跳到“生成完整网站”。它把开发拆为 D01 到 D10:工程与数据访问、登录与权限、工单、知识检索、AI 流式输出、人工复核、固定评测、审计管理、全链路验收、部署方案与模拟上线。每个阶段都要求任务书、自动测试、页面或后端证据、已知限制和人工冻结。
这个过程也适用于其他行业:
flowchart TD
A["定义业务目标与不做什么"] --> B["写接口、状态与验收契约"]
B --> C["AI 实现当前最小阶段"]
C --> D["自动测试 + 失败路径"]
D --> E["人工看页面、证据与限制"]
E --> F{"可接受?"}
F -->|"否"| G["补充约束、修复、记录失败"]
G --> C
F -->|"是"| H["冻结阶段产物"]
H --> I["进入下一阶段"]
“AI 执行,人做选择”不表示人只负责点确认。人负责范围、权限、风险阈值、接受标准,以及是否允许进入下一阶段;AI 可以查资料、生成候选实现、跑测试、整理证据。没有这些判断,AI 只会更快地产生不受约束的代码。
对于第一次做这类项目的团队,我建议按下面顺序开工:
- 写一页范围声明:目标用户、唯一主路径、明确不做的动作、成功与失败怎样判定。
- 画出工单和 AI 运行的状态机,并列出每条边的守卫条件。
- 定义角色到资源的权限矩阵,先写越权测试再写页面。
- 用合成、脱敏的数据搭建知识生命周期,保留停用和更新案例。
- 固定模型输出 schema,在服务端校验来源、风险和业务断言。
- 先实现人工确认、拒绝和转人工,再考虑自动发送。
- 建一组可重复运行的安全与业务评测案例,任何改动都跑比较。
- 最后再谈外部渠道、真实订单和部署,不要反过来。
十、先把仓库作为教学工程跑起来
仓库的 README 给出了本地流程:启动 PostgreSQL,复制环境文件,安装依赖,执行迁移,导入合成数据与知识,建立索引,然后分别启动 Web、API 和 Worker。README 中的默认账户也全部使用 .test 域名和统一演示口令环境变量。
可按 README 在本地运行:
1 | git clone https://github.com/Wmengti/enterprise-ai-after-sales-service-platform.git |
之后另开终端启动 npm run dev:api、npm run dev:web,需要后台任务时再运行 npm run dev:worker。没有配置模型密钥时,先检查权限、知识版本、失败和人工路径。真实模型验证需要在本地配置密钥,密钥不应提交进仓库。
“能在本地 production build 跑通”不等于“可以部署为企业生产服务”。仓库 D10 的交付审计明确写的是“已验证的 L0 本地 Demo,不是公网生产上线”。它没有完成云环境兼容性验证、线上备份恢复、告警和值班、SLA、企业 SSO、私有网络和真实客户数据治理。代码即使部署到公网,这些责任也不会自动补齐。
真正要走向生产,还需要单独立项解决:
- 身份接入、租户隔离、最小权限与权限审计;
- 真实订单、退款和消息渠道的幂等性、审批与回滚;
- 数据最小化、脱敏、保留与删除策略;
- 模型供应商、区域、数据使用条款与故障降级;
- 密钥管理、网络隔离、备份恢复演练、监控告警和事件响应;
- 负载、成本、限流、队列积压、模型超时及人工接管预案。
这些项目需要单独计划和验证。它们决定了错误回复、越权访问或数据损失发生后,由谁负责处理。
十一、用问题检查它是否能进入业务流程
准备下一次演示前,可以用下面十个问题反向验收:
- 无权限用户请求一张工单时,系统会不会泄露该工单是否存在?
- 知识文档停用后,新的 AI 运行还能不能引用它?
- 模型编出一个不存在的文档编号,服务端会怎么处理?
- 模型说“已经退款”,而业务系统没有执行退款,结果会是什么?
- 两人并发编辑同一工单,旧版本能否悄悄覆盖新版本?
- 高风险草稿被拒绝或转人工时,是否保存了原因和状态,而不是只消失?
- 能否定位一条最终回复对应的模型、Prompt、知识版本和人工确认人?
- 修改检索阈值后,能否知道哪个固定案例退步了?
- 模型超时、返回坏 JSON、检索没有结果时,客服还能否安全继续工作?
- 如果今天下线模型服务,哪些业务仍可运行,哪些必须明确转人工?
如果大部分问题只能回答“应该可以”,系统还不适合被称为企业 Agent。先把答案落实为接口契约、自动测试、审计字段和演练记录,再扩展能力。
结语
可靠的售后 Agent 应限制模型能看到的数据,也限制模型建议能进入哪些业务环节。授权、当前有效的知识和结构化输入约束前者;校验、人工确认、审计和评测约束后者。
这个仓库是一个教学样本。它从工单主路径出发,把权限、RAG、受约束生成、人工复核、回归评测和证据化开发连接起来。它没有证明自己已经能处理真实客户数据,更不是生产平台。它提供的启发很朴素:先设计停止条件、失败路径和责任人,再提高 Agent 的自主程度。
有了这些基础,再接入更多渠道、工具调用和模型,才是在扩展一条可以检查的业务闭环。









