客服收到一封退款邮件,系统需要读取订单、核对规则、判断是否缺少资料,再给出处理建议。这里既有语言理解,也有不能随意改变的业务条件。如果把整个过程写成“请妥善处理退款”,模型可能给出通顺的答复,却没有检查订单是否已经退款。
Embabel 为 JVM 应用提供组织这类工作的方式:把允许执行的动作、输入输出和完成条件写进程序,再用规划机制选择下一步。它可以与现有 Java、Kotlin 和 Spring 应用结合。本文按 2026 年 9 月 23 日官方仓库及指南说明概念,以退款工单作为设计示例,没有运行真实退款或模型调用。项目仓库
一封邮件进入系统以后,需要变成什么
先不要急着设计一个“全能客服 Agent”。可以把第一版输出限定为一份待人工审核的建议:订单是否找到、适用哪条规则、还缺什么信息,以及建议怎样回复。
输入中至少区分原始邮件与模型提取结果。原始邮件是证据,提取出来的订单号和诉求则可能有误。模型若把订单号少读一位,后续查询应返回未匹配状态,而不是寻找一个相似订单就继续处理。
接下来由确定性的查询动作读取订单,返回结构化事实,例如订单状态、金额和历史退款记录。再由规则判断哪些条件满足,哪些仍待核实。模型可以帮助解释复杂文本,但查询结果不应被改写成更符合它预期的事实。
最后形成建议对象,包含依据和缺失信息。这样即使流程暂时不能完成,系统仍能告诉客服具体卡在哪里。一个只含“建议退款”的字符串,很难支持后续审查。
Action、Condition 和 Goal 怎样落到业务里
可以把“提取订单线索”“查询订单”“检查退款条件”“生成回复草稿”看作不同动作。每个动作接收自己需要的输入,产生明确结果;条件决定某个动作何时可以执行,目标描述这一轮希望得到的最终结果。
在退款示例中,生成回复草稿不应要求退款已经实际执行。相反,执行退款应属于另一条经过授权的流程,必须拿到完整订单与批准信息。把两者混在同一个泛化动作里,就很难限制试验范围。

上图用于理解动作、状态与目标之间的关系。具体流程仍由你的领域对象与条件决定,图里有一条通向目标的路径,不代表业务上已经满足执行条件。
Embabel 默认采用 GOAP 思路进行规划,也支持其他策略。官方指南说明了根据当前状态选择动作、执行后再评估的过程。不同规划方式与动作内部的模型输出都会影响实际执行;使用前应确认具体模式。官方用户指南
类型能帮助表达条件,但不会替你核实事实
把结果命名为 ApprovedRefund,比到处传递普通字符串更容易表达用途,但类名本身不构成批准。构造这个对象之前,仍需实际检查金额、订单、权限与业务规则。
例如模型生成一个布尔字段 approved: true,不能直接把它转为可执行退款的对象。更合理的设计是让模型输出建议,再由应用根据规则与审核结果生成批准记录。批准记录关联目标订单和金额,后续动作执行前重新核对。
类型也有助于避免把缺失信息当成空字符串一路传下去。“订单不存在”“查询服务失败”“订单号尚未确认”是三种不同情况。它们需要不同下一步:补充资料、重试查询或报告错误。用一个统一的 null 表示,会迫使每个动作重新猜原因。
写设计说明时,可以给每种结果列一个真实形态的样本,但使用虚构订单与测试金额。先检查这些对象能否覆盖常见异常,再加入模型调用,比边调提示词边补数据结构更容易维护。
重新规划以后,也要知道哪些事已经做过
假设订单查询成功,规则服务临时失败,流程后来恢复。查询可以重做,已经发送的邮件或退款操作则不能随意重复。规划器知道可以选择哪些动作,外部系统仍需要自己的执行记录与去重机制。
可以为有副作用的动作保存业务标识与结果。重试前查明上一笔是否已经完成,超时也不能简单等同于失败。例如下游已经退款,但响应在网络中丢失,重新提交就可能产生重复处理风险。
需要等待人工意见时,把待审核内容保存下来,包括订单、金额、建议和依据。若后续订单状态变化,原来的审核结论是否仍有效,应重新判断。不能因为会话里曾出现“同意”,就永久允许对任何更新后的计划执行。
这些设计同样适用于文章发布、合同草稿或库存调整。Embabel 提供动作组织方式,业务上的唯一性、时效和权限仍要在实际接口中落实。
第一轮测试可以完全不用真实模型
先让“提取线索”返回预设的测试对象,让订单查询读取固定数据。这样能检查流程是否走到正确结果,而不受模型每次输出变化影响。
准备几种情况:订单可匹配且资料完整;订单号缺失;已经退款;规则服务失败;用户请求的金额超过允许范围。每种情况都先写出预期结果,再观察动作执行顺序与最终状态。若确定性样本都无法正确结束,就先修流程,不必靠提示词补救。
之后再把其中一个动作替换为真实模型,单独测试提取准确性。给它包含两个订单号、转发邮件、口语描述和不完整信息的样本,检查是否能保留不确定性。把模型质量与流程正确性分开测试,失败原因会清楚很多。
日志应记录动作名称、输入输出的必要摘要、耗时和失败类别。客服邮件与订单数据可能含个人信息,调试所需的记录不必等于把所有原文都复制到普通日志中。
同一份工单多次进入系统,也值得单独测试。用户可能重复发送邮件,客服可能点两次按钮,消息队列也可能重新投递。流程应能关联同一业务请求,并说明这是重新分析还是继续先前的处理。若确实允许重新分析,旧建议与新建议要能区分,审核人员才能知道自己批准的是哪一份。
模型或规则更新后,可以回放已经确认结果的工单样本。先比较提取出的字段和选择的动作,再比较回复文字,避免只看语言更流畅就认定新版本更好。对涉及金额的情况,保留预期值与计算过程;发现差异时,能定位到查询数据、规则版本或模型解释中的具体一步。
从官方模板开始,固定依赖再扩展
官方提供 Java 模板,适合作为查看依赖和项目结构的入口。采用时选择明确的提交或版本,核对 JDK、构建工具与模型配置,再按模板说明运行。本文不提供未编译过的注解骨架,避免把省略实现的示意代码误当成可直接执行的程序。Java 模板
需要特别留意文档路径中的 SNAPSHOT。它描述的是正在发展的版本,不能保证与你从依赖仓库取得的稳定包完全一致。遇到注解、方法或配置项不匹配时,先比对版本,而不是从不同年代的示例里拼出一套代码。
接入现有 Spring 应用时,优先复用已存在的查询和业务服务,通过小动作调用它们。不要把所有业务逻辑搬进提示词,也不必为了使用框架重写已有事务。应用中原来的权限检查和测试仍应继续发挥作用。
什么时候值得增加这层编排
如果任务只有一次文本分类,普通服务方法加一次模型调用可能已经足够。若任务存在多种前置条件、需要补充信息、会等待人工意见,或有多条可到达目标的路径,明确的动作与状态模型才更有帮助。
评估时可以比较同一项业务的两份实现说明:一份是普通流程代码,一份是 Embabel 动作与目标。看哪个更容易解释失败、增加新步骤和编写测试。框架本身并不自动减少复杂度;它需要与实际流程的结构匹配。
第一版能够稳定产出一份可核查的退款建议,就已经足以评估收益。等动作范围、失败恢复与审核方式都清楚以后,再决定是否让其中某些步骤自动执行。











