Solon v3.9.0

react - ReActInterceptor 拦截器

</> markdown
2026年1月24日 下午9:14:59

1、内置拦截器

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

2、ReActInterceptor 各时机点说明

层级拦截方法触发时机典型应用场景
智能体级onAgentStart智能体开始运行(初始化后)记录全流程追踪 ID、预加载 Session 数据
onAgentEnd智能体完成任务(Final Answer)或达到步数限制统计总 Token 消耗、清理临时资源、持久化轨迹
模型级onModelStart向 LLM 发起单次推理请求之前动态注入 Stop 词、修改温度参数、Prompt 安全检测
onModelEnd获取到模型响应,但尚未开始解析逻辑时内容风险过滤、检测“复读机”死循环、原始响应存档
循环级onReason接收到 LLM 返回的完整推理消息,尚未拆解为具体 Action/Thought 之前。正则解析自定义标签(如非标准 Action 解析)、手动截断推理过程、提取推理元数据。
onThought模型推理结果解析出 Thought 部分时UI 打字机效果展示、记录思维链(CoT)日志
onAction模型解析出工具调用(Action),执行前触发工具调用权限校验、参数格式二次修正、计费预警
onObservation工具执行完毕,获取到结果(Observation)后观测外部系统返回数据、敏感信息脱敏、数据清洗

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

继承自拦截方法作用描述
FlowInterceptorinterceptFlow拦截底层的 FlowEngine 执行,可以控制整个执行图是否启动。
onNodeStart拦截 ReAct 流程图中各个具体节点(如 ReasoningNode)的开始。
onNodeEnd拦截 ReAct 流程图中各个具体节点(如 ReasoningNode)的开始
ChatInterceptorinterceptCall作用于最底层的 ChatModel 调用,可直接操作底层的 ChatRequest/Response。
ToolInterceptorinterceptTool最实用的扩展点:可以直接拦截工具的执行链。例如:如果某工具返回 404,拦截器可以直接伪造一个“请检查参数”的返回给模型。

3、ReActInterceptor 拦截器接口参考

ReActInterceptor 拦截器,同时继承了 FlowInterceptor 和 ChatInterceptor,所以它还可以拦截流程图(Flow)和聊天模型(ChatModel)的执行。

ReActInterceptor

import org.noear.solon.ai.chat.ChatRequestDesc;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.ai.chat.interceptor.ChatInterceptor;
import org.noear.solon.flow.intercept.FlowInterceptor;
import org.noear.solon.lang.Preview;

import java.util.Map;

/**
 * ReAct 拦截器
 * <p>提供对 ReAct 智能体执行全生命周期的监控与干预能力。包括智能体起止、模型推理前后以及工具执行环。</p>
 */
public interface ReActInterceptor extends AgentInterceptor, FlowInterceptor, ChatInterceptor {

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

    /**
     * 模型推理周期:发起 LLM 请求前
     * <p>可用于动态修改请求参数、Stop 词或注入 Context</p>
     */
    default void onModelStart(ReActTrace trace, ChatRequestDesc req) {
    }

    /**
     * 模型推理周期:LLM 响应后
     * <p>常用于死循环(复读)检测或原始响应审计</p>
     */
    default void onModelEnd(ReActTrace trace, ChatResponse resp) {
    }

    /**
     * 推理节点:接收 LLM 返回的原始推理消息
     */
    default void onReason(ReActTrace trace, AssistantMessage message) {
    }

    /**
     * 推理节点:解析出思考内容 (Thought) 时触发
     */
    default void onThought(ReActTrace trace, String thought) {
    }

    /**
     * 动作节点:调用功能工具 (Action) 前触发
     * <p>可用于权限控制、参数合法性预检</p>
     */
    default void onAction(ReActTrace trace, String toolName, Map<String, Object> args) {
    }

    /**
     * 观察节点:工具执行返回结果 (Observation) 后触发
     */
    default void onObservation(ReActTrace trace, String result) {
    }

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

FlowInterceptor


import org.noear.solon.flow.*;
import org.noear.solon.lang.Preview;

/**
 * 流拦截器
 */
public interface FlowInterceptor {
    /**
     * 拦截流程执行, eval(graph)
     *
     * @param invocation 调用者
     * @see org.noear.solon.flow.FlowEngine#eval(Graph, FlowExchanger)
     */
    default void interceptFlow(FlowInvocation invocation) throws FlowException {
        invocation.invoke();
    }

    /**
     * 节点运行开始时
     *
     * @since 3.4
     */
    default void onNodeStart(FlowContext context, Node node) {

    }

    /**
     * 节点运行结束时
     *
     * @since 3.4
     */
    default void onNodeEnd(FlowContext context, Node node) {

    }
}

ChatInterceptor

import org.noear.solon.ai.chat.ChatRequest;
import org.noear.solon.ai.chat.ChatResponse;
import org.reactivestreams.Publisher;

import java.io.IOException;

/**
 * 聊天拦截器
 */
public interface ChatInterceptor extends ToolInterceptor {
    /**
     * 拦截 Call 请求
     *
     * @param req   请求
     * @param chain 拦截链
     */
    default ChatResponse interceptCall(ChatRequest req, CallChain chain) throws IOException {
        return chain.doIntercept(req);
    }

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