sidebar_position: 7
title: "Subagent Delegation"
description: "Spawn isolated child agents for parallel workstreams with delegate_task"
lang: ru
Делегирование субагента
Инструмент delegate_task порождает дочерние экземпляры AIAgent с изолированным контекстом, ограниченными наборами инструментов и собственными терминальными сеансами. Каждый ребенок получает новый разговор и работает самостоятельно — только его итоговое содержание входит в контекст родителя.
Одна задача
delegate_task(goal="Debug why tests fail",context="Error: assertion in test_foo.py line 42",toolsets=["terminal","file"])
Параллельная партия
По умолчанию до 3 одновременных субагентов (настраиваемые, без жесткого потолка):
delegate_task(tasks=[{"goal":"Research topic A","toolsets":["web"]},{"goal":"Research topic B","toolsets":["web"]},{"goal":"Fix the build","toolsets":["terminal","file"]}])
Как работает контекст субагента
:::Внимание Критическое: Субагенты ничего не знают
Субагенты начинают с совершенно нового разговора. Они ничего не знают об истории разговоров родителя, предыдущих вызовах инструментов или обо всем, что обсуждалось перед делегированием. Единственный контекст субагента исходит из полей goal и context, которые родительский агент заполняет при вызове delegate_task.
Это означает, что родительский агент должен передать в вызове все, что нужно субагенту:
# BAD - subagent has no idea what "the error" isdelegate_task(goal="Fix the error")# GOOD - subagent has all context it needsdelegate_task(goal="Fix the TypeError in api/handlers.py",context="""The file api/handlers.py has a TypeError on line 47: 'NoneType' object has no attribute 'get'. The function process_request() receives a dict from parse_body(), but parse_body() returns None when Content-Type is missing. The project is at /home/user/myproject and uses Python 3.11.""")
Субагент получает целенаправленное системное приглашение, созданное на основе вашей цели и контекста, которое инструктирует его выполнить задачу и предоставляет структурированное описание того, что он сделал, что он нашел, любых измененных файлов и любых возникших проблем.
Практические примеры
Параллельные исследования
Исследуйте несколько тем одновременно и собирайте резюме:
delegate_task(tasks=[{"goal":"Research the current state of WebAssembly in 2025","context":"Focus on: browser support, non-browser runtimes, language support","toolsets":["web"]},{"goal":"Research the current state of RISC-V adoption in 2025","context":"Focus on: server chips, embedded systems, software ecosystem","toolsets":["web"]},{"goal":"Research quantum computing progress in 2025","context":"Focus on: error correction breakthroughs, practical applications, key players","toolsets":["web"]}])
Проверка кода + исправление
Делегируйте рабочий процесс проверки и исправления в новый контекст:
delegate_task(goal="Review the authentication module for security issues and fix any found",context="""Project at /home/user/webapp. Auth module files: src/auth/login.py, src/auth/jwt.py, src/auth/middleware.py. The project uses Flask, PyJWT, and bcrypt. Focus on: SQL injection, JWT validation, password handling, session management. Fix any issues found and run the test suite (pytest tests/auth/).""",toolsets=["terminal","file"])
Многофайловый рефакторинг
Делегируйте большую задачу рефакторинга, которая заполнила бы родительский контекст:
delegate_task(goal="Refactor all Python files in src/ to replace print() with proper logging",context="""Project at /home/user/myproject. Use the 'logging' module with logger = logging.getLogger(__name__). Replace print() calls with appropriate log levels: - print(f"Error: ...") -> logger.error(...) - print(f"Warning: ...") -> logger.warning(...) - print(f"Debug: ...") -> logger.debug(...) - Other prints -> logger.info(...) Don't change print() in test files or CLI output. Run pytest after to verify nothing broke.""",toolsets=["terminal","file"])
Подробности пакетного режима
Когда вы предоставляете массив tasks, субагенты работают параллельно, используя пул потоков:
Максимальный параллелизм: 3 задачи по умолчанию (настраивается через delegation.max_concurrent_children или DELEGATION_MAX_CONCURRENT_CHILDREN env var; этаж 1, без жесткого потолка). Пакеты, превышающие лимит, возвращают ошибку инструмента, а не автоматически усекаются.
Пул потоков: использует ThreadPoolExecutor с настроенным лимитом параллелизма в качестве максимального количества рабочих процессов.
Отображение хода выполнения. В режиме CLI в виде дерева отображаются вызовы инструментов от каждого субагента в режиме реального времени со строками завершения каждой задачи. В режиме шлюза прогресс группируется и передается обратному вызову родительского процесса.
Упорядочение результатов. Результаты сортируются по индексу задачи, чтобы соответствовать порядку ввода, независимо от порядка завершения.
Распространение прерываний: прерывание родительского элемента (например, отправка нового сообщения) прерывает работу всех активных дочерних элементов.
Делегирование одной задачи выполняется напрямую, без накладных расходов на пул потоков.
Переопределение модели
Вы можете настроить другую модель для субагентов через config.yaml — это полезно для делегирования простых задач более дешевым/быстрым моделям:
# In ~/.hermes/config.yamldelegation:model:"google/gemini-flash-2.0"# Cheaper model for subagentsprovider:"openrouter"# Optional: route subagents to a different provider
Если этот параметр опущен, субагенты используют ту же модель, что и родительский.
Советы по выбору набора инструментов
Параметр toolsets определяет, к каким инструментам имеет доступ субагент. Выбирайте исходя из задачи:
Шаблон набора инструментов
Вариант использования
["terminal", "file"]
Работа с кодом, отладка, редактирование файлов, сборки
["web"]
Исследования, проверка фактов, поиск документации
["terminal", "file", "web"]
Полнофункциональные задачи (по умолчанию)
["file"]
Анализ только для чтения, проверка кода без выполнения
["terminal"]
Системное администрирование, управление процессами
Определенные наборы инструментов блокируются для субагентов независимо от того, что вы указываете:
- delegation — заблокировано для конечных субагентов (по умолчанию). Сохраняется для дочерних элементов role="orchestrator", ограниченных max_spawn_depth — см. Ограничение глубины и вложенная оркестровка ниже.
- clarify — субагенты не могут взаимодействовать с пользователем
- memory — запись в общую постоянную память не производится.
- code_execution — дети должны рассуждать шаг за шагом.
- send_message — отсутствие кроссплатформенных побочных эффектов (например, отправка сообщений Telegram)
Макс. итераций
У каждого субагента есть лимит итераций (по умолчанию: 50), который определяет, сколько циклов вызова инструмента может потребоваться:
delegate_task(goal="Quick file check",context="Check if /etc/nginx/nginx.conf exists and print its first 10 lines",max_iterations=10# Simple task, don't need many turns)
Дочерний тайм-аут
Субагенты уничтожаются как застрявшие, если они молчат более delegation.child_timeout_seconds секунд настенных часов. Значение по умолчанию — 600 (10 минут). В более ранних версиях это значение было увеличено с 300, поскольку модели, основанные на аргументации, для нетривиальных исследовательских задач, уничтожались на полпути. Настройте его для каждой установки:
delegation:child_timeout_seconds:600# default
Уменьшите его для быстрых локальных моделей; поднимите его для моделей медленного рассуждения при решении сложных задач. Таймер сбрасывается каждый раз, когда дочерний элемент выполняет вызов API или инструмента — только действительно бездействующие работники инициируют уничтожение.
💡 Tip
Диагностический дамп при тайм-ауте нулевого вызова
Если время ожидания субагента истекло после выполнения **нулевых** вызовов API (обычно из-за недоступности поставщика, сбоя аутентификации или отклонения схемы инструмента), `delegate_task` записывает в `~/.hermes/logs/subagent-timeout--.log` структурированную диагностику, содержащую снимок конфигурации субагента, трассировку разрешения учетных данных и любые ранние сообщения об ошибках. Гораздо проще выявить первопричину, чем в предыдущем случае с тайм-аутом.
Мониторинг запущенных субагентов (/agents)
TUI предоставляет наложение /agents (псевдоним /tasks), которое превращает рекурсивное разветвление delegate_task в первоклассную поверхность аудита:
Живое древовидное представление запущенных и недавно завершенных субагентов, сгруппированных по родительскому элементу.
Стоимость каждого филиала, токен и объединение файлов.
Элементы управления убийством и паузой — отмените конкретный субагент в процессе выполнения, не прерывая его братьев и сестер.
Последующий обзор: просматривайте пошаговую историю каждого субагента даже после того, как он вернулся к родительскому агенту.
Классический интерфейс командной строки просто печатает /agents как текстовую сводку; TUI — это то место, где сияет накладка. См. TUI — команды слэша.
Ограничение глубины и вложенная оркестровка
По умолчанию делегирование является плоским: родительский элемент (глубина 0) порождает дочерние элементы (глубина 1), и эти дочерние элементы не могут делегировать дальше. Это предотвращает неконтролируемое рекурсивное делегирование.
Для многоэтапных рабочих процессов (исследование → синтез или параллельная оркестровка подзадач) родитель может создавать дочерние элементы оркестратора, которые могут делегировать своих собственных исполнителей:
delegate_task(goal="Survey three code review approaches and recommend one",role="orchestrator",# Allows this child to spawn its own workerscontext="...",)
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, конфигурацию поставщика и пул учетных данных (включение ротации ключей при ограничениях скорости).
Делегирование против выполнения_кода
Фактор
делегат_задача
код_выполнения
Рассуждение
Полный цикл рассуждений LLM
Просто выполнение кода Python
Контекст
Свежий изолированный разговор
Никаких разговоров, только сценарий
Доступ к инструментам
Все неблокируемые инструменты с рассуждениями
7 инструментов через RPC, без рассуждений
Параллелизм
3 параллельных субагента по умолчанию (настраиваемые)
Одиночный сценарий
Лучший вариант
Сложные задачи, требующие решения
Механические многоступенчатые трубопроводы
Стоимость токена
Высшее (полный цикл LLM)
Нижний (возвращается только стандартный вывод)
Взаимодействие с пользователем
Нет (субагенты не могут уточнить)
Нет
Практическое правило: Используйте delegate_task, когда подзадача требует рассуждения, суждения или многоэтапного решения проблемы. Используйте execute_code, когда вам нужна механическая обработка данных или сценарии рабочих процессов.
Конфигурация
# In ~/.hermes/config.yamldelegation:max_iterations:50# Max turns per child (default: 50)# max_concurrent_children: 3 # Parallel children per batch (default: 3)# max_spawn_depth: 1 # Tree depth (1-3, default 1 = flat). Raise to 2 to allow orchestrator children to spawn leaves; 3 for three levels.# orchestrator_enabled: true # Disable to force all children to leaf role.model:"google/gemini-3-flash-preview"# Optional provider/model overrideprovider:"openrouter"# Optional built-in provider# Or use a direct custom endpoint instead of provider:delegation:model:"qwen2.5-coder"base_url:"http://localhost:1234/v1"api_key:"local-key"
:::совет
Агент автоматически осуществляет делегирование в зависимости от сложности задачи. Вам не нужно явно просить его о делегировании — он сделает это, когда это имеет смысл.