Год назад AI-ассистенты для разработчиков были экзотикой, сегодня бюджеты команд на облачные модели сопоставимы с зарплатами джунов. Среди форматов — веб-интерфейсы, IDE-плагины и CLI-агенты, работающие прямо в терминале. Последние выглядят скромнее всего, но устроены неожиданно сложно.
В основе любого CLI-агента лежит простой цикл из пяти шагов: принять сообщение пользователя, собрать контекст, отправить запрос в языковую модель, исполнить запрошенные инструменты, вернуть результат модели и повторить. Выход из цикла — когда модель сигнализирует, что задача выполнена. Всё остальное — сжатие контекста, система разрешений, память между сессиями, рендер диалога — надстройки над этим скелетом.
| Режим | Что разрешено |
|---|---|
| Стандартный | Чтение — автоматом, запись/шелл — по подтверждению |
| Автопропуск | Читает и пишет без вопросов, но опасное — всё равно спрашивает |
| План | Только чтение, никаких изменений (для разработки архитектурного плана) |
| «Опасный» | Всё разрешено, включая бэкап с предупреждением при входе |
Одно из самых неожиданных инженерных решений в разобранном агенте — UI на собственном React-реконсиляторе. Терминал — это буфер символов, и на первый взгляд декларативный подход здесь избыточен. Тем не менее именно так разработчики получили компоненты, hooks, state и даже hot reload прямо в TTY. Вместо DOM реконсилятор рисует в символьный буфер.
UI одного из агентов построен на собственном React-реконсиляторе — декларативные компоненты и hooks работают прямо в терминале.

Прежде чем запрос уйдёт в модель, он проходит препроцессор: строка разбирается на слэш-команды (/help, /compact, /model), упоминания файлов (@src/foo.ts), вставленные картинки. Часть команд исполняется локально и до модели не доходит — /help возвращается как системная реплика в историю диалога без расхода токенов. /compact работает иначе: запускает отдельный ход модели с промптом «сверни историю в сводку». Один синтаксис, две разные природы.
Поток ответов от модели — не монолитный JSON, а инкрементальная последовательность типизированных событий: начало текстового блока, дельта текста, начало вызова инструмента, дополнение аргументов, закрытие блока, финальная статистика токенов. Разбор этого потока реализован как отдельный генератор — конечный автомат, в котором легко допустить ошибку при самостоятельной реализации.
Отдельного внимания заслуживает оркестратор инструментов. Когда модель за один ход запрашивает несколько вызовов, агент группирует их в пачки по принципу: инструменты только для чтения запускаются параллельно, изменяющие состояние — строго последовательно. Последовательность [read, read, read, grep, edit, read] превращается в три пачки: параллельная четвёрка, одиночный edit, затем финальный read. Порядок нарушить нельзя — если модель сначала просит отредактировать файл, а потом прочитать его же, перестановка даст неверный результат.
Рендер ответа в терминале идёт параллельно с исполнением инструментов: пока модель ещё генерирует текст, первые вызовы уже могут выполняться — при условии, что протокол стриминга позволяет достоверно определить, что аргументы завершены. Это заметно сокращает общее время ответа на задачи, где модель последовательно читает несколько файлов перед редактированием.

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


