首页 / 文章 / 循环工程:利用验证器和停止规则构建智能体循环。

循环工程:利用验证器和停止规则构建智能体循环。

构建四个堆叠式智能体循环的实用指南:ReAct基础、评分系统、LangGraph路由、循环契约、事件触发器以及爬山算法与故障防护机制。

2535 词

这一切背后的思路其实很简单:不要再逐条指令地操控人工智能,而应设计它所处的循环结构。需要牢记的是,限制你可信任范围的是验证器而非模型本身,可以想象的是四个相互嵌套的循环。具体构建方法包括:循环的各个组成部分、每层的代码实现、循环出错的原因,以及防止其耗尽预算的停止规则。掌握这些之后,即便你在睡觉时,也能让循环自动准备拉取请求。

代码示例均遵循已文档化的API,模型ID仅为占位符,任何仅为伪代码的片段都会在开头注释中说明。文中会贯穿一个典型示例,这也是该领域的常规入门案例:一个能够重现故障测试、修复问题、让非代理自身机构对修复结果进行验证,并最终创建草稿拉取请求的编程循环。

循环的五个组成部分

无论使用何种框架,一个完善的循环始终由五个部分构成。缺少其中任何一部分,循环都会出现异常、停滞或无限运行。

  1. 触发器。启动循环的要素,可以是人工输入、定时触发、Webhook消息或新的数据行。
  2. 机器可检测的目标。“让测试通过”符合要求,而“改进代码”则不符合。如果软件无法判断目标是否达成,循环同样无法做到。
  3. 能提供实时反馈的工具。代理需要通过运行代码、读取错误信息或调用API来对现实世界采取行动并查看结果。
  4. 精简且受控的状态管理。需保留目标、临时记录以及已尝试过的操作日志。过大的状态会导致循环运行变慢、偏离轨道并超出其上下文限制。
  • 明确的停止规则。这是最容易被忽视的部分。没有停止规则的循环实际上就是账单账户中的缺陷。
  • 应规划三种退出方式而非两种。成功:验证通过,即可交付结果;放弃:预算或迭代次数已达上限,需停止并总结剩余工作;转交:智能体遇到了仅应由人类做出的决策,因此需要升级处理。设计良好循环的关键在于识别出它不应自行处理的场景。

    循环1:智能体循环

    所有智能体都在运行的核心流程就是2022年提出的ReAct模式:思考、通过调用工具执行操作、观察结果,然后重复此过程直至完成。到了2026年,这一流程已被刻意设计,不再依赖人工干预。在其最简单的形式中,仅包含一次函数调用:

    from langchain.agents import create_agent
    def run_tests() -> str:
    """Run the project's test suite and return the raw output."""
    …
    agent = create_agent(
      model="anthropic:claude-opus-5",
      tools=[run_tests],
      system_prompt="You are a careful Python engineer. Fix failing tests.",
      )
    # create_agent returns a graph that calls tools in a loop, repeating
    # until the model replies with no tool calls. The loop runs on .invoke()
    

    那段简短的代码其实隐藏着一个循环,你应该能够想象出来。下面是同样的控制结构,仅以伪代码形式呈现,且未使用任何框架。请注意,所有的退出路径都是有限制的:

    # PSEUDOCODE - shows the control structure a harness implements.
    # The helper names below are yours to supply, not a real library API.
    def run_loop(goal):
      state = init_state(goal) # goal + scratchpad + attempt log
      for step in range(MAX_STEPS): # hard cap: never loop forever
        thought = model.reason(state) # ReAct: reason…
        action = model.choose_action(state) # …then pick a tool call
        result = tools.execute(action) # touch the real environment
        state = update(state, thought, action, result)
        state = compact(state) # keep context under budget
        if verifier.passes(state): # deterministic check = reward
          return success(state)
        if no_progress(state) or budget.exhausted():
          return escalate_to_human(state) # third exit: hand-off
      return escalate_to_human(state)
    

    在所有这些形状中,请记住这个。其余的都是它的变体。

    循环2:添加验证器

    单纯的智能体会自行决定何时完成任务,而依赖这种方式就容易导致虚假的成功结果。因此需要将智能体封装在评估器中,使其根据评分标准检查自己的工作。当检测到问题时,会将反馈重新传回智能体,循环继续进行,直到达到上限。验证中间件位于 deepagents 包中。

    from deepagents import RubricMiddleware, create_deep_agent
    from langchain.messages import HumanMessage
    from langgraph.checkpoint.memory import InMemorySaver
    RUBRIC = """
    - All tests pass in run_tests
    - No test is skipped or deleted to force a pass
    """
    agent = create_deep_agent(
      model="anthropic:claude-opus-5",
      system_prompt="You are a careful Python engineer.",
      middleware=[
      RubricMiddleware(
      model="anthropic:claude-haiku-4–5", # a cheap grader is fine
      system_prompt="Grade against the rubric. Be strict.",
      max_iterations=5, # the stop rule (default is 3)
      ),
      ],
      checkpointer=InMemorySaver(),
     )
    # The rubric is passed at invoke time - not to the constructor.
    result = agent.invoke(
      {
      "messages": [HumanMessage("Make the failing tests pass.")],
      "rubric": RUBRIC,
      },
      config={"configurable": {"thread_id": "fix-tests-session"}},
    )
    

    其工作原理如下:每当智能体即将完成任务时,一个独立的评分子智能体会根据评分标准读取对话记录。若判定为needs_revision,则会将反馈以HumanMessage的形式重新放入对话中,智能体随后继续处理。只有satisfied、failed、max_iterations_reached和grader_error这几种情况才会使循环结束并终止流程。如果评分器需要自行执行实际检测,可为其提供作为BaseTool实例的工具。

    验证器有两种类型,合理选择是关键所在。

    • 确定性验证器:执行测试、验证架构并确定分数。成本低、速度快且不会给出虚假结果,因此应优先尝试这类验证器。
  • 以大语言模型作为评判者:另一个模型根据评分标准进行打分。这种方法适用于目标较为模糊的情况,但位置、冗长度以及自我偏好偏差都可能影响结果。绝不能让执行任务的智能体成为唯一的评判者。
  • 将其转化为图结构

    当任务不再简单时,显式的图结构比隐藏的循环结构更佳:节点、边以及停止决策的节点都一目了然。一个研究智能体可由三个节点构成,所有的停止决策都由路由器来决定:

    from typing import Literal, TypedDict
    from pydantic import BaseModel, Field
    from langgraph.graph import END, StateGraph
    class ResearchState(TypedDict):
    question: str
    draft: str
    verdict: str
    feedback: str
    iterations: int
    class Verdict(BaseModel):
    status: str = Field(description='"verified" or "needs_work"')
    feedback: str = Field(description="claims lacking support, if any")
    def decide(state: ResearchState) -> Literal["research", "__end__"]:
    if state["verdict"] == "verified": # success exit
    return "__end__"
    if state["iterations"] >= MAX_ITERATIONS: # surrender exit
    return "__end__"
    return "research" # else: loop again with the feedback
    builder = StateGraph(ResearchState)
    builder.add_node("research", research_node) # generator
    builder.add_node("verify", verify_node) # verifier
    builder.add_edge("research", "verify")
    builder.add_conditional_edges(
    "verify", decide, {"research": "research", "__end__": END}
    )
    builder.set_entry_point("research")
    graph = builder.compile()
    

    那段代码中并没有什么巧妙的提示语句,真正的智慧体现在结构上:一个节点负责生成结果,另一个节点负责验证,而路由器则将验证结果转化为继续执行并反馈信息或停止执行。LangGraph将哨兵标记__end__与END视为相同的东西。

    循环契约

    正是在这里,思维方式的转变变得具体化。你不再需要编写指令,而是只需描述“完成”的条件,也就是奖励函数以及停止规则。这些内容就是你需要审查、对比并提交的成果:

    目标:在 payments-refactor 分支上实现绿色 CI 构建。所谓“完成”,意味着所有测试都通过,且没有为作弊而跳过或删除任何测试。步骤:阅读失败的测试用例,修复可能的原因,然后重新运行。记忆机制:记录已尝试过的方法,避免重复操作。一旦出现绿色状态,就提交草稿 PR;经过六轮尝试后,总结剩余工作;或者当涉及身份验证或支付逻辑时,将任务交给其他人处理。

    没有任何指令被输入模型。实际编写的内容包括目标、检查项、记忆规则以及三种退出条件,而这套规则体系就是循环工程。

    第3和第4个循环:向外层叠加

    一个设计良好的单个循环就已经很有帮助了。如果在它之外再包裹更多循环,且每个循环的运行速度更慢,其效果会呈指数级提升。第1和第2个循环负责完成正确的工作,而第3和第4个循环则使其具备连续性并能够自我改进。

    循环3:事件

    外部事件会将你的循环从由你调用的工具转变为可自动运行的服务。在任何内容发布之前,这里也是设置人工审批环节的理想位置:

    # Loop 3: an event turns the loop into a service
    from pydantic import BaseModel
    class CIEvent(BaseModel):
      branch: str
    @app.post("/webhook/ci-failed")
    def on_ci_failure(event: CIEvent):
      if not event.branch.startswith("fix/"): # cheap triage first
        return {"skipped": True}
      result = agent.invoke(
        {
        "messages": [HumanMessage(
          f"Fix the failing test on {event.branch}.")],
        "rubric": TEST_GREEN_RUBRIC,
        },
        config={"configurable": {"thread_id": event.branch}},
      )
      open_draft_pr(result) # a human approves the merge, not the loop
      return {"opened_pr": True}
    

    第4轮循环:爬山法

    最外层的循环速度最慢,它作用于循环本身。每次运行都会留下痕迹。分析模块会读取这些痕迹,找出不断重复出现的故障,并提出对相关组件的修改建议:包括提示语、工具以及供人类审核的评分标准。想象一下返回箭头——它不只是向起点反馈信息,还会深入到内层循环并对其进行修改。系统正在自我改进。

    需要注意一点:外层循环会放大其内部的内容。只有当内层验证机制足够强大时才添加外层循环,因为在一个薄弱的验证机制基础上再加第四轮循环,只会大规模地生成错误的结果。

    为何这属于工程实践

    这些约束措施看似繁琐的官僚程序,但一旦将智能体视为闭环反馈控制器——一种点对点的映射关系——就不再有这种感觉了。目标值即为设定点,智能体则是控制器,而各种工具与环境共同构成被控系统。验证器则充当传感器的角色,它发出的“需要改进”判定即为误差信号,用于触发后续的修正动作。任务完成意味着系统已收敛。无论被控系统是喷气引擎还是测试套件,控制器都会根据设定点与传感器读数之间的差异来驱动运行。

    同样的术语用于描述循环终止的两种方式:一种是振荡,无限重复同一修复步骤;另一种是发散,在资金不断消耗的同时逐渐偏离目标。约束条件不过是维持其行为范围的稳定性要求,而最重要的规则是安全机制必须确保程序能够终止,因为无法信任智能体来完成这一任务。

    四种循环共同作用的一天

    观察这四种循环在一天早晨中的运作过程。09:14时,支付重构相关的测试失败,随之触发了一个webhook,即第三种循环的启动,而此时并没有人进行任何操作。在接下来的七分钟内,智能体会读取失败信息、应用修复、重新运行测试,再次遇到新故障后又继续修复,并记录下所有的尝试过程(第一种循环)。每轮结束后,确定性评估工具会运行整套测试,确保没有为强行通过而跳过任何步骤(第二种循环)。到第四轮时,测试结果即为合格。

    在09:22时,循环会以正确的方式结束,此时会生成一份说明变更内容及原因的PR草案。由于该变更涉及支付功能,必须由人工进行审批。在夜间,自动检测机制发现这是当周第三起时区相关错误,于是会生成一份新的检查规则草案,随后进入你的审核环节(第4轮循环)。明天的处理流程会比今天更高效。

    你几乎错过了整个过程。早上只有待审核的PR草案以及需要做出的决定,却没有键盘可以操作。

    当循环出错时

    循环具有放大效应,且这种放大作用是双向的。每种故障模式都会在循环的特定位置产生影响,并都存在标准的防护机制,其核心原则始终如一:负责生成内容的模块绝不能同时承担评判功能。最简单的防护方法是在让验证器独立运行之前,先用已知正常的输入和已知异常的输入对其进行测试,确保它能拒绝那些异常输入——因为未经测试的验证器只不过是一种带有成本限制的观点而已。

    何时不应构建循环

    急于对所有内容都使用循环,本身就是一种故障模式。在以下情况下应将其视为单次调用即可:

    • 只需一次处理就足够了,比如总结、翻译或数据提取等操作。循环只会增加成本和延迟。
    • 无法对任何目标进行验证。如果没有办法判断“是否完成”,就不会有错误信号,从而导致循环持续运行并耗费资源。
  • 一些错误一旦发生就无法撤销,比如转账、删除数据或给客户发送邮件。此时必须停止循环并将任务移交他人处理。
  • 人工操作会更快。如果手动完成某项任务需要十秒,那么循环就成了一种低效的工具。
  • 循环设计不仅涉及如何构建循环,还关乎判断哪些问题适合使用循环来解决。

    要像会一直从事这份工作一样来设计它

    所需的工具包括:结构分析、智能体循环、验证器、图结构、契约、外部循环以及故障目录。应为循环配备强大的验证器,设置强制停止机制并限定其不可逾越的边界。在风险较高的环节加入人工检查点,并记住:即使循环找到了解决方案,也不代表你就完全理解了问题。之后就让它继续运行,就像那些打算长期从事工程师工作而非仅负责启动任务的人那样。

    更高的层次

    在让循环无人监控之前,有一个问题值得探讨:验证器即便功能极其弱小,仍能显示绿色状态吗?为此我们建立了一个基准测试。该测试记录了各种奖励操纵行为,并根据它们能通过的次数来评估各个关卡的设置效果。有一个关卡无视智能体自身的报告,而是重新运行之前提出的那种确定性检测方法作为首选方案,但它未能阻止八次尝试中的任何一次。重新运行测试套件仅能确认奖励条件已得到满足,而这恰恰正是奖励操纵行为所要达到的目的。

    因此,如果验证机制限制了系统的发展,那么接下来最稀缺的技能就显而易见了:设计、版本控制以及不断改进验证流程本身。人们将这称为评估工程,即设定循环必须达到的标准。单个循环内的验证工作属于手工操作范畴,而评估工程则涉及多个循环,通过数据集和评分标准来判断整个系统是在进步还是退步。

    强化某个验证环节就像爬梯子,其最终高度往往出乎意料。最有效的验证方式其实并非复杂的代码,而只是几条智能体永远无法看到的断言。因此,验证的限度处于一个尴尬的位置——它更取决于保留数据的质量以及能否防止这些数据泄露回循环中,而非验证环节本身的构建质量。