一份差旅报销在手机上发起:Agent 已经调过发票 OCR、核过差旅标准,卡在"补一个成本中心编码"这一步。用户把手机放下,打开 PC 后台想接着办。此时 PC 端的 Agent 只有两个选择——把前面五轮重新问一遍,或者真正接上那一次任务。
多数团队把跨平台当成适配问题:每个端能不能调起 Agent、能不能渲染流式输出。真正让项目延期的是另一个问题:任务中间状态归谁所有。适配解决"哪里都能跑",接续解决"跑了一半换端还算不算同一次任务"。
为什么会话接续比多端适配难
三个端最不像的地方不是屏幕尺寸,而是进程能活多久。移动端应用随时可能被系统回收,浏览器刷新就丢内存,桌面端可以几天不关窗口。把任务状态放在当前进程内存里,在移动端等于赌运气。
第二层差异是工具能力边界。桌面侧 Agent 能读写本地文件树、操作其他应用窗口;小程序只有平台开放的那部分 API;浏览器受存储配额与跨域策略限制。同一套工具编排落到三个端,要按能力重新裁剪。
第三层是用户预期。手机上的对话短,以问答和确认居多;PC 后台的任务长,以多步配置和批量操作为主。用户在两端的"未完成任务"心理模型不同,接续粒度也就不能一个模子。
三层叠起来,跨端接续其实在回答一个所有权问题:任务的中间状态放在哪、谁有权改、改冲突了听谁的。下面三条路线,本质是对这个问题给出三种回答。
三条技术路线,各自把状态放在哪
| 维度 | 路线 A:服务端权威状态机 | 路线 B:客户端持有 + 增量同步 | 路线 C:事件日志重放 |
|---|---|---|---|
| 状态所有权 | 服务端,会话即一个工作流实例 | 各端本地,靠同步层合并 | 事件存储,状态由重放推导 |
| 接续粒度 | 步骤级,可从最后完成的检查点续跑 | 轮次级,衔接最近若干轮上下文 | 事件级,可从任意位置重放 |
| 重复副作用风险 | 中,取决于每一步是否幂等 | 低,不会自动重跑已完成的工具调用 | 高,重放会重新触发外部调用 |
| 首包延迟 | 多一次状态拉取与校验 | 最低,状态就在本地 | 中,重放本身有计算成本 |
| 实现成本 | 高:状态机 + 检查点存储 + 过期与清理 | 中:需要冲突合并与版本策略 | 中高:事件存储 + 全链路幂等键 |
| 典型适用 | 包含资金、库存、工单写入的长任务 | 单端为主、偶尔换端的问答型助手 | 已有消息总线、需要审计回放的场景 |
| 主要失败模式 | 检查点存了但某步不幂等,恢复时重复下单 | 两端并发写同一字段互相覆盖 | 日志膨胀,重放放大外部调用量 |
路线 A 把会话当作工作流实例:服务端持有状态机与检查点,每完成一步落一次点,任何一端进来先拉状态再续跑。代价是要建检查点存储,还要配过期与清理,否则存储会无界增长。
路线 B 让每个端各自持有上下文,靠同步层合并。它不会自动重跑已完成的工具调用,副作用风险最低,但两端同时改同一字段时会互相覆盖。
路线 C 不存"当前状态",只存事件日志,需要时重放。审计与回放能力最好,前提是整条链路幂等——否则重放会把外部调用放大若干倍。
桌面端会话可以长驻数天,状态生命周期和进程内存的关系与移动端完全是两套,端侧差异可以直接参看 AI Agent 工程化·桌面端实战指南。
四个会让接续失败的断点
断点一:副作用已经发生,检查点还没写
工具调用成功了,支付已扣、工单已建,进程却在这条结果写回检查点之前被回收。恢复时状态显示"该步骤未执行",于是又执行一次。这是跨端接续里最常见的数据事故来源。
对策是把幂等键的生成权交给业务实体,而不是每次请求现生成。键由业务主键加步骤标识拼成,同一个实体在同一业务版本下重放时,外部系统返回同一结果而不是新建一条记录。
断点二:待确认参数躺在对话文本里
用户在手机上补的"成本中心 CC-1042"如果只存在于那段对话文本里,换端开新会话就看不见了。模型会礼貌地再问一遍,用户会认为这个 Agent 根本没记住。
对策是把待确认项从对话中抽出来,做成结构化槽位与会话文本分离。接续时只重问缺失槽位,已经确认的字段原样回填。这一条改动量不大,但对"接续感"的提升最直接。
断点三:交接权限只能在会话创建时定
如果用的是托管 Agent 平台,交接介质的挂载时机往往被平台限制死。阿里云百炼的 Managed Agent 跨会话记忆交接文档写明:记忆存储只在会话创建时挂载,向已存在的会话追加挂载请求会返回 400,要改挂载只能新建会话。
同一份文档还给出了两条验证结论。一是接收端"即便配置了写工具,也应把记忆存储挂成只读,作为第二道防线"——测试中只读会话被要求追加内容时,在真正发起写调用之前就拒绝了,API 回读确认内容未变。二是该记忆文件树不能用 bash 触达,必须通过 read / write / edit 文件工具读写,指令里要显式写明"用文件工具,不要用 bash 命令"。
工程含义很明确:交接的权限边界属于架构决策,不是运行时可调参数。"事到临头再补个权限"这条路在平台层面就不存在。
断点四:两端同时写同一份交接笔记
同一份工作笔记被发起端写、被接收端也在写,最后写入者覆盖前者,中间那几行结论直接消失。这类冲突在单端演示里永远不会出现,上线第一周就会撞上。
可行做法是条件更新。上述文档的机制是把上一次读到的 content_sha256 放进更新请求的 precondition,hash 过期则返回 HTTP 409,错误码为 memory_precondition_failed_error,而新写入的内容保持完好。
应用侧的处理是重读、合并、重新提交,而不是重试覆盖。另外要注意,元数据里的 user_id 并不会自动隔离记忆存储内容——共享同一个记忆存储的会话共享内容,需要隔离时要按业务主体分配独立存储。
幂等先于检查点
AWS 的 Well-Architected Agentic AI Lens(AGENTREL03-BP03)把这条因果关系写得很直白:检查点只有在恢复安全时才有用,而恢复只有在步骤幂等时才安全。它对幂等步骤的定义是:同样的输入跑一次和跑五次结果相同,因此重试或恢复不会叠加副作用。
文档把这条约束的后果说得很硬:没有幂等保证时,基于检查点的恢复会产生重复副作用或数据损坏,实现顺序上要先把每一步设计成幂等,再上检查点。它给这条最佳实践缺失时暴露的风险等级标为 High。
对应到实现上,它要求外部调用带幂等键、状态变更走条件写、事件发出要有去重逻辑。检查点还需要生命周期管理:设置基于 TTL 的过期,任务成功完成后显式清理,让检查点存储保持在有界范围内。托管运行时会覆盖一部分粗粒度工作——文档提到 AgentCore Runtime 提供跨停止与恢复的托管会话存储,持久化文件系统状态,属于"粗粒度那一段";步骤级的检查点与从失败点重驱则由工作流编排承担。
一条可执行的落地顺序
- 先给每个外部写操作定义幂等键(业务主键 + 步骤标识),上线前用同一个键重复调用,确认返回一致且只产生一条记录。
- 把状态拆成两半:可重放的事件日志,以及不可重放的待确认槽位。前者丢了能重算,后者必须持久化。
- 检查点落在步骤的自然边界上,不要落在对话轮次上——轮次边界和业务边界不对齐,恢复时就会出现半完成的步骤。
- 交接介质单独存储,接收端只读挂载,写入只允许发起端在任务完成时落一次。
- 给并发写加条件更新(content_sha256 或版本号),收到 409 走重读、合并、重提,不做覆盖式重试。
- 设定检查点 TTL 与完成后的显式清理,并接入监控:存储增长与访问延迟要能提前暴露,而不是等恢复失败才发现。
如果团队已经算过多端交付的投入,可以对照 AI Agent 跨平台 ROI 拆解:四端 TCO 对照 里的口径,先确认接续方案的投入量级再决定路线。
怎么判断该选哪条路线
- 任务链路只有读操作、换端只是换界面:路线 B 就够,别为了"架构完整"上状态机,那只会增加首包延迟和维护面。
- 链路里有资金、库存、工单这类不可回滚的写入:必须走路线 A,并且幂等键要先于检查点落地,顺序反了等于给自己埋重复执行。
- 已有消息总线、需要审计回放与事后追责:路线 C 合适,但要预算重放带来的外部调用放大,以及日志的存储与清理成本。
- 已经用了托管 Agent 平台:粗粒度状态持久化可以外购,步骤级幂等与检查点清理仍得自己做,这部分没有厂商能替你完成。
如果现有链路里已经有资金或库存写入、而跨端接续还没解决,建议先停下来把幂等键补齐再谈换端体验。案例页里有我们在多端交付中的架构取舍记录,也可以直接联系我们说明当前架构,一起判断该补哪一层。
四个端具体怎么分工、哪些状态必须服务端持有,在 AI Agent 工程化实战:跨平台四端案例分析 里有逐端的取舍记录。
常见问题
三个端共用一个会话 ID 就能接续吗?
不够。会话 ID 只解决"找到哪次对话",不回答"上一步的副作用是否已经生效"。接续真正依赖的是步骤级的完成标记与幂等键,会话 ID 只是寻址。
只做 Web 加小程序,也需要状态机吗?
看有没有不可回滚的外部写入。只有查询与生成类任务,客户端持有上下文加同步就够;一旦涉及下单、扣款、建单,即使只有两个端也需要服务端权威状态。
检查点直接存 Redis 行不行?
粗粒度可以,但要同时补三件事:过期策略、任务完成后的显式清理、以及幂等保证。如果 Redis 自身重启会丢数据,恢复语义就退化成"从头再来",那就不能算检查点。
接续时用户会不会被重复确认一遍?
取决于待确认项有没有结构化。槽位与会话文本分离之后,接续只重问缺失的那几项,已确认字段直接回填;反之模型只能靠读对话历史猜测,重复确认几乎必然发生。
有没有现成方案可以直接买?
托管平台覆盖的是粗粒度那一段:跨停止与恢复的会话存储、记忆挂载与只读交接。步骤级幂等、并发条件更新、检查点清理这些仍然要写进你自己的业务代码。
