Глава 2

Инструменты ИИ-агентов: как проектировать надежные функции

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

От задачи к работающей системе
  1. Архитектура ИИ-агентов: графы, ReAct и HITL
  2. Инструменты ИИ-агентов: контракты и безопасность
  3. Память ИИ-агентов: состояние, чекпойнтер и RAG
  4. Продакшн ИИ-агентов: надежность и наблюдаемость
Содержание страницыСхемы функций и структурная генерацияВалидация до выполненияДоверенный исполнитель: код, а не модельRead vs Write: разделение инструментовИдемпотентность, таймауты и ретраиГраница данных и инструкцийMCP, Skills и Plugins: протокол не дает правПример контракта инструмента

Схемы функций и структурная генерация

Модель не может выполнить код инструмента. Она возвращает структурированное описание вызова: имя функции и параметры. Чтобы это описание было корректным, вы должны передать модели схему функции: имя, описание, параметры и их типы.

Pydantic позволяет описать схему в виде Python-класса и автоматически генерировать JSON-схему. Это удобно для интеграции с LLM API. Однако важно помнить: структурная генерация не гарантирует истинность. Модель может вернуть валидный JSON с фактически неверными данными.

Схема — это контракт на уровне формата. Она гарантирует, что вызов будет передан в правильной структуре, но не гарантирует, что параметры имеют смысл. Проверка смысла — задача бизнес-логики.

  • Модель возвращает имя функции и параметры, но не выполняет ее.
  • Схема функции: имя, описание, параметры, типы.
  • Pydantic: описание схемы и генерация JSON-схемы.
  • Структурная генерация не гарантирует истинность данных.
  • Схема — контракт формата, а не смысла.

Валидация до выполнения

Прежде чем выполнить инструмент, необходимо проверить параметры. Сначала — формальная валидация по схеме: типы, обязательные поля, форматы. Затем — бизнес-проверки: например, есть ли у пользователя право на выполнение операции, не превышает ли сумма лимит.

Pydantic выполняет формальную валидацию при создании объекта. Бизнес-проверки должны выполняться в коде инструмента или в отдельном слое. Не полагайтесь на модель: она может выбрать инструмент, который не подходит для данного контекста.

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

  • Формальная валидация: типы, обязательные поля, форматы.
  • Бизнес-проверки: права, лимиты, допустимые значения.
  • Не полагайтесь на модель в вопросах безопасности.
  • Ошибка валидации должна быть понятной для модели.
  • Определите обязательные и опциональные параметры.
  • Добавьте проверку типов и форматов.
  • Реализуйте бизнес-проверки в коде инструмента.
  • Сформулируйте понятные сообщения об ошибках.

Доверенный исполнитель: код, а не модель

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

Например, если модель решила вызвать get_order_status, ваш код выполняет функцию get_order_status(**arguments). Модель не имеет прямого доступа к базе данных или файловой системе. Она может только предложить вызов, а вы решаете, выполнить его или нет.

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

  • Модель предлагает вызов, код выполняет.
  • Доверенный код контролирует доступ к ресурсам.
  • Дополнительные проверки: логирование, аутентификация, лимиты.
  • Модель не имеет прямого доступа к базе данных или файлам.
  1. Модель: выбрать инструмент get_order_status
  2. Код: проверить параметры
  3. Код: выполнить get_order_status('12345')
  4. Код: вернуть результат модели
  5. Модель: сформировать ответ

Read vs Write: разделение инструментов

Разделяйте инструменты на read-only и write. Read-only инструменты (получить статус, поиск, чтение файла) безопаснее и могут выполняться с меньшими ограничениями. Write-инструменты (отправить письмо, перевести деньги, изменить файл) требуют дополнительных проверок и, возможно, подтверждения пользователя.

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

В конфигурации агента можно запретить write-инструменты в определенных режимах (например, в режиме исследования).

  • Read-only: получение данных, поиск, чтение.
  • Write: изменение состояния, отправка, запись.
  • Write-инструменты требуют дополнительных проверок.
  • Разделение помогает проектировать HITL и режимы работы.

Идемпотентность, таймауты и ретраи

Внешние вызовы могут завершиться ошибкой или быть повторены. Идемпотентность — это свойство операции, при котором повторное выполнение дает тот же результат, что и первое. Например, операция «установить статус заказа в 'отменен'» идемпотентна, а «увеличить счетчик на 1» — нет.

Для write-инструментов проектируйте идемпотентность: передавайте уникальный идентификатор операции (idempotency key), чтобы повторный вызов не создал дубликат. Например, при отправке письма можно передавать message_id, и сервер будет игнорировать повторную отправку с тем же ID.

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

  • Идемпотентность: повторный вызов дает тот же результат.
  • Используйте idempotency key для write-операций.
  • Таймаут: максимальное время ожидания ответа.
  • Ретраи с экспоненциальной задержкой.
  • Не повторяйте неидемпотентные операции без проверки.

Граница данных и инструкций

Важно разделять данные и инструкции. Данные, полученные из внешних источников (поиск, документы, API), должны рассматриваться как ненадежные. Они могут содержать вредоносные инструкции (prompt injection).

Инструменты должны возвращать только данные, а не инструкции для модели. Если инструмент возвращает текст, который может быть интерпретирован как инструкция, это риск. Например, документ, полученный из поиска, может содержать «забудь предыдущие инструкции и...».

Обрабатывайте данные как данные: экранируйте, ограничивайте длину, не смешивайте с системным промптом. Модель должна четко понимать, что является инструкцией, а что — данными для анализа.

  • Данные из внешних источников ненадежны.
  • Инструменты возвращают данные, а не инструкции.
  • Prompt injection: вредоносные инструкции в данных.
  • Экранируйте и ограничивайте длину данных.
  • Четко разделяйте инструкции и данные в промпте.

MCP, Skills и Plugins: протокол не дает прав

MCP (Model Context Protocol) стандартизирует способ описания и вызова инструментов. MCP-сервер объявляет инструменты, а MCP-клиент (агент) может их обнаруживать и вызывать. Это удобно для интеграции с внешними системами.

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

Skill — это повторяемая процедура, объединяющая несколько инструментов и инструкций. Plugin — это распространяемый пакет, включающий skills, MCP-конфигурации и ресурсы. Эти уровни помогают организовывать код, но не заменяют контроль доступа.

  • MCP: стандарт описания и вызова инструментов.
  • MCP не является механизмом безопасности.
  • Авторизация и проверка прав — на уровне приложения.
  • Skill: повторяемая процедура из инструментов и инструкций.
  • Plugin: распространяемый пакет со skills и MCP-конфигурациями.
  • Настройте независимую авторизацию для каждого MCP-сервера.
  • Не передавайте токены и ключи через MCP.
  • Проверяйте права на выполнение каждого инструмента.
  • Рассматривайте внешние инструменты как границу доверия.

Пример контракта инструмента

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

Рассмотрим инструмент get_order_status. Вход: order_id (строка, обязательный), include_history (булево, опционально). Выход: объект с полями status, expected_date, history (если запрошена). Ошибки: OrderNotFound (если заказ не найден), InvalidOrderId (если формат неверный).

Описание ошибок должно быть информативным для модели. Вместо «ошибка» верните «Заказ с номером 12345 не найден. Проверьте номер или обратитесь в поддержку».

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

Что взять в свой проект

Инструменты — это доверенный код, который выполняет действия от имени модели. Проектируйте четкие контракты, валидируйте параметры, разделяйте read и write, обеспечивайте идемпотентность и помните, что MCP — это протокол, а не безопасность.

Источники и документация

  • Инструменты и структурная генерация в LLM (учебные материалы Сбера)
  • Архитектура современных агентных harnesses (учебные материалы Сбера)
  • Разработка и применение мультиагентных систем в корпоративной среде (Сбер)