У вас есть модель, API к ней и идея продукта с агентом. Кажется, осталось написать цикл: отправить запрос, получить tool call, выполнить его и отправить результат обратно. Можно приступать к интерфейсу?
Я тоже успел так подумать. Потом написал много кода, который писать не следовало, и познакомился с подводными камнями, о существовании которых по простому демо не догадаешься. В этой статье разберу, из каких частей на самом деле складывается агентная система, почему каждая из них превращается в отдельный проект и где стоит приложить собственные усилия.
Привет, Хабр! Меня зовут Игорь Цупко. Этот текст вырос из моего доклада о внутреннем устройстве агентных систем. Я буду сознательно упрощать детали: реализации у Codex, Claude Code, OpenCode и других различаются, но основные инженерные задачи удивительно похожи. Мой главный совет звучит резко: не начинайте с разработки собственного ядра агента. Ближе к концу объясню, что делать вместо этого и когда исключение всё-таки оправдано.
Сначала договоримся о терминах
Вокруг слов «агент» и «harness» пока нет единой границы. Для этой статьи проведу её так:
Агент — ядро, которое организует работу с моделью, обрабатывает её ответы, вызывает инструменты и решает, продолжать ли цикл.
Harness — всё, что окружает это ядро и помогает ему работать в конкретном продукте: пользовательский интерфейс, настройки, данные, инструменты, MCP-подключения, skills, память и интеграции.
Модель — отдельная система, которая выполняет инференс и возвращает токены. Она не становится агентом только потому, что умеет отвечать на вопросы.

Агент в центре, harness вокруг него, модель — отдельный участник системы. Схема упрощённая, но полезная для дальнейшего разговора.
Даже в этой схеме скрыто несколько самостоятельных компонентов. Исполняемый код агента можно представить как stateless-процесс: он получает вход, выполняет логику и не должен рассчитывать, что его оперативная память навсегда останется с ним. Есть окружение, где этот процесс получает CPU и RAM. Есть отдельное постоянное хранилище разговоров, файлов, изображений и настроек пользователя. Есть внешние API, к которым агент обращается.
А если мы строим корпоративный продукт, между агентом и моделью обычно появляется LLM proxy. Через него удобно проводить авторизацию, защищать секреты и персональные данные, вести каталог моделей, учитывать лимиты и стоимость запросов. За прокси уже находится провайдер с оборудованием, на котором идёт инференс.
Важно различать эти части до того, как вы начнёте писать код. Иначе очень легко назвать «маленьким агентом» целую платформу, которую предстоит построить.
К тому же каждый компонент живёт по своим правилам. Процесс агента можно перезапустить, но разговор пользователя после перезапуска должен остаться. Модель может быть заменена, но при этом не должны исчезнуть права доступа и история действий. Внешний сервис может упасть — агенту всё равно надо понятно сообщить, что произошло, а не молча зависнуть на tool call. Граница между компонентами нужна не ради красоты диаграммы: она помогает понять, кто отвечает за восстановление и где искать сбой.
Готовых агентов уже много, и они решают разные задачи
Чтобы не рассуждать в вакууме, посмотрим на несколько существующих решений. Codex тесно встроен в стек OpenAI. OpenCode делает ставку на работу с разными провайдерами: за этой фразой скрыта заметная архитектурная работа, потому что провайдеры не во всём одинаково понимают запросы, инструменты и события ответа. Claude Code выстроен вокруг моделей Claude.
Есть и другой тип продуктов. OpenClaw позиционируется как персональный помощник. Hermes уделяет много внимания развитию памяти и skills по мере работы с пользователем. Ouroboros экспериментирует ещё смелее и способен менять собственный код, а не только инструкции вокруг него. Grok Agent делает ставку на параллельные и фоновые сценарии.
Здесь нет универсального победителя. Есть разные наборы компромиссов. Но прежде чем делать ещё один набор, полезно заглянуть внутрь хотя бы базового цикла.
Agent loop: четыре шага, за которыми прячется большая система
На слайде всё выглядит почти безобидно:
Агент отправляет модели запрос вместе с инструкциями, описаниями инструментов и историей разговора.
Модель возвращает поток типизированных событий. В нём может быть текст, вызов инструмента, служебные события и другие данные.
Агент выполняет запрошенные действия: запускает локальную логику, обращается к API или хранилищу, ждёт результата.
Если есть причина продолжать, результат инструмента снова отправляется модели. Если нет — цикл завершается.

На диаграмме цикл помещается в четыре пункта. В рабочем продукте у каждого пункта вырастают свои условия, ошибки и состояния.
Например, набор доступных tools зависит от модели и настроек. Разница возникает не только между OpenAI и Anthropic: отдельные версии моделей и промежуточные сервисы тоже могут поддерживать разные форматы. Инструмент может завершиться ошибкой, вернуть неожиданные данные или не ответить вообще. Вызовы иногда можно исполнять параллельно, а иногда результат одного нужен для запуска другого.
И всё это работает по сети. Значит, нужно решить, когда повторять запрос после обрыва соединения, сколько раз повторять и не вызовет ли повтор побочный эффект дважды. «Сделать retry» звучит легко, пока tool call не списывает деньги или не меняет данные пользователя.
Рядом появляются ограничения на время и память, телеметрия, конфигурация провайдеров, персонализация, учёт расходов и способ показывать состояние пользователю. Поэтому agent loop — не просто цикл while. Это основа жизненного цикла продукта.
Причём ошибки tools нельзя просто вернуть в чат как сырой текст исключения. Агенту нужно понять, можно ли повторить действие, стоит ли предложить пользователю исправить доступ и не является ли ошибка признаком того, что дальнейшие шаги уже бессмысленны. Когда tool предоставлен внешним MCP-сервером, заранее знать все его варианты отказа вообще невозможно. Эту неопределённость приходится обкладывать общими правилами и наблюдаемостью.
Поток событий: здесь заканчивается романтика простого API
Для связи с моделью используют разные способы доставки событий. SSE позволяет отправить запрос и читать ответ как поток событий поверх HTTP. WebSocket даёт двустороннее соединение: можно отправлять данные, пока взаимодействие уже идёт, и работать с бинарными данными. На стороне модели тоже есть несколько API: у OpenAI — Chat Completions и Responses API, у Anthropic — Messages API.

Транспорт отличается по возможностям. Поверх него агенту всё равно придётся понимать структуру событий конкретного API.
Самое неприятное не в названии протокола, а в том, что ответ приходит по кусочкам. Отдельное событие сообщает о начале ответа, другое добавляет элемент, третье приносит очередной фрагмент текста, четвёртое закрывает элемент. Tool call тоже может собираться постепенно. Надо правильно сопоставить части, обработать прерывание потока, не потерять уже полученный результат и не показать пользователю состояние, которого на самом деле ещё нет.
Если у вас появляется желание написать собственный парсер стриминга для нескольких провайдеров, я могу только пожелать удачи. Там уже работали умные люди, и не один месяц.
Сложность ещё и в том, что серверный 200 OK не означает успешного завершения агентной задачи. Соединение могло оборваться посередине, инструмент — выполниться уже после обрыва, а клиент — не получить финальное событие. Если затем повторить запрос без понимания состояния, легко запустить действие дважды. Такие случаи редко встречаются в демо, зато очень хорошо встречаются в эксплуатации.
Промпт — не магическая фраза
Помните эпоху советов «ты архитектор с 15-летним опытом» и «пишите только на английском»? Сегодня сильным моделям чаще нужен не такой ритуал, а понятный контекст и доступные действия. При этом остаётся важнейшее правило: инструкции не превращают модель в детерминированную программу. Она может не выполнить шаг или интерпретировать его иначе.
Условно разделим отправляемый контекст на системную часть и историю общения с пользователем. В реальных API могут быть и другие уровни инструкций, но для нашей схемы достаточно двух. В системной части находятся сведения о роли агента, среде, доступных инструментах, skills и памяти. В истории — запросы, ответы и результаты действий.
Инструкция о роли агента может казаться скучной «шапкой»: кто ты, где работаешь, какая сегодня дата, к чему у тебя есть доступ. Но написать её хорошо непросто. Слишком расплывчатая не помогает, слишком подробная съедает контекст и начинает конфликтовать с задачами пользователя. Когда-то системные промпты популярных продуктов даже пытались выманивать и коллекционировать. Интереснее другое: ни один секретный текст не отменяет необходимость проверять результат работы агента.
Описание инструмента — тоже в основном текст. Мы объясняем модели: вот tool shell, вот его параметры, вот для чего он нужен. Модель читает описание и решает, когда вызвать инструмент. Магия работает настолько хорошо, что на ней держится значительная часть смысла агента. Но именно поэтому текст инструкции и формат результата становятся частью программного интерфейса, который нужно проектировать и проверять.
Контекст надо сжимать, но при этом не потерять смысл
История чата, которую видит пользователь, и фактический контекст модели — не одно и то же. Агент решает, какие сообщения, результаты tools и служебные блоки передать в следующий запрос. По мере работы контекст растёт, а вместе с ним растут задержка и стоимость.
Один из способов справиться с этим — компактификация. Длинную историю отдают модели с просьбой выделить главное, а затем используют полученное краткое изложение вместо старой части переписки.

Длинную историю заменяет краткая выжимка. Место экономится, но модель, которая делала выжимку, должна была угадать, что понадобится позже.
Вот неприятный сценарий. Пользователь пять сообщений назад договорился с агентом о важном ограничении. Система провела компактификацию, ограничение не попало в summary, а агент теперь уверенно действует так, будто разговора не было. Для пользователя это выглядит как внезапная глупость модели. На самом деле ошибка находится в нашей логике работы с контекстом.
Нужно выбрать момент сжатия, модель для него и инструкцию, которая не выбросит важные детали. При этом сама операция тоже тратит токены. Получается не «включить галочку compact», а задача со своей оценкой качества.
Есть и другой приём экономии — кэширование префикса промпта. Инструкции и описания инструментов в начале многих запросов почти не меняются. Провайдер может сохранить вычисления для неизменного префикса и обработать только добавившуюся часть. При удачном попадании в кэш стоимость ниже, но для этого префикс должен остаться действительно неизменным. Разработчики некоторых агентов специально следят за стабильностью этого блока вплоть до байта. Да, настолько тонкими становятся оптимизации, когда вы строите своего агента.
И компактификация, и кэширование служат экономии, но воздействуют на разные вещи. Первая меняет содержание контекста и рискует забыть нужное. Второе стремится сохранить часть контекста неизменной, чтобы не пересчитывать её заново. Смешать их в одну настройку «сделать дешевле» нельзя: у них разные эффекты и разные способы проверки.
За каждым названием tool стоит отдельный продукт
Допустим, мы пережили стриминг и научились работать с контекстом. Что агент должен уметь делать? Пользователь ожидает примерно следующее:
читать и менять файлы, причём часто в рамках проектов и командных workspaces;
запускать команды, следить за процессами и работать на Linux, macOS и Windows;
искать в интернете и обращаться к внешним API;
генерировать изображения;
задавать уточняющие вопросы человеку, иногда прямо во время выполнения задачи;
вести план, управлять собственным контекстом и делегировать работу субагентам.
Каждый пункт выглядит как одна строка в списке инструментов. За ней — права доступа, ограничения, UI, обработка ошибок и тестирование. Например, «спросить человека» — это не просто вывести текст. Агент может приостановить действие, предложить три варианта ответа, получить выбор и продолжить с правильного места. А иногда он должен работать дальше, пока вопрос ещё висит на экране. Для этого нужно явно продумать состояние процесса и интерфейса.
До инструментов ещё нужно добраться через конфигурацию. Агент должен знать, у какого провайдера просить инференс и чьим ключом платить за него. Ему нужны параметры окружения, телеметрия и понятная реакция на нехватку памяти или времени выполнения. Продукт может предлагать персонализацию — например, заранее задавать роль пользователя и контекст его команды. Всё это влияет на запрос к модели, но живёт за пределами красивой схемы с четырьмя стрелками.
Субагенты добавляют ещё один уровень. Родительскому агенту нужны средства запустить их, передать контекст и доступные tools, дождаться результата и разобраться, кто за что отвечает. А если несколько субагентов общаются друг с другом, мы получаем маленький протокол координации. Самая простая ошибка здесь знакома любому руководителю: задачу сформулировали вроде бы понятно, а исполнитель сделал именно то, что было сказано, но совсем не то, что подразумевалось. Агентам это тоже свойственно.
В простом сценарии можно дать агенту CSV и попросить запустить отдельную работу для каждой строки. В более сложном — назначить субагентам роли исследователя, исполнителя и проверяющего. Тогда родительскому агенту приходится не только распределить задания, но и написать им инструкции, совместить результаты и заметить противоречия. Делегирование не снимает сложности; оно переносит её в постановку задач и координацию.
MCP: подключить инструменты легко, обслуживать их трудно
MCP позволяет подключать инструменты внешних сервисов. Их список формирует уже не только разработчик агента: пользователь может добавить собственные серверы. Представьте, что он подключил 30 серверов, а у каждого по 10 инструментов. Что теперь будет с размером системного промпта? Даже если агент умеет загружать описания tools по требованию, модель ещё должна решить, что их пора загрузить.
Внешний MCP-сервер может не отвечать, прислать неожиданный результат или оказаться недоверенным.
А ещё есть расширения протокола MCP. Например, MCP Apps добавляют интерактивные виджеты. Агент может показать пользователю схему, пользователь кликает на элемент, а агент использует этот выбор для следующего действия. Прекрасный UX — и одновременно задача по изоляции стороннего кода, который не должен добраться до секретов или навредить браузеру пользователя. Удачи в реализации в своём агенте!
Skills: инструкция, которая сама должна попасть в нужный момент
У skills другой механизм. Это набор инструкций, часто в Markdown-файле SKILL.md, и инструменты, через которые агент может эти инструкции найти и прочитать. В основной промпт обычно кладут не весь текст каждого skill, а короткий каталог: название, назначение, путь к файлу и правило, когда его читать. Уже здесь приходится проектировать маршрутизацию: описание должно помочь модели выбрать нужный навык, но не раздувать каждый запрос.

В промпте виден imagegen с коротким описанием и путём к SKILL.md. Сама подробная инструкция пока не загружена.
Разберём кейс. Пользователь пишет: «Сделай картинку с Москва-Сити». Модель получает эту просьбу вместе с каталогом skills и видит, что imagegen подходит для генерации изображения. Но чтобы воспользоваться им правильно, ей нужно пройти ещё один круг agent loop:
Модель решает прочитать skill и возвращает не картинку, а вызов
skills.readс адресом инструкции.Агент выполняет этот вызов.
skills.readвозвращает обычный текстSKILL.md: какие действия доступны, в каком порядке их делать, какие параметры передавать и как работать с результатом.Агент добавляет этот текст в следующий запрос к модели. Только теперь модель может следовать подробной инструкции и, например, вызвать инструмент генерации изображения с описанием Москва-Сити.
Результат генерации снова проходит через цикл: его нужно получить, показать человеку или продолжить работу, если инструкция требует ещё одного шага.

На слайде видно важное место: чтение skill не исполняет его. Текст инструкции возвращается в модель, и та заново решает, что делать дальше.
Значит, «у агента есть skill» ещё не означает «агент надёжно его применит». Он может не сопоставить просьбу с описанием, не вызвать skills.read, пропустить часть инструкции или вызвать нужный инструмент с неподходящими параметрами. Ссылки на другие файлы, скрипты и шаблоны добавляют новые шаги. При тестировании приходится проверять всю цепочку на разных формулировках просьбы, а после обновления модели — проверять снова. Сложность skills скрыта как раз в этом переходе между текстом, выбором модели и реальным действием.
Память: забыть плохо, запомнить лишнее ещё хуже
Под «памятью агента» часто понимают не один файл, а ещё и отдельный процесс. Фоновая задача просматривает разговоры, просит модель выделить важное и сохраняет отдельные записи памяти. Из них собирают memory_summary — короткую карту того, что агенту вообще известно о пользователе и его работе.

Фоновый процесс превращает разговоры в отдельные записи, а затем — в summary. На каждом переходе можно потерять важное или обобщить лишнее.
Что происходит потом? В шаблоне инструкций агента есть место для подстановки: {{ memory_summary }}. Перед очередным запросом туда вставляют актуальную выжимку. Таким образом, агент сразу видит краткое содержание памяти в промпте, даже если не открывал ни одного файла. Рядом лежат правила, как найти подробности: сначала посмотреть на summary, затем при необходимости открыть индекс памяти и конкретные записи.

Тот самый слайд с MEMORY_SUMMARY BEGINS и {{ memory_summary }}: summary инъектируется прямо в инструкции, а полные воспоминания агент должен читать отдельно.
Возможны как минимум три неприятности, которые вам нужно учесть в своей реализации.
Модель не сохранила важное — и пользователь в сотый раз объясняет одно и то же.
Агент получил только краткое summary и не сходил за деталями, хотя они были нужны.
Или, наоборот, он запомнил случайную просьбу как постоянное предпочтение.
Тут сложно даже сформулировать критерий правильности. Что считать устойчивым предпочтением, а что — контекстом одной задачи? Когда новая запись должна заменить старую? Как дать пользователю исправить память, не заставляя его разбираться во внутреннем формате? Если не ответить на эти вопросы, «память» будет регулярно удивлять человека в худшем смысле слова.
Я один раз попросил написать пример на JavaScript — теперь агент может решить, что я всю жизнь мечтал работать только на JavaScript. Пользователь обычно даже не видит конкретную запись памяти, из-за которой так происходит. Старые воспоминания нужно пересматривать и удалять, противоречия — разрешать. Это отдельная область инженерии, а не бесплатное свойство модели.
Guardrails — не одна проверка перед запуском команды
Агент с инструментами способен ошибиться дорого. Он может предложить деструктивную команду, отправить данные не туда или изменить то, чего пользователь менять не просил. Поэтому защита собирается из нескольких слоёв: обучение модели, системные инструкции, детерминированные проверки действий, дополнительные проверки с помощью модели, изоляция процессов и сетевые ограничения.

Каждый слой закрывает часть риска. Ни один в одиночку не делает систему безопасной.
Начнём разбирать этот пирог изнутри. Первый слой — сама модель: при обучении ей прививают правила безопасного поведения. Второй — системный промпт: агент получает инструкции о допустимых действиях в данном продукте. Оба слоя нужны, но оба работают через вероятностное поведение модели. Они не дают твёрдой гарантии, что конкретный вызов инструмента безопасен.
Третий слой — детерминированные проверки в коде агента. Прежде чем исполнить, например, вызов shell, можно разобрать команду и искать опасные операции. Звучит просто, пока команда не состоит из нескольких частей, переменных, перенаправлений и вложенных вызовов. Проверке надо понять, что реально будет исполнено, не заблокировать массу нормальных задач и при этом не пропустить обходной путь. Для каждого типа инструмента правила приходится проектировать отдельно.
Четвёртый слой — проверка с помощью другой модели. Когда опасность зависит от смысла запроса и состояния задачи, набора жёстких правил мало. Можно подготовить отдельный запрос и попросить модель-оценщик решить, допустимо ли действие. Но тогда появляется ещё один промпт, который нужно защищать от инъекций, ещё одна модель с ошибками и ещё одна задержка перед выполнением. Её ответ тоже нельзя считать доказательством безопасности.
Пятый слой — песочница операционной системы и сетевая политика. Даже если предыдущие проверки ошиблись, процесс должен иметь только необходимый доступ к файлам, другим процессам и сети. На macOS в докладе я приводил Seatbelt; в Linux и Windows механизмы другие. Нужно определить границы доступа, запустить инструмент внутри них и не сломать полезные сценарии. Одним системным промптом этот слой не заменить.
И остаётся согласование с человеком. Чем строже правила, тем чаще агент просит подтвердить действие. Если каждый шаг требует клика «Approve», пользователь привыкает нажимать Enter не читая — или включает полный доступ. Поэтому надо решать, какие действия разрешать автоматически, когда спрашивать и как понятно объяснять риск. Ошибка в этом интерфейсе может обнулить всю работу предыдущих слоёв.
Вот почему guardrails — чудовищно сложная инженерная часть, а не один if перед запуском команды. Нужны правила для разных инструментов, изоляция на разных платформах, испытания на реальных сценариях и пересмотр защиты после изменений моделей и tools. Если вы начинаете писать своё ядро, эту работу вы тоже забираете себе.
Когда собственное ядро всё-таки имеет смысл
После всего сказанного было бы нечестно утверждать, что своё ядро не нужно никогда. Я вижу несколько причин всерьёз рассматривать такой путь.
Первая — вам требуется необычно жёсткая управляемость процесса. Допустим, агент работает с юридическими документами и каждое утверждение должно опираться на конкретный источник. Или он выполняет операции с заказами и деньгами, где нельзя позволить пользователю уговорить его на скидку в 100%. В медицинском сценарии цена ошибки может быть ещё выше. Здесь понадобится много проверок и чётко заданных переходов между этапами. При этом даже такие требования не означают автоматически, что надо переписать agent loop: сначала стоит проверить, можно ли обеспечить контроль вокруг готового ядра.
Вторая причина — вы действительно исследуете другой способ работы агента. Например, в LangGraph разработчик задаёт граф шагов и состояние, а исполнение идёт по его переходам. В экспериментальной архитектуре SKILL.state длинная история диалога заменяется явным изменяемым состоянием навыка: на очередном шаге модель получает инструкцию, текущее состояние и последнее наблюдение. А Jev показывает ещё один вариант для частей такого процесса: вместо генерации текста модель быстро возвращает типизированные решения, которые код может использовать для выбора следующей ветки. Это разные по устройству примеры, но каждый заставляет заново решить, кто управляет переходами и что передавать модели на следующем шаге. Вот это уже причина менять agent loop, а не просто добавлять очередной tool.
А вот экономия токенов сама по себе — слабый повод начинать с собственного агента. Часто нужного эффекта можно добиться в LLM proxy: маршрутизировать разные задачи на разные модели, использовать кэш, менять политику лимитов. Это несравнимо меньшая зона ответственности, чем совместимость API, стриминг, память, tools и guardrails одновременно.
Как сделать свой продукт, не переписывая agent loop
Первый способ удивительно прост: ясно ставить задачу готовому агенту. Если вы знаете, какие инструменты у него есть, можно попросить его использовать нужные данные и вернуть результат в нужной форме. Это не абсолютная гарантия — модель может проигнорировать подсказку, а чрезмерно подробный план иногда мешает. Но прежде чем писать новую архитектуру, такой вариант стоит проверить на практике.
Если нужен собственный интерфейс и контроль над интеграциями, интереснее другой путь — app-server. Это отдельный процесс с готовым агентным ядром. С одной стороны он взаимодействует с моделью. С другой к нему подключается ваше приложение: локально через stdin/stdout, удалённо через WebSocket. Между приложением и сервером идут структурированные сообщения, JSON-RPC.

Собственный GUI и инструменты можно строить вокруг готового agent loop. Приложение общается с app-server, а он берёт на себя работу с моделью.
Такой интерфейс позволяет передавать настройки, объявлять собственные tools, получать события о ходе работы и возвращать результаты вызовов. Codex — один из примеров подобного подхода; у других агентных проектов есть свои серверные интерфейсы. Конечно, интеграция не становится бесплатной. Зато вы направляете усилия на особенности своего продукта, а не заново решаете весь список задач выше.
И вот здесь появляется большое поле для работы, которое часто недооценивают: UX. Простая кнопка «fork thread» может позволить безопасно проверить альтернативный ход мысли. Два разговора рядом — в одном исследование проблемы, в другом работа над кодом — меняют то, как человек пользуется агентом. Для непрограммиста ещё полезнее, когда агент сразу знает его роль из корпоративной системы и получает нужные данные через инструменты, без просьбы каждый раз объяснять устройство компании.
Собственные tools писать как раз имеет смысл. Они и связывают агента с реальными задачами, данными и ограничениями вашего продукта. Здесь harness перестаёт быть абстрактной «обвязкой» и становится тем, за что пользователь выбирает именно ваше решение.
Вместо заключения, или TLDR
Если вы пролистнули сразу сюда, вот короткая версия:
Стриминг, совместимость провайдеров, инструменты, контекст, память, безопасность и UI — самостоятельные инженерные задачи. Их нельзя получить бесплатно вместе с доступом к LLM API.
Skills чудовищно сложны в эксплуатации: модель должна вовремя выбрать навык, прочитать инструкцию и пройти все шаги; текст
SKILL.mdсам себя не исполнит.Память не сводится к сохранению фактов: надо извлечь нужное, собрать
memory_summary, подставить его в промпт и добиться, чтобы агент вовремя открыл подробности и забыл устаревшее.Guardrails — несколько разных слоёв от правил в модели до проверок команд и песочницы. Их нужно совместить так, чтобы агент не навредил и пользователь не привык подтверждать всё подряд.
Для большинства продуктовых задач разумнее брать готовое ядро и строить вокруг него свои инструменты, интеграции и пользовательский опыт.
Своё ядро оправдано, когда вам действительно нужен другой agent loop или уровень контроля, который нельзя обеспечить поверх существующего решения.

Если хочется унести из статьи одну мысль, пусть это будет она.
Я пришёл к этим выводам не только после чтения чужого кода. С вопросами о модели, инструментах, памяти и границе между ядром и продуктом пришлось разбираться при разработке агента Ardor. Этот опыт хорошо отрезвляет: самый интересный результат для пользователя рождается не там, где мы переписали очередной цикл вызова модели, а там, где агент наконец смог надёжно работать с его задачами и окружением. Если вы тоже строите такие системы, мне будет интересно обсудить, какие части своего harness вы считаете действительно уникальными.

