Главная / Статьи / Инженерия циклов: создание циклов агентов с использованием верификаторов и правил остановки.

Инженерия циклов: создание циклов агентов с использованием верификаторов и правил остановки.

Практическое руководство по созданию четырех стекированных циклов агентов: основы ReAct, инструменты оценки по шкале, механизмы маршрутизации LangGraph, контракты циклов, триггеры событий, алгоритмы подъема по склону и меры защиты от сбоев.

2535 слов

Идея, стоящая за всем этим, проста в изложении. Не нужно управлять ИИ по одной инструкции за раз — следует спроектировать цикл, в котором он будет работать. Суть заключается в том, что именно верификатор, а не сама модель, определяет границы того, чему можно доверять; следует представлять себе четыре вложенных друг в друга цикла. Вот как это сделать: составляющие цикла, код для каждого уровня, способы сбоев циклов и правила остановки, предотвращающие истощение бюджета. В итоге вы будете знать достаточно, чтобы позволить циклу готовить pull request даже во время вашего сна.

Примеры кода соответствуют задокументированным API; идентификаторы моделей являются местоимениями, а любые фрагменты, представляющие собой лишь псевдокод, обозначаются в комментариях. Приводится один типичный пример, используемый в этой области: цикл программирования, который воспроизводит несработавший тест, исправляет его, проверяет результаты исправлений с помощью чего-то другого, кроме самого агента, и создает черновик PR.

Пять компонентов цикла

Независимо от используемой платформы, качественный цикл всегда состоит из пяти элементов. Если пропустить один из них, цикл будет сбоить, застопориться или работать бесконечно.

  1. Триггер. Фактор, запускающий цикл — будь то сообщение от человека, запланированный сигнал, webhook или новая строка в таблице.
  2. Цель, которую может проверить машина. Фраза «добиться прохождения тестов» подходит, а «улучшить код» — нет. Если программное обеспечение не может определить, достигнута ли цель, то и цикл этого сделать не сможет.
  3. Инструменты для получения реальной обратной связи. Агент должен взаимодействовать с окружающей средой и видеть результаты, запуская код, читая сообщения об ошибках или вызывая API.
  4. Ограниченное, управляемое состояние. Необходимо сохранять цель, временные записи и информацию о пройденных попытках. Чрезмерное количество данных замедляет работу циклов, приводит к их блужданию и выходу за рамки разрешенного объема данных.
  • Четкие правила остановки. Это самый часто игнорируемый аспект. Цикл без правила остановки представляет собой ошибку в учетной записи для оплаты.
  • Планируйте три варианта выхода, а не два. Успех: проверка пройдена, следовательно, можно отправлять результат. Отказ: исчерпан бюджет или лимит итераций, поэтому необходимо остановиться и подвести итоги того, что осталось. Передача задачи: агент столкнулся с решением, которое должен принимать только человек, поэтому задача передается на более высокий уровень. Частью проектирования хорошего цикла является определение тех вызовов, которые он не должен выполнять самостоятельно.

    Цикл 1: цикл агента

    В центре находится цикл, который уже используют все агенты — шаблон ReAct 2022: размышление, действие путем вызова инструмента, наблюдение за результатом и повторение до завершения. В 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.

    Существует два вида верификаторов, и правильный выбор из них — ключ к успеху.

    • Детерминистичные: выполняют тесты, проверяют схему и подтверждают оценку. Они дешевы, быстры и нельзя обмануть ими, поэтому стоит попробовать их в первую очередь.
  • LLM в роли судьи: вторая модель оценивает результаты по установленным критериям. Этот подход подходит для нечетких целей, но существуют риски из-за предвзятости, связанной с позицией, избыточностью информации и личными предпочтениями. Никогда не ставьте агента, выполнившего работу, единственным судьей ее качества.
  • Преобразование в граф

    Когда задача становится более сложной, чем простая, явный граф лучше, чем скрытые циклы: узлы, ребра и момент принятия решения о прекращении работы видны всем. Исследовательский агент представляет собой структуру из трех узлов, причем каждое решение о прекращении работы принимается маршрутизатором:

    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. Успех означает прохождение всех тестов без их пропуска или удаления с целью обмана. Шаги: прочитать неудачный тест, исправить вероятную причину и запустить процесс снова. Правило запоминания: вести журнал уже попробованных подходов, чтобы ничего не повторялось. Процесс останавливается при получении зеленого статуса путем создания черновика 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 тест payments-refactor проваливается, и запускается webhook — это цикл 3, причем никто ничего не вводит. В течение следующих семи минут агент читает сообщение об ошибке, вносит исправления, запускает тест снова, читает новое сообщение об ошибке и снова вносит исправления, ведя журнал попыток (цикл 1). После каждого раунда детерминистичный оценщик запускает весь набор тестов и проверяет, что ничего не было пропущено для фиктивного успешного результата (цикл 2). Четвертый раунд завершается с результатом «зеленый».

    В 09:22 цикл завершается правильным образом: создается проект патча, в котором указано, что изменилось и почему. Его должен одобрить человек, так как изменения касаются процессов оплаты. В течение ночи механизм отслеживания ошибок обнаруживает, что это уже третья ошибка, связанная с часовыми поясами на неделе, и генерирует новую проверку согласно правилам, которая проходит вашу проверку (цикл 4). Завтрашняя работа начнется более эффективно, чем сегодняшняя.

    Вы проспали большую часть этого процесса. Утром есть проект патча и необходимое решение, но нет клавиатуры, чтобы что-то быстро ввести.

    Когда циклы выходят из строя

    Циклы усиливают процесс, причем усиление происходит в обоих направлениях. Каждый способ сбоя воздействует на цикл в определенной точке и имеет стандартные меры защиты; при этом постоянно повторяется одна идея: то, что генерируется, не должно одновременно выполнять функцию оценки. Самая дешевая мера защиты — протестировать верификатор на входных данных, известных как качественные, так и некачественные, прежде чем оставить цикл без контроля. Необходимо убедиться, что он отклоняет некачественные данные, поскольку верификатор, не прошедший тестирование, представляет собой лишь мнение с определенными ограничениями.

    Когда не стоит создавать цикл

    Попытка включить циклы во все процессы сама по себе является способом сбоя. В следующих случаях лучше ограничиться одним вызовом:

    • Достаточно одного прохождения, как при составлении краткого изложения, переводе или чистой обработке данных. Циклы лишь увеличивают затраты и время выполнения.
    • Невозможно проверить достижение цели. Без способа определения «завершения» отсутствует сигнал об ошибке, что приводит к продолжению работы цикла с потерями средств.
  • Ошибки невозможно отменить, например, при переводе денег, удалении данных или отправке писем клиентам. Цикл должен остановиться и передать управление другому элементу.
  • Человек сделает это быстрее. Если выполнение задачи вручную занимает десять секунд, то цикл — худший инструмент для этой работы.
  • Инженерия циклов подразумевает не только знание того, как их создавать, но и понимание того, какие проблемы действительно требуют использования циклов.

    Создавайте так, будто собираетесь оставаться на этой работе

    Вот необходимые инструменты: анатомия процесса, цикл агента, верификатор, граф, контракт, внешние циклы и каталог сбоев. Обеспечьте цикл надежным верификатором, функцией принудительной остановки и установите пределы, которые он не может превысить. Добавляйте человеческие контрольные точки там, где риски действительно велики, и помните, что то, что цикл находит решение, не означает, что вы его понимаете. Затем позвольте ему работать, как это делает тот, кто собирается оставаться инженером, а не просто человеком, который его запустил.

    Следующая ступень

    Есть вопрос, который стоит задать перед тем, как оставить цикл без присмотра: насколько слабым может быть верификатор, чтобы всё равно показывать зелёный статус? Для ответа на этот вопрос был создан критерий оценки. Он включает записи случаев манипуляций с наградами и оценивает настройки контрольных точек по количеству таких манипуляций, которые они позволяют пройти. Контрольная точка, игнорирующая собственный отчёт агента и перезапускающая набор тестов — то есть детерминистическую проверку, рекомендованную ранее в качестве первого шага — не остановила ни одной из восьми попыток манипуляции. Перезапуск набора тестов лишь подтверждает, что условия для получения награды были выполнены, и именно это и достигается с помощью манипуляций с наградами.

    Если верификатор ограничивает систему, становится очевидной следующая недостающая навык — проектирование, версионирование и улучшение самих проверок. Его называют инженерией оценки, задачей по установлению критериев, которые должен преодолеть алгоритм. Один верификатор представляет собой элемент внутри одного цикла. Инженерия оценки охватывает множество таких элементов через наборы данных и критерии оценки, которые показывают, улучшается ли система в целом или ухудшается.

    Укрепление процедуры проверки подобно лестнице, и её верхняя точка остаётся неожиданной. Оказывается, лучшей проверкой может быть совсем не сложный код, а лишь несколько утверждений, которые агенту никогда не разрешали видеть. Поэтому предел верификации находится в довольно неудобном месте. Он зависит меньше от качества построения процедуры проверки и больше от качества данных, которые хранятся отдельно, и от того, не просочатся ли они обратно в цикл.