长任务场景下 ReAct Agent 的可靠终止机制设计与实现

历史问题描述

历史ReAct设计:根据think + act来实现的,think则是进行ai call,何时进行act 是看ai call的结果中是否有tool call。

img

按照该历史设计思路,对于判断思考是否要执行,强硬的直接以是否有tools调用来作为判断了,这个偏差太大,仅仅使用是否有tool调用来判断ReAct任务停止时不可靠的。【实际在长任务过程中无法直接以没有tool调用作为运行结束的情况,需要新增finish tool来间接实现】

优化设计思路

优化设计流程图

img

image.png

实现内容

封装一个FinishTool

image.png

使用这个tool的时机?

1)系统提示词中需要增加stop tool的使用

image-20260217002452805

/**
 * 任务完成调用工具提示语
 */
public static final String STOP_TOOL_PROMPT = String.format("""

        请确认目标问题是否已经处理完成,若是已完成可以使用工具:
        - %s:%s
        """, TASK_FINISHED_TOOL_NAME, TASK_FINISHED_TOOL_DESCRIPTION);

2)在think过程里针对最后一条message为aimessage时需要加强暗示

在react框架下的think中,进行ai call前,若是一组消息的最后一条为aimessage 表示最近的一次没有进行function call 就很有可能是执行结束了。

image-20260217002558985

此时我们会去主动插入一条usermessage,如下:

private void checkNeedAddToolStopPrompt(List<ChatMessage> curCallMessages) {
    if (!CollectionUtils.isEmpty(curCallMessages)) {
        // 若是最后一条消息是ai回复内容 而非tool调用,此时需要任务加上一个提示,让其确认是否完成任务了!
        if (curCallMessages.get(curCallMessages.size() -1) instanceof AiMessage) {
            // 若最后一条消息是工具执行结果,则需要添加一个思考消息,提示模型继续思考
            log.debug("[DynamicAgent.think] 上一次行动后,添加思考消息,提示模型继续思考");
            curCallMessages.add(UserMessage.from(AgentGlobalConstant.STOP_TOOL_PROMPT));
        }
    }
}

对于STOP_TOOL_PROMPT的提示词就是1)中的部分。

支持参数开启选择stop tool

默认的话开启的,在ReActAgent中设计了一个AgentSettings:

private final AgentSettings agentSettings;

public class AgentSettings {
    // 最大执行步骤数量
    private final int maxSteps;
    // ai call执行失败 重试次数
    private final int aiCallRetry;
    // 默认ai call重试 超时等待 10秒
    private final long aiCallRetryDelay;
    // 是否需要使用stop tool,若是不需要,直接根据返回ai message判断
    private final boolean isNeedStopTool;

    private AgentSettings(Builder builder) {
        this.maxSteps = CommonUtil.getOrDefault(builder.maxSteps, 10);
        this.aiCallRetry = CommonUtil.getOrDefault(builder.aiCallRetry, 3);
        this.aiCallRetryDelay = CommonUtil.getOrDefault(builder.aiCallRetryDelay, 10 * 1000);
        this.isNeedStopTool = CommonUtil.getOrDefault(builder.isNeedStopTool, true);
    }

实际使用的时候为:

image-20260217003747327

使用方面

**何时需要设置为true?**你的任务实际比较大的任务情况,为长任务运行场景则需要使用stop tool,若是短任务则直接可以设置为false。


整理者:长路 时间:2026.2.17

评论区请在客户端页面查看