Акты Становления

012: Агент/Делегат

Протокол для изоляции контекста выполнения. Вызывается свойством _delegate объекта Вызов и выполняет Действие или новый Запрос в изолированной среде, при этом свойство _scopes обеспечивает контролируемый доступ к родительскому контексту.

Паттерн Делегирования решает критическую проблему масштабирования и композиции возможностей агента. Он предоставляет мощный механизм для выполнения Инструментов в изолированных средах (песочницах), предотвращая смешение контекстов и обеспечивая настоящую многоразовость использования. Делегируя Вызов внешнему делегату — будь то определение другого Запроса или Действие в подзапросе — система может создавать сложные агентные поведения из автономных, независимо разработанных компонентов.

Проблема: Монолитные Инструменты и Смешение Контекстов

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

  1. Большие схемы: У LLM есть практические ограничения на сложность схем, которые они могут обработать в одном запросе. Объединение множества сложных Инструментов может превысить эти лимиты, мешая LLM правильно обрабатывать доступные опции.
  2. Смешение контекстов: Когда все Инструменты работают в одном контексте, LLM может поддаться влиянию нерелевантной информации, что приводит к неверному выбору Инструмента или заполнению параметров.
  3. Отсутствие многоразовости: Инструмент, определённый для одного агента, нелегко перенести к другому, не захватив с собой весь его контекст.

Делегирование решает эти проблемы, вводя Изоляцию через Делегирование — способ передать Вызов во внешнюю, изолированную среду выполнения.

Вызов Делегата

Сигналом к делегированному выполнению служит свойство _delegate в схеме Инструмента. Это свойство указывает системе рассматривать Вызов не как встроенную операцию, а как запрос к внешнему делегату.

Свойство _delegate является строкой и может использоваться двумя способами:

  • Сохранённый, многоразовый Запрос{href="./001_agent_request.md"} — это наиболее распространённая форма Идеи. Паттерн Делегирования является основным механизмом для композиции этих Идей в более сложные системы. Подробнее см. в 101: Концепция/Идея.

    Ссылка на сохранённый Запрос: Строка может быть путём или URL к JSON-файлу, который определяет автономный Запрос — JSON-объект, содержащий свойства context и schema. Это позволяет Инструменту делегировать своё выполнение совершенно отдельному набору инструкций.

  • Создание анонимного делегата: Строковый литерал 'anonymous' сигнализирует о создании анонимного делегата. Это используется для создания новой, изолированной среды выполнения для Вызова Инструмента (скрытого или явного) без необходимости в промежуточном JSON-файле. Он автоматически создаёт новую, пустую область видимости для Вызова.

Выполнение в Изолированной Среде

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

Здесь Область видимости контекста становится критически важной. Свойство _scopes в схеме Инструмента действует как мост, явно объявляя, какие части родительского контекста должны быть «импортированы» в выделенное рабочее пространство делегата. Это даёт родительскому агенту точный контроль над тем, что может видеть делегат, предотвращая смешение контекстов и обеспечивая настоящую инкапсуляцию.

Обработка Больших Схем

Делегирование также предлагает решение для управления Инструментами с очень большими или сложными схемами вывода. Вместо включения огромной схемы _output в основной запрос, что потенциально может вытеснить другие инструменты, Инструмент можно определить только с его входными параметрами и указателем _delegate.

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

Стратегии Разрешения Делегатов

Инструмент становится Делегатом просто за счёт включения свойства _delegate в свою схему. Это сигнализирует, что Вызов должен быть делегирован. Ключевой вопрос — когда это делегирование разрешается. Система поддерживает две стратегии, позволяя найти компромисс между строгой безопасностью и динамической гибкостью.

1. Разрешение во время выполнения (по умолчанию)

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

Этот метод открывает мощную парадигму, невозможную в традиционном коде: LLM действует как интеллектуальный связующий слой. Агент может сгенерировать Вызов с параметрами, которые не идеально соответствуют ожидаемой схеме input делегата. Во время выполнения система собирает контекст делегата и предоставленные вызывающим входы, и LLM в подзапросе получает задачу устранить этот разрыв.

Это значительное преимущество, так как оно позволяет делегатам обновляться и развиваться независимо. Даже если делегат изменит структуру своих входных данных, вызывающие агенты не сломаются сразу. LLM попытается адаптировать старый формат Вызова к новой схеме input, обеспечивая уровень устойчивости и слабой связанности, уникальный для этой архитектуры.

Процесс выглядит следующим образом:

  1. Агент генерирует Вызов к модульному Инструменту.
  2. Исполнитель видит свойство _delegate и инициирует процесс делегирования.
  3. Сборка контекста: Исполнитель получает файл определения делегата (если он не анонимный) и собирает базовый контекст. Затем он использует _scopes для добавления контекста вызывающего.
  4. Сопоставление входов: params из Вызова упаковываются в Входное Сообщение и добавляются в контекст. Именно здесь вступает в игру «связующая» способность LLM, так как она будет использовать эти входные данные для выполнения логики делегата, даже если схемы не совпадают идеально.
  5. Выполнение: Создается новый, изолированный Запрос с объединенным контекстом. Результат возвращается как вывод исходного Вызова.

2. Предварительное разрешение (опционально)

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

В этом режиме система предварительно загружает определение Запроса делегата и объединяет его схему input со схемой параметров Инструмента. Это позволяет LLM агента видеть точные требования делегата с самого начала, гарантируя, что сгенерированный Вызов будет идеально сформирован и типобезопасен. Важно отметить, что это предварительное слияние может также включать схему _output делегата, обеспечивая строгий контракт для ожидаемого результата.

Этот подход обеспечивает безопасность традиционных контрактов API, где и входы, и выходы известны и проверены. Он жертвует гибкостью разрешения во время выполнения и лучше всего подходит для критически важных, чётко определенных интеграций, где слабая связанность не является желаемой характеристикой.

Пример: Гибкое сопоставление входов во время выполнения

Этот пример демонстрирует концепцию «LLM как связующее звено», где делегат может быть успешно выполнен, даже если Вызов вызывающего агента не идеально соответствует входной схеме делегата. Это поведение разрешения во время выполнения, используемое по умолчанию.

Точка зрения вызывающего

Агенту-оркестратору нужно отправить сообщение. Он знает об Инструменте sendMessage, который делегирует задачу внешнему агенту, идентифицированному по URL. На основе своего контекста он генерирует Вызов с параметрами userId и text, не зная внутренних требований делегата.

// ВЫЗОВ, СГЕНЕРИРОВАННЫЙ ОРКЕСТРАТОРОМ
{
  "_tool": "sendMessage",
  "_delegate": "http://example.com/agents/speaker_EN",
  "userId": "u_123",
  "text": "Hello, world!"
}

Точка зрения делегата и итоговый контекст

Делегат speaker_EN — это отдельное определение Запроса. Во время выполнения система упаковывает параметры вызывающего в свойство input Входного Сообщения. Важно, что она также включает собственную схему делегата, которая не соответствует предоставленным входным данным (input). Теперь LLM делегата отвечает за преодоление этого семантического разрыва, интеллектуально сопоставляя userId с recipientId и text с messageBody. Это преобразование не программное; это семантическое сопоставление, происходящее в скрытом пространстве LLM.

// ИТОГОВЫЙ КОНТЕКСТ ДЛЯ ПОДЗАПРОСА
[
  {
    "type": "system",
    "message": "You are an expert in messaging in English."
  },
  {
    "type": "input",
    // Это необработанные входные данные, предоставленные вызывающим агентом.
    "input": {
      "userId": "u_123",
      "text": "Hello, world!"
    },
    // Это ожидаемый формат входных данных для делегата
    "schema": {
      "type": "object",
      "properties": {
        "recipientId": { "type": "string" },
        "messageBody": { "type": "string" }
      }
    }
  }
]

Пример: Создатели музыки

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

Рассмотрим рабочий процесс с двумя специализированными делегатами: Композитором и Звукорежиссёром.

  • Звукорежиссёр — это низкоуровневый эксперт. Это автономное определение Запроса, сосредоточенное на физике звука и знающее, как управлять синтезаторами для создания конкретных аудиоданных.

  • Композитор — это специалист среднего уровня. Его основная задача — создать песню. Он использует свои собственные встроенные инструменты для генерации мелодии и музыкальной структуры. Чтобы реализовать эту идею, он делает Вызовы к делегату Звукорежиссёр для синтеза реальных звуков.

Эта двухуровневая иерархия — распространённый паттерн. Однако истинная сила делегатов заключается в их динамической, управляемой задачами композиции.

Такая компоновка обеспечивает гибкую оркестрацию. Высокоуровневый Продюсер может делегировать задачу Композитору, который, в свою очередь, использует Звукорежиссёра. Однако Продюсер также может обойти Композитора и взаимодействовать со Звукорежиссёром напрямую для выполнения конкретных задач.

Продюсер

Композитор

Звукорежиссёр

Теперь давайте представим высокоуровневого агента-Продюсера. Цель Продюсера — создать готовую запись. В зависимости от конкретной задачи, Продюсер может по-разному организовывать своих делегатов:

  • Иерархическая оркестрация: Для создания песни Продюсер может сделать один Вызов к делегату Композитор. Продюсер даёт общие указания («Мне нужна грустная баллада»), а Композитор выполняет весь свой внутренний рабочий процесс, включая вложенные Вызовы к Звукорежиссёру. В этом случае Продюсеру не нужно знать о существовании Звукорежиссёра.

  • Параллельная оркестрация: Если Продюсеру также нужны конкретные звуковые эффекты для записи (например, шумы или эмбиент), он может делать Вызовы напрямую к делегату Звукорежиссёр для этих задач, параллельно с Вызовом к Композитору.

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

От Делегирования к Областям Видимости

Делегированное выполнение предоставляет изолированную среду, но чтобы быть полезным, делегату нужен способ получать информацию от своего родителя. Свойство _scopes обеспечивает этот механизм, действуя как контролируемый мост между контекстами. Особенности работы этого моста определяются паттерном Область видимости контекста.