Pydantic AI — библиотека для Python, которая возвращает из агента объект по заданной схеме вместо свободного текста: класс описывает поля, библиотека проверяет ответ модели и при расхождении просит исправить. Для рабочего процесса это удобно, когда на выходе нужна карточка с полями для вашей системы, вместо абзаца для чтения глазами. Схема защищает форму результата, а за смысл по-прежнему отвечает человек, который сверяет карточку с исходным документом.
Агент со схемой
Агент создаётся строкой Agent(модель, output_type=Схема), запускается методом run_sync, а проверенный объект лежит в атрибуте result.output. Установка по документации: pip install pydantic-ai или uv add pydantic-ai.
Условный пример: отдел закупок получает письма поставщиков об изменении условий доставки, и сотрудник переносит суть каждого письма в таблицу. Скрипт читает письмо целиком, передаёт агенту текст и просит заполнить карточку: поставщик, тип изменения, дата вступления в силу, краткое содержание и признак «нужна проверка». Агент возвращает объект, скрипт кладёт его в таблицу, а сотрудник сверяет строку с письмом и подтверждает. Запись в учётную систему идёт отдельным шагом с проверкой прав на сервере.
Строка модели в формате «провайдер:название» хранится в настройках сервиса, а доступность модели определяют условия выбранного провайдера. Подобрать модель под задачу помогает материал про выбор поставщика и запасной вариант. Если задача требует нескольких ролей, посмотрите разбор CrewAI: здесь разговор об одном агенте с одной схемой и контролем на каждом шаге.
Схема результата
Схема — самая важная часть: она заменяет вопрос «получилось ли красиво» вопросом «совпала ли форма». В документации библиотеки параметр output_type принимает скаляры, списки, словари, датаклассы и модели Pydantic, а также объединения типов. Для карточки письма поставщика подходит класс Pydantic со строго заданными полями, где вместо произвольных строк стоят ограниченные списки значений.
Поля карточки выводятся из того, что делает сотрудник после чтения письма. Если он вносит в таблицу пять значений, схема содержит пять полей, и лишних полей про запас в ней нет. Каждое добавленное поле увеличивает число мест, где модель способна ошибиться, и число строк, которые человеку придётся сверять с исходным текстом.
| Поле карточки | Тип | Что проверяет схема и код |
|---|---|---|
| supplier | Строка | Совпадение названия с записью в справочнике поставщиков проверяет код |
| change_type | Ограниченный список: срок, адрес, условия оплаты, прочее | Значение вне списка отклоняется схемой, библиотека просит модель исправить ответ |
| effective_date | Дата | Неверный формат отклоняется схемой, а дату в прошлом ловит валидатор |
| summary | Строка до заданной длины | Длину ограничивает схема, смысл сверяет сотрудник |
| needs_review | Логический признак | Для неоднозначных писем ставится значение «да», решение за человеком |
Ограничения лучше выражать средствами самой схемы: списки допустимых значений, диапазоны дат, длина строки. Тогда проверка выполняется до того, как объект попадёт в ваш код, а текст замечания для модели формирует библиотека. Всё, что зависит от справочников и других систем, вынесите в валидатор вывода, который описан в четвёртом разделе.
Поле «прочее» нужно обязательно: когда модели некуда отнести письмо, она выбирает ближайшее значение и ошибается уверенно. Запасной вариант вместе с признаком проверки превращает такие случаи в видимый поток для ручной обработки. Размер потока полезно считать: если «прочее» набирает заметную долю писем, список типов пора пересмотреть.
Инструмент и зависимости
Агенту иногда требуется справка из внутренних данных, например, условия действующего договора с поставщиком. Для этого в библиотеке используются инструменты: функции, зарегистрированные декораторами @agent.tool (с доступом к контексту запуска) и @agent.tool_plain (без него). Строка документации функции превращается в описание для модели, поэтому пишите её так, чтобы по ней было ясно, когда вызывать инструмент и что он вернёт.
Соединения, ключи и справочники передаются через зависимости. Класс зависимостей указывают в параметре deps_type, значения передают при запуске аргументом deps, а внутри инструмента они доступны через объект RunContext. Модель видит имя инструмента, описание и параметры, но секреты остаются в зависимостях на стороне сервера.
- Инструмент только читает: запись в базу, письма и платежи выполняет отдельный код после подтверждения сотрудника.
- Параметры инструмента ограничены по типам: номер договора вместо произвольного запроса к базе.
- Права проверяет сервер по пользователю, запустившему задачу, а текст модели на это решение влияния лишён.
- Каждый вызов попадает в журнал: имя, параметры, время и код результата.
Инструментов у агента держите немного. Каждый добавленный инструмент расширяет поверхность ошибок: модель способна выбрать лишний, передать неподходящий аргумент или вызывать его по кругу. Для разбора письма хватает одного инструмента справки по договору, а остальные данные скрипт собирает заранее и передаёт в запрос готовыми.
Тот же принцип в другом формате показан в статье про минимальный сервер MCP на Python, а широкий взгляд на инструменты и права агента на фреймворке LangChain дан в материале про агента LangChain.
Валидация и повторы
Схема проверяет форму, а бизнес-правила требуют отдельного кода. Библиотека даёт для этого декоратор @agent.output_validator: функция получает уже собранный объект и вправе поднять исключение ModelRetry с текстом замечания, например «дата вступления в силу раньше даты письма». Модель получает замечание и пробует снова. Каждая такая попытка расходует бюджет повторов вывода, который по документации по умолчанию равен единице и настраивается при создании агента или при запуске.
Бюджет повторов защищает от бесконечных обменов: когда он исчерпан, библиотека поднимает исключение, и обработка письма должна завершиться понятным результатом. Перехватывайте его в сервисе и переводите письмо в очередь ручной обработки со статусом «автоматический разбор сорвался». Сотрудник видит исходное письмо и причину, а сервис пишет в журнал номер письма и тип ошибки без полного текста.
Отдельно решите, что считать допустимым результатом. Валидатор отсекает явно неверное: дату из прошлого, неизвестного поставщика, пустое содержание. Правдоподобную ошибку, скажем перепутанный тип изменения, он ловит только по косвенным признакам, поэтому финальную сверку проводит человек. Вводите правила по одному и фиксируйте, какая доля писем теперь уходит на повтор.
Сколько типов входящих писем в вашем отделе разбирают вручную?
Тест без модели
Основную часть проверок можно выполнить без обращения к внешней модели. Документация библиотеки предлагает для этого заменители: TestModel генерирует корректные данные по схеме инструментов и выходного типа, FunctionModel выполняет вашу функцию вместо модели, а менеджер agent.override() подменяет модель внутри кода приложения без правок рабочей логики.
- Запретите внешние вызовы в тестах строкой
models.ALLOW_MODEL_REQUESTS = False: случайное обращение к настоящей модели тогда сразу даст ошибку. - Напишите тест с
agent.override(model=TestModel())и проверьте, что скрипт получает объект нужного класса и кладёт его в таблицу. - Задайте через
FunctionModelответ с датой в прошлом и проверьте, что валидатор поднял повтор, а после исчерпания бюджета письмо ушло в ручную очередь. - Откройте обмен сообщениями через
capture_run_messages()и проверьте, что в запрос к модели попали только разрешённые поля письма.
Эти тесты доказывают, что провода соединены верно. Качество разбора остаётся за кадром, потому что TestModel выдаёт формально правильные данные. Для оценки смысла возьмите набор реальных писем с карточками, заполненными сотрудником, прогоните их на настоящей модели в контролируемом окружении и сравните поле за полем.
Опишите карточку одного типа документа пятью полями, подготовьте десяток писем с эталонными ответами и напишите два теста с TestModel и FunctionModel. Когда форма и повторы работают, подключайте настоящую модель и сверяйте результаты по полям. Если разбор писем нужно встроить в процесс закупок, начните с общей картины на странице про ИИ-агентов для бизнеса.