Гайд · TNWS AI
Как дать агенту Pydantic AI инструмент чтения справки без права записи
Инструмент tool_plain для чтения вымышленной справки: минимальные полномочия, пример вопроса, проверка вызова и защита от ложных ответов.
Что решаем и кому подходит
Поисковый вопрос: «как добавить безопасный читающий tool_plain в Pydantic AI». Отвечать на вопрос о вымышленном расписании по фиксированному словарю вместо угадывания. В официальном описании функция без контекста регистрируется декоратором @agent.tool_plain, а контекстная — @agent.tool. Описание функции и аргументы формируют интерфейс для модели; само наличие инструмента не заставляет её вызвать его в каждом запросе. Доступ к системе определяется переданным Python-кодом, а не вежливостью инструкции. Инструкция опирается на актуальную официальную документацию Pydantic AI, проверенную 20 сентября 2026 года. Примеры предназначены для Python 3.10+ с пакетом pydantic-ai. Используйте модель и учётные данные, доступные именно вашему аккаунту; пример идентификатора из документации не является обещанием доступа. Демонстрационные коды, статусы и суммы вымышлены.
Порядок действий
- Создайте маленький справочник тестовых записей без настоящих персональных данных.
- Зарегистрируйте
tool_plainдля чтения по одному идентификатору; неизвестный идентификатор возвращайте явно. - Попросите агента ответить только после сверки с инструментом и запустите вопрос о конкретной записи.
- Проверьте результат и фактический вызов на контролируемом тесте; затем добавьте тест на неизвестный ключ и на попытку записи.
До сетевого запуска установите pydantic-ai и настройте ключ провайдера предусмотренным им способом. Примеры не содержат действующих секретов. Для воспроизводимого теста зафиксируйте версии Python, пакета и выбранной модели; после обновления снова выполните как удачный, так и отрицательный сценарий. Вызов run_sync использован для наглядного скрипта вне уже работающего асинхронного цикла. Там, где проект асинхронный, применяйте документированный await agent.run(...) и управляйте ресурсами на стороне приложения.
Готовый шаблон для запуска
from pydantic_ai import Agent
SCHEDULE = {"R-7": "выдача по вторникам"}
agent = Agent("openai:gpt-5.2",
instructions="Для сведений о расписании используй справку; неизвестное не придумывай.")
@agent.tool_plain
def read_schedule(code: str) -> str:
"""Прочитать расписание по коду заявки. Ничего не изменяет."""
return SCHEDULE.get(code, "Запись не найдена")
result = agent.run_sync("Когда выдача по коду R-7? Ответь по справке.")
print(result.output)
assert SCHEDULE == {"R-7": "выдача по вторникам"}
Конкретный вход и ожидаемый результат
Вход «Когда выдача по коду R-7?» при справке R-7 → выдача по вторникам. Предметно правильный ответ: выдача по вторникам; фраза модели может быть другой. Вход «Когда выдача по R-8?» при отсутствии записи должен приводить к сообщению о неизвестном расписании, не к догадке о среде. Просьба «поменяй R-7 на пятницу» не должна приводить к изменению словаря, потому что разрешённый инструмент не содержит операции записи.
Почему этот способ работает
При выполнении функции программа получает конкретный code, выбранный моделью. Поэтому отдельно валидируйте этот аргумент на стороне приложения: если вопрос содержал R-7, а инструмент получил R-8, модель может построить правдоподобный ответ по чужой записи. Для настоящего хранилища необходимо связывать запрос с правами вызывающего пользователя вне модели. Краткая документация функции помогает модели выбрать её, но права не определяет. Если инструмент обращается к сети, вводите таймаут, разрешённый адрес и ограничения объёма возвращаемого текста; иначе ответ внешнего источника может стать каналом инъекции в последующие шаги.
Пограничный случай и предметная проверка
Хороший приёмочный тест сравнивает журнал обращений к функции с вопросом пользователя. Добавьте счётчик вызовов и запись безопасного кода: он позволит отличить ответ из справки от совпавшей случайно догадки. Повторите тест с похожими кодами R-7 и R-17, чтобы обнаружить путаницу при извлечении аргумента. Если текст справки был отредактирован, меняйте эталон теста одновременно с источником, но сохраняйте предыдущий результат для объяснения регрессии. В продуктивном сценарии журнал не должен содержать закрытые записи целиком. Даже инструмент чтения способен раскрыть чужую информацию, если проверка авторизации устроена неверно.
Критерии приёмки
- Известный ключ даёт ответ, согласованный со справкой.
- Неизвестный ключ не получает выдуманную дату или день недели.
- Попытка попросить модель записать новое значение не меняет справочник; проверка только финального текста здесь недостаточна.
Проверка успешного выполнения Python-программы не равна проверке верности ответа нейросети. Сопоставьте результат с входом и с доверенным источником данных, затем повторите тест на отрицательном примере. Формулировка текста может отличаться от образца; условия приёмки описывают наблюдаемое поведение, которое действительно нужно пользователю. Если один критерий не соблюдён, не скрывайте сбой повтором без ограничения: сохраните минимальный безопасный воспроизводимый пример и исправьте соответствующий слой — данные, схему, инструмент, инструкцию или обработку ошибки.
Частые ошибки и чего не делать
- Не передавайте агенту универсальный HTTP-клиент или SQL-доступ, если требуется только чтение одной записи.
- Не считайте слова «ничего не изменяет» в docstring реальным ограничением, если код инструмента способен писать.
- Не полагайте, что агент всегда выберет инструмент: проверяйте траекторию там, где справка обязательна.
Вопросы и ответы
Чем tool_plain отличается от tool?
tool_plain не получает RunContext; tool его получает.
Может ли модель ответить без вызова?
Да; обязательную сверку проверяют в тестах и проектируют на стороне приложения.
Можно ли передать реальную БД?
Можно через ограниченную обёртку и контроль прав, но не выдавая модели произвольный доступ.
Официальные источники
Частые вопросы
Чем tool_plain отличается от tool?
`tool_plain` не получает `RunContext`; `tool` его получает.
Может ли модель ответить без вызова?
Да; обязательную сверку проверяют в тестах и проектируют на стороне приложения.
Можно ли передать реальную БД?
Можно через ограниченную обёртку и контроль прав, но не выдавая модели произвольный доступ.
Читайте также
Как извлечь поля заявки из русского письма через Pydantic AI и output_type
Пошаговое извлечение темы и номера заявки в Pydantic AI: схема BaseModel, конкретное письмо, проверка полей и ошибки, которые не исправит одна валидация.
Как ограничить число обращений агента Pydantic AI к модели через request_limit
Ограничение числа модельных шагов Pydantic AI: UsageLimits(request_limit), обработка исключения и тест на цикл инструмента.
Как отклонить фактически неверный ответ Pydantic AI через output_validator
Выходной валидатор Pydantic AI на примере суммы заказа: проверка суммы по каталогу, ModelRetry, границы повторов и критерий приёмки.
Комментарии
Пока тихо. Скажите первое слово