15-02 AgentScope Java特性:流式输出、结构化输出、超时与重试、执行控制
✅AgentScope Java特性:流式输出、结构化输出、超时与重试、执行控制
流式输出
AgentScope Java 的流式输出基于 Reactor 的 Flux
关键类:
Agent.stream(Msg, StreamOptions) — 流式调用入口,返回 Flux
StreamOptions — 流式配置项(事件类型过滤、增量/累积模式等)
Event — 流式事件对象,包含类型、消息内容、是否为最后一条
EventType — 事件类型枚举:ALL、REASONING、TOOL_RESULT、SUMMARY、AGENT_RESULT、HINT
REASONING:Agent 的”思考和规划”阶段产生的事件。对应 ReAct 循环中的 Reasoning 步骤,即模型在决定下一步行动之前的推理输出。(包括TOOL_USE的内容)
TOOL_RESULT:Agent 调用工具(Acting 阶段)执行完成后产生的事件,包含工具的返回结果。
SUMMARY:当 Agent 达到最大迭代次数(maxIters)仍未完成任务时,框架会强制进入总结阶段,让模型总结当前已完成的工作。这个阶段产生的事件就是 SUMMARY。
AGENT_RESULT:Agent 整个 call() 调用的最终返回结果。相当于 agent.call(msg).block() 的返回值以事件形式出现在流中。
HINT:来自 RAG(检索增强生成)、Memory(记忆系统)或 Planning(规划系统)的上下文信息注入事件。这些信息不是模型生成的,而是框架在推理之前主动注入的辅助信息。
ALL:特殊值,表示接收所有类型的事件(但默认仍不包含 AGENT_RESULT)
StreamOptions 配置
1 | StreamOptions options = StreamOptions.builder() // 选择要接收的事件类型 .eventTypes(EventType.REASONING, EventType.TOOL_RESULT) // true = 增量模式(只发送新增内容),false = 累积模式(每次发送全部已累积内容) .incremental(true) // 是否包含推理过程中间 chunk .includeReasoningChunk(true) // 是否包含最终推理结果(把流式输出的内容拼在一起一次性返回) .includeReasoningResult(false) .build(); |
示例
演示REASONING的输出:
1 |
|
输出内容:
1 | data:{"content":[{"type":"text","text":"我是"}],"id":"bf0b7226-221c-9868-b5a0-595c831149de","metadata":{},"name":"WebAgent","role":"ASSISTANT","timestamp":"2026-05-28 16:04:55.254"} |
这里包含了模型的思考过程,另外还有工具调用的过程,主要包含tool_use不包含tool_result
如果想要过滤工具调用的内容,只展示模型的输出,则可以在输出时做过滤。如:
1 | return agent.stream(userMsg, streamOptions) .subscribeOn(Schedulers.boundedElastic()) .map(event -> event.getMessage().getTextContent()) .filter(text -> text != null && !text.isEmpty()); |
即只输出textContext不为空的内容。
演示TOOL_RESULT的输出:
修改StreamOptions如下:
1 | StreamOptions streamOptions = StreamOptions.builder() // 选择要接收的事件类型 .eventTypes(EventType.REASONING,EventType.TOOL_RESULT) // true = 增量模式(只发送新增内容),false = 累积模式(每次发送全部已累积内容) .incremental(true) // 是否包含最终推理结果(把流式输出的内容拼在一起一次性返回) .includeReasoningResult(false) .build(); |
则页面输出:
1 | .... |
即除了前面的reasoning的内容外,还包含了tool_result的结果,即工具调用的结果。
演示****AGENT_RESULT输出:
StreamOptions修改如下:
1 | StreamOptions streamOptions = StreamOptions.builder() // 选择要接收的事件类型 .eventTypes(EventType.AGENT_RESULT) // true = 增量模式(只发送新增内容),false = 累积模式(每次发送全部已累积内容) .incremental(true) // 是否包含最终推理结果(把流式输出的内容拼在一起一次性返回) .includeReasoningResult(false) .build(); |
这样的话就会直接输出最终结果:
1 | data:{"content":[{"type":"text","text":"现在是北京时间2026年5月28日16时13分14秒,也就是下午四点十三分左右。"}],"id":"bd044b03-0b9f-944e-adb7-404cd312ab85","metadata":{"_chat_usage":{"inputTokens":271,"outputTokens":31,"time":1.17,"totalTokens":302}},"name":"WebAgent","role":"ASSISTANT","timestamp":"2026-05-28 16:13:16.155"} |
但是结果是一次性输出的,只不过以stream的形式包装了一下返回给前端了。
结构化输出
AgentScope Java 提供了开箱即用的结构化输出能力,可以让 Agent 的输出直接映射为 Java POJO 对象。其内部实现是通过 StructuredOutputHook + generate_response 工具模式实现自动纠错——如果模型第一次没有按格式输出,框架会自动重试并引导模型调用指定工具。
关键 API:
agent.call(Msg, Class
) — 指定输出类型,返回包含结构化数据的 Msg agent.stream(msgs, options, Class
) — 流式模式下的结构化输出 msg.getStructuredData(Class
) — 从返回消息中提取结构化对象
示例如下:
1 | package cn.hollis.llm.llmentor.agentscope.controller; |
超时与重试
AgentScope Java 通过 ExecutionConfig 统一管理超时和重试行为。它同时适用于模型 API 调用和工具执行,但两者的默认策略不同。
| Column 1 | Column 2 | Column 3 |
|---|---|---|
| 配置项 | 模型调用默认 (MODEL_DEFAULTS) |
工具执行默认 (TOOL_DEFAULTS) |
| timeout | 5 分钟 | 5 分钟 |
| maxAttempts | 3(1次 + 2次重试) | 1(不重试) |
| initialBackoff | 2 秒 | — |
| maxBackoff | 30 秒 | — |
| backoffMultiplier | 2.0(指数退避) | — |
| retryOn | 429/5xx/超时/网络异常 | — |
框架定义了 RETRYABLE_ERRORS 判断逻辑:
会重试:HTTP 429(限流)、HTTP 5xx(服务器错误)、TimeoutException、IOException(网络错误)
不重试:HTTP 400(参数错误)、401/403(认证错误)、其他 4xx 客户端错误
自定义超时与重试配置
1 | package cn.hollis.llm.llmentor.agentscope.controller; |
除了 ExecutionConfig,底层 HTTP 客户端还有独立的传输超时(HttpTransportConfig):
1 | import io.agentscope.core.model.transport.HttpTransportConfig; |
执行控制
AgentScope Java 提供了三层执行控制机制:迭代次数限制、安全中断、优雅关机。
迭代次数限制
控制 ReAct 循环(Reasoning → Acting → Reasoning → …)的最大轮次。达到上限后自动进入 Summary 阶段生成总结。
1 | ReActAgent agent = ReActAgent.builder() .name("BoundedAgent") .sysPrompt("You are a helpful assistant.") .model(model) .maxIters(5) // 最多5轮 Reasoning-Acting 循环,默认值为10 .build(); |
安全中断
用户或系统可以在任意时刻中断正在执行的 Agent。中断后 Agent 会保留完整上下文(包括内存中的对话和未完成工具调用),并返回恢复消息。
中断源(InterruptSource):
USER — 用户主动中断(如点击”停止”按钮)
TOOL — 工具执行逻辑触发中断(如工具检测到需要人工确认)
SYSTEM — 系统触发(超时、资源限制、优雅关机等)
1 | import io.agentscope.core.ReActAgent; |
优雅关机
适用于服务器部署场景(如 Spring Boot 应用收到kill -15)。系统会等待当前正在执行的 Agent 请求完成或达到超时后安全终止,并自动保存会话状态。
关键配置 GracefulShutdownConfig:
1 | import io.agentscope.core.shutdown.*; |
关机时的安全检查点(在这些点位 Agent 才会被中断):
PostReasoningEvent — 推理完成后
PostActingEvent — 工具执行完成后
PostSummaryEvent — 总结生成完成后
这意味着系统不会粗暴截断正在进行的推理或工具调用,而是等当前阶段完整结束后再发起中断。只有当全局超时耗尽时,才会强制中断。
1 | import io.agentscope.core.shutdown.*; |
通过实现 Hook 接口可以在 Agent 生命周期的各个阶段插入自定义逻辑,包括阻止工具执行、修改输入、记录日志等:
1 | import io.agentscope.core.hook.*; |
