agent - 会话挂起(Session Pending)
2026年4月8日 上午10:38:27
在 Agent 的执行过程中,有时需要中断当前的计算流。例如:触发 HITL(Human-In-The-Loop,人机交互) 等待人工审批,或是在特定条件下进行外部强行中断。
注意:
- 挂起是一种临时状态。当该会话(Session)被重新触发执行时,系统会自动重置挂起状态(将 isPending 设为 false),以便计算图能够继续向下推进。
1、会话的挂起接口
通过 AgentSession 对象,可以对当前会话的运行状态进行精细化控制。一旦进入挂起状态,Agent 内部的计算图(Execution Graph)将停止推进。
| 方法 | 描述 |
|---|---|
AgentSession::pending(pending, reason) | 设置挂起状态(true 为挂起,并需提供挂起原因) |
AgentSession::isPending() | 判断当前会话是否处于挂起状态 |
AgentSession::getPendingReason() | 获取挂起原因(通常用于前端展示或后续逻辑判断) |
2、挂起应用场景
会话挂起主要分为 内部逻辑拦截 和 外部异步中断 两种模式。
通过拦截器挂起(适用于:同步、异步、流式响应)
这是最常用的场景,通常用于在工具执行(Action)前进行合规检查或人工授权。
public void useInterceptor() throws Throwable {
ReActAgent agent = ReActAgent.of(null)
.defaultInterceptorAdd(new ReActInterceptor() {
@Override
public void onAction(ReActTrace trace, String toolName, Map<String, Object> args) {
// 模拟 HITL 场景:根据业务逻辑决定是否挂起
if ("delete_user".equals(toolName)) {
trace.getSession().pending(true, "敏感操作,等待人工审批");
}
}
})
.build();
AgentSession session = InMemoryAgentSession.of();
// 发起同步调用
ReActResponse resp = agent.prompt("删除 ID 为 1001 的用户").session(session).call();
// 检查挂起状态
if (session.isPending()) {
System.out.println("执行已挂起,原因:" + session.getPendingReason());
}
}
外部主动中断(适用于:异步调用、流式响应)
在异步或流式任务执行过程中,外部根据用户指令或其他监控事件强行挂起会话。
- 示例 A:异步调用中断
public void asyncInterrupt() throws Throwable {
ReActAgent agent = ReActAgent.of(null).build();
AgentSession session = InMemoryAgentSession.of();
// 发起异步调用
agent.prompt("生成一份万字长文报告").session(session).callAsync() //v3.10.2 后支持 callAsync(内部是个简单的线程调度)
.whenComplete((resp, err) -> {
// 处理最终结果
});
// 模拟外部干预:立即强行挂起
session.pending(true, "用户点击了停止生成");
}
- 示例 B:流式调用中断
public void streamInterrupt() {
ReActAgent agent = ReActAgent.of(null).build();
AgentSession session = InMemoryAgentSession.of();
// 发起流式订阅
agent.prompt("查一下杭州今天的天气").session(session).stream()
.doOnNext(chunk -> {
// 处理流块内容
})
.subscribe();
// 在流传输过程中,外部通过 session 强行挂起计算图
session.pending(true, "资源配额不足,自动挂起");
}