预约代理改期三次,为同一订单收了四笔钱
文章描述一家家政服务公司的AI预约代理在每次改期时重新执行收款流程,导致同一项服务被收取四笔150美元订金。按预约统计的仪表盘未暴露问题,客户层面的重复收费最终引发拒付预警。
AI 深度解读
同一项暖炉更换服务,客户改期三次,AI 就连续收了四笔 $150。预约率上涨 11%、爽约率从 22% 降到 9%,这些漂亮指标没有暴露问题:团队按预约统计收款,却没检查同一项工作究竟收了几次钱。
作者借这次家政服务公司的事故提出一个判断:让 AI 经手付款,关键在于把资金状态绑定到业务对象,并在每次操作前检查。文章给出了政策表、幂等键和审计办法,也留下了一些需要追问的工程细节。
为什么预约指标变好了,客户却开始投诉欺诈
这家公司让 AI 收取预约款约七个月,累计收款已达六位数。直到银行拒付预警信出现,一位客户提供了同卡、同商户的四笔 $150 扣款截图,问题才浮出水面。四笔交易相隔三周,对应的始终是同一项工作。
故障路径很直接:客户改期,系统重新运行预约流程;预约流程包含收款,于是再次扣钱。每次预约在系统里都有效,但「预约有效」无法证明「这次收款应该发生」。
作者介入时,已有 340 项工作存在重复资金占用,未完成服务对应的资金达到 $47,000,拒付率悄悄涨到了原来的三倍。
话术还放大了争议。AI 每次都承诺,$150 的「可退预约款」可以锁定时段,并抵扣最终账单。公司的实际政策却是:提前超过 48 小时取消才可退,48 小时以内不可退,完成服务后用于抵扣。AI 从营销页面学到了「可退」,却没有附带条件。
这里有两个独立问题:系统重复收款,AI 又给出了超出政策的承诺。只改其中一个,另一个仍然存在。
资金政策要能查询,也要能阻止错误操作
作者要求区分四种资金对象:hold 是预留额度,charge 是实际扣款,credit 是抵扣额度,cancellation fee 是取消费用。它们对客户余额、后续结算和退款处理的影响不同,不能统一包装成含糊的 deposit。
因此,客服不能把 hold 描述成已经扣款,也不能单独使用 refundable。退款条件必须出现在同一句话里,明确「提前超过 48 小时取消可退」。报价前还要读取已有资金状态;已经存在 hold 或 charge,就停止继续收取并转人工核实。金额超过服务类型上限,也必须升级处理。
光有措辞规则还不够。作者把原先放在内部 wiki 的政策改成结构化数据,让 AI 在回答和操作前查询:
{
"deposit_policy": {
"version": "2026-10",
"source_of_truth": "billing.deposit_rules",
"by_service_type": {
"diagnostic_visit": { "amount": 0, "type": "none" },
"standard_repair": { "amount": 150, "type": "hold", "capture_on": "completion" },
"install_replacement": { "amount": 500, "type": "hold", "capture_on": "completion" },
"emergency_after_hours": { "amount": 250, "type": "charge", "capture_on": "dispatch" }
},
"refund_window_hours": 48,
"refundable_inside_window": false,
"retained_as": "cancellation_fee",
"max_open_holds_per_job": 1,
"reschedule_behavior": "reuse_existing_hold",
"hard_ceiling_per_customer": 1000,
"forbidden": [
"collecting a second deposit on an existing job",
"calling a hold refundable without stating the window",
"waiving the cancellation fee without human approval",
"quoting a deposit for a service type not in this table"
]
}
}
重点看 max_open_holds_per_job 和 reschedule_behavior:同一项工作最多保留一个未结束的 hold,改期复用已有记录。amount: 0 同样重要,它明确表达诊断服务免费预约,避免把字段缺失留给模型猜测。服务类型查不到,就转人工,不能估一个价格。
这张表也需要正确解读。案例中的暖炉更换收了 $150,而示例表的 install_replacement 是 $500;原文没有说明两者如何对应,不能直接把示例当成该公司的历史配置。
防重复收款,要把检查放到业务记录上
作者给出的技术规则是:
Idempotency key = job_id + intent,例如 J-88213:hold。
幂等的意思是,同一操作重复提交时,返回已有结果,避免再次创建付款。这里的标识绑定工作和付款意图,不能绑定某一轮聊天。客户换渠道、开新会话或隔几周改期,仍然访问同一份资金记录。
操作顺序也很明确:先读取 job 的资金状态,再决定能否付款。已有未结束的资金记录,就不能继续收取。
聊天记录可以帮助理解客户意图,业务记录负责决定这笔钱能不能收。
这比依赖 AI 记得「之前聊过付款」可靠。会话会断,摘要会丢信息,客户也可能从其他入口联系;工作对应的资金状态必须持续存在。
作者称,在其审计的五个可收预约款的部署中,四个存在改期重复占款;唯一没有发生的部署,从第一天就配置了 max_open_holds_per_job: 1。重复占款约占预约的 2%–4%,涉及的 hold 为 $150–$500,相关客户群的拒付率达到基线的 3–5 倍。作者还称,加入操作前读取后,各案例的重复占款都降到了零,预约转化率没有变化。
这些是作者报告的现场观察。原文没有提供样本规模、观察周期和对照设计,不能把它们直接当成普遍有效的实验结论。
收款后的审计,要同时检查账和承诺
作者建议每天生成资金在途报告,并每月执行一次 12 项审计,声称用一份质量尚可的客服导出数据,约 40 分钟可以完成。
审计既查资金,也查对话。资金侧包括:存在两个及以上未结束 hold 的工作数量必须为零;未完成工作上超过 14 天的 hold 要逐项解释;检查改期是否创建新 payment intent、是否超额收款,以及取消费用由谁批准减免。
对话侧分别抽取 20 条包含 deposit 和 20 条包含 refundable 的记录,检查是否区分预留与扣款、是否明确退款窗口。所有引用 AI 承诺的退款工单都要记录。
政策版本也要查。AI 使用的政策表必须与计费系统一致,否则账单已经执行新规则,客服仍可能承诺旧条件。
原文称每日报告有五行,但提供的正文没有列出完整字段,只描述了最后一行与「客户引用了政策不支持的 AI 承诺」有关。这里不能替作者补齐模板。作者还报告,明确禁止前,无条件使用 refundable 的情况占预约款相关表述的 60%–90%;这个比例同样缺少完整统计口径。
我的判断
最有价值的判断,是把问题定位到业务建模和交易约束。换模型、补检索、优化提示词,都可能帮助 AI 找到政策,却无法单独保证付款不会重复发生。
不过,「先读再写」必须配合服务端的并发约束,才能成为可靠的防线。 两个请求可能同时读到空状态,再同时发起收款。原文强调了幂等键,但没有展开数据库约束、支付结果落库、失败重试和异步通知如何协同。
job_id + intent 也有前提。如果一次工作中的 hold 已过期、被取消,之后需要重新授权,长期复用同一个键是否合适,要看支付接口和业务生命周期。原文没有说明这些边界。「一项工作只能有一个有效 hold」与「这项工作永远只能创建一次 hold」需要区分。
语言规则适合作为护栏,却不能代替交易控制。示例规则禁止使用裸词 deposit,但预设的人工核实话术仍含有这个词,规则自身也存在不一致。
我认可这套设计方向,但作者最后附有付费手册入口,文中的比例和「全部降为零」应按作者经验看待。一般团队真正值得复用的是可核验的约束,而不是未经独立验证的效果数字。
能拿来做什么
- 给 AI 预约或订单流程建立持久业务 ID,让改期、新会话和不同渠道都读取同一份资金状态;前端展示金额时,也应区分预留、扣款、抵扣和取消费用。
- 在 Node 付款接口中落实幂等和并发控制,把重复提交、网络重试、客户改期纳入验证,不能只在提示词里要求 AI 检查。
- 将金额、退款窗口、服务类型和升级条件整理成带版本的政策表。明确记录免费项目,遇到未知类型时停止报价,核对 AI 与计费系统的版本是否一致。
- 从每月审计开始,检查重复 hold、超过 14 天的未结记录和无条件退款承诺;把客户拿着聊天截图申请退款的工单作为单独的问题来源。