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

008: Агент/Переменные

Строка со специальным синтаксисом (†<kind>.<path>), используемая в параметрах Вызова инструмента для динамической ссылки на значение из контекста агента.

Переменные основаны на системе Данных, чтобы обеспечить динамические потоки данных. Они делают структурированную информацию интерактивной с помощью двух основных функций:

  • Чтение: Ссылка на значение, существующее в контексте агента (например, сообщение Ввода или Состояния), без необходимости прямого копирования данных в параметры Вызова инструмента.
  • Запись: Сохранение результата в объекте Данных (чаще всего в Состоянии), чтобы его значение было доступно на последующих шагах цикла агента.

Чтение из контекста

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

Ссылка представляет собой простой строковый синтаксис с префиксом в виде кинжала (). Синтаксис: †<kind>.<path>, где <kind> — это тип сообщения Данных (например, state, input), а <path> — это путь к желаемому значению в точечной нотации.

Параметры инструмента с использованием переменных

{
  "_tool": "greetUser",
  "userName": "†input.userName"
}

Эквивалентный код на Typescript

greetUser({
  userName: input.userName,
});

Запись в контекст

Чтобы сохранить результат работы инструмента, Вызов может включать мета-свойство _outputPath. Эта строка — путь вывода — указывает движку исполнения, куда поместить результат, делая его доступным для последующих шагов или будущих итераций цикла. Обычно используется путь, указывающий на объект Состояния (например, †state.user.summary).

_outputPath можно определить двумя способами, что позволяет гибко контролировать поведение инструмента.

Динамический путь (определяется LLM)

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

// Схема инструмента разрешает любую строку для _outputPath
{
  "_outputPath": {
    "type": "string",
    "description": "Путь для сохранения сводки пользователя.",
    "pattern": "^†"
  }
}

Предписанный путь (жёстко заданный)

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

// Схема инструмента закрепляет за _outputPath конкретное значение
{
  "_outputPath": {
    "type": "string",
    "const": "†state.user.summary"
  }
}

Декларативная связь

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

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

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

Альтернативные пути (ветвление)

Использование || в _outputPath позволяет инструменту объявлять возможные исходы. Внутренняя логика инструмента затем определяет, по какому пути записывать результат.

// Если `verifyUser` выполняется успешно, результат записывается в `state.user.verified`;
// в противном случае — в `state.user.failed`.
{
  "_tool": "verifyUser",
  "userId": "perfect-stranger",
  "_outputPath": "†state.user.verified || †state.user.failed"
}

Параллельные пути (разветвление)

Использование && в _outputPath указывает движку выполнить разветвление, записывая один и тот же вывод по нескольким путям одновременно.

// Одновременная запись в объекты `user` и `audit` в состоянии.
{
  "_tool": "generateSummary",
  "text": "Long body of text here...",
  "_outputPath": "†state.user.summary && †state.audit.summary"
}

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

Композиция

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

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

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

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

От эфемерных связей к постоянной памяти

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

Следующий документ, 009: Агент/Состояние, описывает протокол для управления этим постоянным состоянием.