JavaRush /Курси /ChatGPT Apps /Знайомство з агентами: ролі, run‑цикл, детермінізм, ідемп...

Знайомство з агентами: ролі, run‑цикл, детермінізм, ідемпотентність

ChatGPT Apps
Рівень 12 , Лекція 0
Відкрита

1. Що таке агент і навіщо він вам

Агенти не є обовʼязковою частиною ChatGPT App: можна створити скільки завгодно класних застосунків і без LLM‑агентів. Утім, є три вагомі причини розповісти вам про них.

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

ChatGPT випустив Agents SDK для TypeScript і Python. Він справді якісний. Оркестрація агентів працює «з коробки». Над одним складним завданням працюватиме не один агент, а ціла команда. Це дуже перспективний напрям.

Є й навчальна мета. ChatGPT викликає mcp-tools точнісінько так само, як LLM‑агенти викликають свої tools. Щойно ви зрозумієте, як працюють LLM‑агенти, вам стане ясно, як, наприклад, зробити машину станів на боці моделі в застосунку. Так само вивчення Agents SDK дає уявлення про те, як у майбутньому працюватиме ChatGPT SDK.

Тож почнімо.

Що таке LLM‑агент

Якщо ChatGPT App — це красивий і зручний фронтенд вашого сервісу всередині ChatGPT, а MCP‑сервер — це «рушій» з інструментами та бізнес‑логікою, то агент — це щось на кшталт розумного диспетчера, який уміє:

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

Якщо формулювати ближче до офіційної документації Agents SDK, агент — це програма. Маючи доступ до LLM і набору інструментів, вона здатна самостійно планувати кроки для досягнення цілі та виконувати їх через tool‑calls.

Якщо провести паралель із тим, що у вас уже є:

  • У звичайному ChatGPT App модель ChatGPT безпосередньо оркеструє виклики ваших MCP‑інструментів.
  • LLM‑агент на бекенді так само має опис завдання, набір інструментів і сам вирішує, які tools викликати, скільки кроків зробити, коли зупинитися та який результат повернути.

У контексті нашого GiftGenius це може виглядати так:

  • Застосунок без агента: модель безпосередньо викликає searchGifts, потім filterByBudget, потім getDetails — щоразу «думаючи заново»;
  • Застосунок з агентом: ChatGPT викликає MCP‑tool, а бекенд ставить агенту завдання: «Знайди топ‑5 подарунків для такого‑то профілю». Агент робить кілька кроків: збирає додаткову інформацію, викликає різні search‑інструменти, фільтрує, сортує, формує фінальні картки й повертає вже готову структуровану відповідь.

ChatGPT і LLM‑агент на бекенді — це як директор компанії та працівник. У ChatGPT значно більше свободи: він спілкується з користувачем і вирішує, які стратегічні завдання запускати (викликати MCP‑tools). LLM‑агент же працює тільки на бекенді, із користувачем не взаємодіє, але теж «думає» й може викликати свої tools. Своєрідний ChatGPT у спрощеному вигляді.

2. З чого складається агент: LLM, інструкції, інструменти та стан

Зручно уявляти агента як систему з кількох рівнів.

По‑перше, «під капотом» у нас та сама LLM. Це може бути GPT‑5.1 або інша модель, яку використовує Agents SDK. Вона генерує текст, планує кроки, обирає інструменти — коротко кажучи, займається «мисленням», але вже у вашому контексті оркестрації.

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

По‑третє, є набір інструментів агента. Це можуть бути:

  • функції на TypeScript (класичний function calling);
  • HTTP/REST‑інструменти;
  • обгортки над вашими MCP‑tools, щоб агент міг звертатися в той самий бекенд, що й ChatGPT App;
  • вбудовані «hosted» інструменти самого OpenAI (наприклад, web‑search, якщо ви їх підʼєднуєте).

І, нарешті, є правила роботи зі станом і кроками: як зберігається сесійний стан (session state), як зберігаються проміжні результати, як обмежуються цикли. Глибше про це ми поговоримо в наступній лекції про памʼять і стан. Але вже зараз корисно тримати в голові: агент — не «одноразовий запит», а потенційно тривалий процес зі збереженням прогресу.

Якщо подивитися на це очима розробника TypeScript, то в уяві виходить обʼєкт приблизно такого вигляду (псевдокод, близький до Agents SDK TS):

const giftAgent = new Agent({
  model: "gpt-5.1",
  systemPrompt: giftAgentPrompt,
  tools: { searchGifts, filterGifts, checkoutDraft },
  // тут же — налаштування пам’яті, лімітів кроків тощо.
});

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

3. Ролі повідомлень: system / user / assistant / tool у світі агента

Ви вже знайомі з класичними ролями system, user, assistant і tool із Chat Completions. В Agents SDK вони зберігаються, але набувають більш прикладного змісту.

Роль system задає «особистість» і місію агента. Наприклад, для GiftGenius‑агента це може бути: «Ти — агент добору подарунків. Твоє завдання — за мінімальну кількість кроків підібрати 3–7 релевантних варіантів подарунків на основі профілю одержувача та бюджету, а потім підготувати структурований JSON для віджета». Тут же ви прописуєте обмеження: що він не має робити (наприклад, не виконувати реальні покупки без окремого кроку) і як слід працювати з інструментами.

Роль user у контексті агента — це не обовʼязково «жива людина». Найчастіше це «завдання» для агента: ціль, сформульована вашим застосунком, сервісом або іншим агентом. Наприклад, ChatGPT App може викликати агента з user‑повідомленням: «Підбери 5 ідей подарунків для колеги‑розробника, бюджет 50 доларів, нагода — день народження».

Роль assistant — це те, що «говорить» сама модель усередині агента. Тут можуть бути як проміжні міркування й плани, так і фінальна відповідь. Ваше завдання — налаштувати системний промпт так, щоб ці повідомлення були корисні та, за потреби, потрапляли в логи.

Роль tool (або її аналоги в конкретному SDK) описує результати викликів інструментів: «через MCP знайдено 50 товарів», «API повернув помилку тайм-ауту», «БД віддала профіль користувача». Ці повідомлення разом із assistant‑повідомленнями утворюють історію run‑циклу агента.

Зручно звести це в маленьку таблицю:

Роль Хто говорить Приклад у контексті GiftGenius
system
Ви (як розробник агента) «Ти — агент із добору подарунків…»
user
Зовнішній виклик (App, інший агент) «Підбери 5 подарунків до 50 доларів…»
assistant
Модель усередині агента «План: 1) спитати деталі…»
tool
Результат викликаного інструмента «searchGifts повернув 20 варіантів…»

Ця структура важлива, оскільки саме на її основі будується run‑цикл — головний герой сьогоднішньої лекції.

4. Як LLM викликає функції на вашому бекенді

Коли ви звикли до режиму «питання–відповідь», здається, ніби LLM працює за простою схемою: прийшов текст → модель відповіла текстом. Насправді «під капотом» усе влаштовано трохи складніше — і саме тому працює function calling.

Модель отримує не одне питання, а список повідомлень — історію діалогу. Там уже є всі попередні репліки: системні інструкції («хто ти і що можна/не можна»), ваші повідомлення, минулі відповіді моделі, результати інструментів. На кожному кроці модель дивиться на всю цю стрічку як на журнал чату й вирішує: «Яке наступне повідомлення потрібно додати в кінець?»

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

Function calling влаштовано за тим самим принципом. Замість того щоб безпосередньо «запускати функцію», модель робить таке:

  • бачить список доступних інструментів/tools та їхні описи разом з історією діалогу;
  • вирішує: «Зараз логічніше не просто відповісти текстом, а спочатку викликати такий‑то інструмент»;
  • і як наступне повідомлення дописує в історію не звичайну текстову відповідь, а спеціальне повідомлення формату «хочу викликати такий‑то tool з такими‑то аргументами».

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

Тобто:

  • для звичайного Q&A: «наступне повідомлення» = текстова відповідь;
  • для function calling: «наступне повідомлення» = інструкція викликати функцію або відповідь після використання функції.

Жодної окремої «магічної команди виклику функції» немає: це просто особливий тип наступного повідомлення, яке модель додає в кінець ланцюжка.

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

5. Run‑цикл агента: як він «думає» крок за кроком

Фактично LLM‑агент — це певний обʼєкт або алгоритм на вашому сервері, який запускає агентний run‑цикл. Це розширений цикл «питання → подумати → можливо зробити дію → знову подумати → … → фінальна відповідь». У документації OpenAI це іноді називають agent loop або патерном ReAct (Reason + Act + Observe).

На концептуальному рівні один run агента виглядає так:

  1. Агент отримує вхідні дані: системні інструкції, завдання (user‑повідомлення), можливо — поточний стан.
  2. Модель генерує крок: або текстову відповідь, або плани й рішення викликати один чи кілька інструментів.
  3. Якщо модель обрала tool‑call, агент викликає відповідний інструмент у коді (це може бути локальна функція, MCP‑tool, HTTP‑запит, доступ до БД тощо).
  4. Результати інструментів додаються в історію як tool‑повідомлення.
  5. Цикл повертається до моделі з новим контекстом. Модель вирішує, що робити далі: продовжувати планування, викликати інший інструмент або завершити завдання фінальною відповіддю.
  6. Коли модель явно або за умовами зупинки завершує run, агент повертає фінальний результат стороні, що викликає.

У вигляді невеликої діаграми це можна показати так:

flowchart TD
    A[Старт run: ціль + system] --> B[Виклик моделі]
    B --> C{Модель хоче
відповісти текстом
чи викликати tool?} C --> D["Текстова відповідь
(assistant)"] D --> E{Задачу завершено?} E -->|Так| F[Фінальний результат] E -->|Ні| B C --> G["Tool‑call
(опис виклику)"] G --> H[Виклик функції / MCP / HTTP] H --> I["Tool‑результат
(tool message)"] I --> B

Якщо перекласти це в спрощений TypeScript‑псевдокод (далекий від реального API, але логічно коректний), вийде щось на кшталт:

async function runAgent(goal: string) {
  let context = buildInitialContext(goal);

  while (!isFinished(context)) {
    const decision = await callLLM(context); // крок агента

    if (decision.type === "tool_call") {		// викликати функцію?
      const toolResult = await callTool(decision.tool, decision.args);	// викликаємо локальну функцію
      context = appendToolResult(context, toolResult);		// додаємо результат у кінець списку
    } else {
      context = appendAssistantMessage(context, decision.message); 
    }

    enforceLimits(context); // ліміти кроків/часу/циклів
  }

  return extractFinalResult(context);
}

Agents SDK бере на себе більшу частину цієї рутини: зберігання історії, маршалінг tool‑calls, логіку повторів тощо. Вам залишається налаштувати конфігурацію та реалізувати самі інструменти.

Run vs step

Важливо розрізняти два поняття:

  • run — це один запуск агента для якоїсь цілі: «підібрати подарунки для цього випадку»;
  • step — один крок run‑циклу: конкретний виклик моделі, який може призвести до текстової відповіді або до tool‑call.

У моніторингу ви бачитимете саме безліч кроків усередині одного run. А ліміти з безпеки та вартості часто задають або «на run», або «на крок».

Тепер, коли зрозуміло, як агент живе всередині одного run і крокує по run‑циклу, подивімося, де взагалі є сенс усе це будувати, а де достатньо простих tools.

6. Де в GiftGenius потрібен агент, а де він зайвий

Перш ніж братися писати агента для всього, корисно чесно запитати себе: «А він узагалі тут потрібен?».

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

У GiftGenius таким завданням може бути «майстер розумного добору подарунків», який:

  • уміє дозапитувати важливі деталі (стать одержувача, хобі, рівень близькості);
  • може звертатися до кількох джерел товарів (різні постачальники через MCP‑tools);
  • фільтрує та ранжує результати;
  • у разі помилок джерел повторює спробу або йде запасним шляхом;
  • повертає не просто список текстів, а структурований список кандидатів із поясненнями та посиланнями на SKU з product feed.

Тут агент буде справді корисний як «оркестратор». Особливо якщо згодом ви захочете доповнити це голосовим або Realtime‑сценарієм чи складною комерцією (ACP).

А от для простого виклику getGiftDetails(giftId) агент не потрібен: звичайний MCP‑tool, що викликається безпосередньо з ChatGPT, повністю покриває цей сценарій. Те саме — із простими «однокроковими» сценаріями на кшталт «скажи опис цього подарунка за текстом продуктової картки».

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

7. Детермінізм: як зробити поведінку агента передбачуваною

Детермінізм у світі LLM‑агентів — річ хитра. Теоретично за однакового входу й однакових налаштувань ви хочете отримувати однаковий план дій і однакову послідовність tool‑calls. На практиці модель залишається стохастичною, але у вас є кілька важелів, щоб підвищити передбачуваність.

По‑перше, класика: температура та інші параметри генерації. Чим нижча температура, тим менше креативу й тим більше «слухняності» моделі. Для агента з добору подарунків ви, найімовірніше, захочете мати не нульовий, але й не надто високий рівень свободи. Інакше модель щоранку вигадуватиме новий спосіб викликати один і той самий інструмент.

По‑друге, чіткі системні інструкції. Якщо ви розмито описуєте поведінку на кшталт «ти можеш викликати різні інструменти й робити що хочеш», не дивуйтеся, що агент то стрибатиме по API, то намагатиметься відповідати «зі стелі». Набагато краще явно описувати, коли саме слід викликати інструмент, які параметри допустимі, як інтерпретувати помилки й у яких випадках потрібно завершувати завдання.

Наприклад, системний промпт для GiftGenius‑агента може містити фрагмент:

Якщо в тебе немає повного профілю одержувача (вік, стать, нагода, приблизний бюджет),
спочатку постав уточнювальні запитання через user-facing канал і дочекайся відповідей.
Лише після цього викликай інструмент search_gifts із заповненим профілем.
Не вигадуй товари зі стелі, завжди спирайся на результати інструментів.

Такі вказівки знижують варіативність рішень і роблять поведінку більш детермінованою.

По‑третє, дизайн самих інструментів. Якщо у вас є три інструменти, які «приблизно одне й те саме» шукають подарунки, модель неминуче іноді обиратиме один, іноді — інший. Краще спроєктувати інструменти з чіткими, непересічними зонами відповідальності та прописати це в описах.

Нарешті, можна використовувати guardrails — правила та схеми, які перевіряють дії агента й результати моделі. В Agents SDK є вбудована підтримка перевірок і обмежень, зокрема на структуру вихідних даних. Якщо модель намагається згенерувати щось не за схемою, ви можете мʼяко її виправити або навіть повторити крок заново.

Міні‑приклад: фіксуємо формат результату

Припустімо, вам потрібно, щоб агент завжди повертав JSON із полем gifts, а всередині були обʼєкти з id, title і score. Ви можете:

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

Псевдокод:

const giftResultSchema = z.object({
  gifts: z.array(z.object({
    id: z.string(),
    title: z.string(),
    score: z.number().min(0).max(1),
  }))
});

// У конфігурації агента
const agent = new Agent({
  /* ... */
  outputSchema: giftResultSchema,
});

Коли модель спробує повернути щось дивне, runner повідомить про помилку валідації. А ви зможете або перепросити модель, або логувати інцидент.

8. Ідемпотентність: чому агент може викликати ваш API двічі

Якщо детермінізм — це про «однаковий план за однакових входів», то ідемпотентність — про безпечність повторів. У контексті агентів вона критично важлива з двох причин.

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

Ви вже обговорювали ідемпотентність на рівні MCP‑tools: не здійснювати подвійні платежі, не створювати те саме замовлення двічі, використовувати idempotency keys у запитах. Зараз усе те саме, але помножене на багатокрокову природу агента.

Уявімо, що в GiftGenius зʼявився інструмент create_checkout_session, який за списком обраних подарунків створює draft‑checkout в ACP/Stripe. Якщо агент вирішить повторити цей виклик через мережеву помилку, ви точно не хочете отримати два окремі замовлення і два списання коштів.

Отже, потрібно:

  • вигадувати зовнішній idempotency key для кожної логічної дії (наприклад, runId + stepIndex або явно згенерований checkoutDraftId);
  • передавати його у ваш бекенд/ACP‑endpoint;
  • на боці бекенда перевіряти, чи не обробляли ви вже цей ключ, і повертати збережений результат замість повторного виконання.

Псевдоприклад на TypeScript:

async function createCheckoutDraft(runId: string, payload: DraftPayload) {
  const key = `gift-checkout-${runId}`;

  const existing = await findDraftByKey(key);
  if (existing) return existing;

  const draft = await stripe.checkout.sessions.create({
    /* ... */,
    idempotencyKey: key, // або власний шар поверх
  });

  await saveDraftWithKey(key, draft);
  return draft;
}

Тепер, навіть якщо агент із якоїсь причини викличе цей інструмент двічі з тим самим runId, ваш код залишиться ідемпотентним: один і той самий логічний крок → один і той самий фактичний результат.

«Спочатку перевірка, потім дія»

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

Safe‑mode/Fake‑mode

На стадії розробки корисно мати «безпечний режим» для небезпечних інструментів: замість реальної дії вони лише логують, що було б зроблено, і повертають псевдорезультат. Для агентів це зручний спосіб прогнати run‑цикл у бойовому середовищі, не ризикуючи грошима чи даними.

9. Міні‑практика: описуємо агента GiftGenius людською мовою

Ми вже поговорили про run‑цикл, детермінізм та ідемпотентність інструментів. Давайте на хвилину відірвемося від коду й перевіримо, як усе це складається в живий сценарій.

Зараз корисно зробити маленьку вправу на папері (або в голові) — без коду.

Уявіть, що ви описуєте простого агента:

  • system
    : ти — помічник із добору подарунків; завжди уточнюєш важливі деталі, не вигадуєш товари, а використовуєш лише результати інструментів.
  • user
    : хочу подарунок колезі до 50 доларів.

Опишіть словами, які кроки такий агент має зробити.

Типовий сценарій може виглядати так.

  1. Спочатку агент перевіряє, чи достатньо інформації. Якщо ні, він ставить уточнювальні запитання: ким приблизно займається колега (дизайнер, розробник, менеджер), чи є якісь табу (алкоголь, жартівливі подарунки), чи є обмеження щодо доставки. Відповіді потрапляють або в session state, або в параметри виклику інструмента.
  2. Потім агент викликає інструмент search_gifts із заповненим профілем: «колега‑розробник, бюджет 50 доларів, категорія — ґаджети та офіс». Інструмент повертає список кандидатів із цінами, категоріями та ID товарів.
  3. Далі агент може викликати додатковий інструмент filter_gifts_by_constraints, якщо зʼясувалося, що частину товарів не можна доставити в потрібний регіон, або вручну відфільтрувати у своєму промпті. Після цього він сортує варіанти за релевантністю та вартістю, можливо, додаючи свої коментарі («підходить, якщо колега любить каву», «гарний варіант для віддаленої роботи»).
  4. Нарешті, агент готує фінальну структуровану відповідь для ChatGPT App: список 5–7 подарунків із короткими описами, підказками щодо використання та посиланнями на Checkout (або на наступний крок — створення draft‑checkout).

Де тут потрібні tool‑calls? Очевидно, у пошуку та фільтрації товарів, у перевірці доступності та у створенні draft‑checkout. Які кроки мають бути ідемпотентними? Насамперед усі операції, повʼязані із замовленнями та грошима: створення draft‑checkout, можливо, запис історії в БД.

10. Типові помилки на перших кроках з агентами

Помилка № 1: агент як «другий ChatGPT без обмежень».
Іноді хочеться просто видати моделі ще один промпт і назвати це «агентом». У результаті виходить штука, яка генерує багато тексту, хаотично викликає інструменти й погано піддається контролю. Щоб цього уникнути, важливо чітко описувати роль агента в system, обмежувати список інструментів і думати про нього саме як про оркестратора з конкретною місією, а не як про «другий всесвіт текстогенерації».

Помилка № 2: відсутність ідемпотентності в інструментах.
Розробники нерідко переносять свої старі HTTP‑обробники під агента «як є», не враховуючи, що тепер runner може автоматично повторювати виклики. У випадку з платежами та замовленнями це може призвести до дуже неприємних наслідків. Правильний підхід — відразу проєктувати інструменти так, щоб повторний виклик із тим самим логічним ключем не призводив до повторної дії.

Помилка № 3: надто креативні налаштування моделі.
Висока температура чудово підходить для вигадування тостів і віршів. Але для агента, який має надійно оркеструвати багатокрокові процеси, це шлях до непередбачуваної поведінки: модель щоразу обиратиме різні інструменти, генеруватиме інші плани й інколи взагалі забуватиме, що в неї є tools. Варто ставитися до агентів як до «службових» сутностей і тримати їх у суворішому режимі.

Помилка № 4: інструмент «на всі випадки життя».
Іноді хочеться зробити один універсальний tool на кшталт execute_any_sql або do_anything_with_orders, а потім дати його до рук агенту. У поєднанні з LLM‑креативністю це майже гарантована загроза безпеці. Набагато краще мати кілька вузькоспеціалізованих інструментів із чіткими контрактами та правами, ніж один «всемогутній» — із повними правами на все.

Помилка № 5: відсутність явних критеріїв завершення run.
Якщо агенту не пояснити, коли потрібно зупинитися, він може почати впадати в нескінченні або майже нескінченні цикли: ще раз перевірити результати, ще раз перепитати користувача, ще раз спробувати викликати інструмент за тієї самої помилки. Часто це проявляється тільки під навантаженням, коли одна із залежностей нестабільна. Правильний спосіб — задавати ліміти на кількість кроків, час run і кількість повторів за однакової помилки, а також описувати в system, що агент має чесно зупинятися, коли вичерпав розумні варіанти.

Помилка № 6: зберігання всього підряд у стані агента.
Оскільки Agents SDK спрощує роботу з session state, є спокуса складати туди все підряд: великі документи, необроблені логи, чутливі дані. Це роздуває контекст, збільшує вартість і створює ризики безпеки. Стан агента має зберігати лише те, що справді потрібно для продовження роботи. Усе інше — у БД, логах та інших шарах, причому з урахуванням приватності.

Помилка № 7: спроба використовувати агента там, де достатньо простого MCP‑tool.
Іноді розробники починають з агента, навіть якщо завдання — просто викликати одну функцію і повернути результат. Це додає складність там, де вона не потрібна: зʼявляються run‑цикл, стан, додаткові логи та потенційні точки відмови. Якщо сценарій укладається в один tool‑call без складного workflow, краще залишити його таким і підключати агента лише тоді, коли зʼявляється справжня багатокроковість.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ