目录
-
- [1. 概述](#1. 概述)
- [2. 环境准备](#2. 环境准备)
-
- [2.1 Maven 依赖](#2.1 Maven 依赖)
- [2.2 API Key](#2.2 API Key)
- [3. ReActAgent 架构](#3. ReActAgent 架构)
-
- [3.1 三种调用方式](#3.1 三种调用方式)
- [3.2 Builder 核心参数](#3.2 Builder 核心参数)
- [4. 第一步:创建模型](#4. 第一步:创建模型)
- [5. 第二步:定义工具](#5. 第二步:定义工具)
-
- [5.1 注解方式](#5.1 注解方式)
- [5.2 接口方式](#5.2 接口方式)
- [6. 第三步:注册工具到 Toolkit](#6. 第三步:注册工具到 Toolkit)
- [7. 第四步:构建 ReActAgent](#7. 第四步:构建 ReActAgent)
- [8. 第五步:调用 Agent](#8. 第五步:调用 Agent)
-
- [8.1 同步调用](#8.1 同步调用)
- [8.2 流式调用(2.0 新 API)](#8.2 流式调用(2.0 新 API))
- [8.3 多轮对话(带 RuntimeContext)](#8.3 多轮对话(带 RuntimeContext))
- [9. 完整 Spring Boot 示例](#9. 完整 Spring Boot 示例)
-
- [9.1 配置类](#9.1 配置类)
- [9.2 控制器](#9.2 控制器)
1. 概述
ReActAgent 是 AgentScope 2.0 的核心推理引擎,实现 ReAct(Reasoning + Acting) 模式------交替进行推理和工具调用,直到得出最终答案。
智能体在每次调用时运行推理-行动循环,下图展示了主要控制流程:
#mermaid-svg-JihK16335oi7sLxw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JihK16335oi7sLxw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JihK16335oi7sLxw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JihK16335oi7sLxw .error-icon{fill:#552222;}#mermaid-svg-JihK16335oi7sLxw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JihK16335oi7sLxw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JihK16335oi7sLxw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JihK16335oi7sLxw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JihK16335oi7sLxw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JihK16335oi7sLxw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JihK16335oi7sLxw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JihK16335oi7sLxw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JihK16335oi7sLxw .marker.cross{stroke:#333333;}#mermaid-svg-JihK16335oi7sLxw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JihK16335oi7sLxw p{margin:0;}#mermaid-svg-JihK16335oi7sLxw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JihK16335oi7sLxw .cluster-label text{fill:#333;}#mermaid-svg-JihK16335oi7sLxw .cluster-label span{color:#333;}#mermaid-svg-JihK16335oi7sLxw .cluster-label span p{background-color:transparent;}#mermaid-svg-JihK16335oi7sLxw .label text,#mermaid-svg-JihK16335oi7sLxw span{fill:#333;color:#333;}#mermaid-svg-JihK16335oi7sLxw .node rect,#mermaid-svg-JihK16335oi7sLxw .node circle,#mermaid-svg-JihK16335oi7sLxw .node ellipse,#mermaid-svg-JihK16335oi7sLxw .node polygon,#mermaid-svg-JihK16335oi7sLxw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JihK16335oi7sLxw .rough-node .label text,#mermaid-svg-JihK16335oi7sLxw .node .label text,#mermaid-svg-JihK16335oi7sLxw .image-shape .label,#mermaid-svg-JihK16335oi7sLxw .icon-shape .label{text-anchor:middle;}#mermaid-svg-JihK16335oi7sLxw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JihK16335oi7sLxw .rough-node .label,#mermaid-svg-JihK16335oi7sLxw .node .label,#mermaid-svg-JihK16335oi7sLxw .image-shape .label,#mermaid-svg-JihK16335oi7sLxw .icon-shape .label{text-align:center;}#mermaid-svg-JihK16335oi7sLxw .node.clickable{cursor:pointer;}#mermaid-svg-JihK16335oi7sLxw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JihK16335oi7sLxw .arrowheadPath{fill:#333333;}#mermaid-svg-JihK16335oi7sLxw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JihK16335oi7sLxw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JihK16335oi7sLxw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JihK16335oi7sLxw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JihK16335oi7sLxw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JihK16335oi7sLxw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JihK16335oi7sLxw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JihK16335oi7sLxw .cluster text{fill:#333;}#mermaid-svg-JihK16335oi7sLxw .cluster span{color:#333;}#mermaid-svg-JihK16335oi7sLxw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JihK16335oi7sLxw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JihK16335oi7sLxw rect.text{fill:none;stroke-width:0;}#mermaid-svg-JihK16335oi7sLxw .icon-shape,#mermaid-svg-JihK16335oi7sLxw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JihK16335oi7sLxw .icon-shape p,#mermaid-svg-JihK16335oi7sLxw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JihK16335oi7sLxw .icon-shape .label rect,#mermaid-svg-JihK16335oi7sLxw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JihK16335oi7sLxw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JihK16335oi7sLxw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JihK16335oi7sLxw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 行动
是
否
退出
推理
无工具调用
允许
询问 / 外部
拒绝
有工具调用
输入: 消息 / 事件
等待
外部事件?
处理事件
更新工具状态
将消息添加到上下文
检查下一步动作
返回: 等待
外部交互
必要时压缩上下文
LLM 调用
返回最终消息
批量工具调用
串行 / 并发
执行工具调用
权限
检查
运行工具 → 结果
暂停并发出
RequireUserConfirmEvent
将错误结果返回 LLM
2. 环境准备
2.1 Maven 依赖
xml
<properties>
<agentscope.version>2.0.1</agentscope.version>
</properties>
<dependencies>
<!-- AgentScope 2.0 核心(含 ReActAgent + Model + Toolkit) -->
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-core</artifactId>
<version>${agentscope.version}</version>
</dependency>
</dependencies>
2.2 API Key
bash
export DASHSCOPE_API_KEY=sk-your-key-here
3. ReActAgent 架构
#mermaid-svg-rE61p6szBREGM5dY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rE61p6szBREGM5dY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rE61p6szBREGM5dY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rE61p6szBREGM5dY .error-icon{fill:#552222;}#mermaid-svg-rE61p6szBREGM5dY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rE61p6szBREGM5dY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rE61p6szBREGM5dY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rE61p6szBREGM5dY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rE61p6szBREGM5dY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rE61p6szBREGM5dY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rE61p6szBREGM5dY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rE61p6szBREGM5dY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rE61p6szBREGM5dY .marker.cross{stroke:#333333;}#mermaid-svg-rE61p6szBREGM5dY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rE61p6szBREGM5dY p{margin:0;}#mermaid-svg-rE61p6szBREGM5dY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rE61p6szBREGM5dY .cluster-label text{fill:#333;}#mermaid-svg-rE61p6szBREGM5dY .cluster-label span{color:#333;}#mermaid-svg-rE61p6szBREGM5dY .cluster-label span p{background-color:transparent;}#mermaid-svg-rE61p6szBREGM5dY .label text,#mermaid-svg-rE61p6szBREGM5dY span{fill:#333;color:#333;}#mermaid-svg-rE61p6szBREGM5dY .node rect,#mermaid-svg-rE61p6szBREGM5dY .node circle,#mermaid-svg-rE61p6szBREGM5dY .node ellipse,#mermaid-svg-rE61p6szBREGM5dY .node polygon,#mermaid-svg-rE61p6szBREGM5dY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rE61p6szBREGM5dY .rough-node .label text,#mermaid-svg-rE61p6szBREGM5dY .node .label text,#mermaid-svg-rE61p6szBREGM5dY .image-shape .label,#mermaid-svg-rE61p6szBREGM5dY .icon-shape .label{text-anchor:middle;}#mermaid-svg-rE61p6szBREGM5dY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rE61p6szBREGM5dY .rough-node .label,#mermaid-svg-rE61p6szBREGM5dY .node .label,#mermaid-svg-rE61p6szBREGM5dY .image-shape .label,#mermaid-svg-rE61p6szBREGM5dY .icon-shape .label{text-align:center;}#mermaid-svg-rE61p6szBREGM5dY .node.clickable{cursor:pointer;}#mermaid-svg-rE61p6szBREGM5dY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rE61p6szBREGM5dY .arrowheadPath{fill:#333333;}#mermaid-svg-rE61p6szBREGM5dY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rE61p6szBREGM5dY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rE61p6szBREGM5dY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rE61p6szBREGM5dY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rE61p6szBREGM5dY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rE61p6szBREGM5dY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rE61p6szBREGM5dY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rE61p6szBREGM5dY .cluster text{fill:#333;}#mermaid-svg-rE61p6szBREGM5dY .cluster span{color:#333;}#mermaid-svg-rE61p6szBREGM5dY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rE61p6szBREGM5dY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rE61p6szBREGM5dY rect.text{fill:none;stroke-width:0;}#mermaid-svg-rE61p6szBREGM5dY .icon-shape,#mermaid-svg-rE61p6szBREGM5dY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rE61p6szBREGM5dY .icon-shape p,#mermaid-svg-rE61p6szBREGM5dY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rE61p6szBREGM5dY .icon-shape .label rect,#mermaid-svg-rE61p6szBREGM5dY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rE61p6szBREGM5dY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rE61p6szBREGM5dY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rE61p6szBREGM5dY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ReActAgent
是
否
ReActAgent
Model
(推理引擎)
Toolkit
(工具注册表)
AgentStateStore
(状态持久化,可选)
call()
stream()
streamEvents()
doCall(msgs)
核心推理循环
while (未完成)
- reasoning()
→ Model.stream()
2. acting()
→ Toolkit.callTools()
3. summarizing()
→ 上下文压缩(可选)
返回最终结果
3.1 三种调用方式
| 方法 | 返回类型 | 适用场景 |
|---|---|---|
call(List<Msg>) |
Mono<Msg> |
同步等待完整结果 |
stream(List<Msg>, StreamOptions) |
Flux<Event> |
流式观察(2.0 已废弃) |
streamEvents(List<Msg>) |
Flux<AgentEvent> |
2.0 新 API------27 种细粒度事件 |
3.2 Builder 核心参数
java
ReActAgent agent = ReActAgent.builder()
.name("my-agent") // Agent 名称(必填)
.model(model) // 语言模型(必填)
// 或字符串形式:.model("dashscope://qwen-max")
.toolkit(toolkit) // 工具注册表(可选)
.sysPrompt("你是一个有用的 AI 助手,用中文回答。") // 系统提示词
.maxIters(5) // 最大推理迭代次数
.build();
4. 第一步:创建模型
java
Model model = Model.builder()
.provider("dashscope")
.model("qwen-max")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.build();
5. 第二步:定义工具
5.1 注解方式
java
public class WeatherTool {
@Tool(name = "get_weather", description = "查询指定城市的天气")
public String getWeather(@Param("city") String city) {
// 调用天气 API 并返回结果
return "今天 " + city + " 晴,25℃";
}
}
5.2 接口方式
java
public class CalculatorTool implements Tool {
@Override
public String getName() { return "calculator"; }
@Override
public String getDescription() { return "执行四则运算"; }
@Override
public Object call(Map<String, Object> args) {
double a = (double) args.get("a");
double b = (double) args.get("b");
String op = (String) args.get("op");
switch (op) {
case "+": return a + b;
case "-": return a - b;
case "*": return a * b;
case "/": return a / b;
default: throw new IllegalArgumentException("不支持的操作符: " + op);
}
}
}
6. 第三步:注册工具到 Toolkit
java
Toolkit toolkit = Toolkit.builder()
.addTool(new WeatherTool())
.addTool(new CalculatorTool())
.build();
7. 第四步:构建 ReActAgent
java
ReActAgent agent = ReActAgent.builder()
.name("demo-agent")
.model(model)
.toolkit(toolkit)
.sysPrompt("你是一个有用的 AI 助手,用中文回答。")
.maxIters(5)
.build();
8. 第五步:调用 Agent
8.1 同步调用
java
Msg msg = Msg.builder()
.role(MsgRole.USER)
.content(List.of(TextBlock.builder().text("北京今天天气怎么样?").build()))
.build();
Msg response = agent.call(List.of(msg)).block();
System.out.println(response.getTextContent());
8.2 流式调用(2.0 新 API)
java
agent.streamEvents(List.of(msg))
.filter(e -> e instanceof TextBlockDeltaEvent)
.map(e -> ((TextBlockDeltaEvent) e).getDelta())
.subscribe(System.out::print);
8.3 多轮对话(带 RuntimeContext)
java
RuntimeContext context = RuntimeContext.create();
Msg first = Msg.builder().role(MsgRole.USER).content("帮我算 3+5").build();
Msg r1 = agent.call(List.of(first), context).block();
Msg second = Msg.builder().role(MsgRole.USER).content("再乘以 2").build();
Msg r2 = agent.call(List.of(second), context).block();
9. 完整 Spring Boot 示例
9.1 配置类
java
@Configuration
public class AgentConfig {
@Bean
public Model model() {
return Model.builder()
.provider("dashscope")
.model("qwen-max")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.build();
}
@Bean
public Toolkit toolkit() {
return Toolkit.builder()
.addTool(new WeatherTool())
.addTool(new CalculatorTool())
.build();
}
@Bean
public ReActAgent agent(Model model, Toolkit toolkit) {
return ReActAgent.builder()
.name("demo-agent")
.model(model)
.toolkit(toolkit)
.sysPrompt("你是一个有用的 AI 助手,用中文回答。")
.maxIters(5)
.build();
}
}
9.2 控制器
java
@RestController
public class AgentController {
private final ReActAgent agent;
// 同步
@GetMapping("/call")
public Mono<Map<String, Object>> call(@RequestParam String query) {
Msg msg = Msg.builder().role(MsgRole.USER)
.content(List.of(TextBlock.builder().text(query).build()))
.build();
return agent.call(List.of(msg))
.map(r -> Map.of("query", query, "response", r.getTextContent()));
}
// 流式
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> stream(@RequestParam String query) {
Msg msg = Msg.builder().role(MsgRole.USER)
.content(List.of(TextBlock.builder().text(query).build()))
.build();
return agent.streamEvents(List.of(msg))
.filter(e -> e instanceof TextBlockDeltaEvent)
.map(e -> "data: " + ((TextBlockDeltaEvent) e).getDelta() + "\n\n");
}
}