Цикли проти графів: два підходи до проектування архітектури штучних інтелектуальних агентів.
Інженерія циклів проти інженерії графів для AI-агентів: як працює кожна архітектура, коли вибирати одну замість іншої, та перелік перевірок перед впровадженням у продакшн.
Джерела: Loop Engineering vs. Graph Engineering: The Architecture Shift Quietly Reshaping AI Agents
Два модні терміни, одне архітектурне питання
Усі, хто стежить за ШІ-агентами, які шукають інформацію в Інтернеті, викликають інструменти, пишуть код чи автономно виконують робочі процеси, ймовірно, нещодавно чули два терміни: інженерія циклів та інженерія графів. Вони звучать як маркетингові терміни, але вказують на справжнє структурне рішення.
Уявіть собі агента, який витрачає 40 000 токенів та шість хвилин у реальному часі на розв’язання запитання, яке мало б бути вирішене за три кроки. З моделлю чи запитом усе гаразд. Проблема у самій конструкції, адже агент не може зрозуміти, що він вже намагався щось зробити. Він просто постійно повторює кроки «мислення», «дія», «спостереження», не маючи жодних записів про свій власний процес.
Такий тип невдачи виводить проектування агентів за межі категорії формулювання запитів та переводить його у сферу архітектури програмного забезпечення. Якщо подивитися на це так, майже кожна готова система агентів ґрунтується на одній із двох схем: циклах та графах. У наступному розглядається, що таке кожна з цих схем, як вони будуються, де виникають проблеми та чому перехід від однієї до іншої змінює підхід інженерів до цих систем, а не просто змінює інструменти.
Що насправді робить агент
У будь-який момент часу агент робить одну з трьох речей: він міркує (звернення до LLM), діє (звернення до інструменту) або вирішує, що робити далі. Інженерія агентів — це переважно робота з поєднання цих трьох елементів між собою.
Протягом перших кількох років існування агентів на основі LLM майже всі підходили до їхньої реалізації однаково — у вигляді циклу. Це був очевидний вибір. Агенти у стилі ReAct працювали саме так з самого початку, і це все ще відповідає опису найпростішого агента від Anthropic: моделі, яка автономно використовує інструменти в циклі.
Пізніше агенти отримували складніші завдання: кілька спеціалізованих підагентів, можливість повторних спроб, підтвердження від людини та розгалужені бізнес-правила. Одиночний цикл почав не витримувати такої навантаження. Команди захотіли бачити структуру процесу, а не покладатися на те, що цикл зрештою досягне стабільного стану, і саме ця потреба призвела до появи графової інженерії, яка описує процес через вузли та ребра, не залишаючи все на рівні повторних ітерацій.
Жоден з цих підходів не є неправильним. Вони вирішують різні проблеми, тому кожен заслуговує на уважне розглядання.
Аналогія з кухні
Уявіть собі, що ви навчаєте когось готувати. Інженерія циклів — це повторення однієї інструкції: скуштувати суп, додати сіль, якщо це потрібно, знову скуштувати та продовжувати, поки все не буде правильно. Це один цикл дії, перевірки та, за потреби, повторення. Просто, передбачувано та легко уявити.
Інженерія графів нагадує повноцінний рецепт із гілками. Нарізайте овочі, поки хтось інший кип’ятить воду. Коли обидва етапи будуть готові, поєднайте їх. Якщо той, хто пробує смак, хоче більше спецій, поверніть каструлю на етап приправ, а інакше подавайте страву. Тут немає єдиної послідовності кроків. Існує кілька шляхів, деякі кроки виконуються одночасно, деякі залежать від рішення, а лише певні повертаються назад, якщо щось не так.
Що означає інженерія циклів
Цикл — це первинний та найпростіший спосіб створення агента. Він працює в одному безперервному циклі:
- Отримати вхідні дані, тобто запит або мету користувача.
- Подумайте про те, що робити далі — це крок міркування моделі.
- Дійте, що зазвичай означає виклик інструменту, виконання коду або пошук інформації.
- Спостерігайте за тим, що принесла ця дія.
- Поверніться до кроку 2 та продовжуйте, поки агент не вирішить, що мета досягнута.
Люди часто називають це циклом «міркування, дія, спостереження», і багато ранніх агентів були побудовані на цьому принципі. У рамках практики інженерія циклів розглядає агента як єдиний повторюваний цикл: модель міркує, обирає дію, виконує її, вивчає результат та записує його назад у власний контекст, після чого починає все знову, поки не дійде висновку, що завдання завершене або не досягнута межа.
Кілька моментів пояснюють його популярність:
- Це лежить в основі відомої схеми ReAct (міркування у поєднанні з діями) від Yao та його колег, де сліди міркувань переплітаються з діями, і моделі не потрібно завершувати всі свої роздуми заздалегідь.
- Більшість фреймворків для агентів також визначають „агента“ саме так — як один цикл керування з спільним вікном контексту та інтерфейсом виклику інструментів.
- Його написання займає лише кілька рядків. Станом є хід розмови, а існує лише одна умова завершення. Для кодового асистента, який редагує файл, чи дослідницького агента, який шукає до моменту задоволення, нічого складнішого не потрібно.
- У посібнику Anthropic також сказано: почніть з найпростішого підходу, який працює, і додавайте структуру лише тоді, коли це вимагає завдання.
Проблема полягає у тому, що все, про що мусить розмірковувати цикл — включаючи те, що він вже пробував, що зазнало невдачі та якою була мета — має знаходитися в одному постійно зростаючому вікні контексту. У процесу немає окремої пам’яті; він зберігає лише запис подій.
Як складається цикл
Потік виконання працює від початку до кінця ось так.
Кроки виконання:
- Завдання користувача запускає цикл із визначеною метою.
- На етапі розмірковування модель читає системний запит, історію розмови та останні спостереження, а потім вирішує, що робити далі.
- Перевірка «Чи завершено завдання?» не є окремою системою; сама модель на основі свого контексту вирішує, чи воно завершене.
- Якщо завдання не завершене, модель обирає інструмент та викликає його.
- Результат або помилка інструменту повертається у вигляді спостереження.
- Це спостереження додається до контексту, і цикл знову починається з обробки інформації, маючи трохи більшу історію з кожним проходом.
- Коли модель оцінює виконану роботу, цикл завершується та повертає остаточну відповідь.
Компактна версія на Python демонструє, наскільки мало коду потрібно для цього.
def run_agent(task: str, tools: list, max_iterations: int = 10) -> str:
context = [{"role": "user", "content": task}]
for step in range(max_iterations):
response = llm.generate(context, tools=tools)
if response.is_final_answer:
return response.content
tool_result = execute_tool(response.tool_call)
context.append({"role": "assistant", "content": response.content})
context.append({"role": "tool", "content": tool_result})
return "Stopped: max iterations reached"
Що означає інженерія графів
Інженерія графів — це чітке представлення процесу агента. Це сукупність вузлів, кожен з яких є одиницею роботи, такою як виклик ШІ, виклик інструменту чи фрагмент бізнес-логіки, з’єднаних ребрами, які можуть бути фіксованими або умовними. Усі вузли читають та записують дані в один спільний об’єкт стану з визначеною структурою. Коротко кажучи, робочий процес перетворюється на карту пов’язаних кроків із шляхами між ними, замінюючи один повторюваний цикл.
Вузол може бути будь-яким з наступних:
- агентом — спеціалізованим ШІ з однією функцією, такою як дослідження, написання чи аналіз
- викликом інструменту, наприклад пошуком у Інтернеті, обчисленням чи запитом до бази даних
- точкою прийняття рішень, яка вибирає наступний шлях
- точкою об’єднання, яка поєднує результати з кількох шляхів
Кілька шляхів можуть виконуватися паралельно, а інші є умовними та виконуються лише у разі успішного проходження тесту. Цикли все ще можливі, але вони з’являються лише там, де це необхідно, як контрольований механізм, який повертає роботу на кілька кроків назад, а не сліпо повторює все заново.
Чому графи є привабливими
- Паралелізм. Незалежні завдання можуть виконуватися одночасно та не чекати у черзі.
- Розгалуження. Робочий процес може рухатися різними напрямками залежно від ситуації, а не просто повторювати одні й ті самі кроки.
- Спеціалізація. Кожен вузол може бути окремим експертом із однією конкретною функцією, що більше нагадує спосіб розподілу роботи в людській команді.
- Цілеспрямовані спроби. Коли такий крок, як перевірка якості, провалюється, лише цей крок повертає роботу на перевиконання, а все інше залишається недоторканим.
- Видимість. Оскільки робочий процес представлений у вигляді карти, легше побачити, де виникла проблема та який шлях було обрано.
LangGraph — це фреймворк, побудований на цій ідеї, який моделює робочі процеси як станові, циклічні спрямовані графи. Граф все ще може містити цикли, оскільки вузол може мати ребро, що веде назад до попереднього вузла, тож можливі повторні спроби та ітерації. Змінюється лише те, що цикл стає одним із багатьох ребер, намальованих на карті, яку можна переглядати, і більше не є всією архітектурою.
Це дуже схоже на розрізнення, яке робить Anthropic між робочими процесами, де ШІ та інструменти дотримуються заздалегідь визначених шляхів коду, якими керують розробники, та агентами, де модель динамічно керує власним процесом. Граф може відобразити обидва варіанти в одній структурі: з фіксованими шляхами, де важлива передбачуваність, та гілками, керованими моделлю, де корисна гнучкість, причому різниця буде видна на діаграмі.
Як складається граф
Візьмемо таку саму проблему — агента, який має досліджувати, писати код та переглядати власний результат, і представимо її у вигляді графа.
Крок за кроком:
- START — це точка входу в граф.
- Вузол-маршрутизатор читає поточний стан та обирає шлях. Це може бути звичайний оператор
if/elseабо виклик ШІ для класифікації запиту.
Ось спрощений псевдокод у стилі, який зазвичай обирають більшість фреймворків для графів.
from graph_engine import StateGraph, START, END
def router(state: dict) -> str:
return state["task_type"] # "research" | "code" | "review"
def research_agent(state: dict) -> dict:
state["results"]["research"] = do_research(state["query"])
return state
def code_agent(state: dict) -> dict:
state["results"]["code"] = write_code(state["query"])
return state
def review_agent(state: dict) -> dict:
state["valid"] = validate(state["results"])
return state
def aggregator(state: dict) -> dict:
state["final_output"] = merge(state["results"])
return state
graph = StateGraph(schema=AgentState)
graph.add_node("router", router)
graph.add_node("research_agent", research_agent)
graph.add_node("code_agent", code_agent)
graph.add_node("review_agent", review_agent)
graph.add_node("aggregator", aggregator)
graph.add_conditional_edges("router", {
"research": "research_agent",
"code": "code_agent",
"review": "review_agent",
})
graph.add_edge(["research_agent", "code_agent", "review_agent"], "aggregator")
graph.add_conditional_edges("aggregator", {
"valid": END,
"invalid": "router", # explicit retry edge
})
app = graph.compile()
app.invoke({"query": "...", "results": {}, "task_type": "code"})
Якщо розмістити обидва шаблони поруч, контраст стає більш помітним.
Чому індустрія переходить від циклів до графів
Цей перехід не був раптовим. Через кілька причин цикли почали стикатися з реальними обмеженнями під час створення більш амбітних систем.
Реальна робота не відбувається лінійно. Дослідження, підтримка клієнтів, фінансовий аналіз та процеси обробки контенту мають різні гілки. Якщо йдеться про билінг, потрібно діяти одним шляхом, а якщо це технічна проблема — іншим. Цикл змушує все це уміщувати в одну довгу ланцюгову структуру умов, що швидко ускладнює ситуацію.
Системи з кількома агентами потребували кращої структури. Коли система мала кілька агентів — наприклад, дослідника, узагальнювача та перевіряючого факти — один цикл не міг відобразити ситуацію, коли два агенти мають працювати одночасно або коли один має запуститися лише у разі невдачі перевірки. Граф природним чином дозволяє це відобразити.
З часом більше значення мають видимість та довіра. Раніше, коли агенти виконували складні завдання, командам була потрібна детальна інформація про кожен крок процесу. Можна було створити граф, який показував, де саме все пройшло добре чи погано, тоді як цикл — це непрозорий блок, який виконує однаковий код двадцять разів.
Витрати та швидкість. Кожна марна ітерація забирає час, а іноді й реальні гроші, адже кожен крок обробки — це виклик мовної моделі. Виконання окремих кроків паралельно та повторення лише тієї частини, яку потрібно переробити, є значно ефективнішим.
Тестування та технічне обслуговування стають простішими. Можна поступово створювати, тестувати та змінювати елементи графа по одному. Щільно сплетений цикл зазвичай базується на логіці „усе або нічого“, тож безпечно змінити його після запуску складніше.
Вибір між ними
Нижче наведена приблизна схема прийняття рішень.
Використовуйте цикл, коли:
- завдання має одну мету: один агент, одна ціль та один набір інструментів
- ранній прототип потрібно перевірити перед тим, як витрачати гроші на архітектуру
- кількість кроків є низькою та досить прогнозованою
- одна особа відповідає за все, і нічого не потрібно передавати іншій команді
Використовуйте діаграму, коли:
- беруть участь два або більше спеціалізованих агентів чи ролей
- необхідно забезпечити можливість аудиту спроб повторної роботи, альтернативних рішень чи схвалень людьми
- частини процесу можуть виконуватися одночасно та згодом потрібно їх об’єднати
- необхідно відстежувати виконання, створювати контрольні точки чи відновлювати роботу з певної точки, що неможливо зробити за допомогою повторного відтворення запису
- різні особи чи команди відповідають за окремі сегменти, причому діаграма слугує угодою між ними
Ось корисна перевірка. Якщо код циклу містить примітку на кшталт „На цьому етапі ми вже мали б спробувати X“, це ознака того, що ви неправильно моделюєте граф усередині циклу, і, ймовірно, настав час намалювати граф.
Це не справжній вибір „або/або“. Йдеться про те, щоб підібрати інструмент під завдання. Простий чат-бот, який відповідає на запитання по одному, або невеликий скрипт, який повторює одну чітку дію до завершення, підходять для циклу. Завдання з кількома розгалужувальними кроками, кількома спеціалістами, які працюють разом, можливістю паралельної обробки або потребою у чіткому огляді того, що сталося та чому, підходять для графа. Розумним стандартним варіантом є початок з циклу та перехід до графа в той момент, коли логіка „якщо — то“ стає складною для розуміння.
Чек-лист для впровадження
Перед використанням будь-якого з цих підходів корисно дотримуватися цих звичок:
- Встановіть ліміт кроків. Обидва патерни потребують механізму переривання, адже агент без обмежень не має ліміту на суму рахунку.
- Зробіть перевірку статусу „завершено“ можливою. Умова завершення має бути чимось, що може перевірити тест, а не просто припущенням моделі.
- Додайте інструменталізацію до кожного кроку. Надайте кожному виклику LLM та кожному виклику інструменту власний об’єкт OpenTelemetry span або подібний, уникаючи використання одного об’єкта span для всього процесу.
- Ведіть версіонування графа. Зберігайте визначення в системі контролю версій, як і будь-який код, адже непомітна зміна елементів графа може тихо змінити поведінку.
- Перевіряйте стан на межах вузлів. Перевіряйте типові схеми стану під час входу та виходу з кожного вузла, щоб некоректні дані були виявлені на ранній стадії.
У чому суть
Цикл — це мінімальна структура проектування з одним контекстом, одним циклом та моделлю, яка керує потоком виконання. Він підходить для простих агентів з однією функцією. Граф описує процес через вузли, типи станів та ребра, які можна з’єднувати, розділяти, виконувати паралельно та навмисно повторювати.
Глибша зміна полягає не у тому, що графи кращі. Це перехід від процедурного мислення, яке запитує, що буде далі, до декларативного мислення, яке запитує, якою є форма системи. Графи добре поєднуються з практиками відстеження та спостережуваності, необхідними у виробничих системах, тоді як цикли добре підходять для швидкої ітерації.
Більшість виробничих систем у кінцевому підсумку є графами, створеними на основі циклів, по суті це машини станів, у яких вузли є невеликими циклами у стилі ReAct. Це робить ці два підходи різними рівнями збільшення масштабу однієї архітектури, а не конкурентами. Для будь-якого поточного проекту з агентами доцільно запитати, чи все все ще працює як один довгий цикл, чи настав час представити його у вигляді графа.
Пов’язана література
- Від агентських циклів до графів робочих процесів: типовий стан, брами перевірки та обмежена відновленість — Чому агенти, які працюють довго, не підходять для одного циклу, та як чітко визначені вузли, ребра, типові артефакти, перевірені переходи та дозволи для кожного вузла роблять їх надійними.
- Інженерія агентських механізмів: стан, перевірка та керування моделлю — Погляд на агентів у часі їх роботи: чому запити та контекст недостатні, та як стійкий стан, забезпечення виконання правил, перевірка та можливість спостереження заповнюють цю прогалину.