如何设计一个自动提示智能体的循环系统?完整指南

你有没有遇到过这样的情况:让AI帮你写代码,它给出了一段代码,但运行报错;你把错误贴回去,它修改了,但又有新问题;你反复手动粘贴、提问、再粘贴……几轮下来,你累得够呛,时间也花了不少。

其实,这种“来回拉扯”的操作,完全可以交给一个自动循环系统来处理。今天我们就来聊聊,如何设计一个能自己提示自己、反复执行任务直到完成的智能体循环。

什么是“循环”?为什么单个提示不够用?

很多人以为,使用AI智能体就是写一个很棒的问题,然后得到答案,就结束了。这确实适用于快速问答。但对于真正的多步骤任务,比如“写代码 → 运行测试 → 测试失败 → 读取错误 → 修复代码 → 再运行测试”这样的流程,一个提示远远不够。

想象一下棋类游戏。一个提示就像走一步棋。你看一眼棋盘,走一步,然后轮到对手。如果你只走一步,永远赢不了一整局比赛。

而循环完全不同。它是一套策略——决定每一步怎么走,每步之后检查局面,直到赢了为止。

提示是单次走棋,循环是整套策略。

我们不再手动输入每一步提示,而是设计一套规则,让智能体自己按规则执行。规则只设一次,然后让智能体自己跑完整局。

那么,这套规则怎么设计呢?

循环的五个核心部分

一个能自动提示智能体的循环,由五个部分组成。我们逐一来看。

部分 作用
定义“完成” 告诉循环何时停止的检查机制
构建上下文 每轮喂给智能体的最新信息
行动与捕获 执行步骤并抓取结果
用反馈闭环 把结果转化为下一轮的提示
设置停止条件 保证循环安全的防护栏

下面这张图展示了五个部分如何协同工作:

        +--------------------------------------------------+
        |                     The Loop                     |
        |                                                  |
        |   Build Context  --->  +-------+                 |
        |                        | Agent |                 |
        |                        +-------+                 |
        |                            |                     |
        |                            | acts                |
        |                            v                     |
        |                    Capture Result                |
        |                            |                     |
        |                            v                     |
        |                    Check "Done"? ----- Yes ---> Stop
        |                            |                     |
        |                            | No (feedback)       |
        |                            |                     |
        |                            +---------------------+
        |                       (next turn)                |
        +--------------------------------------------------+
                    Stop conditions wrap the whole loop

我们构建上下文 → 智能体行动 → 捕获结果 → 检查是否完成。如果完成就停止;如果没完成,就把结果作为下一轮的提示,继续循环。停止条件像护栏一样包围整个过程。

接下来,我们详细拆解每一步。

第一步:先定义“完成”的标准

在任何事情运行之前,必须回答一个问题:循环怎么知道自己做完了?

这是第一步,也是最重要的一步。如果连“完成”都描述不清,智能体就没有方向。它要么永远跑下去,要么太早就停止。

所以,在写其他代码之前,先写好完成检查。这个检查必须写在代码里,不能只存在脑子里。

举例来说,如果我们要构建一个修复Bug的智能体,那么“完成”就意味着测试通过。其他场景的例子:

  • 测试全部通过
  • 输出符合某个数据格式
  • 某个评分超过阈值

下面是一个简单的函数示例:

def is_done(result):
    # 完成意味着所有测试都通过
    return result.tests_passed

这个函数返回 True 表示工作完成,返回 False 表示还没完。循环会在每一轮后调用这个函数。

这个检查就像是循环的心跳。每一轮循环都会测一下心跳。如果心跳说“完成了”,循环就停止;如果说“还没好”,循环就再来一轮。

因此,必须从这里开始。循环里的其他所有部分都建立在它之上。

第二步:构建上下文,而不是手动写指令

这是最容易出错的地方。很多人仍然手动喂给智能体信息——每次手动输入新的指令,自己复制粘贴文件和错误日志。

我们必须停止这种做法。与其手动写指令,不如让系统自动构建上下文。

“上下文”在这里指什么?它指智能体本轮做出正确决策所需的一切:

  • 它正在处理的文件
  • 它能使用的工具
  • 上次运行产生的错误日志
  • 它已经尝试过的历史操作

换句话说,提示不再是手动敲出来的,而是由系统的当前状态自动拼装而成。

来看代码示例:

def build_prompt(state):
    return f"""
    目标:{state.goal}
    文件:{state.files}
    上一个错误:{state.last_error}
    历史尝试:{state.past_attempts}

    请决定下一步操作并执行修改。
    """

这里可以看到,提示是从状态(state)构建出来的。我们不需要手动输入错误信息——直接从状态里读取,自动放进提示中。状态变了,提示也跟着变。这就是核心思想。

循环每轮的结构都一样,只有上下文会变化。同一个 build_prompt 函数每次给出的提示都不同,因为背后的状态在不断推进。

第三步:让智能体行动,并捕获所有结果

现在执行这一步。我们把构建好的提示发给智能体,智能体完成它的工作——写代码、调用工具、修改文件等。

但行动只完成了一半工作。另一半是捕获所有输出结果

  • 修改的差异(diff)
  • 运行代码的标准输出
  • 失败时的错误信息
  • 系统的新状态

看代码:

def act_and_capture(prompt, state):
    output = agent.run(prompt)   # 智能体执行工作
    result = run_checks(output)  # 运行测试、抓取日志、获取diff
    return result

这里我们运行了智能体,然后捕获了结果。结果包含了修改差异、输出信息以及检查是否通过。

关键思想是:这个输出不是终点。它会成为下一轮提示的原材料。我们刚捕获的失败信息,正好可以喂回给智能体,让它修复问题。所以必须捕获全部信息,不能丢弃。

第四步:用反馈形成闭环

我们现在有了一个结果。接下来要把这个结果喂回给第一步的“完成”检查。正是这一步,让整个过程成为循环,而不仅仅是单次动作。

只有两条路径:

  • 通过?停止。任务完成。
  • 失败?自动把失败转化为下一轮的提示

第二条路径是精髓所在。当工作失败时,我们不放弃,而是把失败信息转化为下一步指令。类似:“测试失败了,错误信息是XXX,请修复。”

智能体利用刚刚发生的事情,自己重新提示自己。我们没有手动输入新提示——循环自动从失败中构建出来了。

看代码示例:

def loop(state):
    while True:
        prompt = build_prompt(state)      # 第二步:构建上下文
        result = act_and_capture(prompt, state)  # 第三步:行动并捕获

        if is_done(result):               # 第一步:检查完成
            return result                 # 通过了,停止

        # 失败了,把失败转化为下一轮的提示
        state.last_error = result.error
        state.past_attempts.append(result)

这里可以看到循环自己闭合。如果完成就返回并停止;如果没完成,就把错误保存到状态中。下一轮 build_prompt 会自动包含这个错误。智能体利用失败来重新提示自己。循环自我驱动。

第五步:设置停止条件(安全护栏)

没有出口的循环不是系统,而是无底洞。如果智能体持续失败而循环不停,它就会无限消耗时间和金钱。所以必须设计护栏。

我们一次性设置好停止条件,然后让循环安全运行。几个重要的护栏:

  • 限制重试次数:即使任务没完成,达到固定轮数后也停止。
  • 监控成本:超过时间或费用预算就停止。
  • 加入人工确认点:对于重要操作,暂停并让人确认后再执行。

把这些护栏加到循环中:

def loop(state, max_turns=10, max_cost=5.0):
    turns = 0
    cost = 0.0

    while turns < max_turns and cost < max_cost:
        turns += 1
        prompt = build_prompt(state)
        result = act_and_capture(prompt, state)
        cost += result.cost

        if is_done(result):
            return result   # 成功

        state.last_error = result.error
        state.past_attempts.append(result)

    return "已停止:触及安全护栏"   # 安全退出

这里我们用了两个护栏:重试次数上限和成本上限。循环在任务完成、或轮次用尽、或超预算时停止。永远有退出路径。循环不会无限运行。

特别注意:人工确认点对于难以撤销的操作尤其重要。删除文件、发送资金、推送到生产环境等都是典型例子。对于这些操作,必须暂停循环,让人确认后再让智能体执行。

完整循环代码

把五个部分合在一起:

# 第一步:定义完成
def is_done(result):
    return result.tests_passed

# 第二步:从状态构建上下文
def build_prompt(state):
    return f"""
    目标:{state.goal}
    文件:{state.files}
    上一个错误:{state.last_error}
    历史尝试:{state.past_attempts}

    请决定下一步操作并执行修改。
    """

# 第三步:行动并捕获
def act_and_capture(prompt, state):
    output = agent.run(prompt)
    return run_checks(output)

# 第四、五步:用反馈闭环,加上护栏
def loop(state, max_turns=10, max_cost=5.0):
    turns = 0
    cost = 0.0

    while turns < max_turns and cost < max_cost:
        turns += 1
        prompt = build_prompt(state)
        result = act_and_capture(prompt, state)
        cost += result.cost

        if is_done(result):
            return result

        state.last_error = result.error
        state.past_attempts.append(result)

    return "已停止:触及安全护栏"

五个部分协同工作:定义完成、构建上下文、智能体行动、捕获结果、反馈闭环、护栏保护。我们只写一次,然后智能体就能自己完成多步骤任务。

一次完整运行示例

让我们用一个具体例子走一遍。假设目标是“修复登录失败的Bug”。

第一轮:状态中包含目标代码文件,但还没有错误信息。我们构建提示并发送。智能体修改了代码。我们捕获结果。测试仍然失败,错误信息为“密码为空时验证返回true”。还没完成,所以把这个错误保存到状态中。

第二轮:现在 build_prompt 自动包含了第一轮的错误。智能体读到“密码为空时验证返回true”,并修复了那行代码。我们捕获结果。测试通过了。

第三轮:没有第三轮。因为第二轮中 is_done 检查返回了 True,循环自己停止了。

注意最关键的一点:在这整个过程中,我们没有手动输入任何一条提示。第一轮的失败自动成为了第二轮的提示。循环帮我们提示了智能体,并且在任务完成那一刻自行停止。

运行循环的成本

有一点可能会让人意外:写代码很便宜,但让循环一遍又一遍运行代码并不便宜。

模型几秒钟就能写出一段代码,成本很低。但循环会一次又一次地运行模型,轮次接轮次,有时持续数小时。每一轮都有一点成本。一个跑通宵的循环可能执行数千轮。所以真实成本不在于生成一次代码,而在于循环为了达到目标所经历的所有轮次。

这就是为什么第五步的停止条件如此重要。一个不会停止的循环不仅仅是Bug——它在你睡觉时还在持续产生费用。

因此,我们最重要的任务变了:不再是写一个聪明的提示,而是确保循环能够停止。必须限制轮次、监控成本、任务完成立刻停止。

可复用的技能模块

从长远来看,循环本身只是线路,真正的价值在于它所调用的技能。

什么是“技能”?技能是一个小巧、可复用的工具,专门做好一件事。与其让模型每一轮都从头解决同一个问题,不如把那些重复的工作提取出来,变成一个命名工具,让循环直接调用。

基本原则是:当你发现自己反复做同一个步骤时,就把它提取出来做成技能。当你解决了一个棘手的问题时,也把它保存为技能。之后,循环在后续运行中几乎零成本就能获得它。

一个没有任何技能的循环,会让模型每一轮都从头重新解决相同的问题。而一个调用了若干经过验证的技能集合的循环,每增加一个技能就变得更强。这就是让循环随着时间推移越来越有价值、而不是单纯烧钱的原因。

常见错误与避免方法

在实际设计循环时,大部分人容易犯以下错误:

错误一:没有“完成”检查
如果不把完成条件写在代码里,循环永远不知道何时停止。始终先写第一步。

错误二:手动喂提示
如果你还在手动输入每一条提示,那根本不是循环——只是你自己在干活。必须从状态中自动构建提示。

错误三:丢弃输出结果
失败信息就是下一轮的提示。如果不捕获它,就没有东西可以反馈回去。

错误四:没有停止条件
没有出口的循环会无限运行并持续产生费用。始终限制重试次数并监控成本。

错误五:对一次性任务强行使用循环
循环只有在任务可重复且可检查时才值得。对于一次性任务,普通提示更合适。

错误六:循环内没有技能
如果循环每一轮都从头解决相同问题,会浪费时间和token。把重复工作变成可复用的技能。

常见问题解答

问:循环提示系统适合什么样的任务?

答:适合那些需要多步骤、可以自动检验是否完成的任务,比如代码修复、测试驱动开发、文档生成、数据清洗等。对于一次性问答或创意写作,单次提示就够用了。

问:怎么判断一个任务是否值得用循环?

答:可以问自己三个问题:这个任务需要两步以上才能完成吗?我能写一个自动判断“完成”的检查吗?我是否要反复执行类似的任务?如果三个答案都是“是”,那么循环就是合适的选择。

问:循环失败了怎么办?会不会一直卡住?

答:不会,因为我们设计了停止条件(最大轮次、成本上限)。此外你还可以加入人工确认点。循环永远有安全出口。

问:如何控制循环的成本?

答:主要方法有三个:设置最大轮次数、设置成本预算(比如5美元)、优化技能库以减少不必要的推理。另外,选择合适大小的模型也很重要——不是所有任务都需要最大的模型。

问:一个循环里可以嵌套另一个循环吗?

答:可以。复杂任务往往需要多级循环。例如,外层循环负责整体任务规划,内层循环负责具体某个子任务的执行。但要注意控制总成本和复杂度。

问:循环提示系统和大语言模型的关系是什么?

答:循环系统是调度框架,大语言模型是执行引擎。循环负责任务分解、状态管理和流程控制,模型负责每轮的具体推理和行动。两者分工明确。

问:我该如何开始实践?

答:从一个极简版本开始。先写一个 is_done 检查(比如检查某个文件是否存在某行代码),然后写一个 build_prompt 函数,最后加上 max_turns=3 的简单循环。跑通后再逐步增加技能和护栏。

总结

我们不再手动一步一步地操作。我们设计一次循环,给它自我检查的能力和停止机制,然后让它自己跑起来。

  • 提示是单次动作,循环是完整策略
  • 五个部分缺一不可:完成定义、上下文构建、行动捕获、反馈闭环、停止条件
  • 先写“完成”检查,再写其他部分
  • 让状态自动构建提示,绝不手动输入
  • 捕获全部输出,失败就是下一轮的原材料
  • 必须有护栏:限制轮次、监控成本、必要时人工确认
  • 提炼可复用的技能,让循环的价值随时间增长

这就是设计一个能自动提示智能体的循环系统的完整方法。用它来解决真实的、多步骤的问题,让智能体真正为你工作,而不是你为它打工。