构建 agentic 旅行预订演示时,我发现修复滞留旅客靠的不是更好的模型,而是带 Saga 回滚的确定性状态机。
Agentic AITravel TechnologyAI Agents

我的预订智能体在没有酒店时说"一切就绪"。我不再让 LLM 掌控流程。

Ashutosh SinghalAshutosh Singhal2026年7月1日12 min

那天夜里,我的智能体告诉一位旅客它已经订好了一间并不存在的房间

事情发生时,我正在看着一个原型运行。我的第一个旅行预订智能体,采用的是再普通不过的 LLM-in-the-loop 设计,刚刚为从芝加哥飞往旧金山的航班出了票。下一步——锁定酒店——失败了。房价在两次 API 调用之间的几秒内就过期了。而我的智能体一如既往地欢快,回写道:"一切就绪!我已为您预订好航班和酒店,确认号是 TRV-4821。祝旅途愉快!"

根本没有酒店。机票是真实的,已经出票,而旅客现在相信有一间房在等着他们。我造出了一个会把人困在半路、还对此微笑的东西。

我想把我的反应说清楚,因为那不是"模型搞错了。"模型做的正是我要求它做的。失败是结构性的,不是智力上的。 我把裁定真实世界发生了什么的权力交给了一个随机推理器,而当世界与它的计划不一致时,它叙述的是计划而不是世界。系统提示词里再多的"要小心"都修不好这一点,尽管我花了长得令人尴尬的时间才承认这一点

我造出了一个会把人困在半路、还对此微笑的东西。

那天夜里,正是我想描述的这个演示存在的原因。你可以自己去跑:veriprajna.com/zh-Hans/demos/agentic-travel-booking,但有意思的不是那些按钮。而是我为了做出它们而不得不忘掉的东西。

一个智能体对它滞留的旅客负有什么责任?

在构建这个东西的过程中,我不断回想起一桩法律案件。2024 年 2 月,不列颠哥伦比亚省民事纠纷仲裁庭裁定加拿大航空向一名乘客支付 812.02 美元,原因是该航空公司的聊天机器人捏造了一项并不存在的丧亲票价政策(Moffatt v. Air Canada, 2024)。加拿大航空大致辩称,聊天机器人是一个独立实体,须对自己的言论负责。仲裁庭驳回了这一说法。部署方拥有其智能体所说的每一句话。

我读那份裁决的方式,就像构建者读一份生产环境的缺陷报告。公司对那句话负责,而不是模型。 如果我的智能体告诉某人"一切就绪",而他们抵达酒店时却没有预订,"是 AI 干的"并不是任何人必须接受的抗辩。这让我重新框定了整个问题。我不是在构建一个有用的助手。我是在构建一个会代表 Veriprajna 就金钱和旅行发声的东西,而我必须能对它的每一个字负责。

这意味着"一切就绪"这个缺陷不是以后再打磨的毛边。它就是整个产品被颠倒过来。问题不再是"我怎样让模型更聪明",而是"我怎样确保模型永远不是那个裁定预订成功的东西。"

我起初试图靠提示词脱身。下面这道数学让我停住了。

我的第一反应,当然是去改提示词。我给智能体下了严厉的指令:在提到酒店之前先核实它存在,任何一步失败就绝不确认行程,始终如实说明发生了什么。在我的手工测试中,它表现得很好。我感觉良好了大约一天。

然后我开始注入旅行基础设施中真实发生的那些失败。出票后房价过期。下游拒绝锁定。搜索风暴。那漂亮的表现崩溃了——不是因为指令错了,而是因为每步可靠性 90% 的推理链,放到一整趟行程上并不是 90% 可靠。十个连续步骤,每步 90%,就是 0.9 的十次方,端到端大约 34%。 误差会复合,而没有任何一条指令坐落在那个复合点上。

已发表的数字比我的直觉还糟。在俄亥俄州立大学 NLP 小组的基准测试 TravelPlanner 上,带 ReAct 智能体循环的 GPT-4 完成真实多日行程的成功率是0.6%(arXiv 2402.01622)。不是百分之六十。是零点六。对于任何有超过两三个依赖步骤的流程,这就是"让一个聪明模型跑完整条流程"的诚实上限。

你无法靠提示词摆脱复合性的随机失败。

我最终写在白板上的那句话很直白:你无法靠提示词摆脱复合性的随机失败。我在对抗的那些失败——两次调用之间房价过期、出票后锁定被拒——根本不是模型智商的失败。它们是基础设施事件,即便我换成一个聪明十倍的模型,它们仍会以同样的频率发生。那一刻,架构在我脑子里翻转了。

智能体建议,代码决定

我围绕一条可以贴在贴纸上的规则重建了它:LLM 提议,代码定夺。在这个演示里,控制流是一个手工搭建的、大约十个节点的 Python 状态机,模型被允许做的恰好只有两件事。它把自然语言请求解析成带类型的对象,并在最后给人类回复措辞。中间的一切——搜索、政策、核验、锁定、出票、订酒店、提交——都是确定性 Python,要么执行,要么不执行。

其中两个节点是门控,诚实就住在那里。政策门控把企业差旅规则编译成普通代码:仅限经济舱、每航段 600 美元的票价上限、优先承运人、每晚 350 美元的酒店上限。不合规选项不是事后打标,而是物理上不可呈现,在到达旅客之前就被过滤掉。未知的票价族按失败安全处理,当作超政策,而不是当作经济舱放行。

核验门控是我最自豪的那个。在展示任何酒店之前,都按物业 ID 对照预订系统确认。当请求点名一个模型捏造的物业时,门控找不到匹配,于是拒绝将其呈现。智能体选择弃权并如实说明,而不是编造一个听起来可信的度假村。

CRS 核验对一家捏造的酒店失败,标记为 REFUSED,且不向旅客呈现
核验门控抓住了一个虚构的物业。"Tabacon Springs Eco-Lodge"不在预订系统中,因此被拒绝且永不展示,智能体选择弃权而不是捏造一笔预订。

我需要诚实说明那张截图是什么、不是什么。"Tabacon Springs Eco-Lodge"是我故意捏造的合成物业,名字从两家真实度假村糅合而来,用来演示这种失败模式。预订系统、GDS、出票和支付全都是模拟桩。背后没有真实的 Amadeus 或 Sabre 账户。真实的是机制:一道拒绝无法确认的库存的门控,坐落在代码里,模型无法靠话术绕过它。

为什么 Saga 回滚才是区分演示与产品的东西

我本可以停在门控处,就有一个不错的演示。我没有停下来的原因,正是引发这一切的那次失败:航班已经出票之后,酒店步骤挂掉。门控在那里帮不上忙。机票是真的。房间没了。必须有什么东西来清理。

于是机器中的每一步前进动作,在运行的那一刻就登记自己的反向动作。出票登记"作废机票,24 小时窗口。"锁定库存登记其释放。这就是Saga 模式,当预订中途某一步失败时,引擎按相反顺序运行那些补偿,然后才报告发生了什么。旅客被告知真相:机票已作废,没有扣款,这里是你现在可以确认的备选方案。

并排对比:确定性智能体作废机票并报告旅客安全,而基线仍说一切就绪
左边是一个普通的 LLM 智能体,仍在对一笔失败的预订说"一切就绪!"。右边是确定性引擎:酒店提交失败,Saga 按相反顺序补偿,机票在 24 小时窗口内被作废,终态为 rolled_back,旅客安全。

第一次看着那次回滚触发——机票在我未触碰任何东西的情况下自行作废——是我最接近"系统是可信的,而不仅仅是聪明的"那种感觉的时刻。Saga 回滚是大多数演示跳过的东西,而它恰恰是区分演示与产品的全部所在。 它并不光鲜。它也是"一切就绪"与一句诚实的"我无法完成这次预订,而这是我为此做了什么"之间的全部差别。

回滚并不光鲜。它也是滞留旅客与一句诚实道歉之间的全部差别。

演示把这与一个真正的 ReAct 智能体——LLM 掌控的基线——并排跑在完全相同的场景上。这是故意的。我不想打败一个稻草人。我想要诚实的对比:把同样的失败注入两边,这样你看到的差异就只有架构,别无其他。

基准测试证明了什么,又没证明什么?

我把两种架构放进同一批跑,因为我不信任自己的轶事。两百笔合成预订,一个固定种子,同样注入的基础设施失败,穿过确定性引擎,也穿过 LLM 掌控的基线。按那个固定种子的 200 场景合成批次的构造,结果是鲜明的。

基准记分板:跨四项指标对比确定性智能体与普通 LLM 基线
在固定种子的 200 场景合成批次上:一致终态 100% 对 65%,滞留旅客 0 对 40,呈现的虚构预订 0 对 30,平均 GDS 搜索花费 3.25 美元对 7.57 美元。

我想谨慎对待那些数字,因为谨慎的版本才是诚实的。那 100%、零滞留、零虚构,是在固定种子合成批次上按构造为真,而不是我能对你的生产流量做出的开放世界保证。确定性保证之所以成立,是因为代码别无选择。基线的失败从同一份数据中涌现。说得再宽一点,你就从真实结果跨进了营销,而这正是这家公司名字所反对的那件事。

我发现自己谈得最多的是最后一个数字。平均 GDS 搜索花费 3.25 美元对 7.57 美元。被计费的是搜索,而不只是预订,大约每航段 3 到 3.50 美元,而汉莎集团在 2026 年 1 月 1 日再次上调了这些费用。一个在每一步推理上都重新搜索的投机性智能体会烧掉那份利润。带缓存的确定性流程则不会。那个差距是一个利润率数字,且在任何模型质量下都成立,而这正是全部要点。

让我安心入睡的那部分:回执

在我宣布完工之前,我又做了一件事,它最不起眼,却是我最在意的。每一笔预订都会写入一条仅追加的 JSON 审计追踪:模型与版本、带类型的请求、每个节点及其确定性裁决、每一次触发的 Saga 补偿、欧盟《AI 法案》第 50 条披露标志,以及终态。你可以把它导出为单个文件。

导出的审计追踪下载,列出模型、裁决、补偿以及第 50 条标志
可导出的审计追踪。每一笔预订都携带模型记录、每个节点的裁决、每一次补偿,以及第 50 条披露标志,因此部分失败留下的是可归档的痕迹,而不是一团谜。

我不断回想起加拿大航空。当事情出错时——而在旅行领域,事情总有一天会出错——合规负责人必须回答的问题是"智能体告诉了旅客什么,我们能否证明为什么。"欧盟《AI 法案》第 50 条的透明度义务自 2026 年 8 月 2 日起适用,将使这个问题成为常态。一个在每个节点都有裁决的确定性流程会给你一个答案。一条推理链给你的是一份转录和一个耸肩。

如果你想自己按那些按钮,整套东西已上线:veriprajna.com/zh-Hans/demos/agentic-travel-booking。能捅破就捅破。它存在就是为了这个。

我真正改变想法的是什么?

一开始我相信,一个足够好的模型最终会让这一切变得多余,确定性只是前 AGI 过渡期的拐杖。我不再这么想了。我花了数周设计去对抗的那些失败,并不是在等一个更聪明的模型到来。房价仍会在两次调用之间过期。锁定仍会在出票后被拒绝。那些是基础设施的属性,不是智能的属性,而一个完美的推理器会和一个平庸的推理器一样彻底地把旅客滞留下来,如果系统里没有任何东西被建来作废那张机票。

而如果你更愿意看它运行,而不是读我描述,这里是整套端到端运行的样子。

所以我不断问其他构建智能体的人的那个问题,正是那天夜里看着我的造物如此愉快地撒谎时,我不得不问自己的问题。当你的智能体告诉客户"一切就绪"时,你的系统里究竟什么东西真正知道那是真的?如果答案是"大概是模型吧",你面对的不是模型问题。你面对的是控制流问题,而我真心想知道你打算怎么解决它。

相关研究

同步发布于

满怀信心地构建您的 AI。

与一支在打造新一代企业级 AI 方面拥有深厚经验的团队携手合作。让我们助您设计、构建并部署一套值得信赖的 AI 战略。

Veriprajna 深度科技咨询公司 专注于为医疗健康、金融和监管等领域构建安全攸关的 AI 系统。我们的架构均依据成熟的规范进行验证,并配有完善的合规文档。