Skip to content

Обработка субагентов

Что вы освоите после этого урока

  • Поймёте, почему DCP автоматически отключается в сессиях субагентов
  • Узнаете о различиях в стратегиях использования токенов между субагентами и основным агентом
  • Научитесь избегать проблем при использовании функций DCP в субагентах

Ваша текущая проблема

Вы могли заметить: в некоторых диалогах OpenCode функция обрезки DCP как будто «перестаёт работать» — вызовы инструментов не очищаются, статистика экономии токенов не меняется. Это может происходить при использовании определённых функций OpenCode, таких как проверка кода, глубокий анализ и других.

Это не означает, что DCP сломался. Просто эти функции используют механизм субагентов (Subagent), и DCP имеет особую обработку для них.

Что такое субагент

Что такое субагент (Subagent)?

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

Типичные сценарии использования:

  • Проверка кода: Основной агент запускает субагент, который внимательно читает несколько файлов, анализирует проблемы и возвращает краткий список найденных ошибок
  • Глубокий анализ: Основной агент запускает субагента, который выполняет множество вызовов инструментов и логических рассуждений, а затем возвращает ключевые находки

С технической точки зрения, сессия субагента имеет свойство parentID, указывающее на родительскую сессию.

Поведение DCP в отношении субагентов

DCP автоматически отключает все функции обрезки в сессиях субагентов.

Почему DCP не обрезает субагентов?

За этим стоит важная концепция дизайна:

РольСтратегия использования токеновОсновная цель
Основной агентЭффективное использование токеновПоддержание контекста в длинных диалогах, снижение затрат
СубагентСвободное использование токеновСоздание богатой информации для сводки основного агента

Ценность субагента заключается в его способности «тратить токены ради качества информации» — через многочисленные вызовы инструментов и детальный анализ он предоставляет основному агенту высококачественную сводку. Если DCP начнёт обрезать вызовы инструментов в субагенте, это может привести к:

  1. Потере информации: Детальный процесс анализа субагента будет удалён, и невозможно будет создать полную сводку
  2. Снижению качества сводки: Основной агент получит неполную сводку, что повлияет на качество итоговых решений
  3. Нарушению исходного замысла: Субагент специально разработан для принципа «не жалеть токены ради качества»

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

Как DCP обнаруживает субагент

DCP определяет, является ли текущая сессия субагентом, следующим образом:

typescript
// lib/state/utils.ts:1-8
export async function isSubAgentSession(client: any, sessionID: string): Promise<boolean> {
    try {
        const result = await client.session.get({ path: { id: sessionID } })
        return !!result.data?.parentID  // Если есть parentID, значит это субагент
    } catch (error: any) {
        return false
    }
}

Моменты обнаружения:

  • При инициализации сессии (ensureSessionInitialized())
  • Перед каждым преобразованием сообщения (createChatMessageTransformHandler())

Поведение DCP в сессиях субагента

Обнаружив субагента, DCP пропускает следующие функции:

ФункцияОбычная сессияСессия субагентаМесто пропуска
Внедрение системного промпта✅ Выполняется❌ Пропускаетсяhooks.ts:26-28
Стратегия автоматической обрезки✅ Выполняется❌ Пропускаетсяhooks.ts:64-66
Внедрение списка инструментов✅ Выполняется❌ Пропускаетсяhooks.ts:64-66

Реализация кода (lib/hooks.ts):

typescript
// Обработчик системного промпта
export function createSystemPromptHandler(state: SessionState, ...) {
    return async (_input: unknown, output: { system: string[] }) => {
        if (state.isSubAgent) {  // ← Обнаружение субагента
            return               // ← Возврат без внедрения описания инструментов обрезки
        }
        // ... обычная логика
    }
}

// Обработчик преобразования сообщений
export function createChatMessageTransformHandler(...) {
    return async (input: {}, output: { messages: WithParts[] }) => {
        await checkSession(client, state, logger, output.messages)

        if (state.isSubAgent) {  // ← Обнаружение субагента
            return               // ← Возврат без выполнения любой обрезки
        }

        // ... обычная логика: дедупликация, перезапись, очистка ошибок, внедрение списка инструментов и т.д.
    }
}

Практическое сравнение случаев

Случай 1: Сессия основного агента

Сценарий: Вы общаетесь с основным агентом и просите его проанализировать код

Поведение DCP:

Пользователь: "Проанализируй утилитарные функции в src/utils.ts"

[Основной агент] читает src/utils.ts

[Основной агент] анализирует код

Пользователь: "Теперь проверь src/helpers.ts"

DCP обнаруживает паттерн повторного чтения

DCP помечает первое чтение src/utils.ts как подлежащее обрезке ✅

При отправке контекста в LLM содержимое первого чтения заменяется плейсхолдером

✅ Экономия токенов

Случай 2: Сессия субагента

Сценарий: Основной агент запускает субагента для глубокой проверки кода

Поведение DCP:

Пользователь: "Глубоко проверь все файлы в src/"

[Основной агент] обнаруживает сложную задачу, запускает субагента

[Субагент] читает src/utils.ts

[Субагент] читает src/helpers.ts

[Субагент] читает src/config.ts

[Субагент] читает больше файлов...

DCP обнаруживает сессию субагента

DCP пропускает все операции обрезки ❌

[Субагент] создаёт детальный результат проверки

[Субагент] возвращает краткую сводку основному агенту

[Основной агент] генерирует итоговый ответ на основе сводки

Часто задаваемые вопросы

Q: Как подтвердить, что текущая сессия является сессией субагента?

A: Вы можете подтвердить это следующими способами:

  1. Посмотрите логи DCP (если включён режим отладки):

    2026-01-23T10:30:45.123Z INFO state: session ID = abc-123
    2026-01-23T10:30:45.124Z INFO state: isSubAgent = true
  2. Наблюдайте за характеристиками диалога:

    • Субагенты обычно запускаются при обработке сложных задач (например, глубокий анализ, проверка кода)
    • Основной агент может показывать сообщение «Запускается субагент» или аналогичное
  3. Используйте команду /dcp stats:

    • В сессии субагента вызовы инструментов не обрезаются
    • В статистике токенов количество «обрезанных» элементов равно 0

Q: Не приведёт ли полный отказ от обрезки в субагентах к большому расходу токенов?

A: Нет. Причины следующие:

  1. Субагенты недолговечны: Субагент завершает работу после выполнения задачи, в отличие от основного агента, который ведёт длинные диалоги
  2. Субагент возвращает сводку: Основному агенту передаётся краткая сводка, которая не увеличивает нагрузку на контекст основного агента
  3. Разные цели дизайна: Цель субагента — «тратить токены ради качества», а не «экономить токены»

Q: Можно ли принудительно заставить DCP обрезать субагента?

A: Нет, и не следует. DCP специально разработан, чтобы позволить субагентам полностью сохранять контекст для создания качественных сводок. Принудительная обрезка может:

  • Привести к неполноте информации в сводке
  • Повлиять на качество решений основного агента
  • Нарушить концепцию дизайна субагентов в OpenCode

Q: Учитывается ли использование токенов в сессиях субагента в статистике?

A: Сессии субагентов сами по себе не учитываются в статистике DCP. DCP отслеживает экономию токенов только в сессиях основного агента.

Итоги урока

  • Обнаружение субагента: DCP определяет сессии субагента через проверку session.parentID
  • Автоматическое отключение: В сессиях субагента DCP автоматически пропускает все функции обрезки
  • Причина дизайна: Субагентам нужен полный контекст для создания качественных сводок, а обрезка может нарушить этот процесс
  • Границы использования: Субагенты не стремятся к эффективности токенов, а стремятся к качеству информации — это отличается от целей основного агента

Анонс следующего урока

В следующем уроке мы изучим Часто задаваемые вопросы и устранение неполадок.

Вы узнаете:

  • Как исправить ошибки конфигурации
  • Как включить отладочные логи
  • Частые причины, почему токены не уменьшаются
  • Ограничения сессий субагентов

Приложение: Ссылка на исходный код

Нажмите, чтобы развернуть расположение исходного кода

Время обновления: 2026-01-23

ФункцияПуть к файлуНомера строк
Функция обнаружения субагентаlib/state/utils.ts1-8
Инициализация состояния сессииlib/state/state.ts80-116
Обработчик системного промпта (пропуск субагента)lib/hooks.ts26-28
Обработчик преобразования сообщений (пропуск субагента)lib/hooks.ts64-66
Определение типа SessionStatelib/state/types.ts27-38

Ключевые функции:

  • isSubAgentSession(): Обнаружение субагента через session.parentID
  • ensureSessionInitialized(): Обнаружение субагента при инициализации состояния сессии
  • createSystemPromptHandler(): Пропуск внедрения системного промпта в сессиях субагента
  • createChatMessageTransformHandler(): Пропуск всех операций обрезки в сессиях субагента

Ключевые константы:

  • state.isSubAgent: Флаг субагента в состоянии сессии