Інжиніринг запитів чи контексту, керування та циклів? Дебагування штучних інтелектуальних агентів пошарово
Інжиніринг запитів, інжиніринг контексту, інжиніринг керування та інжиніринг циклів — кожен з них зазнає невдачі по-своєму. Процедура з аналізу слідів допомагає виявити ту складову, яка зламалася.
Коли штучний інтелект у продакшені поводиться неналежним чином, команди схильні сперечатися щодо термінології замість того, щоб аналізувати докази: один інженер пропонує кращий запит, інший звинувачує контекст, ще один — інструментарій. Інженерія запитів, контексту, інструментарію та циклів не є суперечливими підходами; це чотири послідовні шари, і кожен з них зазнає невдачі по-своєму. У цьому посібнику кожен шар описується на прикладі простого коду агента, а потім наводиться алгоритм, який допомагає визначити, який саме шар вийшов з ладу, перш ніж змінювати будь-який код.
Чотири шари штучного інтелект-агента у короткому огляді
- Інженерія запитів визначає інструкції, які надсилаються до моделі.
- Інженерія контексту визначає, що бачить модель перед тим, як дати відповідь.
- Інженерія керування створює середовище, у якому працює модель: інструменти, пам’ять, файли, дозволи та механізми відновлення.
- Інженерія циклів проєктує цикл, який забезпечує роботу системи, контролює її прогрес та вирішує, коли припинити її роботу.
Найбільш дорогі інциденти з агентами виникають через виправлення проблем у одному з цих шарів.
Коли демо працює, а продакшн — ні
Цей сценарій знайомий. Агент виглядає бездоганним у демо-версії. Через кілька днів після запуску він починає повторювати цикли, витрачати токени, забувати те, що йому сказали годину тому, або зазнає збоїв, коли інструмент повертає неочікуваний контент.
Команда ділиться на групи. Хтось пропонує переписати запит, хтось інший вважає, що це проблема контексту, а ще хтось підозрює пристрій кріплення. Без спільного способу виявлення причини несправності дводенне виправлення перетворюється на двотижневу роботу з переписування, оскільки кожен патч застосовується до шару, який раніше працював без проблем.
Ось практична причина, чому потрібно тримати ці чотири терміни окремо. Кожен з них позначає окреме місце, де може виникнути проблема, і як тільки ви можете їх розрізнити, виправлення помилок стає процесом, а не грою в здогадки.
PACT: мнемонічний принцип для чотирьох шарів
Компактний спосіб запам’ятати шари під час інциденту — PACT: Prompt, Awareness, Control, Trajectory. Кожне слово відповідає одному запитанню:
- Prompt: чи було завдання чітко визначене?
- Awareness: чи отримав модель інформацію, необхідну для цього кроку?
- Контроль: чи може середовище виконання безпечно та надійно виконати те, про що просить модель?
- Траєкторія: чи приводить цей повторюваний процес до кінцевого результату, який можна перевірити?
Метою не є створення ще одного шару жаргону. Метою є зробити межі між типами збоїв настільки зрозумілими, щоб їх можна було легко згадати, коли щось йде не так.
Як з’явилися ці рівні та чому важливий порядок
Ці терміни з’явилися приблизно в такій послідовності, по мірі того, як агенти набували нових можливостей:
- Інженерія запитів (приблизно з 2022 по 2024 рік) була першою навичкою: формулювання запитів, приклади, обмеження та шаблони для кількох запитів до однієї моделі.
- Інженерія контексту (приблизно з 2024 по 2025 рік) стала ключовою, коли агенти почали одночасно обробляти отримані документи, історію розмов та визначення інструментів. Фокус змістився з того, як сформулювати запит, на те, що насправді бачить модель. Anthropic, LangChain та Chroma сприяли поширенню цього підходу серед фахівців, а коментарі Андрея Карпаті допомогли включити його до ширших інженерних дискусій.
- Інженерія керування (початок 2026 року) стала пріоритетною, коли агенти отримали доступ до файлової системи, можливість виконання команд терміналу та здатність працювати годинами. Увага зосередилась на діапазоні дій агента та на поведінці після невдалих викликів інструментів. Робота OpenAI над Codex зробила це важливою проблемою для кодувальних агентів; їхній опис інженерії керування з використанням Codex є корисним основним джерелом інформації.
- Інженерія циклів (середина 2026 року) — це найновіша категорія. Навіть за наявності відповідної інфраструктури все одно потрібно вирішувати, що робити на кожній ітерації та коли зупинитися: спостерігати, діяти, перевіряти, повторювати чи припинити. IBM має пояснювальний матеріал про інженерію циклів, якщо ви хочете інше формулювання.
Ці дати вказують на моменти, коли ці терміни набули популярності, а не на формальні віхи, і на момент написання термінологія ще формується. Важливим моментом є те, що нічого не було замінено. Кожен рівень додавався поверх попереднього, оскільки кожне підвищення автономії вимагало власного механізму керування.
Інженерія запитів: локальний контракт
Інженерія запитів — це мистецтво формулювання, структурування та пояснення інструкції так, щоб відповідь була більш прогнозованою. Без неї виникають нечіткі інструкції, непостійні формати вихідних даних та ситуація, коли модель змушена здогадуватися, що ви мали на увазі.
У кодувальному агенті запит на перегляд коду може виглядати так:
SYSTEM: You are a code reviewer.
Given a diff, output ONLY valid JSON:
{"issues": [{"line": int,
"severity": "low|medium|high", "note": str}]}
No prose. No markdown fences.
If there are no issues, return {"issues": []}.
Цей запит встановлює локальний контракт. Він призначає роль, описує процес трансформації (вхідні відмінності, список проблем), фіксує формат вихідних даних аж до назв полів та допустимих значень серйозності, а також визначає випадок порожнього результату, щоб подальше оброблення ніколи не мусило мати справу з прозою чи відсутньою ключовою інформацією.
Поширеною думкою є те, що інженерія запитів є застарілою. Це не так; це найглибший шар обробки. Кожен контекстний конвеєр зрештою передає моделі інструкцію, і слабка інструкція в межах чудової інфраструктури все одно дає слабкі результати, лише тепер упаковані в вражаючу інфраструктуру.
Інженерія контексту: кураторство в межах бюджету
Інженерія контексту — це процес вибору для кожного запиту тих документів, історії, визначень інструментів та даних пам’яті, які мають потрапити до вікна, а також, так само усвідомлено, тих, які не будуть включені. Якщо цього не дотримуватися, модель відповідає на основі застарілої інформації, відхиляється від правильного напрямку через нерелевантні знайдені уривки чи втрачає фокус через те, що вікно переповнене матеріалом, доданим на випадок потреби.
Інструмент для створення контексту для кодувального агента може знаходити кандидатів, переорієнтувати їх за рангом та стиснути історію:
def build_context(query, full_history, kb):
relevant = retrieve(query, kb, top_k=8)
reranked = rerank(relevant, query)[:3]
summary = summarize_if_long(
full_history, max_tokens=800
)
return {
"docs": reranked,
"history": summary,
"query": query,
}
Сприймайте це як воронку. Етап отримання даних розкидає широку мережу з вісьмома кандидатами, етап переранжування залишає три найбільш релевантні, а історія розмови узагальнюється до приблизно 800 токенів лише тоді, коли вона стає довгою. Функція повертає невеликий, структурований пакет даних, а не сирі матеріали. Ключовими навичками тут є відбір, ранжування та стиснення, а не обсяг інформації.
Саме тому найпоширеніше непорозуміння, що інжиніринг контексту означає надання моделі більше інформації, зазвичай є хибним. Більший контекст схильний містити більше шуму: застарілі інструкції, повторювані факти та суперечливі докази. Більша частина роботи полягає у виборі того, що залишити без уваги.
Інжиніринг контексту є ширшим за RAG
Генерація з підсиленням за допомогою пошуку — це одна з технік у рамках інженерії контексту, яка охоплює етап пошуку інформації. Пайплайн RAG може отримати вісім фрагментів та перевідсортувати їх до трьох, як описано вище. Інженерія контексту також включає стиснення історії, форматування визначень інструментів, підтримку актуального стану критичних завдань, надсилання результатів перевірки назад до моделі та вирішення питання про те, що слід пропустити.
Кодувальний агент без будь-якого сховища векторів все одно має реальну проблему з контекстом, яку потрібно вирішити. Статус Git, відкриті файли, помилки компілятора, результати тестів, поточний план та журнал попередніх дій — усе це має надійти до моделі у придатній формі.
Інженерія використання ресурсів: межа між наміром та ефектом
Хаб є тією частиною системи, яка не є моделлю: інструменти та доступ до файлів, постійна пам’ять, правила дозволів, пісочниці, відстеження та все, що відбувається у разі збою. Без якісного хаба у вас буде агент, який добре міркує, але не може діяти відповідно, або агент, який діє, але не має надійного способу відновлення у разі помилки виклику інструменту.
Пример виклику інструменту ілюструє цю ідею:
def call_tool(tool_name, args, retries=2):
for attempt in range(retries + 1):
try:
result = TOOLS[tool_name](**args)
log_trace(tool_name, args, result, status="ok")
return result
except ToolError as e:
log_trace(tool_name, args, str(e), status="failed")
if attempt == retries:
return {"error": str(e), "recoverable": False}
args = repair_args(args, e)
Цей інструмент не намагається вирішити завдання. Він визначає межу між тим, що запитує модель, та тим, що робить реальна система. Кожна спроба фіксується разом із її аргументами, результатом та статусом. Поразка призводить до обмеженої кількості повторних спроб із виправленими аргументами, а коли всі спроби вичерпані, він повертає структуровану помилку, позначену як непоправна, щоб користувач отримав дані, з якими може працювати, замість винятку, який зупиняє виконання.
Хочеться ототожнити цей інструмент із будь-якою фреймворк-системою агентів, яку ви встановили. Фреймворк надає основу; цей інструмент — це сукупність конкретних рішень, які ви приймаєте на його основі: що записується, що робить невдала виклик, який стан зберігається після збою, які команди дозволені та як результати виконання подаються назад моделі.
Інженерія циклів: контракт завершення
Інженерія циклів визначає роботу кожної ітерації, спосіб, яким агент оцінює, чи досягає він прогресу, та, що найважливіше, умови для зупинки. Характерною проблемою є необмежений цикл: агент продовжує викликати інструменти та витрачати токени, оскільки ніхто не повідомляє йому, що він завершив роботу чи застряг.
Мінімальний контролер виглядає так:
def run_loop(task, harness, max_iters=15, stall_limit=3):
state = init_state(task)
stalls = 0
for i in range(max_iters):
action = plan_next_step(state)
result = harness.call_tool(action.tool, action.args)
state = update_state(state, result)
if is_goal_met(state):
return state, "success"
if made_no_progress(state):
stalls += 1
if stalls >= stall_limit:
return state, "stalled — escalate"
else:
stalls = 0
return state, "max iterations reached"
Тут застосовано кілька обмежень. max_iters встановлює максимум загальної кількості ітерацій, is_goal_met забезпечує можливість завершення успішно, а лічильник затримок відстежує послідовні ітерації без прогресу, скидаючись щоразу, коли прогрес відновлюється. Після stall_limit ітерацій з затримками цикл повертає окремий статус, який вимагає подальшого розгляду ситуації, замість того щоб продовжувати роботу мовчки. Кожен шлях виходу повертає чітку причину, що полегшує подальшу класифікацію виконань.
Центральною ідеєю є контракт завершення: чітка мета, сигнали прогресу, які можна виміряти, обмежена кількість спроб, бюджети на час та токени, крок перевірки та чітка політика дій у разі затримки прогресу. Щодо реалізацій цих ідей у TypeScript, дивіться bounded agentic loops for LLM tool use.
Інженерія циклів та інструментальних комплексів часто плутають. Інструментальний комплекс визначає, що може торкатися агент, та як обробляються збої на рівні окремих інструментів. Цикл знаходиться над ним та визначає поведінку крок за кроком, включаючи момент, коли слід завершити виконання в цілому.
Чотири шари поруч
- Запит (P): відповідає за інструкцію. Типовий збій: модель неправильно розуміє намір або повертає інформацію неправильного формату. Перше, що потрібно перевірити – сам вихідний результат.
- Контекст (A): відповідає за стан, готовий до обробки моделлю. Типовий збій: модель діє на застарілій, відсутній або відволікаючій інформації. Перше, що потрібно перевірити – знімки контексту за кожен крок.
- Інструментальний комплекс (C): відповідає за виконання та відновлення. Типовий збій: помилка під час виклику інструменту, сліпі спроби повтору або неможливість відновлення. Перше, що потрібно перевірити – записи про збої в трасуванні дій інструменту.
Як відрізнити баг у механізмі керування від багу в циклі
Найефективніший спосіб заощадити час — це помітити, що два різні баги ззовні виглядають однаково. Агент, застряглий у циклі через несправний контролер, та агент, застряглий через несправну обробку інструментів, проявляють однакові симптоми: він продовжує працювати, витрати зростають, і ніхто не розуміє причини. Короткий чек-лист допомагає їх відрізнити від інших проблем.
1. Отримайте трасування викликів інструментів
Якщо всі виклики успішні та дають логічні результати, але агент постійно використовує один і той самий інструмент з майже незмінними аргументами, це вказує на цикл.
2. Шукайте повторні збої інструментів
Якщо певний інструмент постійно зазнає невдач, а агент продовжує спроби, не змінюючи свого підходу, слід підозрювати харнес.
3. Перевірте, що міг бачити модель
Якщо здається, що модель забуває певний факт під час виконання завдання, перевірте створення контексту: обрізку, заміну, стиснення чи спосіб передачі стану між кроками.
4. Останнім перевірте результат
Якщо інструменти працювали, контекст був точним, а цикл завершився коректно, але відповідь все одно неправильна, перегляньте запит.
Орієнтовне правило
Баги в циклах полягають у рішенні щодо подальших дій. Баги в харнесі — у тому, що відбувається, коли щось ламається. Баги в контексті — у тому, що може бачити модель. Баги у запиті — у тому, про що ви просили.
Відповідайте на запитання, яке з чотирьох є актуальним, перш ніж щось редагувати.
Кейс-стаді: рецензент запитів на зміни, який не зупинявся
Уявіть команду, яка створює агента для кодування, що переглядає запити на зміни. Тестування проходить без проблем. У продакшені деякі перегляди тривають понад 40 хвилин за один запит на зміни, що призводить до несподіваних рахунків.
Перша теорія полягає у тому, що інструкція занадто нечітка, тому агент занадто багато думає. Інструкцію перепишують, але нічого не змінюється. Друга теорія стосується контексту: можливо, агент щоразу перечитує весь репозиторій. Однак дані показують інше — отримання інформації відбувається правильно, і завантажуються лише важливі файли.
Потім хтось уважно аналізує запис викликів інструментів. Агент неодноразово викликає свій інструмент для виконання тестів, і кожен виклик завершується без помилок. Насправді набір тестів провалюється через нестабільний інтеграційний тест, який не має відношення до запиту на зміни. Агент продовжує намагатися виправити цей провал за допомогою несумісних змін у коді та повторного виконання тестів, оскільки ніщо не підказує йому, що він вже зробив достатню кількість спроб щодо цієї підмети та має зупинитися та передати справу на вищий рівень.
Це не проблема запиту, не проблема контексту та не проблема інструментального комплексу; інструменти працювали саме так, як було спроєктовано. Це суто помилка циклу. Послідовний аналіз крок за кроком дозволяє дійти такого висновку.
Крок 1: підтвердити, що інструменти працюють
Успішне виконання тестів у записі викликів виключає найпростіші проблеми інструментального комплексу, такі як команда, яка ніколи не виконується, або адаптер, який постійно викидає помилки.
Крок 2: порівняння стану між ітераціями
Результати тестування знаходяться в контексті агента, а їх отримання відбувається у правильних межах, тому модель не пропускає необхідні докази.
Крок 3: перевірка на збіжність
У репозиторії відбуваються зміни з кожною ітерацією, але сигнал перевірки, який має значення, ніколи не покращується. Не існує детектора застою та жодних обмежень на кількість спроб досягнення однієї й тієї самої підмети.
Крок 4: навчання контролера виявляти застій
Рішенням є невелика частина логіки контролера, яка порівнює показники прогресу між кроками:
if progress_signature == previous_signature:
stagnant_steps += 1
else:
stagnant_steps = 0
if stagnant_steps >= 3:
escalate("no measurable progress")
stop()
progress_signature може бути чим завгодно, що відображає значущий прогрес, наприклад набір невдалих тестів разом із їхніми повідомленнями про помилки. Якщо він не змінюється, лічильник застою зростає; після трьох кроків застою контролер піднімає ситуацію на вищий рівень із поясненням причини та зупиняється. Будь-яка реальна зміна скидає цей лічильник.
Можна піти ще далі та обмежити кількість спроб для кожної конкретної причини невдачі, а не лише загальну кількість ітерацій. Це розрізнення є важливим: п’ятнадцять продуктивних ітерацій можуть бути цілком прийнятними, тоді як п’ятнадцять спроб проти однієї нерозв’язної проблеми у тесті є суцільною марною тратою часу. Справжнім рішенням є не робити модель менш впертою, а надати контролеру чітке визначення стану застою.
Кейс-стаді: обмеження, яке зникає з контексту
Уявіть тепер агента, який на початку міграції встановлює правило, згідно з яким ніщо не повинно пошкодити існуючих клієнтів. Через сорок кроків розмова стає сконденсованою, і це обмеження зникає у резюме. Тоді агент пропонує зміну схеми, яка може пошкодити систему.
Це виглядає як помилкове міркування, але причина криється в іншому. Порівняйте контекст, який модель фактично отримувала на різних етапах. Якщо обмеження було присутнє на п’ятому кроці, але відсутнє на сороковому, то рішення полягає у оптимізації контексту: зберігати критичні інваріанти окремо від розмови, змушувати резюме передавати чіткі обмеження далі та припинити вважати сиру історію єдиним джерелом істини.
Фраза „модель забула“ ніколи не є повною діагнозом. Корисне запитання — що саме було надано моделі.
Шари, а не заміна
Кожна новіша дисципліна ґрунтується на старіших, а не замінює їх. Агент виробництва обгортає чіткий запит у ретельно підібраний контекст, запускає його в надійному середовищі та керує всім цим за допомогою цілеспрямованого циклу. Послідовність елементів відображає те, що командам доводилося додавати з часом: спочатку більш чіткі інструкції, потім краще підібрана інформація, далі середовище виконання для моделі та нарешті контролер, який підтримує це середовище у роботі без постійного нагляду. Якщо ви вирішуєте, чи має ваш власний движок виконання чи фреймворк керувати цим зовнішнім циклом, порівняння движків виконання та складених фреймворків розглядає всі аспекти цього вибору.
Перефразовано через PACT:
- Запит: визначити інструкцію.
- Усвідомленість: створення стану, над яким буде працювати модель.
- Контроль: забезпечення того, щоб виконання було прозорим, обмеженим та можливим до відновлення.
- Траєкторія: перетворення повторень на прогрес, який можна виміряти, з завершенням у перевіреному результаті.
Потім потрібно прив’язати рішення до проблеми. Модель, яка неправильно розуміє чітко визначене завдання, потребує коригування. Модель, якій бракує фактів, від яких вона залежить, потребує додаткового контексту. Розумні рішення, які не перетворюються на надійні дії, вимагають оптимізації. Дії, які успішні, хоча загальний процес так і не досягає стабільного стану, вимагають корекції логіки циклів.
Поширені запитання про шари агентів
Чи є інженерія оптимізації просто іншою назвою для фреймворку агентів?
Ні. Фреймворк надає будівельні блоки. Комплекс інструментів складається з рішень, які ви приймаєте під час їх об’єднання: поведінка у разі збою інструменту, збережений стан, логування, дозволи та спосіб повернення результатів до моделі.
Чи потрібна інженерія циклів для асистента з одним запитанням?
Не дуже. Інженерія циклів стає важливою, коли агент виконує кілька дій за завданням та мусить самостійно або за допомогою коду контролера вирішити, чи завершено роботу. Бот для запитань та відповідей з одним етапом майже не має циклів для проектування.
Який шар варто вивчати спочатку?
Почніть з інженерії запитів та контексту, потім переходьте до комплексу інструментів та циклів. Перш ніж ви можете відлагоджувати час виконання та код контролера, вам потрібно розрізняти погані інструкції та відсутній стан.
Чи може одна помилка охоплювати кілька шарів?
Так, і саме ці випадки зазвичай є найскладнішими. Баг у контексті може приховати сигнал прогресу від циклу, через що це виглядає як баг циклу. Слідкуйте за причиною збою на всіх рівнях, а не просто усувайте перший помітний симптом.
Чек-лист для наступного інциденту з агентом
- Ці чотири терміни описують механізми керування, а не суперечливі тенденції: інструкцію, стан готовності моделі, виконання та відновлення, а також постійний прогрес із правилом зупинки.
- Починайте кожне розслідування зі запису дій, а не з запиту: запитайте, що бачила модель, що робив движок під час виконання, що змінилося між ітераціями та чому контролер вирішив продовжити роботу.
- Успішні виклики інструментів, які повторюються з майже ідентичними аргументами, вказують на проблему в циклі; постійні збої з сліпими спробами повторення вказують на проблему в системі керування.
- Надайте циклам чітке визначення стану затримки, бажано за певними ознаками збою, а також шлях ескалації.
- Зберігайте стійкі обмеження поза областю компресування історії, щоб їх не можна було стерти під час компактування.