12 паттернов построения ИИ-агентов, извлечённых из утечки исходного кода Claude Code
Оригинальный заголовок: Claude Code's Source Got Leaked. Here's What Agent Builders Should Actually Learn From It.
Автор разобрал архитектуру, всплывшую после утечки исходников Claude Code, и пришёл к выводу: в её основе лежит не секретный алгоритм, а цикл while на Python — меньше 30 строк — плюс словарь инструментов, а останавливается всё по stop_reason!
Автор выделил из утёкшего кода 12 комбинируемых паттернов инженерии ИИ-агентов и предложил четырёхнедельный план освоения — удобно сверить со своей реализацией и найти пробелы.
Перевод пока неполный. Переключитесь на оригинал, чтобы прочитать весь текст.
Самый мощный инструмент Anthropic для разработчиков оказался полностью раскрыт изнутри. Утечка исходного кода Claude Code за считанные часы разошлась по GitHub, Reddit и X. Разработчики ожидали найти проприетарные алгоритмы, секретное дообучение модели или скрытый конкурентный барьер.
А нашли цикл while, несколько инструментов и много продуманной инженерии.
Утечка не раскрыла тайну — она показала чертёж. И если вы создаёте ИИ-агентов, этот чертёж ценнее любой тайны. Сообщество Learn Claude Code уже свело архитектуру к 12 композиционным сессиям, которые может изучить каждый.
Вот что действительно важно для тех, кто строит агентов, и почему большая часть этого пригодится, даже если вы никогда не писали ни строки кода.
Главный сюрприз: один цикл делает всё
Вся основа Claude Code — это цикл с одним условием выхода. ИИ получает задачу, решает, какой инструмент использовать, проверяет результат и повторяет, пока не закончит.
flowchart LR
A[Your Request] --> B[AI Decides]
B --> C[Runs a Tool]
C --> D{Done?}
D --> |no| B
D --> |yes| E[Returns Answer]Вот и всё. Менее 30 строк Python. Никаких фреймворков оркестрации, движков рабочих процессов или графовых баз данных.
Вот реальная структура:
def agent_loop(query):
messages = [{"role": "user", "content": query}]
while True:
response = client.messages.create(
model=MODEL, system=SYSTEM, messages=messages,
tools=TOOLS, max_tokens=8000,
)
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason != "tool_use":
return # Done. The only exit.
results = []
for block in response.content:
if block.type == "tool_use":
output = run_tool(block.name, block.input)
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
})
messages.append({"role": "user", "content": results})Всем потоком управляет одно условие выхода: stop_reason != "tool_use". Модель продолжает вызывать инструменты, пока не решит, что закончила. Никакой машины состояний, никакого обхода графа — только цикл while и растущий список сообщений.
Ранее я подробно писал о том, как работает этот агентный цикл. Утечка подтвердила все архитектурные ставки: цикл «собрать — выполнить — проверить», тонкий клиент, управление потоком на стороне модели.
Большинство команд слишком усложняют своего первого агента. Они хватаются за LangChain, CrewAI или AutoGen ещё до того, как напишут хотя бы строку собственного кода. Утечка доказала: самый мощный работающий в продакшене ИИ-агент для разработки устроен по схеме, которая помещается на каталожной карточке.
Вывод: начинайте с самого простого работающего цикла. Усложняйте только тогда, когда реальные проблемы вынудят вас это сделать. Команды, которые выпускают агентов быстрее всех, не используют самые навороченные фреймворки — они запускают вариации именно этого цикла.
Инструменты — это просто словарь
Чтобы добавить Claude Code новые возможности, не нужно переписывать цикл. Каждый инструмент — это функция, зарегистрированная в таблице поиска. ИИ решает, какой инструмент вызвать. Клиент находит его в таблице, выполняет и возвращает результат.
TOOL_HANDLERS = {
"bash": lambda **kw: run_bash(kw["command"]),
"read_file": lambda **kw: run_read(kw["path"], kw.get("limit")),
"write_file": lambda **kw: run_write(kw["path"], kw["content"]),
"edit_file": lambda **kw: run_edit(kw["path"], kw["old_text"],
kw["new_text"]),
}Карта диспетчеризации — это словарь Python. Один поиск по словарю заменяет любую цепочку if/elif. Добавить новый инструмент — значит написать одну функцию-обработчик и добавить одну запись в словарь. Тело цикла остаётся таким же, как в версии на 30 строк выше.
| Компонент | Что он делает |
|---|---|
| Схема инструмента | JSON-описание, которое ИИ читает, чтобы понять инструмент |
| Функция-обработчик | Выполняет действие (с песочницей для путей ради безопасности) |
| Карта диспетчеризации | Поиск по словарю {tool_name: handler} |
Песочница для путей не даёт выйти за пределы рабочего пространства:
def safe_path(p: str) -> Path:
resolved = (WORKDIR / p).resolve()
if not resolved.is_relative_to(WORKDIR):
raise ValueError(f"Path escapes workspace: {p}")
return resolvedКаждый файловый инструмент перед обращением к диску вызывает safe_path(). ИИ может запросить чтение /etc/passwd — обработчик откажет. Безопасность обеспечивает клиент, а не модель.
Вывод: команды, которые берут эту схему на вооружение, рассказывают, что новые возможности агента появляются за часы, а не за дни. Архитектура масштабируется без изменений в конструкции. Нужен инструмент для запросов к базе данных? Одна функция, одна запись в словаре, ноль изменений в цикле.
ИИ сам планирует свою работу
На многошаговых задачах Claude Code не действует наугад. Сначала он составляет себе чек-лист, а затем выполняет пункты один за другим. Встроенная система «напоминаний» подсказывает ИИ обновить чек-лист, если он давно этого не делал.
TodoManager state
[ ] Set up database schema
[>] Write API endpoints <- currently working
[x] Create project structureОграничение сделано намеренно: в статусе in_progress может находиться только один пункт. Так приходится фокусироваться последовательно. А если модель не обновляет чек-лист 3+ раундов, харнесс добавляет сообщение <reminder>Update your todos.</reminder> в следующий результат инструмента.
Это решает реальную проблему. На длинных задачах ИИ-модели теряют нить: повторяют уже сделанное, пропускают шаги или уходят в сторону. Чек-лист не даёт им обманывать самих себя. Более общий принцип я разобрал в посте про паттерны агентного проектирования: паттерн рефлексии (циклы «производитель — критик») решает ту же задачу — удерживать ИИ в фокусе за счёт явной структуры, а не надеяться, что он сам не собьётся.
Результат: агенты, которые планируют перед действием, выполняют многошаговые задачи в 2-3 раза быстрее тех, кто действует импровизируя. Если ваш агент ненадёжен на сложных задачах, скорее всего, стоит начать именно с этого паттерна.
Субагенты сохраняют основной поток чистым
Вот паттерн, который удивил многих рецензентов. Когда Claude Code нужно что-то исследовать, он не засоряет собственную память всей промежуточной работой. Он порождает «субагента» с чистым, пустым контекстом. Субагент проводит исследование, возвращает краткое резюме, и вся его рабочая память выбрасывается.
flowchart LR
subgraph Parent["Parent Agent (preserved)"]
P1[Working on task]
P2[Gets: 'X uses pytest']
P3[Continues work]
end
subgraph Child["Subagent (disposable)"]
C1[Fresh context]
C2[Reads 5 files]
C3[Runs 3 commands]
C4[Summary only returned]
end
P1 --> |"'find testing framework'"| C1
C4 --> |"one-paragraph summary"| P2The child’s entire message history (possibly 30+ tool calls, thousands of tokens of file contents) gets discarded. The parent receives a one-paragraph summary as a normal tool result.
This maps directly to the multi-agent collaboration pattern I wrote about: decomposition creates focus. A research agent that only researches produces better answers than a generalist juggling research alongside its main task. The difference is that subagents here are disposable by design. No persistent identity, no message bus. Spawn, summarize, discard.
Context window management is the #1 silent killer of agent quality. Every file read, every command output, every search result eats into the AI’s working memory. When that memory fills up, the AI starts making worse decisions. Subagents are the fix.
The outcome: Agent systems that isolate research from execution produce higher quality results on complex tasks. Your main agent makes better decisions because it only sees clean summaries, not raw data dumps.
Знания загружаются по запросу, а не заранее
Claude Code не пихает в системный промпт все возможные инструкции. Вместо этого он использует двухуровневый подход:
Layer 1 (System prompt, always loaded):
┌──────────────────────────────────┐
│ You are a coding agent. │
│ Skills available: │
│ - git: Git workflow helpers │ ~100 tokens per skill
│ - test: Testing best practices │
│ - review: Code review process │
└──────────────────────────────────┘
Layer 2 (On demand, via tool_result):
┌──────────────────────────────────┐
│ <skill name="git"> │
│ Full git workflow instructions │
│ Branching conventions... │ ~2,000 tokens per skill
│ Commit message format... │
│ </skill> │
└──────────────────────────────────┘Первый уровень — лёгкое меню доступных навыков. Почти ничего не стоит. Второй уровень — полные инструкции для конкретного навыка, которые подгружаются только тогда, когда ИИ обращается к load_skill("git").
Представьте ресторан. Официант не заучивает все рецепты — он знает меню. Когда вы делаете заказ, он передаёт на кухню конкретное блюдо.
Математика здесь очевидна. 10 навыков по 2,000 токенов каждый — это 20,000 токенов, постоянно висящих в системном промпте. При загрузке по запросу вы тратите ~1,000 токенов на меню и подгружаете только те 1-2 навыка, которые действительно нужны за сессию. Это снижение на 60-80% токенов.
Что в итоге: меньше затрат, быстрее ответы, а ИИ остаётся сосредоточенным на текущей задаче, а не перебирает 20,000 токенов инструкций, которые ему не понадобятся.
Память не обязана быть бесконечной. Достаточно умной.
Именно этот подход делает Claude Code пригодным для работы с большими кодовыми базами. Три уровня сжатия работают вместе:
flowchart TB
TR[Tool Result] --> L1["Layer 1: Micro-compact\n(every turn, silent)"]
L1 --> Check{"Tokens\n> 50,000?"}
Check --> |no| Continue[Continue normally]
Check --> |yes| L2["Layer 2: Auto-compact\n(save transcript, summarize)"]
L2 --> Fresh[Fresh context + summary]
Manual["Layer 3: Model calls\ncompact tool"] --> L2- Микрокомпактизация: На каждом ходу результаты инструментов старше 3 раундов заменяются заглушками вроде
[Previous: used read_file]. ИИ по-прежнему знает, что читал этот файл. Само содержимое при этом исчезает. - Автокомпактизация: Когда число токенов превышает 50,000, весь диалог сохраняется на диск (
.transcripts/), после чего вызов LLM сжимает беседу до нескольких абзацев. Все сообщения заменяются этим резюме. - Ручная компактизация: ИИ может сам запустить сжатие, когда понимает, что впереди большая задача.
Это агентный аналог чекпоинтинга контекстного окна — одного из 15 продакшен-паттернов, о которых я писал. Принцип тот же: периодически сжимать состояние в компактное резюме и продолжать работу с чистого окна. Записи на диске означают, что ничего не потеряно по-настоящему — просто вынесено из активного контекста.
Без сжатия агент упирается в лимит памяти, прочитав примерно 30 файлов. Для реальной работы этого мало. С тремя уровнями сжатия он может работать сколько угодно.
Что в итоге: Команды, которые строят продакшен-агентов для многочасовых сессий, все так или иначе реализуют этот стек сжатия. Это не опциональная инфраструктура. Это обязательный минимум для любого агента, которому предстоит работать над реальными проектами.
Задачи переживают падения. Диалоги — нет.
Claude Code хранит список задач в виде файлов на диске, а не в памяти ИИ. Каждая задача — это JSON-файл со статусом, зависимостями и владельцем. Когда одна задача завершается, она автоматически разблокирует зависимые.
flowchart TB
T1["Task 1\ncompleted"] --> T2["Task 2\npending (unblocked)"]
T1 --> T3["Task 3\npending (unblocked)"]
T2 --> T4["Task 4\nblocked by 2,3"]
T3 --> T4Это DAG (направленный ациклический граф), сохранённый на диск:
.tasks/
task_1.json {"id":1, "status":"completed", "blockedBy":[]}
task_2.json {"id":2, "status":"pending", "blockedBy":[]}
task_3.json {"id":3, "status":"pending", "blockedBy":[]}
task_4.json {"id":4, "status":"blocked", "blockedBy":[2,3]}Завершение задачи 1 запускает _clear_dependency(1), который удаляет 1 из списка blockedBy у всех остальных задач. Задачи 2 и 3 разблокируются автоматически. Граф в любой момент отвечает на три вопроса: что готово, что заблокировано, что сделано.
Если ИИ упадёт, что-то забудет или его контекст сожмут, доска задач всё равно останется на диске. Агент продолжит ровно с того места, где остановился.
Что в итоге: Агентные системы с постоянными графами задач спокойно переживают прерывания. Пользователь может закрыть ноутбук, перезапустить инструмент, даже пересесть на другую машину — работа продолжится. Это и есть разница между демо и продуктом.
Агенты, которые сами находят себе работу
А вот тут становится интересно. В ранних паттернах ведущий агент раздавал все задачи вручную. Так не масштабируется. В утёкшей архитектуре автономные напарники сами сканируют доску задач, берут невзятые задачи и работают над ними без указаний.
Жизненный цикл:
stateDiagram-v2
[*] --> Spawn
Spawn --> Working
Working --> Idle : task done or idle signal
Idle --> Working : inbox message or unclaimed task found
Idle --> Shutdown : 60s timeout, nothing to doВ фазе простоя напарник опрашивает каждые 5 секунд:
- Проверяет входящие на сообщения от других агентов
- Сканирует
.tasks/в поисках задач в статусе ожидания, без владельца и без блокировок - Если нашёл — берёт и возвращается к работе
- Если за 60 секунд ничего не появилось — корректно завершает работу
Одна тонкость: после сжатия контекста агент может забыть, кто он. Харнесс заново вставляет блок идентичности (<identity>You are 'alice', role: coder</identity>), как только число сообщений опускается ниже порога. Идентичность переживает сжатие.
Я разбирал разницу между workflow и агентом в прошлом посте. Главный тест: «Кто управляет шагами и их порядком?» В этом паттерне ответ — полная автономия. Никто не раздаёт работу. Ни один ведущий агент не делегирует. Агенты сами находят задачи на общей доске и берут их.
Что в итоге: Команды рассказывают, что самоорганизующиеся пулы агентов разгребают бэклоги в 2-3 раза быстрее, чем подход с ведущим агентом. Издержки на координацию исчезают, потому что координатора нет.
Несколько агентов — ноль коллизий
Последний и самый сложный паттерн: когда несколько ИИ-агентов одновременно работают с одной кодовой базой, каждый получает собственный изолированный каталог (git worktree). Агент A правит аутентификацию в одной копии. Агент B чинит UI в другой. Их изменения не мешают друг другу.
flowchart TB
subgraph Control[".tasks/ (what to do)"]
T1["task_1.json\nworktree: auth-refactor"]
T2["task_2.json\nworktree: ui-login"]
end
subgraph Execution[".worktrees/ (where to do it)"]
W1["auth-refactor/\nbranch: wt/auth-refactor"]
W2["ui-login/\nbranch: wt/ui-login"]
end
T1 <--> |"bound by task_id"| W1
T2 <--> |"bound by task_id"| W2Доска задач отслеживает, что нужно сделать. Worktrees отслеживают, где каждый агент это делает. Они связаны по ID задачи. Создание worktree с task_id=1 автоматически переводит задачу в in_progress. Удаление worktree с complete_task=True помечает задачу выполненной и отправляет событие жизненного цикла в .worktrees/events.jsonl.
Без изоляции два агента, одновременно правящие один и тот же файл, испортят работу друг друга. Это ИИ-аналог ситуации, когда двое печатают в одном Google Docs и удаляют абзацы друг друга.
Это связано с паттерном ограничения зоны воздействия из моего разбора производственных агентов. Worktrees — это изоляция на уровне файловой системы. Зона воздействия каждого агента ограничена его собственным каталогом. Неудачная правка в одном worktree не затронет другой.
Результат: команды, запускающие параллельных ИИ-агентов с изоляцией через worktree, сообщают, что завершают работу над фичами в 2-3 раза быстрее, чем при последовательном подходе. Архитектура позволяет делать это безопасно, потому что у каждого агента своя песочница.
Главный урок: скучное побеждает хитрое
Вот чему эта утечка в итоге научила сообщество разработчиков. Самый мощный ИИ-агент для разработки в продакшене работает не на секретном алгоритме. Он работает на паттернах, которые существуют в программной инженерии уже десятки лет:
| Паттерн | Что он делает в Claude Code | Аналог из старого мира |
|---|---|---|
| Цикл агента | Запускает инструменты, пока задача не выполнена | Событийный цикл (Node.js, игровые движки) |
| Диспетчеризация инструментов | Направляет вызовы инструментов обработчикам | Архитектура плагинов |
| TodoWrite | Планирует перед выполнением | Доски управления проектами |
| Субагенты | Изолируют исследование от основного потока | Микросервисы с чистыми интерфейсами |
| Загрузка навыков | Загружает инструкции по требованию | Ленивая загрузка, внедрение зависимостей |
| Сжатие контекста | Сжимает память, когда она заполнена | Сборка мусора |
| Граф задач | Хранит цели с зависимостями | Очереди заданий на основе баз данных |
| Фоновые задачи | Выполняет медленные операции параллельно | Пулы потоков, асинхронные воркеры |
| Команды агентов | Координирует постоянных напарников | Очереди сообщений, pub/sub |
| Протоколы | Структурированные рукопожатия между агентами | RPC, паттерны запрос-ответ |
| Автономные агенты | Сами берут задачи с общей доски | Планировщики с перехватом работы |
| Изоляция worktree | Изолирует файловую систему каждого агента | Изоляция контейнеров, песочницы |
Ни одна из этих идей не нова. Ново то, что их применяют к ИИ-агентам в целостной, компонуемой системе, где каждый слой опирается на предыдущий, не заменяя его.
Вывод: чтобы строить ИИ-агентов продакшен-уровня, не нужна степень PhD по машинному обучению. Нужны прочные основы программной инженерии и дисциплина начинать с простого.
С чего начать
Если вы строите агентов сегодня, утечка даёт чёткую последовательность:
- Первая неделя: соберите цикл. Один инструмент (bash или вызов API), одно условие выхода. Добейтесь, чтобы что-то работало от начала до конца.
- Вторая неделя: добавьте карту диспетчеризации инструментов. Регистрируйте 3-4 инструмента, не трогая цикл.
- Третья неделя: добавьте чек-лист задач, чтобы агент планировал перед действием.
- Четвёртая неделя: добавьте сжатие контекста, чтобы агент мог работать над проектами реального размера.
Всё остальное — субагенты, навыки, координация команд, worktrees — надстраивается поверх этих четырёх основ, не заменяя их.
Главный вывод
Утечка Claude Code показала: разрыв между любительскими и продакшен-агентами создаёт не секретная технология, а инженерная дисциплина. Простой цикл, чёткие границы инструментов, сохраняемое состояние и грамотное управление памятью.
Теперь этот план открыт. 12 паттернов складываются друг в друга. Каждый решает конкретную реальную задачу, с которой рано или поздно столкнётся любой, кто делает агентов. Вопрос не в том, понадобятся ли вам эти паттерны, а в том, дойдёте ли вы до них своим горьким опытом или научитесь на этой утечке.
Лучшие агенты — не самые умные. Они самые компонуемые.
Источник: Kondasamy Jayaraman · Engineering Blog · kondasamy.com