У воркшопі на каналі AI Engineer розробник Effect і співзасновник Effectful Майкл Арнальді показує, як він будує застосунки на TypeScript з бібліотекою Effect і водночас проектує робочі процеси для кодових агентів. Арнальді вже щонайменше пів року не пише код вручну — за нього це роблять LLM‑моделі, зокрема для низькорівневих бібліотек на TypeScript і Rust. На цьому тлі він детально розбирає, як правильно давати агентам інструкції, які інструменти їм відкривати, як організовувати контекст і чому «більше токенів» не означає «краще».

Цей матеріал зосереджений саме на дизайні інструкцій і робочих процесів для агентів: від заборони «watch»-режимів до циклічного запуску через bash‑скрипт, спрощення набору тулів і обмеження контекстного вікна.
Інструкції як частина коду: навіщо агентам agents.md
У демонстраційному проєкті Арнальді стартує з порожнього репозиторію: ініціалізує git, налаштовує Bun як рантайм, додає тести через bun test і строгі діагностики TypeScript. Паралельно з технічною інфраструктурою він одразу закладає інфраструктуру для агентів — спеціальний файл agents.md у корені репозиторію.
Цей файл виконує роль «readme для моделей»: у ньому описані доступні команди, важливі ресурси в кодовій базі та особливі правила поведінки. Ключова ідея — не покладатися на те, що LLM «якось здогадається», а явно задати рамки, в яких агент працює з проєктом.
Одна з найважливіших інструкцій у agents.md стосується запуску команд у «watch»-режимі. Агентам прямо забороняють виконувати щось на кшталт bun test --watch або піднімати дев‑сервери, які не завершуються самі. Причина проста й дуже практична: агент легко може «застрягти» в довгоживучому процесі, вичерпати ліміти інструментів або просто перестати робити прогрес, очікуючи завершення того, що за визначенням не завершується.
У людському робочому процесі розробник інтуїтивно розуміє, що --watch — це «запусти й тримай», а не «запусти, дочекайся результату й вийди». Для моделі це неочевидно: вона бачить команду як рядок тексту й не має вбудованого розуміння життєвого циклу процесів. Тому Арнальді виносить цю логіку в явні правила. Агентам дозволяють запускати лише команди, які гарантовано завершуються, щоб кожен крок був атомарним і спостережуваним.
Таке формалізоване «керівництво для агентів» перетворює їхню взаємодію з проєктом на керований протокол. Замість того, щоб сподіватися на «розумну поведінку» моделі, розробник задає чіткі обмеження, які запобігають класу типових збоїв — від завислих процесів до нескінченних логів, що забивають контекст.
Цикл замість сесії: bash‑скрипт як керівник агента
Ще один важливий елемент архітектури — спосіб, яким Арнальді взагалі запускає кодового агента. Замість довгої безперервної сесії з наростаючим контекстом він використовує простий, але показовий підхід: bash‑скрипт, який запускає агента в циклі.
Схема виглядає так: скрипт формулює для агента невелике завдання, дає йому можливість виконати потрібні дії (запустити тести, змінити файли, перевірити типи), після чого процес агента завершується. Далі скрипт може знову викликати агента з оновленим станом репозиторію й новою, так само невеликою задачею.
Цей «пульсуючий» режим має кілька наслідків.
По‑перше, контекстне вікно кожного виклику залишається відносно малим. Агенту не потрібно тягнути за собою всю історію попередніх кроків, логів і промптів. Він бачить актуальний стан коду, релевантні інструкції з agents.md і конкретну ціль на поточний крок. Це знижує ризик того, що модель почне плутатися в довгій історії або втратить фокус.
По‑друге, такий підхід природно розбиває велику задачу на послідовність дрібних. Замість «зроби мені весь бекенд» агент отримує «ініціалізуй репозиторій», «налаштуй TypeScript», «додай Effect v4 beta», «створи базовий тест» тощо. Кожен крок можна перевірити звичайними інструментами розробника — тестами, компіляцією, лінтерами.
По‑третє, це дає розробнику контроль над ритмом і межами взаємодії. Якщо агент починає «нести нісенітницю», його можна просто не запускати наступного разу або змінити інструкції в agents.md. Немає довгої «магічної» сесії, яку важко відмотати назад; є низка чітко окреслених ітерацій.
У підсумку bash‑скрипт перетворюється на оркестратора, а не на дрібну утиліту. Він визначає, коли агент «прокидається», що він бачить, що має зробити й коли «засинає» до наступного виклику. Це прямо пов’язано з тим, як Арнальді розуміє природу LLM: як модель із обмеженим, фіксованим контекстом, а не як істоту з тривалою пам’яттю.
Менше інструментів — більше якості: один execute замість зоопарку тулів
Окрема лінія в його експериментах — це спрощення інтерфейсу інструментів, доступних агенту. Інтуїтивно може здаватися, що чим більше спеціалізованих тулів ми дамо моделі — окремо для тестів, окремо для форматування, окремо для запуску конкретних скриптів, — тим краще вона впорається. Досвід Арнальді вказує на протилежне.
Він описує, що отримував кращі результати, коли замість багатьох інструментів залишав один універсальний — умовний execute, який може виконати довільний TypeScript. Такий інструмент дозволяє агенту самостійно писати невеликі фрагменти коду для допоміжних задач: від аналізу структури проєкту до генерації проміжних артефактів.
Причина ефективності тут знову ж таки у відповідності до того, як тренувалися моделі. Кодові LLM у пост‑тренувальній фазі проходили підкріплювальне навчання саме на роботі з кодовими базами: читати файли, змінювати їх, перевіряти, чи компілюється проєкт. Вони добре вміють писати й запускати код, але значно гірше — орієнтуються в довільних, штучно вигаданих API інструментів.
Коли ми даємо моделі десяток різних тулів із власними схемами аргументів, ми фактично додаємо ще один шар «мови», яку вона має вивчити на льоту. Це збільшує когнітивне навантаження на модель і підвищує ймовірність помилок: неправильні параметри, не той інструмент для задачі, плутанина між схожими командами.
Один інструмент execute, який приймає шматок TypeScript і виконує його, радикально спрощує картину. Модель працює в знайомому для себе середовищі — коді — й може будувати складніші дії як композицію простих програм. Це не означає, що спеціалізовані інструменти завжди погані, але досвід Арнальді показує, що стартувати варто з мінімального набору, а не з «панелі приладів» на пів екрана.
Що бачить агент: gitignore, node_modules і пріоритет власного коду
Ще одна практична деталь, яка часто залишається поза увагою, — це те, які саме файли взагалі потрапляють у поле зору агентів. Арнальді наголошує: кодові моделі тренувалися насамперед на роботі з «першопартійним» кодом користувача, а не з вмістом node_modules чи зовнішньою документацією.
Це має прямі наслідки для того, як варто організовувати проєкт.
По‑перше, деякі інструменти, що обгортають LLM, свідомо ігнорують файли, які потрапляють під .gitignore. Арнальді наводить приклад Cursor, який не індексує gitignored‑файли. Якщо бібліотека або важливі конфігурації випадково опиняються в ігнорованих директоріях, агент їх просто не побачить.
По‑друге, моделі «де‑оптимізовані» для читання node_modules. Це не формальна заборона, але в процесі навчання їх привчали приділяти основну увагу саме коду користувача. Логіка зрозуміла: типовий сценарій — розробник працює зі своїм застосунком, а не з внутрішнім кодом залежностей. У результаті, навіть якщо потрібна бібліотека фізично присутня в node_modules, агент значно охочіше дивитиметься на файли в основному дереві проєкту.
Звідси випливає стратегія, яку Арнальді робить центральною для своєї роботи з Effect: якщо ви хочете, щоб агент добре використовував бібліотеку, не покладайтеся на документацію чи node_modules. Клонуйте репозиторій бібліотеки прямо в проєкт — наприклад, у repos/effect — і дайте агенту зрозуміти, що це частина його «рідного» коду.
Це не просто трюк із файловою системою. Це спосіб узгодити середовище з тим, як модель була навчена. Вона очікує, що найважливіші патерни й приклади будуть у тій самій кодовій базі, де вона працює. Коли бібліотека стає частиною цієї бази, агент починає вивчати її так само, як вивчав би будь‑який інший модуль застосунку: читає файли, шукає приклади, копіює структури.
У поєднанні з agents.md, де явно вказано, що в repos/effect лежить код Effect і його варто використовувати як джерело найкращих практик, це створює для моделі чіткий сигнал: «ось тут те, на що треба орієнтуватися».
Коли великий контекст шкодить: чому 1M токенів — не панацея
На тлі гонки за дедалі більшими контекстними вікнами Арнальді займає стриману позицію. Він прямо говорить, що контекст на мільйон токенів — не обов’язково благо, а часто й джерело проблем, особливо коли в одному вікні змішуються кілька різних задач.
Щоб зрозуміти цю позицію, він повертається до базової архітектури LLM. Модель не має довготривалої пам’яті в людському сенсі. Вона проходить три основні етапи: масштабне попереднє навчання на інтернеті, спеціалізацію на певних задачах і пост‑тренування (зокрема підкріплювальне навчання для коду). Після цього її параметри «заморожуються»: взаємодія з користувачами не додає нових знань у модель.
Усе, що модель «пам’ятає» в межах однієї сесії, — це вміст контекстного вікна: масив повідомлень, який подається на вхід нейромережі. Чим більше ми туди запихаємо, тим складнішим стає завдання для моделі: їй потрібно вловити релевантні фрагменти, відкинути шум і все одно згенерувати коректну відповідь.
Коли в контексті одночасно живуть логи тестів, шматки коду, попередні інструкції, проміжні міркування й нові задачі, модель може почати плутати пріоритети. Вона може опиратися на застарілу інструкцію, ігнорувати свіжіші уточнення або просто «загубитися» в деталях, які вже не мають значення.
Звідси випливає ключовий висновок: великий контекст корисний лише тоді, коли він добре структурований і тематично однорідний. Якщо ж у ньому змішано кілька різних потоків роботи, це радше шкодить, ніж допомагає. Саме тому Арнальді так наполягає на дрібних, ізольованих кроках агента через bash‑цикл і на компактних, сфокусованих інструкціях у agents.md.
Замість того, щоб намагатися «запам’ятати все», він проектує систему, у якій кожен виклик моделі містить тільки те, що справді потрібно для поточного кроку. Це не скасовує переваг великого контексту — наприклад, для аналізу великого файлу чи довгої функції, — але ставить під сумнів ідею, що розширення вікна автоматично робить агента розумнішим.
Архітектура навколо «дурної» машини
У підсумку вся стратегія Арнальді зводиться до однієї простої, але дисциплінованої думки: LLM — це потужна, але в певному сенсі «дурна» машина. Вона не вчиться від вашої взаємодії, не має інтуїції щодо процесів і не розуміє вашого проєкту так, як це робить людина. Вона вміє дуже добре продовжувати текст, якщо ви правильно організували вхід.
Звідси випливають усі його практичні рішення.
Він не дозволяє агентам запускати «вічні» процеси, бо модель не розуміє, що таке життєвий цикл дев‑сервера. Він запускає агента короткими циклами через bash‑скрипт, бо модель не має надійної довготривалої пам’яті в межах сесії. Він спрощує набір інструментів до одного універсального execute, бо модель краще працює з кодом, ніж із вигаданими API. Він клонує бібліотеки в репозиторій і явно вказує на них у agents.md, бо модель тренували дивитися на «свій» код, а не на node_modules.
І нарешті, він не захоплюється гігантськими контекстними вікнами, бо розуміє: більше інформації без структури — це більше шуму, а не більше знань.
Цей підхід не робить з LLM магічного розробника. Натомість він перетворює модель на інструмент, який працює в чітко визначених рамках і виконує добре сформульовані, невеликі задачі. У світі, де все більше команд намагаються інтегрувати агентів у свої пайплайни розробки, така тверезість і увага до деталей можуть виявитися важливішими за чергове збільшення кількості параметрів чи токенів.
Висновок
Досвід Майкла Арнальді показує, що ефективні кодові агенти — це не стільки про «розумніші моделі», скільки про правильну інженерію навколо них. Чіткі інструкції в agents.md, заборона на «watch»-режими, циклічний запуск через bash, мінімалістичний набір інструментів і уважне ставлення до того, які файли бачить агент, дають відчутний приріст якості.
Усе це будується на реалістичному розумінні можливостей LLM: вони не вчаться від ваших сесій, не пам’ятають учорашні розмови й легко губляться в надлишку контексту. Але в добре спроєктованому середовищі, де кожен крок обмежений, перевіряється тестами й підкріплений живим кодом бібліотек, а не лише документацією, ці ж моделі вже сьогодні здатні писати складні бібліотеки так, що їхній автор місяцями не торкається клавіатури.
Для команд, які хочуть перетворити LLM із «розумного автодоповнення» на справжнього учасника розробки, уроки цього підходу очевидні: менше магії, більше інженерії.
Джерело
Відео: Vibe Engineering Effect Apps — Michael Arnaldi, Effectful


