Благодаря наблюдаемости мы можем связать поведение агентов с реальными бизнес-задачами, выявлять узкие места в производительности и более предсказуемо контролировать расходы.
Начиная работу с наблюдаемостью ИИ-агентов, мы обычно используем базовые вещи: сбор спанов, вызовов инструментов и количества токенов, как было описано в предыдущей статье по наблюдаемости.
В продакшене наблюдаемость — это нечто большее, чем просто сырые события. Она помогает связать поведение агента с реальными бизнес-задачами, находить узкие места в производительности и прогнозировать расходы.
Когда пользователи взаимодействуют с нашими агентами, нам нужны ответы на реальные вопросы:
- Какой пользователь ждал ответа 35 секунд?
- Почему агент инициировал четыре поиска отелей вместо одного?
- Почему составление одного плана поездки потребовало в десять раз больше токенов, чем ожидалось?
- Как отслеживать внутренние запросы к базе данных внутри пользовательских инструментов?
Сегодня мы выводим наш планировщик путешествий на новый уровень. Мы научимся внедрять бизнес-метаданные с помощью propagateAttributes(), диагностировать логические циклы, аудировать утечки токенов с помощью wrapFunctionWithSpan(), инструментировать бэкенд-сервисы с помощью декораторов и настраивать защитные механизмы конфиденциальности для продакшена.
Давайте реализуем это в реальном проекте!
Начало работы
Если вы хотите писать код вместе со мной, я рекомендую клонировать репозиторий проекта и перейти в его папку:
Проверьте доступные ветки:
Вы увидите две ветки:
- article-start: Базовый агент из нашей первой статьи.
- main: Завершенный агент с продвинутой наблюдаемостью.
Чтобы следовать по шагам, переключитесь на стартовую ветку:
Но перед началом нам нужны два ключа API:
- Ключ API Google AI Studio для запуска модели Gemini.
- Ключ интеграции Progress Agent Engineering для сбора трассировок и спанов.
Создайте файл .env в корне проекта:
Убедитесь, что агент запускается:
Теперь давайте внедрим бизнес-метаданные в наши трассировки.
В нашей предыдущей статье Progress Agent Engineering собирал спаны под именем сервиса family-travel-planner. Но в загруженной продакшн-среде ваш список трассировок получает сотни выполнений каждую минуту.
Искать неудачный запуск по исходной временной метке или случайным идентификаторам трассировок вроде 4bf92f3577b3... непросто, потому что, когда техподдержка получает тикет, они слышат: «Пользователь usr_4102 с VIP-уровнем пытался спланировать поездку на Ибицу, и запрос превысил тайм-аут».
SDK Progress помогает решить эту проблему с помощью propagateAttributes(). Представьте это как общий контекст для вашего выполнения. Любые теги, которые вы внедряете, автоматически передаются во все дочерние спаны, созданные во время этого запроса, включая потоки Genkit, вызовы модели Gemini и выполнение пользовательских инструментов.
Откройте src/app.ts и оберните вызов планирования поездки в propagateAttributes():
Теперь нам не нужно передавать идентификаторы пользователей через каждый аргумент функции или управлять низкоуровневыми объектами спанов OpenTelemetry.
Запустите проект из терминала:
Теперь откройте панель мониторинга Progress по адресу и перейдите в Observe > Tracing:
- Нажмите на Фильтры (Filters) на верхней панели.
- Выберите Тег (Tag), установите условие содержать (contains) и введите tier:vip (или user:usr_4102).
- Панель мониторинга отфильтровывает ненужный трафик и показывает только подходящие запуски.
Нажмите на выполнение, а затем выберите любой дочерний спан инструмента, например find-hotels:
Спан find-hotels отображает наши бизнес-теги (user:usr_4102, tier:vip, destination:Ibiza). Теги автоматически распространились по всему дереву выполнения.
До сих пор мы прикрепляли бизнес-контекст к нашим трассировкам. Теперь давайте посмотрим, что происходит, когда инструменты возвращают неожиданные данные и агенты застревают в циклах.
Диагностика логических циклов с помощью визуализации трассировок
ИИ-агенты работают в итеративном цикле: модель читает промпт, вызывает инструмент, просматривает вывод инструмента и решает, что делать дальше.
Что происходит, когда инструмент возвращает пустые данные?
Предположим, пользователь просит роскошный пляжный отель на Ибице дешевле 30 евро за ночь. Наш инструмент поиска отелей проверяет свои записи, ничего не находит и возвращает пустой массив: [].
Для нас [] — это допустимый результат. Но для языковой модели пустой массив вызывает недоумение. Модель предполагает, что параметры ее поиска были немного неточными, поэтому она корректирует ключевые слова и снова отправляет запрос. Она вызывает инструмент во второй раз, снова получает [] и вызывает его в третий и четвертый раз.
Этот паттерн называется циклом рассуждений агента. Агент повторяет вызовы инструментов без продвижения вперед, тратя время выполнения и умножая затраты на токены.
Когда агент зацикливается, визуализация трассировки в Observe > Tracing выявляет явные предупреждающие знаки:
Вы можете определить цикл рассуждений по трем четким признакам:
- Повторяющиеся спаны инструментов: длинная лестница из одинаковых вызовов инструментов.
- Растущая задержка: общая продолжительность увеличивается с 3 секунд до более чем 40 секунд.
- Растущее использование токенов: каждая попытка несет в себе все предыдущие неудачные попытки в истории промптов.
Мы исправляем это, комбинируя два защитных механизма:
- Лимиты шагов (maxTurns): установите жесткое ограничение на количество ходов, чтобы Genkit останавливал выполнение, если агент зацикливается.
- Защитные ответы инструментов: никогда не возвращайте тихий пустой массив []. Возвращайте понятное сообщение, объясняющее, почему нет результатов, и инструктируйте модель не повторять попытку.
Откройте src/tools/hotels.ts и обновите логику поиска с помощью схемы защитного ответа:
Затем откройте src/agent.ts и установите maxTurns: 4 для вызова генерации:
Когда инструмент возвращает status: 'NO_MATCHES' с явными инструкциями, языковая модель немедленно останавливается. Вместо того чтобы зацикливаться, она предлагает пользователю скорректировать свой бюджет.
Запустите проект снова. Откройте трассировку выполнения на панели мониторинга инструмента наблюдаемости Progress:
Посмотрите на ход выполнения:
- Ход 1 (Сбор инструментов): Gemini анализирует запрос и вызывает find-flights, find-hotels и find-activities.
- Ход 2 (Синтез): Gemini получает результаты работы инструментов и строит финальный маршрут.
- Чистое выполнение: поток завершается за два хода с общим количеством спанов восемь за 3,3 секунды. Никаких циклов, никаких повторных попыток.
Мы защитили нашего агента от циклов рассуждений. Теперь давайте рассмотрим, как тяжелые полезные данные инструментов вызывают утечки токенов и как отслеживать внутренние операции с данными.
Аудит утечек токенов и санитизация полезных данных инструментов
В руководствах инструменты возвращают чистый, минималистичный JSON. В реальных приложениях инструменты запрашивают партнерские API или базы данных.
Один вызов API отелей часто возвращает от 30 до 50 результатов. Каждый объект отеля включает в себя идентификаторы базы данных, расшифровку налогов, коды запасов номеров, URL-адреса изображений и правила отмены.
Если ваш инструмент передает этот сырой объем данных обратно в Genkit, весь ответ размером более 20 КБ попадает в контекст модели. Поскольку агенты отправляют предыдущие результаты работы инструментов на каждом шаге, этот раздутый объем данных отправляется повторно при каждом последующем шаге.
Решение заключается в использовании паттерна передачи данных DTO (Data Transfer Object): всегда фильтруйте внешние данные, чтобы модель получала только те поля, которые ей нужны.
Genkit отслеживает вызовы инструментов верхнего уровня автоматически. Но как отслеживать внутренние операции, такие как обрезка данных или проверка локального кэша?
SDK Progress предоставляет функцию wrapFunctionWithSpan() для создания пользовательских дочерних спанов внутри любой функции.
Откройте src/tools/hotels.ts и добавьте санитизацию данных с помощью wrapFunctionWithSpan():
Когда запускается getHotelsForDestination(), она вызывает sanitizeHotelPayloadTraced() для сырых данных поставщика перед возвратом чистых результатов модели.
Обратите внимание на влияние на потребление токенов и производительность:
Запустите проект снова. На панели мониторинга Progress observability разверните диапазон (span) инструмента find-hotels:
Обратите внимание на новый дочерний диапазон:
- Внутри find-hotels появляется дочерний диапазон с именем sanitize-hotel-payload и типом TASK.
- В правой панели отображается тег operation:payload-sanitization.
- Диапазон автоматически наследует активные бизнес-теги (user:usr_4102, tier:vip).
Теперь вы можете измерять точную длительность логики очистки данных независимо от задержки внешней сети.
До сих пор мы инструментировали автономные функции. Теперь давайте рассмотрим, как инструментировать бэкенд-сервисы на основе классов с помощью декораторов.
Бэкенд-сервисы с @workflow и @task
Что происходит, когда нашему агенту необходимо использовать существующие бэкенд-сервисы, такие как платежные процессоры, менеджеры бронирования или базы данных инвентаря?
Progress SDK предоставляет декораторы TypeScript (@workflow и @task) для подключения методов класса непосредственно в активное дерево трассировки.
Создайте src/services/booking.ts:
Убедитесь, что в вашем tsconfig.json включен параметр "experimentalDecorators": true.
Благодаря добавлению @workflow и @task методы вашего сервиса отображаются как дочерние диапазоны в рамках активного выполнения. Вы можете быстро определить, была ли задержка вызвана моделью или внутренним запросом к базе данных.
До сих пор мы инструментировали уровни нашего приложения. Теперь давайте настроим защитные механизмы обеспечения конфиденциальности для продакшена.
Защитные механизмы конфиденциальности для продакшена с помощью traceContent
Наблюдаемость требует сбора телеметрии, но производственные системы должны защищать конфиденциальность пользователей.
В локальной разработке запись текста промптов, входных данных инструментов и выводов модели полезна для отладки. В продакшене пользователи вводят конфиденциальную информацию: имена путешественников, возраст детей и личные заметки.
В соответствии с нормативными актами о конфиденциальности, такими как GDPR, CCPA и SOC2, хранение незамаскированных персональных данных в системах телеметрии создает риски нарушения комплаенса.
Progress SDK предоставляет опцию traceContent в bootstrap.ts для элегантного решения этой проблемы.
Откройте bootstrap.ts и установите traceContent в зависимости от вашего окружения:
Когда задано NODE_ENV=production, параметр traceContent: false указывает SDK собирать время выполнения, иерархию диапазонов, имена инструментов, количество токенов и затраты, не допуская попадания исходного текста промптов и личных данных в облачные логи.
Запустите агента в продакшен-режиме:
В терминале появляется подтверждение того, что режим конфиденциальности активен:
Ваши трассировки записывают полные операционные метрики (задержку, количество токенов и иерархию диапазонов), сохраняя при этом конфиденциальность пользователей.
Заключение
Наблюдаемость — это то, что помогает нам превратить ИИ-эксперимент в надежную, готовую к продакшену программную систему. Сегодня мы рассмотрели пять основных практик наблюдаемости с помощью Progress SDK:
- Бизнес-метаданные: Мы использовали propagateAttributes() из платформы наблюдаемости Progress Agent Engineering для добавления контекста пользователя и сеанса во все дерево диапазонов.
- Предотвращение циклов: Мы объединили maxTurns и защитные оболочки инструментов, чтобы остановить циклы рассуждений агента.
- Аудит утечки токенов: Мы использовали DTO для обрезки полезных данных вендоров и отслеживали очистку с помощью wrapFunctionWithSpan().
- Инструментирование бэкенда: Мы использовали декораторы @workflow и @task для трассировки методов сервиса.
- Конфиденциальность в продакшене: Мы настроили traceContent для защиты конфиденциальных пользовательских данных в продакшене.
Применяя эти практики, вы можете создавать ИИ-агенты с уверенностью в том, что ваша система прозрачна, эффективна и экономична.
Начните бесплатно использовать платформу Progress Agent Engineering.
Попробовать сейчас
Приятной работы с наблюдаемостью!
Дополнительные ресурсы
- Часть 1: Добавление наблюдаемости в ИИ-агент Genkit с помощью Progress Agent Engineering
- Документация Genkit
- Платформа Progress Agent Engineering
- Документация по Progress TypeScript SDK












