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

008: Агент/Вывод

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

Система агентов поддерживает две формы вывода: промежуточные результаты Вызовов Инструментов, записываемые в контекст, и Финальный Вывод всего итеративного процесса.

Запись в контекст с помощью Пути Вывода

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

Хотя любое Сообщение с Данными может служить черновиком для рабочего процесса, мета-свойство Путь Вывода в Вызове является основным механизмом для записи в него. Когда выполняется Вызов Инструмента с этим свойством, система добавляет его результат в контекст как новое сообщение.

Это новое сообщение является стандартным Сообщением с Данными, но оно включает в себя два дополнительных элемента метаданных, которые скрыты от LLM:

  • _call: Исходный Вызов Инструмента, который сгенерировал этот вывод.
  • _date: Временная метка в формате ISO, указывающая, когда был записан вывод.
  • _outputMethod: Метод, указанный в исходном вызове, который определяет, как эти данные должны быть объединены с другими данными.

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

Определение Пути Вывода

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

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

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

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

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

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

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

Динамическое разрешение переменных

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

Когда необходимо разрешить Ссылку на Переменную, например †data.user.name, движок ищет по сообщениям контекста в обратном хронологическом порядке (от новых к старым).

  • Если обработчик находит сообщение для целевого пути с _outputMethod равным set (или без метода, так как set является значением по умолчанию), он немедленно останавливается. Значение этого сообщения является конечным, и все более старые сообщения для этого пути игнорируются. Это поведение называется «побеждает последняя запись».
  • Если обработчик находит сообщения с методами, такими как merge, push или concat, он продолжает поиск назад, собирая все такие сообщения, пока не достигнет сообщения с set или начала контекста. Затем он восстанавливает конечное значение, применяя эти собранные операции в хронологическом порядке (от старых к новым).

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

Пример: Добавление и разрешение

1. Начальное состояние

Контекст начинается с исходного сообщения data.

[
  {
    "type": "data",
    "data": { "user": { "name": "Alex", "status": "active" } }
  }
]

2. Выполнение вызова инструмента

Вызывается инструмент для обновления статуса пользователя.

// Выполняемый вызов
{
  "_tool": "updateUserStatus",
  "newStatus": "inactive",
  "_outputPath": "†data.user.status"
}

3. Контекст после выполнения

Движок добавляет новое сообщение с выводом, которое включает метаданные о вызове, его сгенерировавшем.

[
  // Исходное сообщение с данными
  {
    "type": "data",
    "data": { "user": { "name": "Alex", "status": "active" } }
  },
  // Добавленное сообщение вывода из вызова
  {
    "type": "data",
    "data": { "user": { "status": "inactive" } },
    "_call": {
      "_tool": "updateUserStatus",
      "newStatus": "inactive",
      "_outputPath": "†data.user.status"
    },
    "_date": "2025-10-26T12:00:00Z"
  }
]

4. Разрешение переменной

  • Для разрешения †data.user.status движок сначала проверяет последнее сообщение. Он находит user.status и возвращает "inactive".
  • Для разрешения †data.user.name движок проверяет последнее сообщение, не находит user.name, затем проверяет предыдущее сообщение. Он находит его там и возвращает "Alex"

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

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

Вызовы без Пути Вывода

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

Эфемерные рассуждения для скрытых вызовов

Для скрытого вызова отсутствие _outputPath позволяет ему функционировать как эфемерный шаг рассуждения — «мысль», которая информирует последующие действия в том же ходу, но не сохраняется в постоянное Состояние. Это мощный метод структурирования процесса рассуждений LLM.

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

«Выполнил и забыл» для явных вызовов

Для явного вызова Действия отсутствие _outputPath сигнализирует об операции «выполнил и забыл». Цикл Исполнения вызовет Действие, но не будет ждать результата и не сохранит его в контексте.

Это полезно для побочных эффектов, когда возвращаемое значение не требуется для продолжения текущего рабочего процесса. Типичные примеры:

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

Взаимодействие с другими системами

От эфемерных выводов к постоянному состоянию

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

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