· 7 мин · Разработка

Системный промпт Claude Code: инженерные уроки для разработчиков агентов

Системный промпт Claude Code: инженерные уроки для разработчиков агентов

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

Именно поэтому недавнее публичное обсуждение системных промптов Claude и Claude Code полезно, хотя утекшие или собранные промпты не стоит принимать за непреложную истину. Дампы промптов часто бывают неофициальными, неполными, устаревшими или извлечёнными из состояния продукта, которого уже не существует. Сам Claude Code быстро развивается, а нынешняя линейка Claude — Opus 4.8, Sonnet 4.6, Haiku 4.5 и Fable 5 с контекстом 1M — предлагает разработчикам агентов совсем иные компромиссы, чем предыдущие поколения.

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

Эта статья посвящена таким урокам.

Уроки системного промпта Claude Code без копирования самого промпта

Выражение «системный промпт Claude Code» стало кратким обозначением вопроса «как серьёзный агент для программирования объясняет модели, как ей себя вести?». Это неверный вопрос, если он ведёт к археологии промптов, но верный, если ведёт к улучшению проектирования агентов.

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

УровеньЧто контролируетПример
Системные инструкцииСтабильный контракт поведения«Предпочитай минимальные изменения; не создавай коммиты без запроса».
Политика разработчикаПравила конкретного продукта«Используй apply_patch; никогда не выполняй разрушительные команды без одобрения».
Схема инструментаЧто модель действительно может делатьread_file, edit_file, run_shell, update_plan
Разрешения среды выполненияК чему процессу разрешён доступПесочница, рабочий каталог, сетевая политика
Инструкции пользователяЦель конкретной задачи«Исправь падающий тест аутентификации».

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

Лучше использовать промпт для объяснения намерений, а среду выполнения — для принудительного ограничения возможностей.

Например, не ограничивайтесь инструкцией в промпте:

Do not delete files unless the user asks.

Выделите удаление в отдельный инструмент, требующий подтверждения:

{
  "name": "delete_file",
  "description": "Delete a file from the workspace.",
  "input_schema": {
    "type": "object",
    "properties": {
      "path": { "type": "string" },
      "reason": { "type": "string" },
      "user_confirmed": { "type": "boolean" }
    },
    "required": ["path", "reason", "user_confirmed"]
  }
}

Затем обеспечьте соблюдение этого требования вне модели:

def delete_file(path: str, reason: str, user_confirmed: bool):
    if not user_confirmed:
        raise PermissionError("delete_file requires explicit user confirmation")
    if not path.startswith(WORKSPACE_ROOT):
        raise PermissionError("cannot delete files outside workspace")
    os.remove(path)

Промпт объясняет агенту, как думать. Граница инструмента определяет, что может произойти.

Иерархия инструкций — это инженерный интерфейс

Модели Claude хорошо следуют многоуровневым инструкциям, но сами уровни всё равно нужно тщательно спроектировать. Если у вашего агента для программирования есть системные инструкции, инструкции разработчика, проекта и пользователя, у каждого уровня должна быть чёткая задача.

Полезная иерархия выглядит так:

  • Системные инструкции: идентичность, подход к безопасности, общие принципы работы.
  • Инструкции разработчика: механика продукта, правила использования инструментов, стиль ответов, модель разрешений.
  • Инструкции проекта: соглашения конкретного репозитория, команды тестирования, заметки об архитектуре.
  • Инструкции пользователя: текущая задача.

В рабочих процессах в стиле Claude Code это явно выражено через такие файлы, как CLAUDE.md, а также через конфигурацию командной строки и контекст сеанса. Для разработчиков агентов более общий урок состоит в том, что локальные инструкции проекта должны иметь ограниченную область действия и переопределять другие инструкции только там, где это уместно.

Простой файл инструкций проекта может выглядеть так:

# CLAUDE.md

## Build and Test
- Use `pnpm test -- --runInBand` for focused test runs.
- Do not run `pnpm deploy` unless explicitly requested.

## Code Style
- Prefer small functions over large service classes.
- Do not add new dependencies without explaining why.

## Repo Notes
- API routes live in `apps/api/src/routes`.
- Generated GraphQL types live in `apps/web/src/generated`; do not edit them manually.

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

Это можно смоделировать явно:

PRIORITY = {
    "system": 4,
    "developer": 3,
    "project": 2,
    "user": 1,
}

def resolve_conflict(existing_rule, new_rule):
    if PRIORITY[new_rule.source] > PRIORITY[existing_rule.source]:
        return new_rule
    return existing_rule

В реальном агенте модель также должна объяснять пользователю конфликты:

I can update the source schema and regenerate the types, but I should not edit
`src/generated` directly because the project instructions mark it as generated.

Одно это предложение предотвращает на удивление много ущерба.

Границы инструментов важнее вежливости промпта

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

Основной механизм — граница инструмента.

Серьёзный агент для программирования должен различать:

  • Чтение файлов
  • Поиск по файлам
  • Редактирование файлов
  • Выполнение команд
  • Установку пакетов
  • Доступ к сетевым ресурсам
  • Удаление или перемещение файлов
  • Создание коммитов или веток
  • Открытие пул-реквестов
  • Изменение секретов или конфигурации развёртывания

С моральной точки зрения эти операции не равнозначны.

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

ОперацияПолитика по умолчаниюПочему
Чтение файлов рабочего пространстваРазрешитьНеобходимо для сбора контекста
Поиск с помощью rgРазрешитьНизкий риск и высокая полезность
Редактирование отслеживаемых исходных файловРазрешить с показом различийОсновной рабочий процесс программирования
Запуск целевых тестовОбычно разрешатьПроверяет изменения
Установка зависимостейЗапросить разрешениеИзменяет окружение и файлы фиксации зависимостей
Удалять файлыЗапросить разрешениеЛегко привести к необратимой потере данных
Доступ к сетиЗапросить разрешение или запретитьМожет привести к утечке данных или недетерминированному поведению
Редактирование секретовЗапретить по умолчаниюШирокий масштаб возможного ущерба
Создание коммитов с изменениямиЗапросить разрешениеИстория репозитория принадлежит пользователю
РазвёртываниеЗапретить без явного запросаВлияние на рабочую среду

Здесь также важен выбор модели. Для большинства рабочих циклов агентов для программирования я предпочитаю модели класса Sonnet: они хорошо сочетают задержку, стоимость и способность рассуждать. Opus 4.8 — модель, к которой я бы обратился, когда агенту нужен более глубокий архитектурный анализ и синтез или сложная отладка. Haiku 4.5 подходит для быстрой классификации и лёгкого обзора репозитория. Контекст 1M у Fable 5 интересен для понимания больших кодовых баз, но длинный контекст не отменяет необходимости в качественном поиске, чтении с ограниченной областью и дисциплине использования инструментов.

Даже контекст на миллион токенов может содержать не тот файл.

Подтверждение пользователя должно быть конкретным, а не формальным

Неудачный интерфейс подтверждения выглядит так:

May I proceed?

Продолжить что? Редактирование одного файла? Запуск миграций? Удаление каталога?

Хорошее подтверждение конкретно:

I need confirmation before running:

`rm -rf apps/web/.next`

Reason: remove a stale Next.js build cache that may be causing the local
runtime error. This deletes only generated build output and does not touch
source files.

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

Я рекомендую представлять подтверждение в виде структурированного состояния, а не обычного текста:

{
  "action": "run_shell",
  "command": "rm -rf apps/web/.next",
  "risk": "destructive_generated_artifact",
  "requires_confirmation": true,
  "confirmation_prompt": "Delete generated Next.js cache at apps/web/.next?"
}

Тогда ваш исполнитель команд оболочки сможет обеспечить его соблюдение:

def run_shell(command, confirmed=False):
    risk = classify_command(command)

    if risk.requires_confirmation and not confirmed:
        return {
            "status": "needs_confirmation",
            "message": risk.prompt
        }

    return subprocess.run(command, shell=True, cwd=WORKSPACE_ROOT)

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

Команды, с которыми стоит обращаться осторожно

Для них нужны явно заданные правила:

rm -rf path
git reset --hard
git clean -fd
git push --force
npm install some-package
pip install -r requirements.txt
docker compose down -v
kubectl delete ...
terraform apply

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

Доступ к файлам — это проектирование контекста

Самая недооценённая часть проектирования агентов для программирования — доступ к файлам. В промпте можно написать «сначала изучи нужные файлы», но среда выполнения должна делать такое поведение удобным.

Как минимум, предоставьте модели инструменты для следующих действий:

  • Быстрый поиск файлов по имени
  • Поиск по тексту
  • Чтение ограниченных диапазонов строк в файлах
  • Просмотр различий в git
  • Атомарное применение патчей

Минимальный набор инструментов может выглядеть так:

[
  {
    "name": "search_files",
    "input_schema": {
      "type": "object",
      "properties": {
        "query": { "type": "string" },
        "glob": { "type": "string" }
      },
      "required": ["query"]
    }
  },
  {
    "name": "read_file",
    "input_schema": {
      "type": "object",
      "properties": {
        "path": { "type": "string" },
        "start_line": { "type": "integer" },
        "limit": { "type": "integer" }
      },
      "required": ["path"]
    }
  },
  {
    "name": "apply_patch",
    "input_schema": {
      "type": "object",
      "properties": {
        "patch": { "type": "string" }
      },
      "required": ["patch"]
    }
  }
]

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

rg "createSession|verifySession|SessionStore" apps packages
sed -n '1,220p' apps/api/src/auth/session.ts
sed -n '1,180p' apps/api/src/routes/login.ts
git diff -- apps/api/src/auth/session.ts

Пользователи Claude Code узнают этот ритм: найти, изучить, изменить, проверить. Разработчикам агентов стоит заложить этот цикл в поведение по умолчанию.

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

Типичные сбои: что происходит на самом деле, когда агенты ошибаются

Большинство агентов для программирования ошибаются не эффектно. Их ошибки выглядят правдоподобно.

Вот типы сбоев, которые я вижу чаще всего.

1. Агент устраняет симптом

Тест падает, потому что API возвращает 401. Агент меняет тест так, чтобы тот ожидал 401. Сборка проходит, продукт сломан.

Как снизить риск:

  • Требуйте от агента объяснить причинно-следственную цепочку.
  • Просите целевые тесты перед масштабными изменениями.
  • Предпочитайте исправления исходного кода обновлению снимков, если пользователь не просил изменить поведение.

2. Агент вносит слишком много изменений

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

Как снизить риск:

Make the minimal change that fixes the issue. Do not perform opportunistic
refactors unless they are necessary for correctness.

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

git diff --stat
git diff -- apps/api/src/auth/session.ts

3. Агент доверяет устаревшему контексту

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

Как снизить риск:

  • Перед редактированием перечитывайте файлы, если они могли измениться.
  • Проверьте git diff перед применением патчей.
  • Считайте вывод инструментов более актуальным, чем сведения из истории разговора.

4. Агент скрывает сбой инструмента

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

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

{
  "tool": "run_shell",
  "command": "pnpm test auth",
  "exit_code": 1,
  "stdout": "...",
  "stderr": "Cannot find module '@repo/config'",
  "status": "failed"
}

Затем дайте агенту инструкцию:

If a tool call fails, do not claim success. Diagnose the failure or clearly
report the blocker.

5. Агент записывает секреты в контекст

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

Как снизить риск:

  • По умолчанию блокируйте известные файлы с секретами.
  • Маскируйте значения, похожие на токены, в выводе инструментов.
  • Требуйте явного разрешения пользователя для доступа к путям, содержащим секреты.

Пример правил доступа к путям:

DENY_PATTERNS = [
    ".env",
    ".env.*",
    "**/secrets/**",
    "**/*.pem",
    "**/*.key",
]

def can_read(path):
    return not any(fnmatch(path, pattern) for pattern in DENY_PATTERNS)

Инструктировать модель не раскрывать секреты — хорошо. Не давать модели видеть ненужные ей секреты — ещё лучше.

Проектирование цикла агента на основе Claude API

Если вы создаёте решение непосредственно на Claude API, самый простой полезный цикл выглядит так:

  1. Отправьте системные инструкции и инструкции разработчика.
  2. Передайте задачу пользователя.
  3. Позвольте Claude запрашивать вызовы инструментов.
  4. Выполните инструменты в своей среде выполнения.
  5. Верните результаты инструментов.
  6. Повторяйте, пока модель не выдаст окончательный ответ.

Упрощённая структура запроса выглядит так:

{
  "model": "claude-sonnet-4-6",
  "max_tokens": 4096,
  "system": "You are a coding agent. Make minimal, correct changes...",
  "messages": [
    {
      "role": "user",
      "content": "Fix the auth timeout bug and add a regression test."
    }
  ],
  "tools": [
    {
      "name": "read_file",
      "description": "Read a bounded section of a workspace file.",
      "input_schema": {
        "type": "object",
        "properties": {
          "path": { "type": "string" },
          "start_line": { "type": "integer" },
          "limit": { "type": "integer" }
        },
        "required": ["path"]
      }
    }
  ]
}

Концептуально ответ с вызовом инструмента выглядит так:

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "I’ll inspect the auth timeout path first."
    },
    {
      "type": "tool_use",
      "name": "read_file",
      "id": "toolu_123",
      "input": {
        "path": "apps/api/src/auth/session.ts",
        "start_line": 1,
        "limit": 220
      }
    }
  ]
}

Затем ваша среда выполнения возвращает результат:

{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_123",
      "content": "export function createSession(...) { ... }"
    }
  ]
}

Точный синтаксис SDK зависит от версии вашего клиента, но принцип проектирования остаётся неизменным: Claude предлагает действия, ваша среда выполнения выполняет или отклоняет их, а на следующем ходе модель получает результат.

Именно это разделение делает систему понятной.

Команды и настройки Claude Code, которые стоит изучить

Даже если вы не используете Claude Code напрямую, его рабочий процесс даёт полезные примеры продуктовых решений.

Типичная начальная настройка проекта:

claude
/init

Это создаёт или обновляет инструкции проекта, чтобы в будущих сессиях были понятны соглашения, принятые в репозитории.

На практике сессия часто выглядит так:

claude "Find why the billing webhook test is flaky. Do not edit files yet."
claude "Patch the smallest fix and run the focused test."
claude "Show me the diff and summarize remaining risks."

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

{
  "mode": "investigate",
  "can_edit": false,
  "can_run_tests": true,
  "requires_confirmation_for": ["network", "delete", "install"]
}

Затем переключайте режимы явно:

{
  "mode": "implement",
  "can_edit": true,
  "can_run_tests": true,
  "requires_confirmation_for": ["network", "delete", "install", "commit"]
}

Главное здесь — не конкретная команда, а правила взаимодействия. Пользователи должны знать, когда агент только читает, когда меняет файлы и когда собирается сделать что-то с побочными эффектами.

Почему дампы промптов ненадёжны

Репозиторий на GitHub, в котором собраны системные промпты и конфигурации моделей, стал популярным, потому что инженерам естественно интересно, какие инструкции получают реальные инструменты. Я понимаю этот интерес. Чтение промптов может показать продуктовые предпочтения: какие риски беспокоят разработчиков, какие рабочие процессы они оптимизируют и как общаются с моделью.

Но скопированные промпты ненадёжны по нескольким причинам:

  • Они могут быть неофициальными. Вы можете не знать, как их извлекли и являются ли они полными.
  • Они могут быть устаревшими. Промпты агентов меняются вместе с моделями, инструментами и правилами продукта.
  • Они зависят от скрытого поведения среды выполнения. Промпт, в котором упоминается инструмент, бесполезен без реализации этого инструмента.
  • В них заложены компромиссы, специфичные для продукта. Ограничения Claude Code могут не соответствовать модели угроз вашего агента.
  • Они могут создавать ложную уверенность. Хорошо составленный промпт не обеспечивает соблюдение прав доступа.

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

Более полезное упражнение — спросить: какую проблему решает эта инструкция? Затем решите эту проблему в собственном стеке, предусмотрев поддержку и в промпте, и в среде выполнения.

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

  • Воспринимайте Claude Code system prompt как обсуждение архитектуры, а не как возможность скопировать и вставить готовое решение.
  • Размещайте устойчивые правила поведения в системных инструкциях и инструкциях разработчика, соглашения репозитория — в файлах проекта, а цели задачи — в сообщениях пользователя.
  • Обеспечивайте соблюдение ограничений для действий с высоким риском через инструменты и права среды выполнения, а не только через текстовые инструкции.
  • Требуйте конкретного подтверждения для разрушительных действий, сетевых операций, изменений зависимостей и действий, влияющих на рабочую среду.
  • Предоставьте агенту ограниченный доступ к файлам, быстрый поиск, атомарное применение патчей и структурированные сообщения о сбоях инструментов.
  • Оптимизируйте цикл, который работает на практике: изучить, спланировать, внести минимальные изменения, проверить, кратко описать риски.
  • Исходите из того, что скопированные промпты могут быть устаревшими или неполными; стройте устойчивое поведение агента на явно заданных возможностях и понятной обработке сбоев.
A

Этот блог публикует AI Prime Tech. Статьи готовятся с помощью ИИ; прежде чем полагаться на сведения, зависящие от версии, такие как идентификаторы моделей, цены и лимиты, сверяйте их с официальной документацией.

Получите более дешёвый доступ к API Claude

Один ключ API для Claude Opus 5.5, Sonnet 5, Haiku 4.5 и Fable 5.1, а также GPT-6 моделей. Оплата по мере использования, без подписки.

Получить ключ API →
AI Prime Tech — независимый сторонний API-шлюз. Claude™ и Anthropic® — товарные знаки Anthropic, PBC. Связь с этой компанией или одобрение с её стороны не подразумеваются.