---
title: "react - ReActInterceptor  拦截器"
---


### 1、内置拦截器


| 拦截器 | 名称 | 描述 |
| -------- | -------- | -------- |
| HITLInterceptor     | 人工介入拦截器     | 该拦截器通过 ReAct 协议的生命周期钩子实现流程管控     |
| StopLoopInterceptor     | 逻辑死循环拦截器     | 该拦截器通过监控 LLM 的输出内容指纹，防止智能体陷入无效的迭代循环     |
| ContextCompressionInterceptor     | 智能上下文压缩拦截器     | 该拦截器通过“滑动窗口”机制，在保证 ReAct 逻辑链完整性的前提下，对 ReActTrace 历史消息进行截断压缩。     |
| ToolRetryInterceptor     | 工具执行重试拦截器     | 该拦截器为 ReAct 模式下的工具调用提供韧性支持，具备物理重试与逻辑自愈双重机制。     |
| ToolSanitizerInterceptor     | 工具结果净化拦截器     | 该拦截器在 ReAct 模式的 Observation 阶段执行，负责对工具返回的原始数据进行加工。     |


### 2、注册与启停

拦截器通过 `options` 注册，支持指定顺序（index 越小越先执行）：

```java
ReActAgent agent = ReActAgent.of(chatModel)
        .options(o -> o
                .interceptorAdd(new ContextCompressionInterceptor())
                .interceptorAdd(new MyAuditInterceptor(), 100))
        .build();
```

自定义拦截器建议继承 `AbsReActInterceptor`（4.0.0+），它实现了 `isEnabled()` / `setEnabled()`，可在运行期动态开关：

```java
public class MyAuditInterceptor extends AbsReActInterceptor {
    @Override
    public void onToolCallStart(ReActTrace trace, ToolExchanger toolExchanger) {
        //权限预检、参数合法性校验
    }
}
```

若直接实现 `ReActInterceptor` 接口，`isEnabled()` 默认返回 `true`，`setEnabled()` 为空实现（即无法关闭）。

> 注意：`isEnabled()` 由框架在调用各时机点前检查，但覆盖并不完全。`onReasonEnd`、`onThought` 目前不受 enabled 开关约束，编写时不要把“关闭即完全静默”当作前提。


### 3、ReActInterceptor 各时机点说明

时机点按一轮 ReAct 循环的真实执行顺序排列：


| 层级 | 拦截方法 | 触发时机 | 典型应用场景 |
| -------- | -------- | -------- | -------- |
| 智能体级     | onAgentStart     | 智能体开始运行（初始化后）     |  记录全流程追踪 ID、预加载 Session 数据     |
|       | onAgentEnd     | 智能体完成任务（Final Answer）或达到步数限制     |  统计总 Token 消耗、清理临时资源、持久化轨迹     |
|   循环级（Reason）    | onReasonStart     | systemPrompt 构建完成、消息组装之前     |   上下文压缩、工作记忆窗口管理、注入动态指令（可直接改写 systemPromptBuf）    |
|       | onReasonRetry     | Reason 请求失败且即将重试前（4.0.4+）     |   按异常收紧上下文（如 Token 超限时加大压缩力度）；返回 true 表示已改写上下文，下一次尝试会重新组装消息    |
|       | onReasonEnd     | 接收到 LLM 返回的完整推理消息，尚未拆解为具体 Action/Thought 之前      |   解析自定义标签（如非标准 Action 解析）、手动截断推理过程、提取推理元数据、统计单轮耗时    |
|      | onThought     | （4.0.4 弃用，改用 onReasonEnd）模型推理结果解析出 Thought 部分时     |  UI 打字机效果展示、记录思维链（CoT）日志     |
|   循环级（Action）    | onActionStart     | 本轮全部工具调用解析完成、逐个执行之前（4.0.4+）     |   批量审批（HITL 批挂起）、整体权限校验、批量改参    |
|       | onToolCallStart     | 单个工具调用执行前     |   单工具权限控制、参数合法性预检    |
|        | onPlan     | 规划模式下，模型调用 create_plan / update_plan_progress 时（属于工具执行过程）      |    审核并修正智能体生成的行动计划，注入强制约束    |
|       | onToolCallEnd     | 单个工具执行完成后（强闭环，位于 finally 块）     |   观测外部系统返回数据、敏感信息脱敏、数据清洗、改写 result    |
|       | onObservation     | （4.0.4 弃用，改用 onToolCallEnd）同上     |  同上     |
|       | onActionEnd     | 本轮全部工具执行完毕后（4.0.4+；会话挂起时不触发）     |   批量结果汇总、清理批次状态    |

关于强闭环：`onToolCallEnd` 放在 `finally` 块中，无论成功、失败、挂起、中断都保证被调用。而 `onActionEnd` 在会话挂起（Pending）时会被跳过，避免前端误判本轮 Action 已执行完毕。

由于 ReActInterceptor 具备多重身份，还可以覆盖以下底层方法实现更精细的控制：


| 继承自 | 拦截方法 | 作用描述 |
| -------- | -------- | -------- |
| ChatInterceptor     | onPrepare     | 在构建 ChatModel 请求之前触发，可动态调整 ChatOptions、追加系统指令。     |
| ChatInterceptor     | interceptCall     | 作用于最底层的 ChatModel 同步调用，可直接操作底层的 ChatRequest/Response。     |
| ChatInterceptor     | interceptStream     | 作用于最底层的 ChatModel 流式调用。     |
| ToolInterceptor     | interceptTool     | 最实用的扩展点：可以直接拦截工具的执行链。例如：如果某工具返回 404，拦截器可以直接伪造一个“请检查参数”的返回给模型。     |
| ToolInterceptor     | isEnabled / setEnabled     | 拦截器启停开关。     |


### 4、ReActInterceptor 拦截器接口参考

ReActInterceptor 同时继承了 `AgentInterceptor` 和 `ChatInterceptor`（而 ChatInterceptor 又继承 `ToolInterceptor`），所以它除了 ReAct 生命周期，还可以拦截聊天模型（ChatModel）与工具（Tool）的执行。


ReActInterceptor

```java
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.lang.Nullable;
import org.noear.solon.lang.Preview;

import java.util.Collection;

/**
 * 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 error         执行异常（成功时为 null）
     * @param durationMs    工具执行耗时（毫秒）
     */
    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 error         执行异常（成功时为 null）
     * @param durationMs    工具执行耗时（毫秒）
     * @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
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);
    }
}
```


ToolInterceptor


```java
package org.noear.solon.ai.chat.interceptor;

import org.noear.solon.ai.chat.tool.ToolResult;

/**
 * 工具拦截器
 *
 * @author noear
 * @since 3.8.1
 */
public interface ToolInterceptor {
    /**
     * 是否启用
     */
    default boolean isEnabled() {
        return true;
    }

    /**
     * 设置是否启用
     */
    default void setEnabled(Boolean enabled) {

    }

    /**
     * 拦截工具调用
     *
     * @param req   请求
     * @param chain 拦截链
     */
    default ToolResult interceptTool(ToolRequest req, ToolChain chain) throws Throwable {
        return chain.doIntercept(req);
    }
}
```
