---
title: "react - ReActAgent 配置与构建"
---

`ReActAgent` 采用 “Planning + Reasoning + Acting（规划 + 推理 + 行动）” 闭环模式。它能够根据用户目标，自主思考（Thought）、选择工具执行动作（Action）、观察结果（Observation），直至完成任务。



| 分类     | 参数名称                  | 类型            | 默认值      | 说明                                                            |
|----------|---------------------------|-----------------|-------------|-----------------------------------------------------------------|
| 身份定义 | name                      | String          | react_agent | 智能体唯一标识，决定了 Session 存储中的 `TraceKey（__name）`。  |
|          | role                      | String          | /           | 核心字段。角色描述，帮助模型识别自身角色或供团队调度。          |
|          | profile                   | AgentProfile    | /           | 核心字段。挡案描述，帮助模型识别自身角色或供团队调度。          |
| 决策大脑 | chatModel                 | ChatModel       | /           | 充当大脑，负责理解需求、分派任务与总结。                        |
|          | modelOptions              | Consumer        | /           | 用于精细控制模型的参数（如调低 Temperature 以稳健决策）。       |
|          | instruction               | String          | 中文模板    | 核心指令。告诉模型要怎么做，要注意什么。                        |
|          | systemPrompt              | String          | /           | 系统提示词（与 role + instruction 互为替代）。                  |
| 执行控制 | maxTurns                  | int             | 5           | 单次任务允许的最大推理步数，防止成员间无限"思考"导致死循环。    |
|          | retryConfig               | int, long       | 3, 1000L    | 决策失败或解析异常时的自动重试次数及延迟。                      |
|          | autoRethink               | boolean         | false       | 无法得出答案时是否自动重新思考                                  |
| 存储输出 | sessionWindowSize         | int             | 10          | 记忆窗口大小。加载最近 N 条历史消息作为上下文。                 |
|          | outputKey                 | String          | /           | 任务结束后的结果回填至 `FlowContext` 的键名。                   |
|          | outputSchema              | String/Type     | /           | 结构化输出。约束输出格式（JSON Schema），确保结果符合业务预期。 |
| 扩展定制 | interceptors              | `List`          | /           | 生命周期拦截器，用于监控思考过程、工具调用等过程。              |
|          | tools                     | `Map`           | /           | 工具。                                                          |
|          | toolContext               | `Map`           | /           | 工具调用时共享的上下文数据（如数据库连接、用户信息）。          |
|          | talents                   | `List`          | /           | 才能。                                                          |
|          | attr(name, val)           | String, Object  | -           | 设置单个自定义属性，运行时可读取，@since 4.0.4                  |
|          | attrs(vals)               | Map             | -           | 批量设置自定义属性，@since 4.0.4                                |
| 运行模式 | planningMode              | boolean         | false       | 推理前先制定执行计划（Plan-ReAct 模式）                         |
|          | planningInstruction       | String/Function | -           | 自定义规划指令                                                  |
|          | feedbackMode              | boolean         | false       | 允许主动寻求外部帮助/人工介入                                   |
|          | feedbackDescription       | String/Function | -           | 反馈描述                                                        |
|          | feedbackReasonDescription | String/Function | -           | 反馈原因描述                                                    |

关键配置点补充说明

- 关于职责描述 (description)：在 ReActAgent 中，描述不仅是给人看的，更是给"模型"看的。一个清晰的描述能让模型更准确地判断何时该调用什么工具。
- 关于终止标识 (finishMarker)：系统会根据 `name` 自动生成。当模型认为任务已达成，输出该标识后，Agent 将提取内容作为最终答复。
- 关于最大推理回合数 (maxTurns)：在推理协作中，模型可能会产生反复确认或死循环。该参数是"保险丝"，确保系统不会因为无限对话而耗尽 Token。




### 2、ReActAgent 构建

- 基础版：具备工具能力的智能体

适用于逻辑固定的线性任务。赋予智能体一组工具，让其自主调度解决问题。

```java
// 创建一个具备数据库查询能力的智能体
ReActAgent dbAgent = ReActAgent.of(chatModel)
     .name("data_helper")
     .role("数据助手，负责查询用户信息及订单状态")
     // 1. 注入工具（支持注解方法或 FunctionTool 实例）
     .defaultToolAdd(new MyUserTools())
     // 2. 限制步数防止死循环
     .maxTurns(5)
     .autoRethink(true)
     .build();

// 执行：模型会根据问题判断是否需要调用工具
String result = dbAgent.prompt("帮我查一下用户 ID 为 1001 的最近一笔订单金额")
     .call()
     .getContent();

```

- 进阶版：精细化控制专家团队

这是一个包含重试策略、拦截监控及性能调优的复杂示例。

```java
// 创建一个全能的技术支持专家
ReActAgent techAgent = ReActAgent.of(chatModel)
     // --- 1. 身份与职责定义 ---
     .name("tech_support_expert")
     .role("技术支持专家（负责处理复杂的客户技术问题，包括查询数据库和排查日志）")
    
     // --- 2. 注入工具与重试策略 ---
     .defaultToolAdd(dbTool)
     .defaultToolAdd(logTool)
     .retryConfig(3, 2000L) // 决策失败自动重试
     .maxTurns(12) // 允许最多 12 步推理，处理深度问题
     .autoRethink(true) //启用自我反思（由 llm 决定超过 maxTurns 后，还要不要继续）
    
     // --- 3. 配置决策大脑的运行策略 ---
     .modelOptions(options -> {
        options.temperature(0.1); // 调低温度，让决策更严谨
     })
    
     // --- 4. 插入定制化逻辑 ---
     .defaultInterceptorAdd(new ReActInterceptor() {
     @Override
     public void onThought(ReActTrace trace, String thoughtContent, AssistantMessage assistantMessage) {
        System.out.println("🤖 思考中: " + thoughtContent);
     }
    
     @Override
     public void onAction(ReActTrace trace, ToolExchanger toolExchanger) {
        System.out.println("🛠️ 执行工具: " + toolExchanger.getToolName() + "，参数: " + toolExchanger.getArgs());
     }
     })
     .build();

// 执行调用：模型会分析问题，决定先查数据，再分析情况
String finalAnswer = techAgent.prompt("用户 ID 为 9527 的反馈登录失败，请排查原因并给出建议。").call().getContent();
```



### 3、ReActInterceptor 接口参考


```java
/*
 * Copyright 2017-2025 noear.org and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.noear.solon.ai.agent.react;

import org.noear.solon.ai.agent.AgentInterceptor;
import org.noear.solon.ai.agent.react.task.ToolExchanger;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.ai.chat.interceptor.ChatInterceptor;
import org.noear.solon.ai.chat.message.AssistantMessage;
import org.noear.solon.ai.chat.message.ChatMessage;
import org.noear.solon.ai.chat.tool.ToolCall;
import org.noear.solon.lang.Nullable;
import org.noear.solon.lang.Preview;

import java.util.Collection;
import java.util.List;

/**
 * ReAct 智能体拦截器
 * <p>提供对智能体起止、模型推理、工具执行等全生命周期的监控与干预能力</p>
 *
 * @author noear
 * @since 3.8.1
 */
@Preview("3.8.1")
public interface ReActInterceptor extends AgentInterceptor, ChatInterceptor {

    /**
     * 智能体生命周期：开始执行前
     */
    default void onAgentStart(ReActTrace trace) {
    }

    /**
     * 推理节点：Reason 阶段开始前（在 systemPrompt 构建和消息组装之前触发）
     * <p>适合做上下文压缩、工作记忆窗口管理等预处理操作</p>
     */
    default void onReasonStart(ReActTrace trace, StringBuilder systemPromptBuf) {
    }

    /**
     * 推理节点：Reason 请求失败且即将再次尝试时触发。
     * <p>拦截器可以在此根据异常调整 WorkingMemory。返回 true 表示已为下一次请求
     * 修改了请求上下文；ReasonTask 会在下一次尝试中重新组装消息和请求。</p>
     *
     * @param trace        当前推理追踪
     * @param error        本次请求异常
     * @param attempt      即将进行的尝试序号（从 1 开始）
     * @param systemPrompt 当前 Reason 使用的系统提示词
     * @return 是否修改了下一次请求所依赖的上下文
     * @since 4.0.4
     */
    default boolean onReasonRetry(ReActTrace trace, Throwable error, int attempt, String systemPrompt) {
        return false;
    }


    /**
     * 推理节点：接收 LLM 返回的原始推理消息
     */
    default void onReasonEnd(ReActTrace trace, ChatResponse resp, AssistantMessage message, long durationMs) {
    }

    /**
     * 计划节点：接收 LLM 返回的原始推理消息
     */
    default void onPlan(ReActTrace trace, AssistantMessage message) {

    }

    /**
     * @since 4.0.4
     */
    default void onActionStart(ReActTrace trace, Collection<ToolExchanger> toolCalls) {

    }

    /**
     * 动作节点：调用功能工具 (Action) 前触发
     * <p>可用于权限控制、参数合法性预检</p>
     */
    default void onToolCallStart(ReActTrace trace, ToolExchanger toolExchanger) {
    }

    /**
     * 观察节点：工具执行完成后触发（100% 强闭环，放在 finally 块中）
     * <p>无论成功、失败、挂起、中断，此方法保证被调用</p>
     *
     * @param trace         ReAct 追踪上下文
     * @param toolExchanger 工具交换器（含 toolName、args、result）
     * @param observation   观察结果消息（成功时为工具输出，失败时为错误描述；挂起/中断时为空消息）
     * @param durationMs    工具执行耗时（毫秒）
     * @param error         执行异常（成功时为 null）
     */
    default void onToolCallEnd(ReActTrace trace, ToolExchanger toolExchanger,
                               @Nullable ChatMessage observation,
                               @Nullable Throwable error,
                               long durationMs) {
    }

    /**
     * @since 4.0.4
     */
    default void onActionEnd(ReActTrace trace, Collection<ToolExchanger> toolCalls) {

    }

    /**
     * 智能体生命周期：任务结束（成功或异常中止）时触发
     */
    default void onAgentEnd(ReActTrace trace) {
    }

    //-------------------



    /**
     * 思考节点：Reason 阶段完成后触发
     * <p>无论是否解析出有效的 thoughtContent，此方法都会被调用</p>
     *
     * @param trace            ReAct 追踪上下文
     * @param thoughtContent   提取后的思考内容（可能为空字符串）
     * @param assistantMessage 原始 LLM 响应消息（含 toolCalls、content、reasoning 等完整信息）
     * @deprecated 4.0.4 {@link #onReasonEnd(ReActTrace, ChatResponse, AssistantMessage, long)}
     */
    @Deprecated
    default void onThought(ReActTrace trace, String thoughtContent, AssistantMessage assistantMessage) {
    }

    /**
     * 动作节点：调用功能工具 (Action) 前触发
     * <p>可用于权限控制、参数合法性预检</p>
     *
     * @deprecated 4.0.4 {@link #onToolCallStart(ReActTrace, ToolExchanger)}
     */
    @Deprecated
    default void onAction(ReActTrace trace, ToolExchanger toolExchanger) {
    }

    /**
     * 观察节点：工具执行完成后触发（100% 强闭环，放在 finally 块中）
     * <p>无论成功、失败、挂起、中断，此方法保证被调用</p>
     *
     * @param trace         ReAct 追踪上下文
     * @param toolExchanger 工具交换器（含 toolName、args、result）
     * @param observation   观察结果消息（成功时为工具输出，失败时为错误描述；挂起/中断时为空消息）
     * @param durationMs    工具执行耗时（毫秒）
     * @param error         执行异常（成功时为 null）
     * @deprecated 4.0.4 {@link #onToolCallEnd(ReActTrace, ToolExchanger, ChatMessage, Throwable, long)}
     */
    @Deprecated
    default void onObservation(ReActTrace trace, ToolExchanger toolExchanger,
                               @Nullable ChatMessage observation,
                               @Nullable Throwable error,
                               long durationMs) {
    }
}
```



* ChatInterceptor


```java
/*
 * Copyright 2017-2025 noear.org and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.noear.solon.ai.chat.interceptor;

import org.noear.solon.ai.chat.ChatOptions;
import org.noear.solon.ai.chat.ChatRequest;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.ai.chat.ChatSession;
import org.noear.solon.ai.chat.prompt.Prompt;
import reactor.core.publisher.Flux;

import java.io.IOException;

/**
 * 聊天拦截器
 *
 * @author noear
 * @since 3.3
 */
public interface ChatInterceptor extends ToolInterceptor {
    /**
     * 预处理（在构建请求之前触发）
     * <p>用于动态调整配置、补充或修改提示词（Prompt）以及注入系统指令</p>
     *
     * @param session        当前聊天会话（可用于获取历史消息、元数据或状态标记）
     * @param options        聊天配置（可修改，影响模型参数等）
     * @param originalPrompt 原始提示词（包含用户消息和上下文）
     * @param systemMessage  系统指令容器（可追加，将作为 System Message 发送）
     */
    default void onPrepare(ChatSession session, ChatOptions options, Prompt originalPrompt, StringBuilder systemMessage){

    }

    /**
     * 拦截 Call 请求
     *
     * @param req   请求
     * @param chain 拦截链
     */
    default ChatResponse interceptCall(ChatRequest req, CallChain chain) throws IOException {
        return chain.doIntercept(req);
    }

    /**
     * 拦截 Stream 请求
     *
     * @param req   请求
     * @param chain 拦截链
     */
    default Flux<ChatResponse> interceptStream(ChatRequest req, StreamChain chain) {
        return chain.doIntercept(req);
    }
}
```