Семь шаблонав цікла агентаў і прычыны ўпадку кожнага з іх: ReAct, Maker-Checker і іншыя.
Практычны каталог дзеянняў агентаў у цікле, ад планування-дзеяння-пераканання да адказа чалавека, з рэкамендаціямі пра тое, калі кожны варыянт падходзіць, калі яго трэба адмовіцца і як выбраць оптымальны варыянт.
Крыніцы: Agentic Loops & Design Patterns
Ніхто не повінен суджаты агента за тым, як ён звучыць. Важліве — гэта поведэння, колі ёсць велікій трафік, колі шчось ламаецца чы колі прыходыць аўдытор. Саме гэта ёсць основою для вібору правільного патэрна. Патэрні найкрашчэ працуюць, колі іх вікорыстовуюць як архітэктурні прымітыві: кожэн з ніх розв’язуе певну класіфікацію проблем, мае відомі компрэсіі і повінен обіратыся навмісно. Ніжчэ наведэно прыклады з Claude і сітуаціі, колі іх слід унікаты.
1. Плануваты, дыяты, перэвіраты
Гэта фундаментальній патэрн. Агент плануе одын маленькій крок, віконуе одну дыю, а потым перэвірае, чы гэтая дыя прывела яго бліжчэ до чысно візначэноі меты. Такім чыном досягаецца баланс між гнучкісцю і контролем.
// Pseudo-code: Node/TypeScript orchestrating Claude as an agent
async function planActVerifyLoop(ticket) {
let iteration = 0;
const maxIterations = 5;
while (iteration < maxIterations) {
iteration++;
// 1. PLAN: ask Claude for the next step
const plan = await claude.chat({
model: "claude-3-opus",
messages: [
{
role: "user",
content: `You are a coding agent working on ticket ${ticket.id}.
Goal: Make tests pass for this ticket without changing public APIs.
Current context:
${ticket.description}
${ticket.latestFailureLog}
What is the single most useful next action?`
}
]
});
// 2. ACT: execute the suggested action if it's in the allowed action space
const action = parseAction(plan);
const result = await executeAction(action); // run tests, edit file, etc.
// 3. VERIFY: use tests as verification
const verification = await runTests(ticket.testSuite);
if (verification.allPassing) {
return { status: "done", iterations: iteration };
}
// Attach the failure output back into ticket context
ticket.latestFailureLog = verification.failureOutput;
}
return { status: "budget_exhausted" };
}
У гэтым скетчы Воблак займаецца мікрапланаваннем наступных дзеянняў, тады як сам цыкл абавязаны выконваць пераканальнэ праця праз тэсты і сабліжваць ліміт колькасці ітэрацый. Такое раздзеленне не дазволяе сістэме абявляць пра успех толькі таму, што мадэль вярыць у сябе.
Хорашы прыклады — гэта багатоэтапныя інжынерныя задачы з вімірамым працэйным прагрэсам, скрыпты запуску і змены конфігурацыі, якія павінны досягнуць пераканальнага рабочага стану, а таксама внутрашнія інструменты, дзе можна ўбудаваць строгія пераканальнэя меры, такія як тэсты або верыфікацыя схемы.
Паслабныя прыклады — гэта чыста творчая работа, такая як маркетынгавы тэкст або довгія творы, суб’ектывныя рашэння, дзе пераканальнэ праця можа выступаць толькі як крытэрый смаку, і рэальнага часу працэсы, якія не можу пэўніцца колькасцю ітэрацый на крытычным шляху.
2. ReAct (расумець, а потым дзейсці)
ReAct сумешчае короткі прыемкі раздумаў з адзінамі дзеяннямі. Уместо таго, каб загадзя запланаваць весь маршрут, агент аналізуе найновейшы стан, выбірае адзін інструмент, выкарыстоўвае яго, а потым знову раздумвае. Гэта робіць яго практычным выборам для даклуджэнчых або дыягностычных задач, дзе кожная новая спазырка можа правамерна перакашталеты план.
# Pseudo-code: Python coordinator orchestrating Claude tool calls
def react_loop(incident):
iteration = 0
max_iterations = 6
while iteration < max_iterations:
iteration += 1
# REASON: Claude decides what to inspect next
reasoning = claude.chat(
model="claude-3-opus",
messages=[
{
"role": "user",
"content": f"""
You are an SRE assistant triaging a payment incident.
Incident summary:
{incident.summary}
Recent metrics:
{incident.latest_metrics}
Logs snippet:
{incident.logs_snippet}
Decide one next diagnostic action from:
- CHECK_METRICS
- CHECK_LOGS
- CHECK_DB_HEALTH
- SUMMARIZE_FINDINGS_AND_RECOMMEND_ACTION
Explain your reasoning briefly and output JSON with 'action' and 'target'.
"""
}
]
)
action = parse_json(reasoning)
if action["action"] == "SUMMARIZE_FINDINGS_AND_RECOMMEND_ACTION":
return claude.chat(... ) # final summary + recommended steps
# ACT: run the selected diagnostic
observation = run_diagnostic(action, incident)
# Update incident state for the next reasoning step
incident.update_with_observation(observation)
Кожны крок дыягнастыкі выканаецца з чыстай метай, і Claude бачыць новы кантэкст пасля кожнага дзеяння.
Ожывайце яго для дыягнастыкі інцыдэтаў і аналізу коранавыных прычын, для складных процэсаў падтрымкі, дзе кожна адпаведзь зменяе тое, што трэба пераглядзець далей, а таксама для розследаванняў безпекі, у якіх доказы прыходзяць часткова і непаштоўна.
Адкладзіце яго, калі план стабільны і алгорытм ясны, як у апрацоўцы дакументаў у стылі ETL, калі працэсавая здатнасць настолькі высока, што аналіз кожнага кроку становіць ся занадто дорогім, або калі прастор для дзеяння настолькі вузькі, што дадатковыя размышленні нічога не даюць.
3. Аналізаваць і перасматраць
Тут спачатку выконваюцца два этапы – стварэнне і крытыка, а пасля – этап перакорэкцыі. Гэта стварае цялком разумны стандарт для усяго, што патрэбуе перагляду прыходзячы да кліента, рэгулятора чы ў вырабатчыцкую сістэму. Галоўная задача – раз’ядрэнне: крытыкам можа быць іншы запрос, дышэўшы мадэль чы нават механізм правіл.
async function reflectReviseLoop(draftInput: string) {
// 1. GENERATE
const draft = await claude.chat({
model: "claude-3-opus",
messages: [
{
role: "user",
content: `
Write a customer-facing email explaining a declined payment due to suspected fraud.
Constraints:
- empathetic but clear
- no admission of fault
- no promises about future approvals
Context:
${draftInput}
`
}
]
});
// 2. CRITIQUE (using a cheaper model as checker)
const critique = await claude.chat({
model: "claude-3-haiku",
messages: [
{
role: "user",
content: `
You are a compliance checker.
Review the following email for:
- policy violations
- misleading statements
- over-commitments
Output a JSON with:
- issues: list of strings
- safe: boolean
Email:
${draft.content}
`
}
]
});
const review = JSON.parse(critique.content);
if (review.safe) {
return draft.content;
}
// 3. REVISE
const revised = await claude.chat({
model: "claude-3-opus",
messages: [
{
role: "user",
content: `
You wrote this email:
${draft.content}
Compliance issues:
${review.issues.join("\n")}
Rewrite the email to resolve all issues while preserving intent.
`
}
]
});
return revised.content;
}
Этый шаблон падчыя для паведамленняў кліентаў на чулых тэмах, такіх як мошчання, анулювання платэжаў чы змены правілаў, внутрашняга аналізу, які можа быць перапрацаваны, а таксама для будзь-яга кантэнту, дзе супакоўка з правіламі мае першасць над стылем.
Ён не падходзіць для внутрашняга браўстраймінгу з нізкім рызыкам, дзе крытыка стварае труднасці і не забезпечвае рэальнай безпекі, для дужа кораткіх адказаў у чатах, дзе другая перапрацавка ёсць занадта, чы для процэсаў, дзе важліва скорасць, як-то паведамлення пад час адбывання транзакцыі, дзе патрэбна адразуўсюды рэакція.
4. Праектаванне, тэставанне, выправлення
Інжынерныя каманды часта выбіраюць гэты цыкл, адтуды што рэзультат ёсць об’ектыўным і залежыць не ад самага модэлю: набор тэстаў становіцца «зеленым» чы застаецца «чорным». Кожнага разу агент прымае рашэнне пра змяны, запускае тэсты і аналізуе, што не працавало. Пасля чаго ён выправляе проблемы і павтарае процэс, зупіняючыся тады, калі сістэма будзе пераведзена ў вядомы стабільны стан чы будзе досягнута максімальная колькасць ітэрацый.
async function draftTestFixLoop(issue: Issue) {
const maxIterations = 4;
let iteration = 0;
while (iteration < maxIterations) {
iteration++;
// DRAFT: Claude proposes code changes
const patch = await claude.chat({
model: "claude-3-opus",
messages: [
{
role: "user",
content: `
You are an autonomous coding agent.
Ticket:
${issue.title}
${issue.body}
Current failing tests:
${issue.failingTests}
Propose a minimal patch as a diff that makes tests pass
without changing public APIs.`
}
]
});
applyPatchToGitRepo(patch.content);
// TEST: run CI locally or via API
const testResult = await runCi(issue.branchName);
if (testResult.success) {
// FIX_DONE: open a PR with the diff
await openPullRequest(issue, patch.content);
return { status: "done" };
}
// FEEDBACK: update failingTests for next iteration
issue.failingTests = testResult.failureSummary;
}
return { status: "needs_human_review" };
}
Ён працюе з тыквотамі з нізкім рызыком, якія ўжо адгрупаваны і пазначаны як гатовыя для агента, у внутрэшнях інструментах, дзе адвярнуць работу ёсць проста, а таксама з некрытычнымі траекторыямі, якія можаць вытрымаць затрымку і вітакі.
Ўжоўваць яго не трэба для будзь-яых змян, якія пераводзяць грошы безпасэчна праз основныя транзакцыйныя траекторыі, для змян схемы, міграцый і загальных рэфакторынгаў, а таксама для логікі, якая рэгулюецца правіламі, калі аўтаматызаваная змена можа нарабіць праблемы.
5. Крытык і стваральнік
Адны агент стварае, а другі пераканальвае. У платэжах гэта прымае форму контролю «стваральнік-пераканальнік», які ўжо вікорыстоўваецца для операцый з высокім рызыкам, што спрыяе простаму падачы інформацыі командам з рызыка і супакоўкі.
Гэты падход падходзіць там, дзе вялікай значыццю мае другая пара вачэй, калі аўтаматызацыя вплывае на сістэмы, якія блізкія да працы продукту, такія як настройкі, маршрутызацыя чы спавешчэнняя, а таксама для справаздач чы панелей керування з важлівай інформацыяй, якія чытаюць кераванне.
Ён не падходзіць для простых задач, дзе додатковая пераглядка коштуе больш, чым захішчае, для процэсаў, чутлівых да затрымкі, якія должны адпаведаць за адны крок, або для пайплайнаў, дзе слабыя правіла змусілі бы пераканальніка прыйняць все, што выглядае дастаткова добра.
6. Перапрыткі з выкарыстоўваннем памяці
Большасць простых цыклаў проста прабуе зноў. Цыкл перапрыткаў з выкарыстоўваннем памяці фіксуе станы неудач і выкарыстоўвае іх, каб утрымацца ад павторэння тых сабе помылак.
def retry_with_memory_loop(task, max_attempts=3):
failures = []
for attempt in range(1, max_attempts + 1):
# Ask Claude to consider past failures before deciding the next move
decision = claude.chat(
model="claude-3-opus",
messages=[
{
"role": "user",
"content": f"""
You are handling a task with a flaky external API.
Task:
{task.description}
Past failures:
{failures}
Decide whether to:
- RETRY_API
- FALLBACK_TO_CACHE
- ESCALATE_TO_HUMAN
Explain briefly and output JSON: {{ "choice": "...", "reason": "..." }}
"""
}
]
)
choice = parse_json(decision)
if choice["choice"] == "RETRY_API":
result = call_api(task)
elif choice["choice"] == "FALLBACK_TO_CACHE":
result = use_cache(task)
else:
return {"status": "escalated", "failures": failures}
if result.success:
return {"status": "success", "attempts": attempt}
failures.append(result.error_summary)
return {"status": "max_attempts_exhausted", "failures": failures}
Паджэнтныя меты — гэта нестабільныя інтэграцыі, API з обмежэннем частоты запытоў і зовнішнія сістэмы, якімі вы не керуеце, парсаванне дакументаў з нестабільным фарматаваннем, а таксама некрытычныя рабочыя працэсы, дзе можлівы павторныя спробы.
Непаджэнтныя меты — гэта основныя транзакцыйныя працэсы, дзе павторная спроба можа прывесты да дуплікацыі эфектаў, аперацыі, якія не ўсунуць наследкі павторнай спробы, і сцэнарыя, дзе абыходжанне з бядай павінна быць немедыятным і відразу пометкаваным, а не павторвацца таямніча.
7. Адкалканне да людзяў
Гэта шаблон захоўнага механізма для всьго, што стосуецца рэальных грошаў, рэальных кліянтаў аб рыгуляцыйных аспектаў. Гэты цыкл працуе самастойна да певнага моменту, а потым чыста перадае задачу, калі зменшыцца доверлівасць аб падыграе рызык.
async function triageLoop(ticket: Ticket) {
const autoActions = ["LABEL", "ROUTE_TO_QUEUE", "REQUEST_MORE_INFO"];
const decision = await claude.chat({
model: "claude-3-opus",
messages: [
{
role: "user",
content: `
You are a support triage agent in a payments company.
Ticket:
${ticket.body}
Decide one of:
- LABEL (low risk)
- ROUTE_TO_QUEUE (medium risk)
- ESCALATE_TO_HUMAN (high risk / unclear)
Return JSON with:
- choice
- risk_level
- rationale
`
}
]
});
const choice = JSON.parse(decision.content);
if (choice.choice === "ESCALATE_TO_HUMAN") {
await createHumanTask(ticket, choice.rationale);
return { status: "escalated" };
}
// LABEL or ROUTE_TO_QUEUE are automated but bounded
await applyAutomatedTriage(ticket, choice);
return { status: "auto_treated" };
}
Ўжыце яго для будзь-якай аўтаматызаціі, якая можа паспрабаваць пакрашчыць досвіт клёянта чыста ў вачох яго, для процэсаў, дзе частковая аўтаматызація дапамагае, але цэлая автонамія ўскладнюе сітуацыю, а таксама для ранніх версыйяў, якім трэба навучыцца прычынам, перш чым будуць скасаваны правілы карантýна.
Не выкарыстоўвайце яго для абсалютна внутршняях, маło рызыкавых задач, дзе людзі толькі ствараюць зайвыя проблемы, для пакетных заданняў у аддзеле падтрымкі, дзе людская пераглядка не можа быць масштабаваная, і ў сітуаціях, дзе эскалэйшанне толькі перавантажыць працоўнікаў, не пакрашчыўшы рэзультатаў.
Выбір у практыцы
Калі з’яўляецца новая можлівасць для агента, пытанне «Як мне яго запрашаць?» — гэта неправільнае першае пытанне. Чатыры крашчых ўсьмо:
- Какі сігнал паўтарыць рэзультат: тэсты, схемы, правілы, паказнікі чы людская оцэнка?
- Скількі крокаў на практыцы трэба для выпанення задачы?
- Што будзе, калі сістэма зламаецца?
- Каго гэта зачыніць, калі ўсё пойдзе не так?
Адказы паказуюць певную законамасць:
- Жорсткая, бінарная верыфікацыя супакойваеся з этапамі прабныць, тэставання і выправлення.
- Эксплоратыўны падход супакойваеся з методам ReAct.
- Абалоўкі ўжо па правілах і тоне супакойваюцяся з прыемамі перадумвання і праверкі, або з ролямі крытыка і стваральніка.
- Нестабільная асяроддзе вымагае прабавы знову, пры чым неабходна врачымаць мемарыі.
- Высокі рызык значыць, што з самага пачатку трэба включыць можлівасць людзкага утрымання сітуацыі.
Інжынерыя цыклаў, як выявілася, — гэта не столькі хыткая оркестрацыя, сколькі дысцыплінованая працава над сістэмамі.