跳到正文
Elaine Blog
返回

读懂 AgentScope Java Runtime:会话状态怎样进入业务系统

更新于:
Agent Runtime

用户先说“订单 A1042 需要申请退款”,隔一会儿问“处理到哪里了”。Agent 必须知道两次调用属于同一会话,但仅仅记住对话,仍然不能证明退款已经执行。

AgentScope Java 适合用来观察 Agent 的调用状态如何加载、使用和保存。本篇沿这个过程读源码,再把会话状态与业务状态的边界说清。

RuntimeContext 把哪一次调用定位到哪一份状态

RuntimeContext 携带 user ID、session ID 等运行信息。状态存储以用户和会话的组合寻址,避免同名会话在不同用户之间混淆。

// 身份应由服务端认证结果提供;此处 alice 只是教学用户,不能照搬为登录方案。
RuntimeContext context = RuntimeContext.builder()
        .userId("alice")
        // sessionId 关联对话;退款 taskId 与 operationId 仍由业务系统单独维护。
        .sessionId("order-A1042")
        .build();

相同 session ID 不等于相同业务操作。一段对话可能讨论多个申请;一个申请也可能被不同会话查询。让 session ID 直接兼任所有退款幂等键,会把这两种关系混在一起。

沿一次 call 看状态装载

源码解读固定提交 7d321e2。在 ReActAgent.java中,activateSlotForContext 从上下文取得用户与会话,定位对应槽位。

配置 stateStore 时,它读取带版本的状态,更新缓存,并基于加载的权限上下文建立调用需要的 PermissionEngine;没有存储时则使用本地缓存路径。这样可以理解为什么仅仅“同一个 Java 对象还活着”与“换进程后能加载状态”是不同条件。

返回的 CallExecution 将本次状态、权限引擎、槽位和加载版本关联起来。阅读时继续追踪调用生命周期,而不是只看 builder 中是否出现一个 storage 参数。

源码注释也需要核对实现

该快照中 activateSlotForContext 附近的注释提到了 acquireExecution 锁,但 AgentBase.java里的 acquireExecution 当前只是检查是否仍接收请求并返回实例,不能据此宣称它提供了互斥锁。

这个细节说明源码解读不能只复述注释。要沿实际方法、调用上下文和存储契约确认保证;更不能把单实例中的生命周期控制推导成多副本分布式锁。

保存接口是否真的防止覆盖

AgentStateStore.java提供普通保存与版本相关接口。值得重点阅读 supportsVersioning、getVersioned 和 saveIfVersion。

默认 supportsVersioning 为 false;默认 saveIfVersion 会退化为普通保存。这意味着“接口里有 CAS 名字”不等于所有后端都具有 CAS 保证。

例如两个服务副本都读到版本 5,一个添加审批消息,另一个添加工具结果。支持版本比较的后端可以拒绝第二个旧版本写入,让应用处理冲突;无版本后端可能让后写者覆盖先写者。

真正选择存储时,应检查具体实现、冲突策略和失败返回,而不只看接口名称。源码阅读清单同时列出内存与 JSON 文件实现,帮助比较适用范围。

AgentState 保存了什么,还缺什么

Agent 状态可以包含消息、工具相关上下文和权限信息。这些对继续模型循环很重要,但外部订单和支付账本仍有自己的权威来源。

如果用户说“记录一下已经退款”,Agent 将这句话写入记忆,不应让业务数据库自动变为 completed。第二次询问时,回答应查询业务 task ID 与支付回执,再解释当前状态。

相反,支付成功但 Agent 状态保存失败,业务系统也不能因为对话记忆缺失就重复退款。业务 operation ID 与账本对账解决这类问题,AgentStateStore 只承担它定义的状态存储责任。

配套 Java 示例应该怎样读

RuntimeSessionDemo.java下载保留现有 Maven 2.0.1 工程,在同一 RuntimeContext 下进行两次调用,并补充详细注释。它只展示会话延续,不提交退款,也不声称证明跨进程业务恢复。

源码分析使用固定提交,Maven 示例使用已有发布依赖,两者刻意标明版本,不将新快照中的接口直接复制到旧依赖里。运行前需要按 README 配置模型凭据;运行条件与验证范围在指南中单独记录。

真正接到退款系统时,可以提供一个只读 query_task 工具,按认证身份查询任务;另一个 submit_refund_request 工具只创建待审批申请;最终支付由受控业务执行器处理。这样对话与交易通过明确接口连接。

多副本需要补齐哪些设计

首先保证所有副本访问相同权威状态后端。其次确定同一会话是否允许并发,如果允许,怎样合并或拒绝冲突。再检查取消、异常与关闭时是否保存了正确调用实例的状态。

多副本共享文件路径不自动解决锁、损坏和故障恢复。将文件换成数据库也不自动赋予外部支付原子性。框架状态与业务账本分别有自己的并发和事务设计。

这篇项目解读的价值,在于让读者知道如何从调用上下文一路追踪到存储语义。后续遇到其他 Agent SDK,同样可以问:状态键是什么,何时加载,何时提交,冲突怎样发现,哪些事实根本不属于这个存储。


分享这篇文章:

上一篇
读懂 Temporal:历史重放怎样驱动长期业务流程
下一篇
读懂 DBOS:数据库怎样让普通 Python 程序获得持久执行能力