Інжынерыя цікламаў: стварэнне цікламаў агента з верыфікаторамі і правіламі зупінкі.
Практычныя вядомасці па стварэнню чатырох шаргаваных цікламаў агента: базы ReAct, скарынкаванне за крэтырамі, маршрутаванне LangGraph, контракт ціклу, спрычыненні за адбудовамі, метод падйому на хыл і меры захавання ад неудач.
Мыслявы, стоячы за всім гэтым, лёгкая да выказвання. Перастаце кераваць ШІ па адна інструкцыя за раз і спроектуйце цикл, у яком ён працюе. Тэза заключаецца у тым, што самэўпавергач, а не модель, абмежвае тое, чаму можна даваць веры, а картінка, якую трэба мяць у галаве, — чатыры циклы, якія знаходзяцца ўнутрь аднаго другога. Ось як гэта стварыць: часткі циклу, код для кожнага шару, способы, пры якіх циклы збываюцца, і правіла абаранення, якія не дазволяюць ім спалваць ваш бюджет. У канцы вы будете знаць достатнькай інфармаціі, каб падазроўваць циклу на падготовку прыказа пра зміны, пакуль вы спачываете.
Прыклады коду адпавядаюць задокументаваным API, ідэнтыфікаторы модэляў є заместнікамі, а кожны фрагмент, які є толькі псевдокодам, адзначае гэта ў коментары на пачатку. Адні прыклады выканаюцца ўсю час, яны є стандартным пачаткам у гэтый галузі: цикл кодавання, які відтварае неўспэшны тест, вылечвае яго, дазволяе чымусь іншым, чым сам агент, пераканацца ў праверкі вылечэння і стварае праект прыказа пра зміны.
Пяць элементаў ціклу
Незалежна ад таго, якую фрэймворк вы выбіраеце, адлічны цікл завжды складаецца з пяці частак. Якщо прыбыць адну з іх, цікл пачынае спяваць, застаёцца на месцы або продовжваецца без канца.
- Трыгар. Тое, што запускае цікл – будзь-та поведамленне ад чалавека, запланаваны сигнал, webhook або новая строка ў табліце.
- Цель, яую можа пераканаліць машына. Фраза «Зробіць тэсты успешнымі» падходзіць, а «Паспрабаваць пакращыць код» – ні. Якщо програма не можа з’ясавіць, чыгодзеце вы да цялевай точкі, то і цікл не можа.
- Інструменты, які даюць рэальную адзвечнасць. Агент должен дзеяць у рэальным свете і бачыць рэзультаты, запускаючы код, чытаючы stderr або вызываючы API.
- Адмініструемы стан. Следзьце за цэлью, тэмпарарыем для нотатак і записамі пра тое, што вядома было спробавана. Занадта большы стан ўскладнюе роботу ціклу, прычыняе його блуканне і переплыванне меж сваёй контэкстной вікна.
Планаваце трохі выходаў, а не два. Успех: верыфікатор працаваў, тады адправляйце. Здача: бюджет чыста ліміт ітерацый заканчыліся, тады зупніцеся і падсумаваце тое, што засталося. Перадача: агент ступіў на рашэнне, якое павінен прымець толькі чалавек, тады справа прайходзіце на вышэйшы ранг. Частка проектавання хорашага ціклу — гэта адзначэнне тых вызоў, якія ён не павінен выканаць сам.
Цікл 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.
Існуе два відменнікі верыфікатораў, і правильны ўжоць яго выбор — галоўная частка майстэрства.
- Детерміністычны: адмахваецца тэсты, перакананні схемы, парабярэнне балу. Дешавы, быстры і немагчыма яго падласці, таму спачатку пробавайце іх.
Стварыць граф
Калі задача становіць больш, чым простая, явны граф кращы за скрытую петлю: вузлы, рэшткі і месца, дзе вырашаецца прыпыненне, ўсё гэта відкрываецца. Агент-дзеячык падходзіць па трох вузлаў, пры чым кожна рашэнне пра прыпыненне выдваюцца рутэрам:
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 як адно і тое ж.
Контракт ціклу
Сюды і прыводзіцца змена падходу. Уместо напісання інструкцый вы пішаеце спефікацыю стану „завершэння“, тое ў значэнні функцыі награды плюс правіло зупынкі. Гэта тое, што вы пераглядаеце, пораўнюеце і зберагаеце:
Цель: стварыць зелёны результат CI на гілцы 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). Завтрашні процес пачынаецца розумней, чым сённяшній.
Вы спалі большую частку часу. У ранкі є проект прыемкі і рашэнне, якое трэба прымець, але няма клавіатуры, якой можна было б паштурхнуць.
Калі цыклы выходзяць з-пад кантролю
Ціклы павяршваюць, і гэта павяршчэнне відбываецца ў обох напрамках. Кожны спосаб збою паўтарыцца ў цікле en конкрэтным месцы і мае стандартны захід; ёсць адна загальная тэма: тое, што генеруецца, не павінна таксама кантролювалася. Найдешавшы спосаб захисту — запускати верыфікатор на вхідных данных, якія ўжо вядомы як правильныя, і якія вядомы як неправильныя, прычым не застаўляючы цікл самам. Пераканайцеся, што ён адхіляе неправильныя даны, калі ўжо верыфікатор не працаваў, то гэта проста мненне, адзначана певнымі параметрамі.
Калі не трэба ствараць цікл
Прагненне павяршваць усё за дапамою цікла ёсць сама по сабе прычыной збою. У такіх ситуацыях застаўляйце це проста як адзін вызов:
- Дапамога аднае перагляду ўжо достатня, як у случае зі стыкаментам, перакладам чы чыстым выкарыстаннем дадзеных. Цікл толькі збільшае витраты і час адпаведзення.
- Немагчыма верыфікацыя жаднай меты. Без можлівасці пераканацца, чы «завершана» робота, немае сігналу пра абэрасцію, што заставляе цікл продаваць грошы без рэзультатаў.
Інжынерыя циклаў значыць ведаць, якія проблемы патрабуюць викорыстання цикла, так сама як і ведаць, як яго стварыць.
Ствараюце яго так, нібы хочаце застацца на гэй працы
Это і є інструменты: анатамія, цикл агента, верыфікатор, граф, кантракт, зовнішні циклы і каталог неудач. Ужоўце цикл моцным верыфікаторам, чыстай зупінкай і обмежэннямі, якія ён не можа перакрыць. Дадзіце людскія пункты контролю там, дзе рызык справжній, і памятайце, што тое, што цикл дае рашэнне, не значыць, што вы яго разумеете. Потым дазвольце ёму працаваць, як тое робіць чалавек, який плануе застацца інжынерам, а не проста тым, хто яго запускае.
Наступны ўзлёт
Є адзін пытанне, якое варта задаць пры тым, калі цикл работае без нагляду: насколькі слабы можа быть верыфікатор і ўсё ж показваць зелены кольор? Для выявлення гэтага быў створены критэрый. У ём урахоўваюцца зафіксаваныя випадкі маніпуляцый з наградамі, а таксаваныя працуюць за тым, сколькі такіх маніпуляцый яны дазволяюць праўерыцца. Працоўны механізм, які ігнаруе сабеставленне агента і перзапускае набір тэстаў — той самы детерміністычны спосаб перагляду, пропанаванный раней як першы варыянт — не зупініў жадной з восьмі маніпуляцый. Перзапуск набора тэстаў проста падтверджвае, што умовы для отрымання награды былі выпалены, і гэта самэ ўсё, што досягае маніпуляцыя з наградамі.
Тады, якщо верифікатор обмежуе систему, наступны важливы навык – це проектування, версіонування та вдосконалення самых переверків. Люди называюць це інжынеріяю переверкання, задача якої – встановіць стандарты, якія трэба дотримвацца. Одны верифікатор – це майстернасць у рамках адного циклу. Інжынерія переверкання охопляе багато аспектаў, уключаючы наборы дадзеных та крітэрыя, якія паказваюць, чы працоўнасць системы павышаецца чы знижваецца.
Зміцненне „вората“ – це лесвіца, а ўзрост яе неспадзяваўся. Найкращы переверак – цэ не хітры код, а лиш калякі тверджэнняя, якія агент ніколі не меў права бачыць. Таму ліміт переверкання знаходзіцца ў незручным положэнні. Ён залежыць менш ад таго, наскількі добра пабудавана „вората“, а больш ад якасці вашых дадзеных та ад таго, чы не прасочуцца воні назад у цикл.