← Усі статті

JavaScript в обв’язці агента: коли скрипт дешевший за міркування моделі

Інтерпретатор JS у пісочниці замінює частину викликів інструментів і арифметику LLM. Розбір статті на Хабрі про LM Studio і LangChain.

JavaScript в обв’язці агента: коли скрипт дешевший за міркування моделі
Зміст

Коротко

Мовна модель вміє продовжувати текст. Агент з’являється, коли навколо неї збирають обв’язку: виклики інструментів, пам’ять, правила, підтвердження людини. Стаття на Хабрі показує наступний крок: дати моделі писати короткий JavaScript у вузькій пісочниці, щоб арифметика, дати й фільтри JSON не з’їдали контекст і не ламалися на «міркуваннях». Це не «запускай будь-який код на хості», а свідомо урізаний обчислювальний шар.

Що сталося

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

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

У LM Studio плагін js-code-sandbox дає інструмент run_javascript. Без нього модель відповідає датою з навчання; зі скриптом бере поточну дату із середовища виконання. Складніше: «третій четвер після найближчого повного місяця» — модель сама пише розрахунок, а не тримає в голові ланцюжок кроків. Автор чесно застерігає: це лінійне наближення фаз Місяця, не астрономічний рушій — але ідея зрозуміла.

У LangChain той самий прийом оформлено як CodeInterpreterMiddleware на QuickJS. У системну інструкцію явно кладуть обмеження: немає fetch, немає справжньої файлової системи, тайм-аут близько 5 с, стеля пам’яті 64 МБ. За замовчуванням «поточна дата» зі скрипта заборонена: дата — окремий інструмент, а не прихована суперсила інтерпретатора. Якщо скрипту дозволити викликати оголошені інструменти (programmatic tool calling), модель один раз викликає eval, а вже скрипт смикає tools.getCurrentDatetime() і рахує далі — без хороводу «спитати дату → подумати → знову викликати eval».

Чому це важливо

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

Ціна — дисципліна меж. Пісочниця в процесі без мережі не прочитає ~/.ssh, але завислий цикл усе одно потребує тайм-ауту. Підтвердження «кожен підозрілий крок» швидко перетворюється на автозгоду. Якщо скрипту відкрити виклик зовнішніх інструментів, знову з’являється поверхня атаки: впровадження інструкцій може попросити виклик, який уже не є чистою арифметикою.

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

На практиці

  1. Відділіть клас задач «порахувати / відфільтрувати / перетворити» від класу «вирішити, який інструмент викликати». Першим дайте інтерпретатор, другим — явний каталог.
  2. Ріжте можливості пісочниці: без мережі, без довільної файлової системи хоста, з лімітом часу й пам’яті; журналюйте вихідний скрипт.
  3. Не ховайте «поточну дату» і доступ до системи клієнтів усередині інтерпретатора «бо зручно» — оголошуйте окремі інструменти і, якщо скрипту потрібні виклики з коду, білий список цих викликів.
  4. Повторіть простий сценарій локально в LM Studio, перш ніж тягнути QuickJS у свій агент: видно, чи пише модель скрипт, чи продовжує гадати.
  5. Рахуйте вартість: один eval замість п’яти раундів міркувань часто дешевший, але помилковий скрипт усе одно треба ловити тестом або схемою результату.

Підсумок

JavaScript в обв’язці — спосіб віддати моделі те, в чому вона слабка (точна арифметика, стабільні перетворення), не видаючи їй ключі від машини. Сила не в «ще одному інструменті», а в тому, що детермінована логіка перестає займати контекст і ламатися на кожному кроці ланцюжка. Межі пісочниці і білий список викликів важливіші, ніж сам факт, що агент «уміє писати код».