Головна / Статті

Інженерія циклів для AI-агентів: п’ять компонентів, чотири форми та спосіб створення в LangGraph.

Інженерія циклів для AI-агентів: п’ять частин, чотири поширені форми, дослідницький агент з функцією перевірки та повторної спроби в LangGraph, захист від збоїв та ситуації, коли не варто використовувати цикли.

Видавець: REACTAPP.TOP15 хв читання3382 слів

Джерела: Loop Engineering with Agents

Кожен штучний інтелект вже працює у циклі, і майже ніхто навмисно не проектує цей цикл. Саме ця різниця відокремлює агента, який тихо виконує завдання, від того, який протягом ночі спалює бюджет, будучи переконаним, що досягає прогресу. Практика подолання цієї різниці має назву — інженерія циклів.

З структурної точки зору в цьому мало чого. На кожному кроці агент думає про те, що робити, виконує дію, таку як виклик інструменту чи пошук, дивиться, що повернулося, і знову думає. Цей цикл міркувань, дій та спостережень лежить в основі інструментів на кшталт Claude Code та Cursor. Деякий час найбільш затребуваною була навичка формулювання запитів — якомога краще сформулювати прохання. Моделі, які можуть діяти, шукати та читати власний вихід, поставили ще одне питання: що визначає наступний крок агента та що змушує його зупинитися?

Інженерія циклів — це звичка навмисно відповідати на це питання. Дизайнер вибирає мету, критерії перевірки та точку зупинки, а потім створює компактну систему, яка формулює завдання один раз та дозволяє агенту продовжувати ітерації до завершення роботи. Відповідальність переміщується від поступового навчання агента до створення рішень, які випливають із цих інструкцій.

Це чудова ідея, але саме тут починається складна частина. Недбалі цикли витрачають ресурси, ніколи не закінчуються або переконують себе, що просуваються вперед. Хороші цикли є економними, зупиняються у правильний момент та забезпечують надійний результат. Розумніші інструкції не скорочують цю відстань — кращі цикли це роблять.

У наведених нижче прикладах використовується LangGraph, оскільки він дозволяє легко бачити структуру циклу, але ніщо тут не прив’язане до однієї конкретної платформи. Ті самі принципи застосовні з іншою платформою для агентів чи просто з ручно написаним кодом. Платформи змінюються, але концепції залишаються незмінними.

П’ять складових агентського циклу

Перш ніж вирішити, коли цикл є доцільним, корисно знати, з чого він складається. Майже кожен агентський цикл має п’ять складових.

  • Тригер. Якась подія запускає процес, наприклад, коли людина вводить команду «йти», запускається графік, надходить замовлення чи відкривається запит на зміни. Без тригера агент залишається без дії.
  • Перевірна мета. Люп повинен знати, як виглядає завершення, бажано у формі, яку може підтвердити машина. Покращення додатку спонукає до безкінечної роботи — потрібно, щоб усі тести пройшли, або повернута відповідь мала посилання на джерела та справжню межу завершення.
  • Інструменти. Агент має змогу діяти та водночас спостерігати за результатом: виконувати код та читати помилки, або шукати в Інтернеті та аналізувати результати. Якщо середовище ніколи не відповідає, агент може лише здогадуватися.
  • Стан. Це поточний огляд завдання: кількість спроб, результати, кількість пройдених раундів. Це найскладніша частина проектування люпів, оскільки надмірний обсяг стану приховує корисні сигнали під шумом.
  • Правила зупинки. Вони визначають, як закінчується цикл, і існує три варіанти. Успіх означає досягнення мети. Відмова означає вичерпання бюджету спроб. Передача обов’язків означає, що цикл натрапив на щось ризиковане або неоднозначне, тож обов’язки були передані людині замість припущень.

Решта обговорень, які стосуються того, коли слід використовувати цикл, коли — ні та як це робити, ґрунтуються на цих п’яти принципах.

Коли цикл є корисним

Цикл стає необхідним тоді, коли одного проходження моделі недостатньо, і завданню справді потрібно, щоб агент пробував, перевіряв та пробував знову. Чотири сигнали вказують на це.

  • Результати можна перевірити. Це найважливіше. Коли результат можна автоматично перевірити — чи пройшли тести чи ні, чи посилається відповідь на справжні джерела чи ні, чи є JSON-дані коректними чи ні — цей механізм може використовувати цю перевірку для знаходження правильного рішення. Перевірка виконує роль керма, а цикл без неї лише марнує гроші.
  • Перша спроба часто є неправильною, але її можна виправити. Код, чернетки досліджень та очищення неорганізованих даних покращуються з кожною повторною спробою. Агент створює щось, помічає недоліки та їх виправляє.
  • Ніхто не знає, скільки кроків знадобиться. Проблема одного типу сьогодні може вимагати двох кроків, а завтра — семи. Фіксована схема роботи не може так адаптуватися, на відміну від циклу, який продовжується до досягнення мети.
  • Ніхто не спостерігає. Обробка заявок протягом ночі чи повторна спроба нестабільної інтеграції до її успішного завершення вимагає системи, яка сама обирає наступні дії та не чекає на команду.
  • Прикладом може бути дослідницький агент, який перевіряє власні висновки. Він складає відповідь, перевіряє, чи підтверджують джерела кожне твердження, та повертається до детального аналізу слабких місць. Він продовжує цей цикл, поки відповідь не стане достатньо переконливою або не буде досягнута межа. Усі чотири сигнали присутні, і саме такий агент будується далі.

    Загальні форми циклів

    Більшість агентських циклів є варіаціями кількох основних форм. Їх розпізнавання допомагає визначити, яку саме форму потребує проблема, ще до того, як щось буде поєднано разом.

    Генерація та перевірка, іноді називана відображенням. На першому етапі створюється результат, а на другому він перевіряється, і цей процес повторюється до тих пір, поки перевірка не пройде. Сигнал керування є бінарним: перевірка або схвалює результат, або вказує на проблеми. Цей підхід підходить для ситуацій, де можна перевірити правильність, наприклад для коду, який має пройти тести, або для досліджень, твердження яких потребують підтвердження. Саме така форма будується пізніше.

       +-----------+      +-----------+
    -->| Generate  |----->|  Verify   |----- pass -----> [ done ]
       +-----------+      +-----+-----+
            ^                   |
            +------- fail ------+
    

    Виберіть цей підхід тоді, коли існує об’єктивний тест на правильність, і агент повинен продовжувати виправлення до тих пір, поки тест не пройде. Класичним прикладом є агент для написання SQL-запитів, який виконує свій запит та постійно повторює спроби, поки він не буде виконаний та не поверне правдоподібні рядки.

    Оцінювач та оптимізатор, які також називаються генератором та оцінювачем. Оцінювач ставить бал кожній спробі замість простого «так» чи «ні», а цикл спрямований на досягнення найвищого балу, а не лише на правильність. Це корисно, коли немає чіткого критерію проходження чи невдачі, але все одно можна виміряти ступінь кращості, як-от під час налаштування запиту, вдосконалення тексту реклами чи ранжування результатів.

       +-----------+      +-----------+
    -->| Generate  |----->|  Score    |--- good enough --> [ done ]
       +-----------+      +-----+-----+
            ^                   |
            +-- improve --------+
                (use the score)
    

    Виберіть його тоді, коли якість можна виміряти за шкалою та все ще можна їй присвоїти число. Складання слогану продукту з оцінкою чіткості та впливовості, а також постійна оптимізація найкращих варіантів демонструють суть ідеї.

    Планувати, виконувати, перепланувувати. Планувальник визначає кроки, а виконавці їх реалізують; коли будь-який крок виявляє щось несподіване, процес повертається для корекції плану. Цей цикл охоплює весь план, а не лише один результат, тому він підходить для роботи з відкритим кінцем та кількома кроками, як-от дослідження чи проект програмного забезпечення.

       +-----------+      +-----------+
    -->|   Plan    |----->|  Execute  |-- all steps done --> [ done ]
       +-----------+      +-----+-----+
            ^                   |
            +-- replan ---------+
                (hit a surprise)
    

    Виберіть цей варіант, коли завдання має багато кроків, і не всі з них відомі з самого початку. Міграція сервісу в нову фреймворк-систему є ефективною: сплануйте кроки, розпочніть їх виконання та скоригуйте план у момент, коли один із кроків виявить неочікувану залежність.

    Запланований цикл або цикл моніторингу. На відміну від ітераційного підходу до досягнення мети протягом одного запуску, цей варіант активується за таймером або під впливом події для спостереження та реагування — наприклад, для сортування нових заявок, пошуку пошкоджених версій продукту чи повторної спроби виконання ненадійної задачі. Він охоплює певний проміжок часу та не існує всередині одного завдання.

       +-----------+     +-----------+     +-----------+
    -->|   Wait    |---->|   Check   |---->|    Act    |---+
       | (timer /  |     +-----------+     +-----------+   |
       |  trigger) |                                       |
       +-----------+ <-------------------------------------+
            (no fixed end — keeps watching over time)
    

    Виберіть цей підхід, коли не існує єдиної лінії фінішу, а метою є постійний моніторинг та реагування, як-от перевірка поштової скриньки кожні кілька хвилин або щовечірня перевірка застарілих запитів на створення коду.

    Ці схеми не є взаємовиключними. Реальні системи часто поєднують їх, наприклад, запланований цикл, який щоразу після запуску виконує кроки створення та перевірки. Найпоширенішою схемою є «створити та перевірити», яка будується від початку до кінця далі.

    Створення циклу за допомогою LangGraph

    Агент, який будується, — це дослідник, який не довіряє власному першому чернетку. При отриманні запитання він збирає інформацію, пише відповідь, а потім перевіряє кожне твердження за допомогою автентичних джерел. Твердження, яке не має підтримки, надсилається назад для подальших досліджень. Цикл триває, поки відповідь не стане повною, або поки не буде досягнута межа кількості спроб, після чого агент повертає свою найкращу версію та позначає те, що все ще є невизначеним. Коротко кажучи, він дає відповідь, а потім переконує себе, що вона правильна, перш ніж її передати.

    Ця поведінка самоперевірки — це саме цикл генерації та перевірки, тому вона забезпечує чисту першу версію результату.

    LangGraph є хорошим варіантом, оскільки він описує агента як граф. Вузли — це елементи, які виконують роботу, а ребра — це стрілки, які визначають, що буде виконано далі. Ребра можуть вести назад, що дозволяє існування циклу. Проста лінійна ланцюгова структура не може повторюватися, але граф може.

    У дослідника є три посади, тому є три вузли. Перші два розділяють роботу між тим, хто створює, та тим, хто перевіряє; між тим, хто виконує, та тим, хто критикує, які залишаються окремо — це типова структура у циклах.

                        +------------------+
      START ----------> |     Research     | <-------------+
                        | (draft / revise) |               |
                        +--------+---------+               |
                                 |                         |
                                 v                         | needs work
                        +------------------+               | (+ feedback)
                        |      Verify      |               |
                        |  (check claims)  |               |
                        +--------+---------+               |
                                 |                         |
                                 v                         |
                           +-----------+   needs work      |
                           |  Decide   |-------------------+
                           | (router)  |
                           +-----+-----+
                                 | verified / out of tries
                                 v
                              [ END ]
    
    1. Дослідження — це збір матеріалів та підготовка проєкту відповіді.
    2. Перевірка — це аналіз проєкту та перевірка того, чи підтверджуються кожні твердження.
    3. Рішення — це невеликий протокол, який читає вердикт та вирішує, що робити далі: завершити роботу чи повернутися та дослідити слабкі місця.

    Цей приклад працює під Python 3.12. Потрібні три пакети:

    pip install langgraph==1.2.6 langchain-openai==1.3.3 pydantic==2.13.4
    
    • langgraph — це двигун графів та циклів, який включає StateGraph, START та END.
    • langchain-openai обгортає модель чату OpenAI під назвою ChatOpenAI.
    • pydantic визначає структурований результат, який повертає перевірювач.

    Перед запуском у середовищі також має бути наявний ключ API OpenAI:

    export OPENAI_API_KEY="your-key-here"
    
    from typing import TypedDict, Literal
    from langgraph.graph import StateGraph, START, END
    from langchain_openai import ChatOpenAI
    from pydantic import BaseModel, Field
    
    # A model client on OpenAI's Responses API, with the built-in web-search tool
    # bound on — so the model can search the web itself, no extra package needed.
    # "gpt-5" is a reasoning model; swap it for any current model you have access to.
    llm = ChatOpenAI(model="gpt-5", use_responses_api=True)
    searcher = llm.bind_tools([{"type": "web_search"}])
    
    MAX_ITERATIONS = 3         # a stop rule, decided up front
    
    # STATE — the shared memory passed between every node
    class ResearchState(TypedDict):
        question: str          # what we're answering
        draft: str             # the current best answer
        verdict: str           # "verified" or "needs_work"
        feedback: str          # what the verifier said to fix
        iterations: int        # how many times we've looped
    
    # The verifier returns a typed result, so the router gets a clean
    # "verified" / "needs_work" to branch on instead of parsing prose.
    class Verdict(BaseModel):
        status: str = Field(description='"verified" or "needs_work"')
        feedback: str = Field(description="claims lacking support, if any")
    
    # NODE 1 — the maker: search the web, then draft (or revise) the answer.
    def research(state: ResearchState) -> dict:
        prompt = "Search the web, then answer the question. Back every claim with a source.\n"
        if state.get("feedback"):
            prompt += f"A reviewer flagged these gaps — fix them:\n{state['feedback']}\n"
        prompt += f"\nQuestion: {state['question']}"
        draft = searcher.invoke(prompt).text
        return {"draft": draft, "iterations": state["iterations"] + 1}
    
    # NODE 2 — the checker: search for evidence, then critique the draft.
    def verify(state: ResearchState) -> dict:
        evidence = searcher.invoke(
            f"Search the web for evidence to fact-check claims about: {state['question']}"
        ).text
        checker = llm.with_structured_output(Verdict)
        result = checker.invoke(
            "You are a fact-checker. Using the evidence below, reply 'verified' "
            "only if every claim in the answer is supported; otherwise 'needs_work' "
            "and list the unsupported claims as feedback.\n\n"
            f"Evidence:\n{evidence}\n\nAnswer:\n{state['draft']}"
        )
        return {"verdict": result.status, "feedback": result.feedback}
    
    # ROUTER — the heart of the loop. Reads the verdict, picks the next step.
    def decide(state: ResearchState) -> Literal["research", "__end__"]:
        if state["verdict"] == "verified":
            return "__end__"                      # success: goal met
        if state["iterations"] >= MAX_ITERATIONS:
            return "__end__"                      # surrender: out of tries
        return "research"                         # loop back and fix the gaps
    
    # WIRE IT UP
    graph = StateGraph(ResearchState)
    graph.add_node("research", research)
    graph.add_node("verify", verify)
    
    graph.add_edge(START, "research")            # trigger
    graph.add_edge("research", "verify")         # always verify a fresh draft
    graph.add_conditional_edges("verify", decide, {
        "research": "research",                   # the backward arrow = the loop
        "__end__": END,
    })
    
    agent = graph.compile()
    
    result = agent.invoke({
        "question": "What were the main causes of the 2008 financial crisis?",
        "draft": "", "verdict": "", "feedback": "", "iterations": 0,
    })
    print(result["draft"])
    

    Два моменти є особливо важливими. По-перше: обидві вузли доходять до живого вебу через вбудований інструмент OpenAI web_search, підключений за допомогою bind_tools. Вузол research проводить пошук перед складанням тексту, щоб його твердження ґрунтувалися на реальних результатах. Вузол verify проводить пошук ще раз, щоб перевірити проект на основі свіжих даних, а не пам’яті моделі, і саме цей другий пошук надає циклу об’єктивний сигнал. По-друге: verify використовує функцію with_structured_output, яка змушує формувати типовий verdict разом із feedback замість прозового тексту, щоб маршрутизатор міг надійно розгалужуватися без необхідності обробки вільного тексту.

    П’ять елементів циклу чітко відповідають коду:

    • Тригер: виклик invoke(...) із запитанням починає виконання.
    • Перевірювана мета: правила verify можуть бути або verified, або needs_work.
    • Інструменти: обидві вузли використовують вбудований пошук в Інтернеті, research для написання та verify для перевірки.
    • Стан: словник ResearchState переміщує чернетку, відгуки та кількість ітерацій між вузлами.
    • Правила зупинки: маршрутизатор decide завершує процес при успіху або після досягнення MAX_ITERATIONS.

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

    У прикладі є два варіанти завершення. У продакшн-циклах зазвичай додається ще один — передача завдання людині. Коли агент стикається з щось ризикованим чи неоднозначним, йому краще не намагатися здогадатися та не зупинятися мовчки, а зупинитися та передати всю зібрану інформацію для подальшого розгляду. У маршрутизаторі це просто ще один варіант розвитку подій: коли рівень впевненості низький або дія є чутливою, маршрут escalate завершує цикл та представляє чернетку, нерозв’язані питання та здійснені спроби. Вміння визначити, коли не потрібно приймати рішення, є частиною хорошого проектування циклів.

    Способи збою та засоби їх запобігання

    Як тільки цикл починає працювати самостійно, з’являється короткий список передбачуваних збоїв, кожен з яких має стандартний засіб запобігання.

    • Нескінченний цикл. Агент ніколи не вирішує, що все завершено, і продовжує працювати, доки щось не зламається або гроші не закінчаться. Обмеження кількості ітерацій — це жорсткий механізм, як-от MAX_ITERATIONS вище, що забезпечує вихід без залежності від власної думки агента.
    • Спалювання токенів. З кожною ітерацією надсилається все більша кількість контексту, і витрати зростають непомітно. Зберігайте легку структуру даних, передаючи лише те, що потрібно на наступному кроці — поточний проект та конкретні відгуки, але ніколи не всю історію.
    • Уявний прогрес. Агент оголошує про успіх, якого не досяг, наприклад стверджує про виправлення, якого насправді не було. Не дозволяйте йому оцінювати власну роботу з точки зору того, що має значення. Окремий крок перевірки з об’єктивним тестом, тестами, які дійсно виконуються, або джерелами, які справді існують, забезпечує точне визначення того, що вже зроблено.
  • Повторення однієї помилки. Цикл знову намагається виконати ту саму невдалиу дію та знову зустрічається з тією самою проблемою. Необхідно передати попередню помилку до наступної спроби, щоб змінити підхід; саме тому research отримує feedback від перевіряючого.
  • Дії без відповідальності. Під час тривалих виконань стає складно зрозуміти, що сталося та чому. Необхідно фіксувати кожен крок: що бачив агент, які рішення прийняв та що зробив. Спостережуваність перестає бути необов’язковою, як тільки цикл торкається чогось важливого, і існують інструменти на кшталт LangSmith для відстеження таких виконань.
  • Повна автономія з самого початку. Цикл, який працює без нагляду з першого дня, ще не заслужив довіри. Необхідно поступово впроваджувати автономію: спочатку режим лише звітів, у якому описується, що він збирається робити, потім допоміжні зміни, які схвалює людина, і нарешті робота без нагляду — кожен етап досягається перед переходом до наступного.
  • Коли не варто використовувати цикл

    Цикли є потужними інструментами, тому їх легко застосовувати надмірно. У таких ситуаціях краще використовувати щось простіше.

    • Достатньо одного проходження. Підсумування документа, переклад тексту, відповідь на фактичне запитання та класифікація електронного листа — це завдання, які можна виконати один раз. Використання циклу для них лише збільшує витрати, затримки та ризики невдачі. Якщо підходить проста послідовність кроків, використовуйте її.
    • Успіх неможливо визначити. Коли мета є суб’єктивною чи нечіткою, або її може оцінити лише людина, у циклу немає орієнтира, тож він може закінчитися довільно або продовжуватися без кінця. Мета, яку неможливо перевірити, створює автомат із лотерейними барабанами, а не цикл.
  • Помилки можуть бути дорогими або незворотними. Люп, який з кожної ітерації надсилає електронні листи, переказує гроші чи видаляє дані, може швидко завдати серйозної шкоди. Залишайте людину в процесі схвалення або не використовуйте люп для виконання наслідкових дій.
  • Швидкість та витрати мають вищий пріоритет за автономію. Кожна ітерація означає додаткові виклики, ресурси та час. У функціях з великим обсягом роботи, низькою маржою чи чутливістю до затримок передбачуваний один виклик часто кращий за розумний, але дорогий люп.
  • Орієнтовне правило: якщо умови успіху та припинення роботи неможливо сформулювати, люп ще не готовий до реалізації.

    Чек-лист перед використанням люпа

    Інженерія циклів зміщує акцент на момент отримання результату. Написання бездоганного запиту має менше значення, ніж проектування системи, яка керує агентом, тобто його тригерів, цілей, інструментів, стану та правил зупинки. Проте цикл є лише одним із інструментів та ніколи не є стандартним рішенням. Спочатку варто поставити собі п’ять запитань:

    1. Чи можна автоматично перевірити успіх? Якщо ні, пропустіть цикл, адже у нього не буде орієнтира для керування.
    2. Чи покращується завдання з кожною повторною спробою? Якщо достатньо однієї спроби, залишіть все простим.
    3. Що саме означає завершення роботи? Запишіть умову успіху ще до початку програмування.
    4. Коли він має зупинитися? Встановіть жорсткий ліміт, щоб цикл не міг працювати нескінченно.
    5. Чи можна безпечно повторювати дії? Якщо певна ітерація може завдати серйозної шкоди, додайте людський контрольний пункт або не використовуйте цикл на цьому етапі.

    З чесними відповідями на всі п’ять запитань результат може бути надійним циклом, а не лише показовим. Найкраще підходить скромний перший проект: один етап дослідження та перевірки, як описано вище, з чіткими правилами зупинки ще до того, як щось почне розвиватися.

    Останній момент: цикл робить більше, ніж просто прискорює роботу. Він посилює будь-які рішення, які були прийняті, повторюючи як хороші, так і погані рішення зі швидкістю машини. Тож метою не є створити цикл та залишити все як є. Необхідна дисципліна, щоб залишатися достатньо близько, щоб постійно розуміти, що робить цикл після того, як він почне працювати самостійно, щоб його творець залишався його інженером, а не просто людиною, яка натискає кнопку запуску.

    Пов’язана література

  • Практичні нотатки: Експлойт sys.exit(0): як AI-агенти імітують успіх — Детальний посібник з Практичних нотаток: Експлойт sys.exit(0): як AI-агенти імітують успіх: контракти, перевірки та шаблони коду для команд, які впроваджують цю модель.
  • Практичні нотатки: Створення платформи AI з багатьма агентами — Частина 5: Сприйняття — Детальний посібник з Практичних нотаток: Створення платформи AI з багатьма агентами — Частина 5: Сприйняття: контракти, перевірки та шаблони коду для команд, які впроваджують цю модель.
  • Практичні нотатки: Agent Loop Engineering – повний блог про перехід від розробки до використання AI у продакшені — Детальний посібник з Практичних нотаток: Agent Loop Engineering – повний блог про перехід від розробки до використання AI у продакшені: контракти, перевірки та готові фрагменти коду для команд, які впроваджують цю модель.