# Субагенты Claude Code: когда экономят контекст, а когда мешают

> Нужен ли субагент в Claude Code: цена запуска и размер результата по замерам автора, что снижает стартовый контекст, выбор модели и случаи, когда он мешает.
> Author: Roman Belov · Published: 2026-10-21 · Source: https://futurecraft.pro/ru/blog/claude-code-subagents/

В транскриптах субагентов Claude Code на машине автора медианный субагент на пике держит около 117 тыс. токенов контекста, а в основной разговор возвращает около 1 500 символов. Субагент - отдельный экземпляр Claude со своим окном контекста, системным промптом и инструментами: он делает работу в стороне и отдаёт только итог. Ради разницы между пиком и итогом его и запускают.

У той же медианы есть вторая цифра: ещё до первого действия субагент занимает около 58 тыс. токенов. Это цена запуска, и на короткой задаче она съедает всю выгоду. Документация Claude Code описывает механику субагентов подробно, но не говорит, сколько стоит старт и когда он окупается.

Статья о том, как решить, нужен ли субагент в конкретной задаче. В основе: [документация по субагентам](https://code.claude.com/docs/en/sub-agents) (сверено с Claude Code 2.1.318), агрегаты по 648 транскриптам субагентов автора и контролируемый эксперимент из 18 запусков. Выборка одного пользователя с тяжёлой конфигурацией, поэтому вместе с цифрами даны ограничения и скрипт, чтобы повторить замер у себя. Справка по всем полям файла агента уже есть в статье [Claude Code Skills и Agents](https://futurecraft.pro/ru/blog/claude-code-skills-agents/), здесь она не повторяется.

## Что именно изолирует субагент

Обычный (не fork) субагент стартует со свежим окном контекста. Он не продолжает разговор, а получает задачу, которую сформулировал основной агент, и собирает нужный контекст сам.

### Что субагент получает на старте, а чего не видит

| Получает | Не получает |
|---|---|
| Собственный системный промпт (тело файла агента) | Историю основного разговора |
| Сообщение-задачу от основного агента | Файлы, которые основной агент уже прочитал |
| CLAUDE.md пользователя, проекта и локальный (кроме Explore и Plan; отключается через `omitClaudeMd`) | Skills, вызванные в основном разговоре |
| Снимок git status (кроме Explore и Plan) | Auto memory основного разговора |
| Skills из поля `skills` (полное содержимое) | Output style основной сессии |
| Схемы разрешённых инструментов, включая MCP | |

Из правой колонки следует главное ограничение: всё, что основной агент знает из разговора, субагент получит, только если это попало в текст задачи. Встроенные Explore и Plan по [документации](https://code.claude.com/docs/en/sub-agents) стартуют без CLAUDE.md и git status, чтобы исследование было быстрым и дешёвым.

### Что возвращается в основной разговор

Возвращается только финальный ответ субагента. Промежуточные вызовы инструментов, прочитанные файлы и рассуждения остаются в его транскрипте. С версии 2.1.277 результат приходит под заголовком, который помечает его как вывод субагента, с отступом. По [CHANGELOG](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md) это сделано, чтобы текст из результата не выдавал себя за инструкции сессии.

Документация прямо оговаривает две вещи. Первая: результаты накапливаются в основном контексте, и много субагентов с подробными ответами занимают заметное место. Вторая: каждый субагент отправляет собственные запросы, и они идут в те же лимиты использования, что и основной разговор.

### Субагент, fork и skill

| | Skill | Субагент | Fork |
|---|---|---|---|
| Контекст | Текущий разговор целиком | Свежий, только задача | Копия всего разговора |
| Системный промпт и инструменты | Основной сессии | Из файла агента | Основной сессии |
| Модель | Основной сессии или из поля skill | Из цепочки выбора (см. ниже) | Основной сессии |
| Кэш промпта | Общий | Отдельный | Общий с основной сессией |
| Что попадает в основной контекст | Всё | Только итоговый ответ | Только итоговый ответ |

Fork появился как способ отдать побочную задачу без пересказа контекста: он видит то же, что основная сессия, но его вызовы инструментов в основной разговор не попадают. Запустить fork вручную можно командой `/subtask <задача>`. Режим fork включён по умолчанию с версии 2.1.302, отключается переменной `CLAUDE_CODE_FORK_SUBAGENT=0`. Fork не может запускать другие forks. Поскольку системный промпт и инструменты у него те же, первый запрос использует кэш основной сессии, и документация называет fork более дешёвым вариантом для задач, которым нужен тот же контекст. Skill с полем `context: fork` тоже выполняется в отдельном субагенте.

## Что показали замеры

Цифры ниже из двух источников. Первый: агрегаты по реальным транскриптам субагентов автора за весь период, который они хранятся. Второй: эксперимент E2 с одним и тем же тривиальным заданием в разных конфигурациях агента. Содержимое задач не анализировалось и не публикуется, только размеры.

### Метод и выборка

Claude Code пишет транскрипт каждого субагента в `~/.claude/projects/<проект>/<сессия>/subagents/agent-<id>.jsonl`. В каждом ассистентском сообщении есть поле `usage`. Размер контекста хода считался как `input_tokens + cache_read_input_tokens + cache_creation_input_tokens`.

- **Стартовый контекст**: размер на первом ходе (системный промпт, CLAUDE.md, схемы инструментов, описания, задача).
- **Пик**: максимальный размер по ходам.
- **Результат**: длина последнего текстового сообщения субагента в символах.

Пересчёт 6 ноября 2026 года, срез по транскриптам, созданным до 15:00: 648 транскриптов, из них 535 завершённых с ответом. Выборка живая: к вечеру того же дня новые тяжёлые запуски сдвинули медиану старта до ~62 тыс., поэтому при повторе скриптом ниже цифры будут немного другими. Записи с моделью `<synthetic>` (заглушки при ошибках API) исключены. По типам (все 648 транскриптов): general-purpose 577 запусков (89%), кастомные агенты 44 (~7%), агент плагина для передачи задачи внешнему CLI 19 (3%), Explore 8 (1%).

Сумма токенов по ходам как метрика не годится: одни и те же 58 тыс. стартового контекста считаются на каждом ходу заново. Около 91% входных токенов в этих транскриптах приходится на чтение из кэша, поэтому цена хода в деньгах заметно ниже номинальной. Здесь измеряется размер контекста, а не счёт.

### Выгода: пик против результата

| Показатель (535 субагентов) | Медиана | p10 | p90 |
|---|---|---|---|
| Стартовый контекст, токенов | ~58 тыс. | ~17 тыс. | ~82 тыс. |
| Пик контекста, токенов | ~117 тыс. | ~44 тыс. | ~238 тыс. |
| Результат, символов | ~1 500 | ~100 | ~6 300 |
| Вызовов инструментов | 18 | 4 | 55 |

Медианный субагент на пике держит ~117 тыс. токенов, а в основной разговор приходит ответ на ~1 500 символов, то есть несколько сотен токенов. Разница в сотни раз. Без субагента большая часть этого объёма (содержимое прочитанных файлов, вывод команд) легла бы в основной контекст и оставалась бы там до компакции.

Отсюда простая проверка для любой задачи: если ответ по размеру сопоставим с проделанной работой, изоляция ничего не дала.

### Цена: стартовый контекст

Медиана старта ~58 тыс. токенов, p10 ~17 тыс. Это контекст, который субагент занимает до первого действия. В конфигурации автора туда входят большой глобальный CLAUDE.md с правилами, схемы инструментов нескольких десятков MCP-серверов, описания агентов и skills, git status.

Распределение неровное: около пятой части запусков стартует с 10–20 тыс. токенов, основная масса с 40–90 тыс. Из-за этого медиана старта чувствительна к фильтрации. Если не исключить заглушки `<synthetic>`, она поднимается до ~65 тыс., хотя пик и результат почти не меняются. При повторении замера такие записи лучше отбрасывать явно.

### Короткие задачи не окупаются

| Группа | Запусков | Стартовый контекст | Пик | Результат |
|---|---|---|---|---|
| ≤3 вызовов инструментов | 34 | ~55 тыс. | ~55 тыс. | ~1 100 символов |
| ≥15 вызовов инструментов | ~315 | ~66 тыс. | ~156 тыс. | ~1 900 символов |

В коротких задачах контекст почти не растёт после старта: субагент поднимает ~55 тыс. токенов ради ответа на ~1 100 символов. Основной разговор сделал бы те же 1–3 вызова в уже собранном контексте. В длинных задачах соотношение обратное: ~156 тыс. токенов работы сворачиваются в ~1 900 символов. Граница между ними зависит от стартовой цены в конкретной конфигурации, и её можно снизить.

### Что снижает стартовую цену

Эксперимент E2 проверял три рычага: поле `omitClaudeMd`, узкий список `tools` и запуск сессии без MCP-серверов. Условия: Claude Code 2.1.318, модель sonnet (в транскриптах `claude-sonnet-5-5`), временный проект без собственного CLAUDE.md, четыре проектных агента, задача «прочитать файл из одной строки и вернуть её». Каждый вариант запускался 3 раза через `claude -p`, метрика: стартовый контекст субагента по первому ходу его транскрипта.

| Вариант агента | Стартовый контекст, медиана | Изменение |
|---|---|---|
| Без ограничений (baseline) | 56 882 | база |
| `omitClaudeMd: true` | 49 594 | −12,8% |
| `tools: Read, Grep` | 12 232 | −78,5% |
| `tools: Read, Grep` + `omitClaudeMd: true` | 4 667 | −91,8% |
| Baseline, сессия без MCP-серверов | 41 639 | −26,8% |
| `tools` + `omitClaudeMd`, сессия без MCP-серверов | 4 667 | 0% к тому же варианту с MCP |

Сильнее всего действует поле `tools`. Allowlist убирает из контекста субагента схемы всех остальных инструментов, включая MCP, и в этой конфигурации это ~44,6 тыс. токенов. `omitClaudeMd` дал ~7,3 тыс.: в тестовом каталоге был только глобальный CLAUDE.md, с проектным файлом выгода будет больше. Рычаги складываются почти аддитивно, и остаток ~4,7 тыс. токенов можно считать полом для этой версии: системный промпт субагента, две схемы инструментов, тело агента.

Запуск сессии без MCP (`--strict-mcp-config` с пустым конфигом) сократил стартовый контекст основной сессии на 22,6% (69 767 → 53 993) и субагента без ограничений на 26,8%. Агенту с узким `tools` отключение MCP ничего не добавило: MCP-схемы у него и так отсечены. Во всех вариантах субагент вернул один и тот же ответ в 39 символов: рычаги меняют цену запуска, а не то, что приходит в основной разговор.

### Ограничения эксперимента E2

Эти условия нужно учитывать, прежде чем переносить цифры на свою конфигурацию:

- Одна машина, один пользователь, одна версия Claude Code, одна модель, один день.
- Конфигурация очень тяжёлая: около 65 MCP-серверов (436 инструментов в сессии), глобальные правила на ~7 тыс. токенов, около 50 агентов и большой список skills. Baseline 57 тыс. токенов для лёгкой конфигурации нетипичен, и абсолютная экономия у читателя будет меньше. Переносить стоит соотношения между рычагами, а не числа.
- Задача тривиальная, n=3 на вариант. Разброс внутри варианта мал (до ~2%), но это оценки порядка величины, а не доверительные интервалы.
- Не измерялись качество результата на реальных задачах, рост контекста по ходам, время и влияние `tools` на способность агента выполнить задачу. Агенту, которому нужны Bash или Edit, узкий allowlist из двух инструментов не подойдёт.

### Как повторить замер у себя

Скрипт читает только поля `usage` и длину ответов, содержимое транскриптов не выводит. Формат jsonl недокументирован и может меняться между версиями.

```python
import glob, json, os, statistics as st

KEYS = ("input_tokens", "cache_read_input_tokens", "cache_creation_input_tokens")
rows = []
for path in glob.glob(os.path.expanduser("~/.claude/projects/*/*/subagents/agent-*.jsonl")):
    first = peak = None
    result, tools = "", 0
    for line in open(path, errors="ignore"):
        try:
            rec = json.loads(line)
        except ValueError:
            continue
        msg = rec.get("message")
        if rec.get("type") != "assistant" or not isinstance(msg, dict) or msg.get("model") == "<synthetic>":
            continue  # служебные записи и заглушки ошибок
        ctx = sum((msg.get("usage") or {}).get(k) or 0 for k in KEYS)
        first = ctx if first is None else first
        peak = max(peak or 0, ctx)
        for c in msg.get("content") or []:
            tools += c.get("type") == "tool_use"
            if c.get("type") == "text" and c.get("text", "").strip():
                result = c["text"]
    if peak and result:
        rows.append((first, peak, len(result), tools))

med = lambda i, rs=rows: st.median(r[i] for r in rs)
print(f"n={len(rows)} старт={med(0):.0f} пик={med(1):.0f} результат={med(2):.0f} симв.")
short = [r for r in rows if r[3] <= 3]
print(f"<=3 вызовов: n={len(short)} старт={med(0, short):.0f} результат={med(2, short):.0f} симв.")
```

Если стартовый контекст выходит заметно ниже 58 тыс., граница окупаемости у вас сдвинута в пользу субагентов. Claude Code удаляет транскрипты субагентов по истечении срока `cleanupPeriodDays` (по умолчанию 30 дней), поэтому без изменения настройки выборка охватывает примерно последний месяц.

## Когда субагент нужен

Документация рекомендует субагента для задач с объёмным выводом, который не понадобится снова, для принудительных ограничений инструментов и прав и для самодостаточной работы, которая возвращает сводку. Замеры добавляют к этому порог: задача должна быть длиннее нескольких вызовов.

### Объёмный поиск и чтение

Типичный случай: найти все места, где используется функция, прочитать логи, пройтись по десяткам файлов и вернуть короткий список. Для поиска по кодовой базе есть встроенный Explore: он только читает (Write и Edit запрещены), работает с уровнями тщательности quick, medium и very thorough и стартует без CLAUDE.md. Если поиск переходит в действия, подходит general-purpose.

Признак подходящей задачи: ответ можно описать заранее в нескольких строках («список файлов и строк», «три причины ошибки»), а путь к нему потребует десятков вызовов.

### Ограничения по конструкции

Субагент с `tools: Read, Grep, Glob` физически не может ничего изменить, и это надёжнее, чем просьба в промпте. Ревью-агент без Write и Edit или исследователь с доступом только к чтению и веб-поиску выигрывают дважды: права ограничены, а стартовый контекст меньше из-за короткого списка инструментов. Поле `disallowedTools` работает как denylist и применяется раньше `tools`. Некоторые инструменты у субагентов отсутствуют всегда, даже если их перечислить: `AskUserQuestion`, `EnterPlanMode`, `ExitPlanMode` (кроме `permissionMode: plan`), `ScheduleWakeup`, `WaitForMcpServers`, `Workflow`, `EndConversation`, а на пределе вложенности и сам `Agent`.

### Независимые задачи параллельно

По документации в одной сессии одновременно работают до 20 субагентов (`CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` меняет лимит). Субагенты, запущенные из основного разговора без дополнительных настроек, стартуют в фоне: основной агент продолжает работу, результат приходит сообщением позже. Параллельность имеет смысл, когда задачи не зависят друг от друга: три независимых исследования, проверки разных модулей. Каждый запуск платит свою стартовую цену, поэтому десять мелких параллельных задач обойдутся дороже, чем кажется.

### Изоляция правок в worktree

`isolation: worktree` запускает субагента во временном git worktree, и его правки не затрагивают рабочую копию. Документация уточняет деталь, которую легко пропустить: worktree по умолчанию ответвляется от основной ветки репозитория, а не от текущего `HEAD` родительской сессии. Если субагент должен работать поверх незакоммиченных или свежих изменений, это нужно учитывать.

## Когда субагент мешает

### Короткие и точечные задачи

Исправить опечатку, прочитать один файл, проверить значение в конфиге. Замер выше показывает, что такие задачи в тяжёлой конфигурации стоят ~55 тыс. токенов старта ради ответа в ~1 000 символов. Документация называет основной разговор подходящим местом для быстрых точечных правок и задач, чувствительных к задержке: новому субагенту нужно время, чтобы собрать контекст.

### Работа, которой нужна история разговора

Если задача опирается на то, что обсуждалось последние полчаса (решения, отвергнутые варианты, уточнения), обычный субагент начнёт с нуля. Пересказ в тексте задачи теряет детали. Здесь есть три варианта: продолжить в основном разговоре, запустить fork, который видит всю историю, или для вопроса по уже обсуждённому использовать `/btw`. По документации `/btw` отвечает без доступа к инструментам и не добавляет ответ в историю.

Итеративная работа с частыми уточнениями тоже плохо ложится на субагента: каждый раунд правок проходит через пересказ, а не через общий контекст.

### Когда есть дешёвый индексированный поиск

Если в проекте подключён индекс кода (например, граф символов через MCP-инструмент), ответ на вопрос «где определено и кто вызывает» получается одним-двумя запросами к индексу. Субагент, который будет искать то же самое чтением файлов, добавит стартовую цену и десятки вызовов. В глобальных правилах автора для таких проектов прямо записано: исследование кода делает основной разговор через индекс, а не Explore. Замеров этого сравнения нет, это правило из практики, а не результат эксперимента.

### Накопление результатов и ошибки пересказа

Ответ субагента - это сводка, а сводка может ошибаться: пропустить файл, неверно обобщить, уверенно назвать непроверенное. Основной агент видит только итог и проверить его без повторной работы не может. Для решений, от которых много зависит, стоит просить в ответе ссылки на файлы и строки, чтобы выборочно проверить их.

Второй эффект: при многих запусках результаты копятся в основном контексте. Десять субагентов по 6 тыс. символов ответа (p90 из замеров) уже заметны в окне, и сюда добавляются формулировки задач.

### Фон и вложенность

Фоновые субагенты работают с урезанным набором встроенных инструментов; MCP-инструменты сохраняются. Запросы разрешений всплывают в основной сессии с именем субагента, который спрашивает, и при нескольких параллельных запусках это отвлекает. С версии 2.1.318 shell-команда фонового субагента сама уходит в фон через 3 минуты, чтобы не истёк кэш промпта.

Субагенты могут запускать своих субагентов до трёх уровней под основным разговором (`CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH`, значение `1` отключает вложенность). Каждый уровень платит свою стартовую цену и пересказывает задачу, поэтому глубокая вложенность умножает и стоимость, и риск искажения.

## Дерево решения: субагент, fork или основной разговор

| Ситуация | Где выполнять | Почему |
|---|---|---|
| 1–3 вызова, точечная правка | Основной разговор | Старт субагента дороже самой работы |
| Итерации с уточнениями, общий большой контекст | Основной разговор | Субагент не видит историю |
| Вопрос по уже обсуждённому | `/btw` | Без инструментов, не засоряет историю |
| Побочная задача, которой нужен весь контекст | Fork (`/subtask`) | Видит историю, делит кэш, возвращает только итог |
| Десятки чтений и поисков, короткий ответ | Explore или general-purpose | Изоляция окупается |
| Нужны жёсткие ограничения прав | Кастомный агент с `tools` | Ограничение по конструкции, меньше старт |
| Правки, которые не должны задеть рабочую копию | Агент с `isolation: worktree` | Отдельная ветка и каталог |
| Несколько независимых задач | Параллельные субагенты | До 20 одновременно, каждый со своим окном |
| Долгая работа, не помещается в одно окно | Отдельные сессии, фоновые агенты или agent teams | Так рекомендует документация |
| Есть индекс кода | Основной разговор с индексом | Поиск дешевле, чем чтение файлов субагентом |

Большинство случаев решают два вопроса. Первый: сколько вызовов инструментов понадобится. Если их один-три, субагент вряд ли окупится. Второй: нужна ли задаче история разговора. Если нужна, остаются fork и основной разговор.

## Как выбирается модель субагента

### Порядок разрешения

По [документации](https://code.claude.com/docs/en/sub-agents) модель субагента определяется в таком порядке:

1. Параметр `model`, который Claude передаёт в конкретном вызове Agent.
2. Поле `model` во frontmatter агента.
3. Переменная окружения `CLAUDE_CODE_SUBAGENT_MODEL`.
4. Модель основного разговора.

Допустимые значения поля: `sonnet`, `opus`, `haiku`, `fable`, полный ID (например, `claude-opus-5-5`) или `inherit`, то есть модель основного разговора. При подключении к Anthropic API алиасы `opus`, `sonnet` и `haiku` указывают на Opus 5.5, Sonnet 5.5 и Haiku 5.5, а `fable` на Fable 5.1. У облачных провайдеров соответствие может быть другим.

Частая ошибка: считать, что `CLAUDE_CODE_SUBAGENT_MODEL` перебивает всё. Так было в старых версиях; сейчас это значение по умолчанию, и frontmatter или параметр вызова его перекрывают. Чтобы поставить одну модель всем субагентам, нужно добавить `CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1` (с версии 2.1.257). У встроенных агентов свои правила: Plan наследует модель основного разговора, Explore тоже, но если основной разговор идёт на Fable, при подписке Claude, аккаунте Console или LLM-шлюзе Explore переходит на модель за алиасом `opus`.

### Политика выбора и чего замеры не показывают

В правилах автора модель агентов задана политикой: поиск и сбор информации на Sonnet, анализ, планирование и решения на Opus, Haiku для агентов не используется. Это рабочее соглашение, а не вывод из замеров.

Транскрипты такого вывода и не позволяют сделать. В них смесь моделей нескольких поколений, причину выбора (frontmatter, параметр вызова, переменная, наследование) по транскрипту не восстановить, а качество ответов не измерялось. Парных сравнений «одна задача на двух моделях» не было, поэтому утверждать, что Sonnet справляется с теми же задачами не хуже Opus, по этим данным нельзя. Цены и различия моделей разобраны в статье [Claude Opus vs Sonnet](https://futurecraft.pro/ru/blog/claude-opus-vs-sonnet/).

### Effort и thinking

Субагенты наследуют настройку extended thinking основного разговора. Уровень усилия задаётся полем `effort` во frontmatter (low, medium, high, xhigh, max), параметром вызова или переменной `CLAUDE_CODE_SUBAGENT_EFFORT`, которая действует, когда больше ничто не задаёт уровень. Для исследовательского агента с узкой задачей разумно начать с меньшего уровня и поднимать его, если ответы получаются поверхностными.

## Формат файла агента: поля, которые влияют на цену

Агент хранится как markdown-файл с YAML-frontmatter в `.claude/agents/` (проект) или `~/.claude/agents/` (пользователь); базовая настройка Claude Code описана в [полном гайде](https://futurecraft.pro/ru/blog/claude-code-complete-guide/). Пример read-only ревьюера с полями, которые влияют на цену и поведение:

```markdown
---
name: code-reviewer
description: Reviews a diff for bugs and security issues. Use after a feature is implemented. Read-only; for writing tests use test-writer.
tools: Read, Grep, Glob
model: sonnet
maxTurns: 20
---

Review the changes you are pointed to. Report issues by priority
with file:line references. Do not propose rewrites of unrelated code.
```

| Поле | Что даёт | Когда задавать |
|---|---|---|
| `tools` | Allowlist инструментов; без поля наследуются все | Почти всегда: и права, и стартовый контекст |
| `model` | Модель агента (см. выше) | Когда агент должен работать не на модели сессии |
| `maxTurns` | Лимит ходов; по достижении результат помечается частичным | Аудиторы и исследователи, склонные уходить вширь |
| `omitClaudeMd` | Старт без CLAUDE.md (с 2.1.271); managed-политика всё равно загружается | Агентам, которым правила проекта не нужны |
| `isolation` | `worktree`: временный git worktree | Агентам, которые правят код параллельно с вами |
| `autoCompactWindow` | Ранняя компакция субагента, 100 000–1 000 000 токенов | Агентам, читающим длинные логи |

Значение `autoCompactWindow` пишется целым числом: по документации `200k` во frontmatter читается как 200 и игнорируется как выходящее за диапазон. Остальные поля (`permissionMode`, `memory`, `skills`, `mcpServers`, `hooks`, `background`, `color`) описаны в [справочной статье по skills и agents](https://futurecraft.pro/ru/blog/claude-code-skills-agents/).

## Описание агента как роутер

Claude решает, кому делегировать, по полю `description`. Описания всех агентов лежат в контексте основного разговора постоянно, и по документации, если их суммарный объём (без встроенных) превышает 15 000 токенов, Claude Code показывает предупреждение при старте.

### Что работает

В каталоге автора встречаются два паттерна, которые упрощают выбор агента:

1. **Триггер в начале.** «Use after completing a logical unit of code» или «Use when…» с перечнем ситуаций.
2. **Граница с соседом в конце.** Фраза вида «для reference-паттернов используй команду /mcp-server» или «для тест-кода есть агент test-writer» снимает конфликт выбора между похожими агентами, командами и skills.

Добавка «use proactively» по документации повышает шанс автоматического делегирования.

### Антипаттерны

- **Длинные описания с примерами.** В каталоге есть агенты с описаниями по 900–1 000 символов с блоками «Example: User says… use this agent». Такое описание оплачивается в каждом запросе, даже когда агент не нужен.
- **Двуязычные описания.** Работают, но удлиняют текст, который лежит в контексте постоянно.
- **Устаревшие имена в `tools`.** У агента, написанного под старую версию, в списке могут остаться инструменты, которых уже нет или которые у субагентов вырезаются (`AskUserQuestion`). Что Claude Code делает с частично неразрешёнными именами, автор на живом запуске не проверял; список стоит сверять с текущим перечнем инструментов.

### Почему агент не вызывается

- **Файл пропущен.** Без `description` или с невалидным YAML агент не загружается, причина пишется в debug-лог. Файл без `name` считается документацией.
- **Опечатка в поле.** Неизвестные поля молча игнорируются. В `claude --debug` (с 2.1.296) такие поля видны по строке `does not recognize or apply`.
- **Описание не выделяет агента.** Если два агента описаны похоже, Claude может выбрать соседа или обойтись general-purpose.
- **Нужен гарантированный запуск.** Упоминание `@agent-<имя>` в запросе или выбор из списка через `@` запускает конкретного агента; формулировку задачи для него всё равно пишет Claude.

При одинаковых именах побеждает определение с более высоким приоритетом: managed settings, затем флаг `--agents`, затем `.claude/agents/` проекта, `~/.claude/agents/` пользователя и в конце агенты плагинов.

## Сколько агентов нужно

В пользовательском каталоге автора 33 файла агентов. Около 10 из них написаны автором, остальные пришли со сторонним пакетом. При этом 89% всех запусков приходятся на встроенный general-purpose, а все кастомные агенты вместе дают ~7%. Чаще других запускаются исследовательский агент с набором инструментов только для чтения и веб-поиска и read-only ревьюер.

Число файлов агентов о пользе ничего не говорит. Файл агента нужен, когда он что-то фиксирует: узкий набор инструментов, модель, лимит ходов, формат ответа. Для разового делегирования хватает general-purpose с хорошо сформулированной задачей. Начинать разумно с 2–3 агентов под повторяющиеся роли с явными границами между ними, а не каталог «на все случаи», описания которого постоянно занимают контекст.

## Хуки и наблюдаемость

Для контроля субагентов есть события `SubagentStart` и `SubagentStop` с matcher по имени агента. `SubagentStop` получает путь к транскрипту субагента и его последнее сообщение, этого хватает, чтобы логировать запуски или проверять формат ответа. Хуки можно объявить и во frontmatter агента: они работают, пока агент активен, а `Stop` в этом случае превращается в `SubagentStop`. Подробно события и формат хуков разобраны в статье [о хуках Claude Code](https://futurecraft.pro/ru/blog/claude-code-hooks/).

Модель каждого запущенного субагента показывает `/tasks`. Для разбора постфактум остаются транскрипты в `subagents/` и файлы `.meta.json` рядом с ними, где записан тип агента.

CLAUDE.md входит в стартовый контекст субагента, поэтому его размер влияет и на цену делегирования. Как держать CLAUDE.md коротким, разобрано в [гайде по CLAUDE.md](https://futurecraft.pro/ru/blog/claude-md-guide/), а общая логика управления окном описана в статье [о context engineering](https://futurecraft.pro/ru/blog/context-engineering-guide/).

## С чего начать

1. Прогоните скрипт замера на своих транскриптах и узнайте свою стартовую цену субагента. От неё зависит, с какой длины задачи делегирование окупается.
2. Не делегируйте задачи на 1–3 вызова и работу, которой нужна история разговора. Для второго случая есть fork и `/btw`.
3. Задавайте `tools` каждому кастомному агенту. В эксперименте на тяжёлой конфигурации это самый сильный рычаг: −78,5% стартового контекста, плюс ограничение прав по конструкции.
4. Добавьте `omitClaudeMd: true` агентам, которым правила проекта не нужны, и уберите из сессии MCP-серверы, которые не используются.
5. Пишите описания коротко: триггер в начале, граница с соседями в конце, без блоков с примерами. Модель задавайте явно во frontmatter и помните, что `CLAUDE_CODE_SUBAGENT_MODEL` без `_FORCE=1` её не перебивает.
