Delegation
На этой странице
Инструмент delegate_task создаёт дочерние экземпляры AIAgent с изолированным контекстом, ограниченным набором инструментов и собственными сеансами терминала. Каждый дочерний агент получает новый разговор и работает независимо — только его итоговая сводка попадает в контекст родительского агента.
Одиночная задача¶
[code] delegate_task( goal="Отладить причину падения тестов", context="Ошибка: assertion в test_foo.py строка 42", toolsets=["terminal", "file"] )
[/code]
Пакетный параллельный запуск¶
По умолчанию до 3 параллельных дочерних агентов (настраивается, без жёсткого ограничения):
[code] delegate_task(tasks=[ {"goal": "Исследовать тему A", "toolsets": ["web"]}, {"goal": "Исследовать тему B", "toolsets": ["web"]}, {"goal": "Исправить сборку", "toolsets": ["terminal", "file"]} ])
[/code]
Как работает контекст дочернего агента¶
Важно: дочерние агенты ничего не знают
Дочерние агенты начинают с полностью нового разговора. У них нет никаких знаний об истории общения родительского агента, предыдущих вызовах инструментов или чём-либо, что обсуждалось до делегирования. Единственный контекст дочернего агента — это поля goal и context, которые родительский агент заполняет при вызове delegate_task.
Это означает, что родительский агент должен передать всё, что нужно дочернему агенту, в вызове:
[code] # ПЛОХО — дочерний агент понятия не имеет, что такое «ошибка» delegate_task(goal="Исправить ошибку")
# ХОРОШО — дочерний агент имеет весь необходимый контекст
delegate_task(
goal="Исправить TypeError в api/handlers.py",
context="""Файл api/handlers.py содержит TypeError на строке 47:
Объект 'NoneType' не имеет атрибута 'get'.
Функция process_request() получает словарь от parse_body(),
но parse_body() возвращает None, если заголовок Content-Type отсутствует.
Проект находится в /home/user/myproject и использует Python 3.11."""
)
[/code]
Дочерний агент получает сфокусированный системный промпт, построенный из ваших цели и контекста, с инструкцией выполнить задачу и предоставить структурированную сводку о том, что было сделано, что найдено, какие файлы изменены и с какими проблемами столкнулись.
Практические примеры¶
Параллельное исследование¶
Исследуйте несколько тем одновременно и соберите сводки:
[code] delegate_task(tasks=[ { "goal": "Исследовать текущее состояние WebAssembly в 2025 году", "context": "Сосредоточиться на: поддержке браузеров, средах выполнения вне браузера, поддержке языков", "toolsets": ["web"] }, { "goal": "Исследовать текущий уровень внедрения RISC-V в 2025 году", "context": "Сосредоточиться на: серверных чипах, встраиваемых системах, экосистеме ПО", "toolsets": ["web"] }, { "goal": "Исследовать прогресс квантовых вычислений в 2025 году", "context": "Сосредоточиться на: прорывах в коррекции ошибок, практических применениях, ключевых игроках", "toolsets": ["web"] } ])
[/code]
Ревью кода + исправление¶
Делегируйте рабочий процесс ревью и исправления в новый контекст:
[code] delegate_task( goal="Проверить модуль аутентификации на уязвимости и исправить найденные", context="""Проект в /home/user/webapp. Файлы модуля аутентификации: src/auth/login.py, src/auth/jwt.py, src/auth/middleware.py. Проект использует Flask, PyJWT и bcrypt. Сосредоточиться на: SQL-инъекциях, валидации JWT, обработке паролей, управлении сессиями. Исправить все найденные проблемы и запустить тесты (pytest tests/auth/).""", toolsets=["terminal", "file"] )
[/code]
Многофайловый рефакторинг¶
Делегируйте крупную задачу рефакторинга, которая перегрузила бы контекст родителя:
[code] delegate_task( goal="Выполнить рефакторинг всех Python-файлов в src/ — заменить print() на правильное логирование", context="""Проект в /home/user/myproject. Использовать модуль 'logging' с logger = logging.getLogger(name). Заменить вызовы print() на соответствующие уровни логирования: - print(f"Ошибка: ...") -> logger.error(...) - print(f"Предупреждение: ...") -> logger.warning(...) - print(f"Отладка: ...") -> logger.debug(...) - Остальные print -> logger.info(...) Не изменять print() в тестовых файлах или CLI-выводе. Запустить pytest после для проверки.""", toolsets=["terminal", "file"] )
[/code]
Детали пакетного режима¶
Когда вы передаёте массив tasks, дочерние агенты выполняются параллельно с использованием пула потоков:
- Максимальная конкурентность: по умолчанию 3 задачи (настраивается через
delegation.max_concurrent_childrenили переменную окруженияDELEGATION_MAX_CONCURRENT_CHILDREN; минимум 1, без жёсткого ограничения). Пакеты, превышающие лимит, возвращают ошибку инструмента, а не молча усекаются. - Пул потоков: использует
ThreadPoolExecutorс заданным лимитом конкурентности в качестве максимального количества рабочих потоков - Отображение прогресса: в CLI-режиме древовидное представление показывает вызовы инструментов каждого дочернего агента в реальном времени со строками завершения каждой задачи. В шлюзовом режиме прогресс собирается в пакеты и передаётся в колбэк прогресса родительского агента
- Упорядочивание результатов: результаты сортируются по индексу задачи, чтобы соответствовать порядку ввода независимо от порядка завершения
- Распространение прерывания: прерывание родительского агента (например, отправка нового сообщения) прерывает всех активных дочерних агентов
Одиночная задача выполняется напрямую без накладных расходов пула потоков.
Переопределение модели¶
Вы можете настроить другую модель для дочерних агентов через config.yaml — полезно для делегирования простых задач более дешёвым/быстрым моделям:
[code] # В ~/.hermes/config.yaml delegation: model: "google/gemini-flash-2.0" # Более дешёвая модель для дочерних агентов provider: "openrouter" # Опционально: направить дочерних агентов к другому провайдеру
[/code]
Если не указано, дочерние агенты используют ту же модель, что и родительский.
Советы по выбору набора инструментов¶
Параметр toolsets управляет тем, к каким инструментам имеет доступ дочерний агент. Выбирайте в зависимости от задачи:
| Набор инструментов | Сценарий использования |
|---|---|
["terminal", "file"] |
Работа с кодом, отладка, редактирование файлов, сборки |
["web"] |
Исследования, проверка фактов, поиск документации |
["terminal", "file", "web"] |
Полнофункциональные задачи (по умолчанию) |
["file"] |
Анализ только для чтения, ревью кода без выполнения |
["terminal"] |
Системное администрирование, управление процессами |
Некоторые наборы инструментов заблокированы для дочерних агентов независимо от того, что вы укажете:
delegation— заблокирован для листовых дочерних агентов (по умолчанию). Сохраняется для дочерних агентов сrole="orchestrator", ограниченmax_spawn_depth— см. Глубина и вложенная оркестрация ниже.clarify— дочерние агенты не могут взаимодействовать с пользователемmemory— запрещена запись в общую постоянную памятьcode_execution— дочерние агенты должны рассуждать пошаговоsend_message— нет кроссплатформенных побочных эффектов (например, отправка сообщений Telegram)
Максимальное количество итераций¶
У каждого дочернего агента есть лимит итераций (по умолчанию: 50), который ограничивает количество шагов с вызовом инструментов:
[code] delegate_task( goal="Быстрая проверка файла", context="Проверить, существует ли /etc/nginx/nginx.conf, и вывести первые 10 строк", max_iterations=10 # Простая задача, много шагов не нужно )
[/code]
Тайм-аут дочернего агента¶
Дочерние агенты считаются зависшими и завершаются, если они молчат дольше, чем delegation.child_timeout_seconds секунд реального времени. По умолчанию — 600 (10 минут) — увеличено с 300 с в предыдущих версиях, потому что модели с глубокими рассуждениями при нетривиальных исследовательских задачах завершались посередине размышления. Настраивается для каждой установки:
[code] delegation: child_timeout_seconds: 600 # по умолчанию
[/code]
Снижайте для быстрых локальных моделей; увеличивайте для медленных моделей рассуждения на сложных задачах. Таймер сбрасывается каждый раз, когда дочерний агент совершает API-вызов или вызов инструмента — только действительно простаивающие работники вызывают завершение.
Диагностический дамп при тайм-ауте без вызовов¶
Если у дочернего агента истёк тайм-аут при нулевом количестве API-вызовов (обычно: провайдер недоступен, ошибка аутентификации или отклонение схемы инструмента), delegate_task записывает структурированную диагностику в ~/.hermes/logs/subagent-timeout-<session>-<timestamp>.log, содержащую снимок конфигурации дочернего агента, трассировку разрешения учётных данных и любые сообщения о ранних ошибках. Это значительно упрощает поиск корневой причины по сравнению с прежним молчаливым тайм-аутом.
Мониторинг запущенных дочерних агентов (/agents)¶
TUI предоставляет наложение /agents (псевдоним /tasks), которое превращает рекурсивное разветвление delegate_task в первоклассную поверхность аудита:
- Древовидное представление запущенных и недавно завершённых дочерних агентов в реальном времени, сгруппированных по родителю
- Сводки затрат, токенов и затронутых файлов по каждой ветке
- Элементы управления завершением и приостановкой — отмените конкретного дочернего агента на лету, не прерывая его собратьев
- Пост-анализ: просмотр пошаговой истории каждого дочернего агента даже после возврата к родителю
Классический CLI просто выводит /agents в виде текстовой сводки; в TUI наложение раскрывается наиболее полно. См. TUI — Слэш-команды.
Глубина и вложенная оркестрация¶
По умолчанию делегирование является плоским: родитель (глубина 0) порождает дочерних агентов (глубина 1), и эти дочерние агенты не могут делегировать дальше. Это предотвращает неконтролируемую рекурсивную делегацию.
Для многоэтапных рабочих процессов (исследование → синтез или параллельная оркестрация подзадач) родитель может порождать оркестраторов — дочерних агентов, которые могут делегировать свои собственные задачи:
[code] delegate_task( goal="Изучить три подхода к ревью кода и рекомендовать один", role="orchestrator", # Позволяет этому дочернему агенту порождать свои задачи context="...", )
[/code]
role="leaf"(по умолчанию): дочерний агент не может делегировать дальше — идентично поведению плоского делегирования.role="orchestrator": дочерний агент сохраняет набор инструментовdelegation. Ограничиваетсяdelegation.max_spawn_depth(по умолчанию 1 = плоское, поэтомуrole="orchestrator"ничего не меняет при настройках по умолчанию). Увеличьтеmax_spawn_depthдо 2, чтобы позволить дочерним оркестраторам порождать листовых внуков; до 3 для трёх уровней (максимум).delegation.orchestrator_enabled: false: глобальный выключатель, который принудительно устанавливает всем дочерним агентам рольleafнезависимо от параметраrole.
Предупреждение о затратах: При max_spawn_depth: 3 и max_concurrent_children: 3 дерево может достичь 3×3×3 = 27 параллельных листовых агентов. Каждый дополнительный уровень умножает расходы — увеличивайте max_spawn_depth осознанно.
Время жизни и долговечность¶
delegate_task синхронен — не долговечен¶
delegate_task выполняется внутри текущего шага родительского агента. Он блокирует родительского агента до тех пор, пока каждый дочерний агент не завершится (или не будет отменён). Это не фоновая очередь заданий:
- Если родительский агент прерван (пользователь отправил новое сообщение,
/stop,/new), все активные дочерние агенты отменяются и возвращаютstatus="interrupted". Их текущая работа отбрасывается. - Дочерние агенты не продолжают работать после завершения шага родительского агента.
- Отменённые дочерние агенты возвращают структурированный результат (
status="interrupted",exit_reason="interrupted"), но поскольку родительский агент также был прерван, этот результат часто не попадает в видимый пользователю ответ.
Для долговечной фоновой работы, которая должна переживать прерывания или выходить за пределы текущего шага, используйте:
cronjob(action=create) — планирует отдельный запуск агента; не подвержен прерываниям текущего шага.terminal(background=True, notify_on_complete=True)— долго выполняющиеся команды оболочки, которые продолжают работу, пока агент занимается другими делами.
Ключевые свойства¶
- Каждый дочерний агент получает собственный сеанс терминала (отдельный от родительского)
- Вложенное делегирование — по желанию — только дочерние агенты с
role="orchestrator"могут делегировать дальше, и только еслиmax_spawn_depthувеличен со значения по умолчанию 1 (плоское). Отключите глобально с помощьюorchestrator_enabled: false. - Листовые дочерние агенты не могут вызывать:
delegate_task,clarify,memory,send_message,execute_code. Оркестраторы сохраняютdelegate_task, но всё ещё не могут использовать остальные четыре. - Распространение прерывания — прерывание родительского агента прерывает всех активных дочерних (включая внуков под оркестраторами)
- Только итоговая сводка попадает в контекст родительского агента, что обеспечивает эффективное использование токенов
- Дочерние агенты наследуют API-ключ, конфигурацию провайдера и пул учётных данных родительского агента (включая ротацию ключей при ограничениях скорости)
Сравнение: Delegation vs execute_code¶
| Фактор | delegate_task | execute_code |
|---|---|---|
| Рассуждение | Полный цикл рассуждения LLM | Только выполнение Python-кода |
| Контекст | Новый изолированный разговор | Нет разговора, только скрипт |
| Доступ к инструментам | Все незаблокированные инструменты с рассуждением | 7 инструментов через RPC, без рассуждения |
| Параллелизм | 3 параллельных дочерних агента по умолчанию (настраивается) | Один скрипт |
| Для чего лучше | Сложные задачи, требующие суждения | Механические многошаговые конвейеры |
| Стоимость токенов | Выше (полный цикл LLM) | Ниже (возвращается только stdout) |
| Взаимодействие с пользователем | Нет (дочерние агенты не могут задавать уточняющие вопросы) | Нет |
Правило: Используйте delegate_task, когда подзадача требует рассуждения, суждения или многошагового решения проблем. Используйте execute_code, когда нужна механическая обработка данных или скриптовые рабочие процессы.
Конфигурация¶
[code] # В ~/.hermes/config.yaml delegation: max_iterations: 50 # Макс. шагов на дочернего агента (по умолч.: 50) # max_concurrent_children: 3 # Параллельных дочерних агентов на пакет (по умолч.: 3) # max_spawn_depth: 1 # Глубина дерева (1–3, по умолч. 1 = плоское). Увеличьте до 2, чтобы разрешить оркестраторам порождать листовых агентов; до 3 для трёх уровней. # orchestrator_enabled: true # Отключите, чтобы принудительно установить всем дочерним агентам роль leaf. model: "google/gemini-3-flash-preview" # Опциональное переопределение модели/провайдера provider: "openrouter" # Опциональный встроенный провайдер
# Или используйте прямой кастомный эндпоинт вместо провайдера:
delegation:
model: "qwen2.5-coder"
base_url: "http://localhost:1234/v1"
api_key: "local-key"
[/code]
tip Агент обрабатывает делегирование автоматически на основе сложности задачи. Вам не нужно явно просить его делегировать — он сделает это, когда это имеет смысл.
- Одиночная задача
- Пакетный параллельный запуск
- Как работает контекст дочернего агента
- Практические примеры
- Параллельное исследование
- Ревью кода + исправление
- Многофайловый рефакторинг
- Детали пакетного режима
- Переопределение модели
- Советы по выбору набора инструментов
- Максимальное количество итераций
- Тайм-аут дочернего агента
- Мониторинг запущенных дочерних агентов (
/agents) - Глубина и вложенная оркестрация
- Время жизни и долговечность
- Ключевые свойства
- Сравнение: Delegation vs execute_code
- Конфигурация