Запись архива

Промпты для агентов: как правильно формулировать задачи LLM-агентам

Агенты на языковых моделях работают иначе, чем чат-боты. Разбираем, как устроены промпты для агентов, какие элементы обязательны и где кроются типичные ошибки.

Редакционная обложка COMRAD404: Промпты для агентов: как правильно формулировать задачи LLM-агентам
Редакционная обложка COMRAD404: Промпты для агентов: как правильно формулировать задачи LLM-агентам
Редакционная тематическая обложка COMRAD404

Промпты для агентов — это не просто инструкции для языковой модели. Если в чат-боте достаточно сказать «будь полезным ассистентом», то агент должен понимать, какие инструменты у него есть, когда их вызывать, как интерпретировать результаты и в каких рамках он может принимать решения. Ошибка в промпте может стоить агенту нескольких циклов лишних вызовов API или, что хуже, неверного действия в продакшене.

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

Чем промпт агента отличается от промпта чат-бота

Основное различие — в наличии инструментов и циклов рассуждения. Чат-бот отвечает на вопрос и завершает диалог. Агент может выполнять последовательность действий: вызвать функцию, получить результат, проанализировать его, вызвать следующую функцию или вернуть ответ пользователю.

Из этого следуют три ключевых отличия в промпте:

Описание инструментов. Модель должна точно знать, какие функции доступны, какие у них параметры и в каких форматах ожидается ответ.
2. Правила принятия решений. Когда вызывать инструмент, а когда отвечать напрямую. Можно ли повторять вызов при ошибке. Сколько попыток допустимо.
3. Формат вывода. Агент часто должен возвращать структурированные данные (JSON, Markdown, специфичную схему), а не свободный текст.

Эти различия делают промпт для агента скорее конфигурационным файлом, чем инструкцией для человека. Разработчики, которые пытаются адаптировать промпты из ChatGPT для агентов, сталкиваются с тем, что модель начинает «фантазировать» вызовы несуществующих функций или игнорирует ограничения.

Структура системного промпта для агента

На практике системный промпт агента собирается из нескольких логических блоков. Вот типичная структура, которую используют в открытых фреймворках вроде LangChain, AutoGPT и в продакшен-решениях.

Блок Назначение Пример
Идентичность и цель Определяет роль агента и границы его компетенции «Ты — ассистент по бронированию отелей. Ты работаешь только с отелями из базы.»
Список инструментов Перечисление доступных функций с сигнатурами `search_hotels(city, dates, guests)`
Правила вызова инструментов Условия, при которых вызывать каждый инструмент «Если пользователь не указал даты, сначала уточни их, а потом вызывай search_hotels.»
Обработка ошибок Действия при сбое вызова или пустом результате «Если search_hotels вернул пустой список, предложи изменить параметры поиска.»
Формат ответа Требования к структуре финального ответа «Ответ должен содержать поле hotel_name, price и booking_link.»
Ограничения Запреты и границы автономии «Не бронируй отель без подтверждения пользователя. Не вызывай платные API без явного разрешения.»

Каждый блок важен, но на практике чаще всего проблемы возникают из-за нечетких правил вызова инструментов и отсутствия обработки ошибок. Например, в проекте по автоматизации поддержки клиентов один разработчик столкнулся с тем, что агент бесконечно вызывал API поиска, потому что в промпте не было указано, что делать при пустом результате. Логи показали 47 вызовов за 3 секунды, пока не сработал лимит на уровне кода.

Как описывать инструменты в промпте

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

Плохой пример

Функция: search_hotels
Параметры: city, dates, guests

Хороший пример

Функция: search_hotels(city: string, check_in: string (YYYY-MM-DD), check_out: string (YYYY-MM-DD), guests: int) — возвращает список отелей в указанном городе на заданные даты.
Пример: search_hotels(“Москва”, “2026-09-01”, “2026-09-05”, 2)

Чем точнее описаны типы и форматы, тем реже модель ошибается при генерации вызова. Особенно это критично для дат, булевых флагов и enum-параметров. В одном из публичных кейсов от компании Replit инженеры заметили, что модель Claude 3.5 Opus начала путать параметры `temperature` и `top_p` в вызове API, потому что в описании не было указано, что `temperature` принимает значения от 0 до 2, а `top_p` — от 0 до 1. После добавления явных диапазонов ошибки прекратились.

Для моделей семейства GPT рекомендуется также указывать, какие параметры обязательны, а какие опциональны. Это можно сделать через `required` в JSON-схеме function calling, но дублирование в тексте промпта тоже работает.

Границы автономии: что можно и что нельзя

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

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

Что делать: в блоке ограничений явно перечислить:
– Какие действия требуют подтверждения пользователя (например, оплата, удаление данных, отключение критических систем).
– Какие инструменты нельзя вызывать без явного запроса.
– Сколько раз можно повторять вызов при ошибке (обычно 2-3 попытки, затем вернуть ошибку пользователю).

Для агентов, работающих с финансами или персональными данными, рекомендуется добавить правило: «Если действие может изменить состояние системы необратимо, сначала опиши пользователю, что произойдет, и запроси подтверждение».

Обработка ошибок и крайних случаев

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

Типовые сценарии, которые нужно обработать в промпте

– Инструмент вернул пустой список. Действие: предложить изменить параметры запроса.
– Инструмент вернул ошибку 500. Действие: повторить вызов через 1 секунду, не более 2 раз, затем сообщить пользователю о временной недоступности.
– Инструмент вернул данные в неожиданном формате. Действие: игнорировать результат и запросить повторный вызов.
– Пользователь ввел невалидные данные (отрицательное число, пустую строку). Действие: запросить уточнение с указанием допустимого формата.

В проекте LangChain есть примеры таких обработчиков в репозитории `langchain-ai/langgraph`. Разработчики рекомендуют добавлять блок `fallback` для каждого инструмента, где описано, что делать, если основной вызов не сработал.

Как избежать конфликта инструментов

Если два инструмента имеют похожие названия или пересекающиеся возможности, модель может вызывать не тот. Например, `get_weather` и `get_forecast` — модель может путать, какой из них возвращает текущую погоду, а какой — прогноз на неделю. Описания должны быть контрастными.

Практический совет: используйте разные глаголы в начале описания. Для текущего состояния — «получить», для прогноза — «спрогнозировать», для поиска — «найти». Это снижает вероятность путаницы.

Если инструментов больше 10, имеет смысл сгруппировать их по категориям в промпте. Например: «Инструменты для работы с пользователями: … Инструменты для работы с заказами: …». Модели с поддержкой tool calling (GPT-4, Claude 3.5, Gemini 1.5) лучше обрабатывают иерархические описания, чем плоские списки.

Практические рекомендации по отладке

При проектировании промпта для агента стоит придерживаться нескольких принципов.

Во-первых, тестировать промпт на граничных случаях. Что будет, если пользователь передаст пустую строку, отрицательное число или невалидную дату. Модель должна либо корректно обработать это, либо запросить уточнение. Для этого можно использовать библиотеки вроде `promptfoo` или `langfuse`, которые позволяют прогонять тестовые сценарии автоматически.

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

В-третьих, не полагаться на то, что модель «поймёт» намерение разработчика из общего контекста. Промпт для агента должен быть избыточно явным в части ограничений и правил вызова. Лучше написать 10 строк с правилами, чем потом разбираться, почему агент списал деньги с карты пользователя без подтверждения.

В-четвертых, использовать версионирование промптов. При изменении промпта сохраняйте предыдущую версию и сравнивайте результаты A/B-теста. Даже небольшое изменение в формулировке может кардинально изменить поведение агента. Например, замена «можешь вызвать» на «вызови, если» увеличивает частоту вызовов инструментов на 15-20% по данным экспериментов команды Anthropic.

Что почитать дальше

Официальная документация OpenAI по function calling содержит базовые примеры описания инструментов. Anthropic в своих гайдах по агентам подробно разбирает, как проектировать промпты для Claude с поддержкой tool use. В репозитории LangChain есть примеры системных промптов для разных типов агентов — от поисковых до тех, что работают с базами данных.

При работе с агентами стоит также изучить подходы к валидации вызовов функций на стороне приложения: модель может сгенерировать синтаксически корректный, но семантически неверный вызов, и промпт здесь не всегда спасает — нужна дополнительная проверка на уровне кода. Например, перед выполнением вызова можно проверять, что параметры находятся в допустимых диапазонах, а сам инструмент действительно доступен в текущем контексте.