Содержание
Я прочитал код семи открытых агентов, чтобы ответить на один вопрос: как каждый из них решает, что увидит модель. Короткий ответ: ни один не строит индекс вашего кода по умолчанию. Все ищут код так же, как человек в терминале: через grep, find и read. Различаются они тем, что выбрасывают из контекста и в какой момент.
Меня это слегка удивило, потому что публичные разговоры об агентах крутятся вокруг поиска: эмбеддинги, графы кода, карты репозитория. А в этих семи кодовых базах код, который выбирает, что модель прочитает, совсем небольшой. Зато код, который решает, что ей больше не читать, занимает много места, и именно туда ушли инженерные усилия.
Дальше для каждого репозитория указаны пути к файлам, так что всё можно проверить самостоятельно.
Семь репозиториев в выборке
Это агентские репозитории, которые у нас в repowise уже были проиндексированы. Под вывод я их не подбирал. Устроены они по-разному, поэтому сначала разложу их по группам.
Полноценные обвязки. Обвязкой (по-английски harness) я буду называть программу, которая крутит цикл агента: отправляет сообщения модели, выполняет инструменты, которые та запросила, возвращает ей результаты и так по кругу.
- pi (earendil-works/pi): CLI для программирования и библиотеки под ним (слой API к LLM, цикл агента, терминальный UI).
- DeepSeek Harness (deepseek-ai/deepseek-harness): обвязка, в которой любая функция оформлена плагином на фреймворке Cordis.
Универсальные ассистенты, которые заодно пишут код. Это персональные агенты: подключаются к мессенджерам, выполняют задачи по расписанию, ходят в браузер. Программирование для них лишь одна из задач.
- OpenClaw (openclaw/openclaw)
- Hermes Agent (nousresearch/hermes-agent)
Надстройки над чужим агентом.
- OmO (code-yeongyu/oh-my-openagent): плагины и агенты для OpenCode и Codex, а с версии 5.0 ещё и собственный CLI на «senpi», который README называет форком pi.
- free-claude-code (alishahryar1/free-claude-code): прокси, который встаёт между агентом (Claude Code, Codex, pi и ещё восемь) и провайдером модели и перенаправляет запросы на другие модели.
- Публичный репозиторий Claude Code (anthropics/claude-code): ядра агента в нём нет. Есть 13 плагинов, примеры и исходники четырёх встроенных «модов», то есть плагинов, которые подписываются на события движка. Поэтому про Claude Code я могу рассказать только то, что он открывает наружу, а как устроены его собственный поиск и сжатие, отсюда не видно.
Codex CLI, Gemini CLI, OpenCode, Aider, Cline и OpenHands в статью не попали: мы их не индексировали, а писать о коде, который я не читал, не хотелось.
Цифры рядом
| Репозиторий | Что это | Файлов | Строк кода | Health | Чем ищет код | Как ужимает контекст |
|---|---|---|---|---|---|---|
| pi | Обвязка для кода | 2 010 | 379 тыс. | 6,9 | read, bash; grep, find, ls опционально | Пересказ, когда остаётся меньше 16 384 токенов; хранит последние 20 000 |
| DeepSeek Harness | Обвязка на плагинах | 12 578 | 899 тыс. | 6,6 | read, glob, grep, bash; LSP-инструмент опционально | Пересказ на 80 % окна; оставляет 16 % |
| OpenClaw | Ассистент | 19 361 | 4,36 млн | 6,7 | read, ls, shell (ripgrep, fd) | Лимит на вывод инструментов, очистка старых результатов, пересказ |
| Hermes Agent | Ассистент | 8 758 | 2,12 млн | 5,3 | read_file, search_files (ripgrep), terminal | Пересказ более дешёвой моделью: на 50 % окна, если оно от 512 тыс. токенов, иначе на 75 % |
| OmO | Надстройка | 5 591 | 591 тыс. | 8,1 | Инструменты основного агента плюс серверы LSP и ast-grep | Сжатие основного агента; замороженный блок памяти |
| free-claude-code | Прокси | 744 | 168 тыс. | 5,6 | Не его задача | Часть служебных запросов отвечает сам; опциональный фильтр вывода |
| Claude Code (публичный репозиторий) | Плагины и моды | 1 124 | 26 тыс. | 7,6 | Не в этом репозитории | Не в этом репозитории |
Scroll the table sideways to see every column.
Health в repowise оценивает здоровье кода по шкале от 1 до 10: насколько вероятно, что файл принесёт баги, и насколько трудно его менять. Она считается по статическим проверкам и истории git, а оценка репозитория равна среднему по файлам, взвешенному по числу строк кода. В таблице она показана с одним знаком после запятой, как на странице репозитория. Файлы и строки взяты из последнего индекса каждого проекта, снятого между 26 июня и 30 сентября (точные даты в разделе «Как считали»). Строками кода считаются непустые строки без комментариев.
Сразу бросается в глаза разброс размеров. OpenClaw примерно в 167 раз больше публичного репозитория Claude Code. Сравнивать по этой цифре сами агенты нечестно: движка Claude Code в его репозитории нет. Зато хорошо видно, во что вырастает открытый агент, когда ему приходится общаться с мессенджерами, телефонами, браузерами, планировщиками и десятками провайдеров моделей. Часть OpenClaw, которая пишет код, занимает в нём небольшой угол.
Как ищут код: grep, read и по кругу
Все репозитории, где крутится собственный цикл агента, а вместе с ними OmO, дают модели один и тот же базовый набор: прочитать файл, посмотреть каталог, поискать по содержимому, выполнить команду в шелле.
- pi по умолчанию включает четыре инструмента:
read,bash,editиwrite.grep,findиlsлежат вpackages/coding-agent/src/core/tools/и включаются отдельно. Системный промпт по умолчанию вsystem-prompt.tsперечисляет[read, bash, edit, write]. Искать модель должна через шелл. - DeepSeek Harness держит
read,writeиeditв пакетеtool-fs, аglobиgrepвtool-fs-search. Есть и пакетtool-lsp: через языковой сервер модель может перейти к определению или найти ссылки (тот же механизм, что у «go to definition» в редакторе). README прямо расставляет приоритеты: использовать его, «когда текстовый поиск неоднозначен», а «обычная навигация по-прежнему идёт черезsearchиread». В стандартный набор этот пакет не входит. - OpenClaw собирает файловые инструменты в
src/agents/core-coding-tools.ts: read, ls, edit, write, apply_patch и шелл. Отдельного grep-инструмента в основном раннере я не нашёл.src/agents/utils/tools-manager.tsскачивает зафиксированные версии ripgrep и fd, так что поиск идёт через шелл этими бинарниками. - Hermes Agent даёт
search_filesна ripgrep вtools/file_operations_search.pyрядом сread_fileиterminal. - OmO надстраивает структуру над агентом, внутри которого работает: общий демон языкового сервера (
packages/lsp-daemon), инструменты LSP и ast-grep в виде MCP-серверов и правки «hashline», где модель указывает на строку коротким хешем её содержимого вместо номера строки. Когда мы индексировали OmO в июле, его плагин для Codex ещё запускал фоновый индекс CodeGraph при старте сессии (packages/omo-codex/plugin/components/codegraph). Сейчас этого компонента нет, а текущая миграция конфига удаляет старую настройкуcodegraphкак устаревшую.
Получается, единственную функцию, похожую на индекс, убрали, а инструменты на языковом сервере опциональны. По-моему, команды сделали осознанную ставку: модели научились хорошо работать с grep, результат grep всегда свежий, а индекс может устареть или сломаться на машине пользователя. Для поиска функции эта ставка, на мой взгляд, верная. Для вопросов вроде «что сломается, если я это поменяю» я в ней уверен меньше, потому что ответ размазан по файлам, которые друг друга по имени не упоминают.
Как собирается системный промпт
Второй источник контекста включает всё, что попадает в модель ещё до первого сообщения пользователя.
Все они читают файл инструкций проекта. resource-loader.ts в pi ищет AGENTS.override.md, AGENTS.md и CLAUDE.md. В DeepSeek Harness есть плагин agent-instructions, который загружает AGENTS.md или CLAUDE.md и перечитывает их после того, как агент правит файл. У OmO для вложенных файлов инструкций есть agents-md-core и пакет rules-engine. В публичном репозитории Claude Code лежит исходник мода agents-md: он передаёт движку файлы AGENTS.md как файлы инструкций проекта, в том же месте и в том же обрамлении, что и CLAUDE.md, включая вложенные, когда модель читает файл в этой папке. Выходит, все агенты из списка, которые вообще загружают файлы инструкций, читают AGENTS.md, и Claude Code не исключение: его встроенный мод agents-md подхватывает AGENTS.md, если в проекте нет своего CLAUDE.md (или, по отдельной настройке, вместе с ним).
Две детали показались мне хорошо продуманными.
DeepSeek Harness кладёт инструкции в историю сессии. README пакета context говорит, что подмешанные инструкции и ссылки «попадают в историю сессии как сообщения с ролью user, поэтому сохраняются, воспроизводятся и сжимаются как обычная переписка». Выигрыш в том, что правка AGENTS.md посреди сессии не переписывает системный промпт.
Hermes Agent и OmO замораживают память на старте сессии. Hermes ведёт два файла памяти: MEMORY.md (заметки агента) и USER.md (профиль пользователя). Докстринг в tools/memory_tool.py говорит, что оба попадают в системный промпт «как ЗАМОРОЖЕННЫЙ снимок на старте сессии; записи во время сессии уходят на диск, но промпт не меняют». В changelog OmO описано то же исправление: коммит памяти во время сессии больше не переписывает её системный промпт.
Обе команды защищают одно и то же: кэш промпта. Провайдеры берут меньше денег и отвечают быстрее, если начало промпта им уже встречалось. Стоит поменять один байт в начале, и кэш теряется целиком. Удивительно много кода, который отвечает за контекст, существует только ради того, чтобы начало промпта не менялось ни на байт.
Как обрезают: на это уходит основная часть кода
Здесь семь проектов расходятся сильнее всего, и здесь же сосредоточена большая часть кода.
Объём контекста держат в рамках двумя способами. Каждый результат инструмента ограничивают сразу при поступлении, а когда разговор подбирается к пределу модели, включается сжатие контекста (compaction): старые ходы заменяются пересказом, который пишет модель.
| Репозиторий | Лимит на один результат | Когда сжимает | Что оставляет |
|---|---|---|---|
| pi | 2 000 строк или 50 КБ; строки grep режутся на 500 символах | Осталось меньше 16 384 токенов | Последние ~20 000 токенов |
| OpenClaw | По умолчанию 16 000 символов, 32 000 для окон больше 100 тыс. токенов, 64 000 больше 200 тыс.; вывод инструментов не больше 30 % окна | Резерв не больше 25 % окна; до 3 повторов при переполнении | Умолчания ядра агента: резерв 16 384, последние 20 000 токенов |
| Hermes Agent | read_file 100 000 символов | 50 % окна, если оно от 512 тыс. токенов; иначе 75 % | Первые 3 и последние 20 сообщений; середина пересказывается |
| DeepSeek Harness | Сначала вычищаются слишком большие результаты; опционально «сброс» на диск | 80 % окна | Около 16 % окна |
Scroll the table sideways to see every column.
Hermes Agent сжимает раньше большинства. По умолчанию он пересказывает историю на 50 % окна, если у модели окно от 512 тыс. токенов, и на 75 %, если окно меньше. Комментарий в коде объясняет, откуда взялась эта нижняя граница: на маленьком окне сжатие на 50 % освобождает так мало места, что оно срабатывало бы заново каждые один-два хода. На большом окне это намного раньше, чем у DeepSeek Harness (80 %) или pi (он ждёт, пока свободными останутся 16 384 токена, то есть пока окно в 512 тыс. заполнится примерно на 97 %). Пересказ Hermes делает отдельной, более дешёвой «вспомогательной» моделью, а перед этим вычищает большие выводы инструментов (agent/context_compressor.py). За раннее сжатие приходится платить более частыми вызовами пересказа. Взамен модель редко работает с почти полным окном, а на нём ответы обычно портятся. Для персонального ассистента, у которого сессии тянутся днями, такой размен мне кажется разумным.
DeepSeek Harness ждёт, а потом сбрасывает. Он сжимает на 80 % и оставляет около 16 %. Пакеты spill умеют и вовсе вынести большой результат инструмента из контекста: полный текст уходит в файл, а модель получает короткую ссылку и инструкцию, как дочитать. Так же поступает человек, который сохраняет длинный лог в файл вместо того, чтобы вставлять его в чат.
OpenClaw очищает старые результаты инструментов. Кроме лимита на каждый результат, src/agents/embedded-agent-runner/tool-result-truncation.ts заменяет вывод, который пережил окно кэша промпта, на [Old tool result content cleared], а старые картинки на [image removed during context pruning]. Модель помнит, что вызывала инструмент, но самих данных уже не видит.
У pi всё коротко. Вся логика сжатия pi лежит в packages/coding-agent/src/core/compaction/compaction.ts: сжимать, когда до предела меньше 16 384 токенов, оставлять последние ~20 000 токенов, всё до них пересказывать. Из четырёх реализаций эту проще всего прочитать за один присест.
free-claude-code сокращает число запросов к модели. Это прокси, и репозитория он вообще не видит. Зато src/free_claude_code/api/optimization_handlers.py локально, без вызова модели, отвечает на пять видов служебных запросов Claude Code: проверку квоты, определение префикса команды, генерацию заголовка, подсказки и извлечение путей к файлам. Ещё README описывает опциональный фильтр, который укорачивает вывод терминала до того, как его увидит модель.
pi оказался внутри трёх других проектов
Этого я не ожидал: pi, один из самых небольших репозиториев в наборе (379 тыс. строк), обнаруживается внутри трёх других.
- OpenClaw зависит от
@earendil-works/pi-tuiвpackage.json. В егоpackages/agent-coreте же имена файлов сжатия, что у pi (compaction.ts,branch-summarization.ts), и те же умолчания: резерв 16 384 токена и 20 000 последних токенов. В егоtruncate.tsточные лимиты pi: 2 000 строк, 50 КБ, 500 символов на строку grep. Ещё OpenClaw резервирует имена инструментовbash, edit, find, grep, ls, read, write, а это список инструментов pi. Какая история за этим стоит, я не знаю и гадать не буду. По коду видно одно: ядро агента OpenClaw повторяет устройство и числа pi. - OmO пишет в README, что версия 5 «работает на senpi, нашем форке pi».
- У DeepSeek Harness есть пакет
dsh-llm-pi-ai, адаптер к библиотеке pi для API моделей. В описании пакета он назван «двойником для проверки дизайна» основного адаптера DeepSeek, так что по умолчанию он не используется.
Поэтому, если хочется разобраться по исходникам, как устроен цикл агента, я бы начинал с pi. Он достаточно маленький, чтобы прочитать его целиком, а многие проекты покрупнее взяли его решения.
Гигантские функции и что с ними стало
Когда мы индексировали эти репозитории, в двух из них жили две самые длинные функции всего набора. run_conversation в agent/conversation_loop.py у Hermes Agent занимала 6 591 строку (индекс от 19 августа). runEmbeddedAttempt в src/agents/embedded-agent-runner/run/attempt.ts у OpenClaw занимала 4 972 строки (индекс от 26 июня). Обычно такая функция и есть цикл агента: каждое правило повтора, каждая причуда провайдера и каждый путь восстановления становятся ещё одной веткой в единственном месте, которое видит всё.
С тех пор обе команды их разбили. На 6 октября conversation_loop.py у Hermes занимает 1 835 строк против 8 298 в нашем индексе, а run_conversation стала короткой обёрткой над _run_conversation_turn. attempt.ts у OpenClaw сократился с 5 808 строк до 567. Соседняя папка run/ выросла с 65 нетестовых файлов до 173, с именами вроде attempt-prompt-build.ts, attempt-history-prepare.ts и attempt-tool-search-executor.ts.
По-моему, это хорошо показывает, как растёт агентский код. Цикл пишут первым, и в него же попадает каждое исправление, поэтому он быстро распухает. Наши индексы обоих репозиториев сделаны до разбиения, так что оценки health в таблице выше описывают код до него.
Ограничения этих цифр
- Health не измеряет качество агента. Оценка здоровья показывает, насколько безопасно менять код. О том, насколько хорошо агент решает задачи, она ничего не говорит. Самая низкая оценка в этом наборе у Hermes Agent, одного из двух ассистентов, которые держат в одном репозитории интеграции с мессенджерами, десктопные приложения и тесты. Вторая снизу у free-claude-code, небольшого прокси, так что размер и широта проекта объясняют не каждую низкую оценку.
- Claude Code здесь почти не виден. Его оценка описывает только 26 тыс. строк плагинов и модов, кода самого агента в ней нет. Считайте эту строку таблицы «публичной поверхностью расширений».
- У снимков есть даты. Индекс OpenClaw от 26 июня, OmO от 17 июля. Код я цитирую из основной ветки каждого репозитория на 6 октября, поэтому некоторые числа в тексте новее таблицы.
- В реальной работе настройки могут отличаться. Я привёл значения по умолчанию, а пользователи их меняют, и некоторые проекты подбирают значения под конкретную модель или интерфейс.
- Я только читал код. Что работает лучше, раннее сжатие или позднее, можно измерить, но бенчмарков для этой статьи я не запускал.
При чём тут repowise
Сразу оговорюсь: я делаю repowise, слой контекста для агентов. Он индексирует граф зависимостей, историю git и документацию репозитория и отдаёт их по MCP (стандартному протоколу, через который агенты вызывают внешние инструменты). После всего увиденного я бы описал его как дополнение к grep. grep отвечает на вопрос «где это имя». Индекс помогает с вопросами «что от этого зависит» и «почему это так устроено», на которые grep за один вызов не ответит. Все страницы репозиториев, на которые ведут ссылки в статье, построены этим индексом, и любой из этих репозиториев можно подключить к своему агенту.
Как считали
- Репозитории: семь агентских репозиториев, которые уже были проиндексированы в repowise и получили оценку health. Специально для статьи мы ничего не индексировали.
- Цифры: файлы, строки кода, health и самые длинные функции взяты из последнего готового снимка каждого репозитория в нашей базе, прочитаны 6 октября 2026 года. Даты снимков: pi 30 сентября, DeepSeek Harness 28 сентября, Claude Code 27 сентября, free-claude-code 19 сентября, Hermes Agent 19 августа, OmO 17 июля, OpenClaw 26 июня. Health показан с одним знаком после запятой, как на страницах репозиториев.
- Чтение кода: неглубокие клоны основной ветки каждого репозитория на 6 октября 2026 года плюс файлы на проиндексированных коммитах для сравнения «до и после». Все пути к файлам в статье взяты из этих клонов.
- Оценка health: определение дано выше, в разделе «Цифры рядом». Методика описана на странице здоровья кода каждого репозитория.
Если вы поддерживаете один из этих проектов и я где-то ошибся, напишите мне, я исправлю.
Попробовать: подключите любой из этих репозиториев к Claude или ChatGPT и спросите у своего агента, как он обращается с контекстом: так вы заодно проверите мой разбор.