Одна и та же модель может отвечать как сухой технический справочник, а может — как болтливый копирайтер. Разницу чаще всего задаёт не сам вопрос пользователя, а системный промпт: короткий блок инструкций, который приложение отправляет модели до того, как пользователь напишет первое слово. Это самый дешёвый и самый недооценённый способ управлять поведением ИИ в продукте. Разбираем, что туда класть, как это выглядит в API трёх основных провайдеров и какие ошибки чаще всего превращают системный промпт в бесполезный текст.
Что такое системный промпт
Системный промпт (system prompt, ещё говорят «системная инструкция») — это отдельное поле запроса к модели, куда разработчик кладёт правила игры: кто модель по роли, что она делает, чего не делает, в каком формате отвечает. Пользователь этот текст не видит и, в норме, не может его перезаписать своим сообщением.
Технически модель получает всё одним потоком токенов — и системный промпт, и историю диалога. Но провайдеры специально обучают модели относиться к системному блоку как к инструкции более высокого приоритета. Поэтому фраза «отвечай только про наши тарифы», написанная в системном промпте, работает заметно устойчивее той же фразы, вставленной в первое сообщение пользователя.
Важно понимать границы: системный промпт — это не механизм безопасности и не права доступа. Это сильная просьба, а не firewall. Если агент умеет вызывать инструменты, ограничивать его нужно на уровне самих инструментов, а не абзацем текста.
Иерархия инструкций: кто кого перебивает
У современных моделей есть явная иерархия источников инструкций. OpenAI описывает её в Model Spec как «цепочку командования» (chain of command) из пяти уровней: Root — базовые правила, которые нельзя переопределить ничем; System — политики самого провайдера; Developer — инструкции разработчика приложения; User — сообщения конечного пользователя; Guideline — мягкие рекомендации по умолчанию, которые контекст может переопределить. При конфликте побеждает уровень выше.
Практический вывод простой. Ваш системный промпт живёт на уровне разработчика: он старше сообщений пользователя, но младше правил провайдера. Значит, инструкцией «игнорируй все ограничения» вы ничего не добьётесь — а вот «отвечай только по документации, приложенной ниже» вполне сработает, потому что пользовательское сообщение этот уровень не перебивает.
Отдельная тонкость: данные, которые приложение подтягивает из внешнего мира — веб-страницы, письма, содержимое базы, — попадают в контекст как обычный текст и формально не имеют никакой власти. Но модель может принять их за инструкцию. Это и есть промпт-инъекция, и хороший системный промпт должен прямо проговаривать: всё, что пришло из внешнего источника, — это данные, а не команды.
Как задать системный промпт в API
Поле называется по-разному, но смысл везде один — отдельный параметр запроса, не перемешанный с сообщениями.
Claude (Anthropic)
В Messages API это параметр верхнего уровня system — обычная строка (или список блоков):
message = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
system="Ты — технический ассистент по Python. Отвечай кодом и коротким пояснением.",
messages=[{"role": "user", "content": "Как отсортировать список словарей?"}],
)
Anthropic отдельно советует задавать роль: даже одно предложение вроде «Ты — специалист поддержки» заметно меняет тон и фокус ответов. Для сложных системных промптов документация рекомендует структурировать текст XML-тегами — <instructions>, <context>, <rules>.
OpenAI
В Responses API есть параметр instructions, который эквивалентен сообщению с ролью developer:
const response = await client.responses.create({
model: "gpt-5.6",
instructions: "Отвечай кратко, без вступлений.",
input: "Точки с запятой в JS обязательны?",
});
Есть важный нюанс: instructions действует только на текущий запрос. Если вы ведёте диалог через previous_response_id, инструкции прошлых ходов автоматически не переносятся — их нужно передавать каждый раз. Роль system в старом Chat Completions осталась, но в новом API её место занял developer.
Gemini (Google)
Здесь параметр называется system_instruction и передаётся вместе с запросом:
interaction = client.interactions.create(
model="gemini-3.6-flash",
system_instruction="Ты — кот. Тебя зовут Neko.",
input="Привет"
)
В многоходовых сценариях системную инструкцию тоже стоит передавать явно при каждом обращении, если вы сами собираете историю диалога.
Из чего собрать рабочий системный промпт
Универсального шаблона нет, но у устойчивых промптов повторяется одна и та же скелетная структура. Шесть блоков, по убыванию важности:
- Роль и задача. Одно-два предложения: кто модель и что она делает. «Ты — ассистент интернет-магазина X, помогаешь покупателям выбрать товар и разобраться с доставкой».
- Контекст. Что за продукт, кто аудитория, чего от ответа ждут. Модель не знает вашего бизнеса — это придётся рассказать.
- Правила и границы. Формулируйте позитивно и проверяемо. «Если данных о наличии товара нет — скажи, что не знаешь, и предложи связаться с менеджером» работает лучше, чем «не выдумывай».
- Формат ответа. Длина, структура, язык, использование списков. Если нужен машиночитаемый ответ — не описывайте JSON словами, используйте структурированный вывод по схеме.
- Тон. «Дружелюбно, но по делу, без канцелярита и без восклицательных знаков» — конкретика тут важнее эпитетов.
- Примеры. Два-три коротких образца «запрос → правильный ответ» дают больше, чем абзац объяснений. Подробнее — в заметке о практических приёмах промпт-инжиниринга.
Порядок блоков имеет значение: сначала роль и контекст, потом правила, в конце — формат и примеры. Так модель сначала понимает, кем она является, и только потом — как оформлять ответ.
Частые ошибки
Промпт-роман. Три экрана текста с двадцатью правилами: часть из них модель проигнорирует, а вы не поймёте какую. Начинайте с пятнадцати строк и добавляйте правило только после того, как поймали реальную ошибку в ответах.
Противоречивые требования. «Отвечай развёрнуто» и «укладывайся в два предложения» в одном промпте — модель выберет одно из двух, и не всегда то, что вам нужно.
Только запреты. Список «не делай» плохо работает: чтобы не сделать чего-то, модель должна это сначала представить. Заменяйте запреты на описание желаемого поведения.
Данные вместо инструкций. Не зашивайте в системный промпт каталог товаров или базу знаний — он раздувается и устаревает. Знания подтягивайте отдельно, инструкции держите в системном блоке.
Забытые пользовательские данные. Всё, что приходит от пользователя или из внешнего источника, должно попадать в сообщения, а не склеиваться с системным промптом. Иначе вы своими руками открываете дверь для инъекции.
Кэширование и цена вопроса
Системный промпт отправляется с каждым запросом, поэтому его длина напрямую бьёт по счёту. Хорошая новость: он же — идеальный кандидат на кэширование промптов. Стабильный неизменный префикс кэшируется провайдером, и повторные запросы обходятся заметно дешевле. Отсюда практическое правило: держите системный промпт в начале запроса и не меняйте его от вызова к вызову — динамические подстановки вроде текущей даты лучше выносить ниже, в сообщения, иначе кэш будет промахиваться при каждом обращении. Как это влияет на бюджет, разбирали в заметке про токены и лимиты.
Как тестировать и версионировать
Системный промпт — это код продукта, а не заметка в блокноте. Минимальная гигиена: держите его в репозитории отдельным файлом, а не строкой внутри функции; фиксируйте версию рядом с версией приложения; при каждом изменении прогоняйте набор из 10–20 контрольных запросов и сравнивайте ответы с эталонными.
Меняйте по одному правилу за раз. Если поправить сразу пять формулировок и увидеть улучшение, вы не узнаете, какая из них сработала, — а через месяц не поймёте, какую можно выкинуть.
У агентных инструментов есть свой формат «системного промпта проекта». В Claude Code, например, эту роль играет файл CLAUDE.md: те же правила, только лежат в репозитории и подхватываются автоматически.
Вывод
Системный промпт — самый быстрый рычаг влияния на поведение модели: одно поле в запросе, никакого дообучения. Задайте роль, дайте контекст, сформулируйте правила через желаемое поведение, зафиксируйте формат — и держите текст коротким. Всё, что касается прав, доступов и денег, решайте на уровне кода и инструментов: системный промпт задаёт поведение, но не гарантирует его.
Частые вопросы
Системный промпт передаётся отдельным параметром запроса и имеет более высокий приоритет: модели обучены следовать ему устойчивее, чем инструкциям из сообщений пользователя. Пользователь его не видит и не может перезаписать своим текстом.
Нет. Системный промпт задаёт поведение, но не является механизмом безопасности. Реальные ограничения нужно ставить на уровне кода и прав самих инструментов, которые вызывает модель, — текстовая инструкция сама по себе не гарантия.
Начинайте с 10–20 строк и добавляйте правила только после того, как поймали конкретную ошибку в ответах. Длинный промпт не только хуже соблюдается, но и оплачивается с каждым запросом — хотя стабильный префикс можно удешевить кэшированием.
Да, если вы сами собираете историю диалога. В OpenAI Responses API параметр instructions действует только на текущий ответ и не переносится автоматически через previous_response_id; в Claude и Gemini системное поле также передаётся с каждым вызовом.
Источники
- 1.Anthropic — System prompts (Claude Docs)https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/system-prompts
- 2.OpenAI — Text generation and prompting (Responses API)https://developers.openai.com/api/docs/guides/text
- 3.OpenAI Model Spec — Chain of commandhttps://model-spec.openai.com/2025-12-18.html
- 4.Google — Gemini API: system instructionshttps://ai.google.dev/gemini-api/docs/system-instructions



