RFQ 引擎架构:可用性预留与取消策略快照为何重要
大多数 RFQ 自动化忽略的问题
当团队自动化 RFQ 工作流时,他们通常专注于前端:解析买家请求、搜索目录、匹配产品、应用定价。这些工作是真实的,也有工具可用——AI 提取需求,而确定性规则处理定价、审批和 SLA 跟踪,正如 GEP 在其采购自动化分析中所述。Ivalua 2026 年采购指南 确认了同样的模式:AI 处理提取和匹配,规则处理治理。
但两个问题在生产环境中打破了这个模型,而大多数自动化并未解决:
可用性漂移。 一份需要三天谈判的报价,其对应的库存可能在报价价格下已不存在。如果智能体承诺以 $12.40 提供 50 个单位,而买家接受时供应商只剩 12 个,这份报价从一开始就无法交付。智能体没有撒谎——世界在它脚下发生了变化。
策略漂移。 30 天前报价的取消费用可能与预订时生效的费用不同。如果供应商在谈判中途收紧条款,而智能体未在报价时捕获策略,买家后续会争议这笔费用。争议是合理的——条款变了。
解决两者的架构是一个具有两种机制的 RFQ 引擎:原子性可用性预留,在时间窗口内保留受限库存;以及取消策略快照,在报价时刻冻结商业条款。这些不是附加到报价工具上的功能,而是数据模型中的结构性承诺——引擎强制执行的字段、状态转换和生命周期操作。
使其运作的实体模型
生产级 RFQ 引擎需要的不仅仅是请求和报价。实体模型必须将买家意图与供应商响应分开,并且必须独立于目录跟踪受限供应。以下实体构成主干:
Request — 买家意图:联系人、标题、行项目、账单和收货地址、有效期、状态。请求通过定义的状态机移动:initial → in_progress → confirmed → completed,当报价已存在后项目变更时以 modified 作为重入点。
Item — 买家想要的目录产品。项目是通用的;有 UUID、类型、定价模式和计量单位。同一项目映射到多个供应商项目。
ProviderItem — 供应商对该项目的特定提供,按计量单位的基础价格。供应商项目属于供应商公司,可以有多个批次。
ProviderItemBatch — 受限库存单位。每个批次有批号、生产日期、过期日期、单位成本、库存标志和慢动库存标志 slow_move_item。批次是检查和预留可用性的粒度。
Quote — 供应商对已确认请求的定价响应。报价有供应商、销售代表、运输方式和金额、货币、汇率和汇率锁定时间戳、协商轮次(自动计算)以及状态机:initial → in_progress → confirmed → completed 或 disapproved。
QuoteItem — 报价上的一行,将供应商项目和批次链接到数量、单价、小计、折扣和最终小计。关键的是,报价项目携带 hold_token、hold_expires_at、guardrail_price_per_uom 和 slow_move_item — 使可用性预留和盈利保障在行级别可见的字段。
CancellationPolicy — 预订可取消的条款,包含层级、截止日期和罚金规则,按供应商项目界定。
Installment — 与已确认报价关联的付款计划,包含优先级、计划日期、金额、比例和状态机:pending → paid 或 cancelled。
这不是一个扁平表。它是一个带有嵌套解析器的类型化图——请求解析其报价,报价解析其项目,报价项目解析其供应商项目和批次。引擎使用基于 DataLoader 的批量加载,使得有 20 个行项目的报价不会触发 20 次顺序数据库查询。
可用性预留:原子性保留产能
可用性预留是防止可用性漂移的机制。没有它,智能体针对可能已过时的库存快照报价。有了它,智能体在时间窗口内保留产能,报价由真实的、已扣减的供应支持。
预留生命周期有四个状态和严格的转换规则:
| 状态 | 含义 | 允许的转换 |
|---|---|---|
held |
产能已扣减,发放带 TTL(15 分钟)的预留令牌 | confirmed, released, expired |
confirmed |
预订已提交,无第二次产能扣减 | 终态 |
released |
预留已取消,产能已恢复(幂等) | 终态 |
expired |
TTL 已过,产能已恢复(幂等) | 终态 |
关键的设计决策在 confirmed 转换中:无第二次产能扣减。预留已经保留了产能。确认预订将预留转为已确认状态,不会再次触及库存计数。这防止了重复计数——即预留扣减产能后确认又扣减一次,导致系统认为可用供应少于实际的 bug。
预留是原子的。acquireAvailabilityHold mutation 扣减可用产能并返回带 expires_at 时间戳的 hold_token。如果产能不足,操作无副作用地失败——无部分预留,无脏状态。releaseAvailabilityHold 和 expireAvailabilityHold mutation 恢复产能并且是幂等的:对同一令牌调用两次返回相同结果。这对容错很重要——如果网络超时导致重试,系统不会过度恢复产能。
如何映射到报价工作流
考虑一个分销商向有三个不同过期日期和成本批次的供应商报价 200 台工业泵。智能体:
- 调用
check_availability,传入供应商项目 UUID、服务窗口和数量——获取匹配的批次和可用数量。 - 调用
acquire_availability_hold——产能原子性扣减,返回带 15 分钟 TTL 的hold_token。 - 报价项目现在携带
hold_token和hold_expires_at。买家看到的是由真实库存支持的报价,而非目录猜测。 - 如果买家在 15 分钟内接受,智能体调用
confirm_availability_hold——预留转为confirmed,产能锁定,无第二次扣减。 - 如果买家拒绝或 TTL 过期,智能体调用
release_availability_hold或让其过期——产能恢复,下一次报价可以使用。
hold_token 是显式句柄。模型将其作为参数传递,而非隐藏的会话状态。这与 MCP 2026-07-28 release candidate 正式化的显式句柄模式相同:智能体跨工具调用需要的状态成为可见的、可审计的句柄,而非传输层元数据。
取消快照:冻结条款
取消策略漂移是第二个故障模式。供应商可能在报价和预订之间更改取消罚金——30 天前 10% 的罚金变成 7 天前 50%。如果智能体报价了旧罚金而买家接受了,买家会争议新费用。争议是正确的。
架构通过在报价时快照取消策略来解决这个问题。CancellationPolicy 实体有 tiers(带截止日期和罚金百分比的 JSON 结构)、label、description 和 status。当智能体生成报价时,它检索每个供应商项目的活跃取消策略并将策略条款附加到报价。策略 UUID 及其层级被冻结——即使供应商后续更新策略,报价仍携带发出时有效的条款。
search_cancellation_policies 工具按供应商项目和状态过滤,使智能体可以为每个行项目检索活跃策略。策略然后与报价项目关联,而非仅通过外键引用——快照就是策略,不是指向可变记录的指针。
这个模式不仅适用于取消。汇率使用相同方法:QuoteType 携带 fx_rate 和 fx_rate_locked_at——汇率在报价时锁定,而非在预订时查找。如果买家显示货币与供应商报价货币不同,锁定汇率就是买家看到的汇率,不受市场波动影响。
定价层级、分段查找和护栏
定价不是扁平字段。引擎按客户分段、数量和供应商项目解析价格层级。get_item_price_tiers 工具接收客户邮箱和报价项目列表(每个带项目 UUID、供应商项目 UUID 和数量),通过分段联系人查找客户分段,并在单次查询中批量加载所有匹配的价格层级。层级在数据库层面按数量阈值过滤——只返回 quantity_greater_then 和 quantity_less_then 包含请求数量的层级。
折扣提示以相同方式工作,使用分层范围系统:GLOBAL(适用于所有报价)、SEGMENT(适用于客户分段)、ITEM(适用于特定项目)和 PROVIDER_ITEM(适用于供应商对某项目的特定提供)。get_discount_prompts 工具从所有四个范围加载,去重,并返回带条件和规则的合并集合。这意味着一份报价可以同时应用批量折扣(分段范围)、季节性促销(项目范围)和供应商特定清仓(供应商项目范围)——每个有自己的优先级。
报价项目上的 guardrail_price_per_uom 字段是盈利护栏——从供应商项目批次加载的项目最低可接受价格。如果智能体应用使价格低于护栏的折扣,操作不会失败(智能体可能有正当理由),但标志在报价项目响应中可见。slow_move_item 标志标记库存时间过长的项目——智能体可以利用此应用更深折扣,但护栏防止不盈利的定价。
防止无效操作的状态机
没有状态强制的 RFQ 引擎只是电子表格。引擎强制执行四个状态机,每个都有明确的转换规则和操作守卫:
Request: initial → in_progress → confirmed → completed,以 modified 作为重入点。RequestOperationGuard 强制报价只能从 confirmed 请求创建,项目修改只在 initial、in_progress 或 modified 状态允许。
Quote: initial → in_progress → confirmed → completed 或 disapproved。QuoteOperationGuard 强制项目修改只在 initial 或 in_progress 允许,分期只能从 confirmed 报价创建。
可用性预留: held → confirmed / released / expired。三个目标状态都是终态。
Installment: pending → paid 或 cancelled。两个目标状态都是终态。
当已确认请求的项目变更且报价已存在时,请求转为 modified,所有现有报价自动被拒绝——买家必须针对更新后的项目获取新报价。这防止在生成报价的请求变更后接受过时报价。
当报价上所有未取消分期都已支付时,报价自动转为 completed。当请求上至少一份报价完成时,请求自动转为 completed。状态机不是建议性的——引擎验证每次转换,如果操作无效则抛出带当前状态和允许转换的 VALIDATION_FAILED 错误。
模块模式:38 个工具,11 个领域 mixin
此架构的参考实现是单个 MCP 模块——mcp_hospirfq_processor——由 11 个领域 mixin 组合的 38 个注册工具:Request、Item、Availability、Quote、Pricing、Installment、Bundle、Cancellation、File、Segment 和 Catalog。mixin 共享 GraphQLBackedProcessor 基类,提供 GraphQL 客户端、日志器和设置。每个 mixin 贡献自己的工具方法,只访问 self.logger、self.setting 和 self._execute_graphql_query。
工具通过配置块(MCP_CONFIGURATION)注册,声明每个工具的名称、描述、输入 schema(JSON Schema)和模块链接(类名、函数名、返回类型)。MCP runtime 在启动时加载此配置,将工具调用分派到对应的 mixin 方法。@handle_errors 装饰器用结构化错误处理包装每个工具调用,产生带代码的类型化错误响应,如 GRAPHQL_QUERY_FAILED、VALIDATION_FAILED、HOLD_NOT_FOUND、HOLD_ALREADY_EXPIRED、AVAILABILITY_INSUFFICIENT 和 PRICING_MODE_UNSUPPORTED。
38 个工具涵盖完整的 RFQ 生命周期:
| 领域 | 工具 | 关键操作 |
|---|---|---|
| 请求管理 | 8 | 提交、更新、获取、搜索、添加/删除项目、分配/删除供应商项目 |
| 项目管理 | 3 | 搜索项目、获取项目、获取带批次信息的供应商项目 |
| 报价管理 | 4 | 更新报价、获取报价、搜索报价、更新报价项目 |
| 定价 | 3 | 获取价格层级、获取折扣提示、计算报价定价 |
| 分期 | 4 | 创建、更新、创建计划、获取分期 |
| 可用性 | 5 | 检查、获取预留、释放、确认、过期 |
| Bundle | 3 | 搜索 bundle、获取 bundle、搜索组件 |
| 取消 | 2 | 获取策略、搜索策略 |
| 目录 | 1 | 查询目录(知识图谱搜索) |
| 分段 | 1 | 获取分段联系人 |
| 文件 | 2 | 上传、获取文件 |
| 工作流 | 2 | 确认请求+创建报价、确认报价+创建分期 |
两个工作流工具——confirm_request_and_create_quotes 和 confirm_quote_and_create_installments——是将多个原子工具组合为单次调用的便捷操作。前者在一步中确认请求并为选定供应商创建报价。后者在一步中确认报价并创建分期计划。这减少了智能体在最常见多步工作流中需要的往返次数。
inquire_catalog 工具是通往知识图谱的桥梁。它接收自然语言查询、可选命名空间(hotel、flight、activity)和限制,从知识图谱引擎返回排序结果。这就是智能体在报价前发现产品的方式——不是对产品表的 SQL 查询,而是通过知道替代品、兼容性和可用性的目录图进行语义搜索。
此架构为何可推广
参考实现是为旅游和酒店业构建的——有日期界限的库存、入住规则、单人定价、bundle、押金、取消条款。这是压力测试。如果引擎能针对特定日期报价并预订酒店房间,用 TTL 预留可用性,快照取消策略,锁定汇率,应用分段特定定价层级,并交付到分期计划,它就能支持任何具有供应商、买家、受限库存和商业条款的 B2B RFQ 工作流。
推广是结构性的:
- 分销和批发: 用仓库库存替换酒店房间,供应商项目替换供应商 SKU,批次替换批号和过期日期。可用性预留预留库存;取消快照保留退货条款。
- 采购: 用零件和材料替换旅游套餐。基于分段的定价层级应用协商合同费率;护栏价格防止不盈利的采购。
- 制造: 用生产槽位替换服务窗口。可用性预留预留生产线产能;取消策略保留重新安排罚金。
- 现场服务: 用预约窗口替换酒店日期。可用性预留预留技术人员的时间槽;分期计划结构化付款时间表。
实体模型——Request、Item、ProviderItem、ProviderItemBatch、Quote、QuoteItem、CancellationPolicy、Installment——是行业无关的。领域 mixin 是可组合的:采购部署可以去掉 Bundle mixin 并保留其余。制造部署可以在 Availability 旁添加 ProductionSlot mixin。模块模式、状态机和显式句柄方法保持不变。
运行 NetSuite、BigCommerce 和三个供应商目录的分销商获得一个智能体,它通过邮件或门户接收 RFQ,针对目录图解析产品和替代品,按客户分段定价,用有效期预留库存,快照取消条款,锁定汇率,并将接受的报价写回 NetSuite——每次工具调用都被记录,每次状态转换都被验证。该构建是四步方法的第 2-3 阶段,通常在 5-8 周内上线。
请求范围确定的构建。 一周 Discovery。您获得系统清单、工作流图和固定范围——无论是否与我们合作。
想为您的系统构建这个吗?
这里的每份文档都来自真实的生产工作。如果您有目标系统和工作流想法,我们可以在一周内确定范围。
申请定制开发为期一周的发现阶段。您会拿到系统清单、工作流地图和固定范围——无论您最终是否与我们合作开发。