Системный промпт и дизайн инструментов бизнес-агентов на примере Claude Code
Разобрав системный промпт и реализацию инструментов Claude Code, автор приходит к выводу: в основе бизнес-агента лежат системный промпт и дизайн инструментов. Он описывает многоуровневую структуру промпта — объявление роли, ограничения безопасности, правила поведения системы, руководство по выполнению задач, описание инструментов, стиль общения и информация об окружении — и предлагает располагать их в таком порядке: роль и цель в контексте, системные указания, бизнес-процесс, дополнительные рекомендации, форматы работы с инструментами и окружение.
Автор разбирает структуру системного промпта и компромиссы в дизайне инструментов Claude Code, предлагая переносимые шаблоны и запасные варианты для создания собственных бизнес-агентов.
Как спроектировать агента под конкретную задачу бизнеса? Если отбросить управление контекстом, память и прочие дополнительные механизмы, ядро агента, пригодного для бизнеса, — это системный промпт плюс дизайн инструментов. В этой статье на примере разбора дизайна Claude Code мы посмотрим, на какие детали и подходы стоит обращать внимание при создании агента под конкретный бизнес-процесс.
Бизнес-назначение Claude Code
Проектирование агента начинается с его бизнес-процесса. Claude Code — это агент для написания кода. Значит, его ядро таково:
- принять запрос пользователя;
- найти нужные файлы, чтобы понять, куда вносить изменения;
- внести изменения в файлы;
- скомпилировать, запустить, протестировать.
Это и есть базовая модель данного бизнес-процесса. Все промпты и инструменты Claude Code спроектированы вокруг неё.
Системный промпт Claude Code
Ниже — обобщение промптов, извлечённых из Claude Code, в том порядке, в котором они идут в самом промпте Claude Code. Подробности смотрите прямо в оригинале промпта.
Заявление о роли
You are an interactive agent that helps users with software engineering tasks...
Как и в любой стандартной записи промпта, сначала объявляется роль агента.
Характеристики роли задают идентичность агента и настраивают предпочтения модели в выводе. Но самое главное — они настраивают образ мышления модели, то есть угол зрения, под которым она смотрит на задачу.
Описание контекста даёт модели представление о состоянии мира, чтобы на этой основе она выстраивала ход мысли и процесс решения.
Постановка цели тоже критична: она с самого начала даёт модели понять цель и миссию.
Всё это похоже на создание анкеты и «лица» для новорождённого или, если говорить о компаниях, на построение ролевой модели должности при найме. Процесс этот крайне важен и обычно требует тщательной проработки. Но большинство людей, дойдя до этого места, просто пишут какую-нибудь роль наугад.
Ограничения по безопасности
В Claude Code сразу после роли идёт блок ограничений, связанных с безопасностью. Видимо, потому что Anthropic придаёт безопасности огромное значение. Отсюда вывод: когда пишешь промпт, самые важные ограничения нужно ставить в самое начало.
Есть ещё одно правило — никогда не генерировать и не угадывать URL. Непонятно, зачем оно нужно. Скорее всего, Claude обнаружил, что такое поведение срабатывает очень часто.
Правила поведения системы
Эта часть длинная, но это не системное структурированное руководство или набор правил, а скорее заметки по принципу «что встретилось, то и записали». Она больше про внутренние договорённости относительно вывода модели. Больше про низкий уровень, можно даже назвать это метаправилами. Например, как говорить, какие могут быть теги, результаты инструментов и внешние данные и тому подобное.
Это можно понимать как набор протоколов модели-агента в текущем сценарии. Он стоит здесь потому, что эти части требуют высокой степени внедрения и приоритета, и в дальнейшем процессе необходимо гарантировать, что от них не отклоняются.
- Весь текст, который вы выводите вне вызова инструментов, показывается пользователю. Общайтесь с пользователем через текстовый вывод. Вы можете использовать форматирование в стиле GitHub Markdown, оно будет отрендерено моноширинным шрифтом по спецификации CommonMark.
Выполнение задач
Это уже настоящее руководство по выполнению, связанное с бизнесом. Каждый пункт — инструкция «как делать» применительно к разработке ПО. Что-то вроде наставлений или правил поведения для нового сотрудника или других людей.
Но в целом здесь нет системности и структуры. Возможно, это говорит о том, что пункты добавляли по мере того, как они приходили в голову, и со временем они накапливались. А может, это говорит о том, что здесь и не нужно системного руководства в стиле инструкции. (Такие правила, наоборот, могут помогать модели раскрыться.)
Обратите внимание на заголовок: Doing tasks. Сам заголовок — это триггер сценария для модели. Здесь нет привычного для многих оглавления вроде «Руководство по разработке». Дальше тоже много заголовков — таких же глагольно-именных оборотов.
Но лучше ли такой способ подачи промпта? Я поискал в статьях — строгих доказательств нет. Наоборот, во многих работах говорится, что серебряной пули не существует. Судя по коду проекта, вполне вероятно, что такой стиль написания вывели через оценку и A/B-тесты.
Осторожное выполнение операций
Этот фрагмент понять проще. Весь он — о правилах более безопасного и контролируемого написания кода. Включает контекст, причины, примеры и так далее.
Я выделяю его отдельно, потому что это очень важные правила для сценария написания кода.
Использование инструментов
Здесь нет инструкций и правил по отдельным инструментам. Сценарии и способы использования каждого инструмента самодостаточно описаны в самом описании инструмента. Здесь в основном высокоуровневые, общие, межынструментальные рекомендации.
Тон и стиль
Этот фрагмент совсем короткий, в основном про то, как выводить содержимое, ставить ли двоеточие и прочие мелкие детали.
Всё перечисленное — фиксированные блоки, которые какое-то время лежат в глобальном кэше и одинаковы для всех пользователей. Дальше содержимое разветвляется по пользователям, различается для внутренних и внешних или проходит A/B-тесты.
Текстовый вывод
Служит для нормирования содержимого, которое выводит модель. Касается той части, которая в итоге показывается пользователю, чтобы сделать её удобнее для него.
假设用户看不到大多数工具调用和思考过程——只能看到你的文本输出。第一次调用工具前,用一句话说明你要做什么。工作过程中,在关键时刻给出简短更新:有发现时、改变方向时、遇到阻塞时。简短是好的——沉默不是。每次更新一句话几乎总是足够。
Инструкции для конкретной сессии
Эта часть посложнее: она зависит от конфигурации и различается от сессии к сессии. Но по сути это указания про параллельную работу агента и число итераций, а также про shell и skill и так далее.
Дальше идёт блок памяти, в этой статье я его опускаю.
Информация об окружении
Разная информация об окружении:
# Окружение
Окружение, в котором вы вызваны, следующее:
- Основной рабочий каталог: /Users/rayxiang/develop/hyyc-demo
- Является ли git-репозиторием: true
- Платформа: darwin
- Shell:zsh
- Версия ОС: Darwin 25.0.0
- Вы работаете на модели под названием Sonnet 4.6. Точный ID модели — claude-sonnet-4-6.
- Дата отсечения знаний ассистента: август 2025 года.
- Новейшее семейство моделей Claude — это Claude 4.X. Идентификаторы моделей: Opus 4.7 — 'claude-opus-4-7', Sonnet 4.6 — 'claude-sonnet-4-6', Haiku 4.5 — 'claude-haiku-4-5-20251001'. При создании AI-приложений по умолчанию выбирайте самую новую и самую мощную модель Claude.
- Claude Code доступен через терминальный CLI, настольное приложение (Mac/Windows), веб-приложение (claude.ai/code) и расширения для IDE (VS Code, JetBrains).
- В быстром режиме Claude Code использует Claude Opus и ускоряет вывод (без переключения на более слабые модели). Переключается командой /fast; поддерживаются Opus 4.6 и Opus 4.7.
Управление контекстом
# Управление контекстом
当对话变长时,当前上下文的部分或全部会被摘要;摘要连同剩余未摘要的上下文会进入下一个上下文窗口,工作可以继续——你不需要提前收尾或在任务中途交接。
Зачем вообще подсказывать это модели? Предполагаю, что это коррекция самой модели. Возможно, Anthropic обнаружил, что когда контекст почти заполнен, модель автоматически начинает сворачивать задачу — это поведение по умолчанию из предобучения.
Указания в промпте
Вот и вся структура основного промпта. Что из этого можно вынести?
Структура
Я считаю, что все системные промпты агентов можно копировать по этому шаблону:
- контекст, роль, определение цели: фон, задаём базовый цвет;
- системные указания: определяем низкоуровневое поведение, метаправила; в начале они позволяют корректировать базовое поведение модели и хорошо удерживаются в памяти;
- бизнес-процесс: основные правила и моменты, на которые стоит обратить внимание в сценарии;
- дополнительные указания по бизнесу: безопасность? осторожность?
- дополнительная информация об инструментах, тоне, формате, окружении и так далее.
Как писать
Почти все руководства по промптам говорят только об общих приёмах: чётко описать цель, задать роль и так далее. Но, читая промпты Claude Code, замечаешь разницу в тоне по сравнению с обычными промптами: будто это наставление человеку.
На мой взгляд, особенно стоит поучиться двум чертам:
Объяснять причины: как когда учишь новичка — не только показываешь, что делать, но и говоришь, почему так. Нужно объяснить, почему дана такая инструкция и каков контекст.
- 工具调用前不要用冒号。你的工具调用可能不会直接显示在输出中,所以"让我读一下文件:"后跟读取调用这种写法,应改为"让我读一下文件。"(句号结尾)。
**Объяснять последствия:** не только говорить, как делать, но и рассказывать, к каким результатам это приведёт.
写更新时,要让读者能冷启动接上:完整的句子,不出现会话前文里未解释的行话或缩写。但要紧凑——一个清晰的句子好过一个清晰的段落。
Основной набор инструментов
Чтобы агент мог работать в конкретной среде, критически важен дизайн основного набора инструментов.
Инструменты должны покрывать самые частые рабочие сценарии в этой среде и быть оптимизированы под эти сценарии с точки зрения безопасности и эффективности.
Посмотрим, какие ключевые инструменты есть у Claude Code. (Убираем продвинутые вспомогательные инструменты вроде задач и планирования.)
- Чтение и работа с файлами: Read — читать файл, Write — писать файл, Edit — редактировать файл.
- Поиск: Glob — искать файлы, Grep — искать содержимое файлов.
- Выполнение: Bash — инструмент командной строки.
По сути, это и есть минимальный набор инструментов, необходимый для программирования, всё остальное — дополнения. Почему именно они, а не просто bash на всё? Думаю, у разработчиков были глубокие соображения.
Read
Чтение — начало всего. По сравнению с использованием cat и других bash-команд, Read на уровне инструмента задаёт контракт: номера строк. При чтении инструмент выдаёт вывод с номерами строк, и в промпте модели тоже сказано, как понимать эти номера строк. Поэтому последующее редактирование и инкрементальное чтение можно напрямую вести от этой базы. В этом главное отличие и точка оптимизации по сравнению с cat и другими bash-инструментами.
**Мультимодальность:** инструмент read сразу встраивает мультимодальность, что позволяет агенту читать через единую точку входа и снижает неоднозначность инструментов и сложность вызовов.
**Подстраховка на случай аномального поведения:** например, чтение уже прочитанного файла, чтение пустого файла, чтение несуществующего файла — всё это заранее предусмотрено и оформлено как контракт с моделью. Эти ситуации с большой вероятностью возникают при чтении, и их определение внутри инструмента, а не через ошибку bash, позволяет модели понять ситуацию семантически.
**Границы и безопасность:** относительные пути запрещены, shell не используется (чтобы избежать проблем с экранированием), жёстко заданные границы снижают число ошибок.
Инструмент Read относительно прост, потому что он не меняет содержимое, поэтому риск для безопасности ниже.
Edit
Редактирование — это то место, где реализуются все итоговые операции, но изменение — действие повышенной опасности, поэтому Claude Code сделал очень тонкую защиту.
Основной процесс инструмента Edit можно описать так: заменить old_string на new_string, различая глобальную замену и замену только одного вхождения (эти два варианта намеренно сделаны разными, чтобы удобнее обрабатывать исключительные ситуации).
Почему не редактирование по позиции, а редактирование по содержимому? Редактирование по позиции — интуитивный вариант дизайна. Например: заменить строку, начинающуюся в позиции xxxx и имеющую длину 20, на «xxxx».
У редактирования по позиции есть несколько проблем. Во-первых, позиция — это число, а модели тяжело считать математику, поэтому при выводе результата инструмента стабильности может не быть. Во-вторых, так сложнее стабильно обрабатывать исключения при сбое. Замена строки, которая реально есть в оригинале, если её изменили, обязательно провалится. А редактирование по позиции может в любой момент «успешно» выполниться и тихо провалиться. В-третьих, это читаемость и аудируемость. Заменённую строку проще понять семантически и проще проверить.
Страховка на основе стратегии записи по old string
Инструмент Edit использует стратегию замены по содержимому, и это даёт дополнительную защиту результата записи.
- Если old_string не найден в исходном файле, сразу возвращается ошибка. Это защищает от записи неизвестной строки. Напротив, при записи по координатам позиции такая ошибка просто проглатывается.
- Если old_string найден в нескольких местах, но match_all не включён, тоже будет ошибка. Сообщение об ошибке подсказывает модели, как исправиться: либо расширить контекст до единственного совпадения, либо заменить всё.
Эти две вещи трудно сделать при стратегии по позиции. Стоит сменить стратегию — и сложность страховки резко возрастает. Стратегия реализации инструмента — тоже важный фактор при проектировании агента.
Механизм «сначала прочитать, потом изменить»
Так называемый Harness по сути — это защита от случайности в выводе модели.
Одна из важных проблем процесса редактирования — что делать, если правка вносится в то, чего на самом деле не существует, или если содержимое файла изменилось прямо во время правки. Поскольку вывод самой модели нестабилен, такую ситуацию нужно обязательно предусмотреть. Инструмент edit требует сначала прочитать, а потом изменять, и достигает этого эффекта через несколько уровней защиты.
- В промпте модели сначала есть такое требование: если файл уже был прочитан в истории сообщений, можно продолжать, иначе — сразу ошибка.
- Сразу за этим идёт прямое сравнение времени последнего чтения с временем последнего изменения: если оно отличается от записанного времени изменения, запрос отклоняется и требуется перечитать файл.
- Но и после проверки ещё не всё: в конце в критической секции однопоточного окна (без await) выполняется чтение и запись как подстраховка.
- И даже при этом у файла есть функция истории (важный вспомогательный компонент) — если записал неправильно, можно восстановить.
Общая цель — гарантировать, что при записи файл самый свежий.
Write
Write — это отдельный инструмент, его основную идею можно понять так: заменить всё содержимое целевого файла новым содержимым или создать файл.
Почему write не делит один инструмент с Edit? Достаточно было бы добавить один параметр, чтобы объединить их и получить на один инструмент меньше, к тому же обработка частично похожа — это вполне соответствует логике программиста. И действительно, некоторые так и делают. Здесь мы не судим, кто прав, кто виноват; важно подумать и обратным ходом восстановить по реализации Anthropic, какие соображения были у них в тот момент.
Представьте, что было бы, если бы их объединили? Режим вызова инструмента наверняка стал бы таким:
old_string?: string // rewrite 模式不需要
new_string?: string // edit 必需
mode?: 'edit' | 'rewrite'
Очевидные плюсы:
- Меньше инструментов — меньше подсказок в контексте, сложность выбора инструмента моделью явно снижается. Это самый очевидный выигрыш.
- С семантической и логической точки зрения единое выражение тоже легче понять.
Но какова цена?
- С точки зрения бизнеса ключевой вопрос в том, где проходит граница бизнес-решения «изменить небольшой фрагмент или переписать весь текст» — она большая или маленькая? Для модели это точка принятия решения — выбор инструмента или настройка параметра? Логически, если поместить решение в выбор инструмента, когнитивная нагрузка на модель заметно меньше.
- По опыту промпт-инжиниринга (это видно в комментариях телеметрии) надёжность правильного выбора инструмента намного выше, чем правильной комбинации параметров.
С точки зрения инженерии, цена ошибки — очень хороший ракурс.
- Если модель выбрала не тот инструмент, будут явные структурные сбои и ошибочное поведение, которые легко обнаружить, проверить и оптимизировать.
- Другой случай — модель просто заполнила параметры неправильно. Нужно было редактировать, но использовался rewrite для полной перезаписи. Хотя цель всё ещё достигается и синтаксически это допустимо, diff огромный, токены тратятся впустую, к тому же гораздо легче заодно что-то улучшить или внести другую ошибку, и это крайне трудно заметить.
С точки зрения сложности: поскольку Edit — явно более частый сценарий, вынесение его в отдельный инструмент позволяет ужать обработку сложности внутрь инструмента. Разделение также позволяет отдельно записывать и проверять правила доступа и процессы. А объединение запутает пути аудита: раньше у каждого был свой путь, теперь нужно добавить целый набор проверок функций и параметров.
Различия в подстраховке write и edit
У write и edit значительная часть механизмов подстраховки общая: раскрытие путей через hook, сканирование командной памяти на секреты, принудительное «сначала прочитать, потом изменить», двухэтапная проверка устаревания по mtime и так далее.
Но механизм обработки edit явно сложнее и тоньше: чтобы скальпельное редактирование работало лучше.
- Проверка совпадения: редактируемая строка должна уже существовать.
- Нормализация кавычек: обработка случая, когда модель может выдать разные кавычки.
- Защита по типу файла: .ipynb отклоняется и направляется в NotebookEdit.
glob
Основная задача glob — находить файлы по имени или по шаблону имени файла.
Соответствующий сценарий: прежде чем редактировать файл, агенту нужно по задаче и цели найти и понять соответствующий файл.
В основе инструмента glob лежит ripgrep (улучшенная версия grep, написанная на Rust, по производительности лучше grep). По сути внутри:
rg --files --glob '<模式>' --sort=modified --no-ignore --hidden --glob '!<deny目录>' ...
То есть используется режим перечисления файлов ripgrep как движок этого инструмента.
Почему не использовать find или ls из bash? Возможные проблемы такие:
- find не умеет ограничивать длину вывода — может выдать и десятки тысяч, и миллионы строк. Это жёсткое ограничение инструмента find.
- find неупорядочен, а rg может сортировать по mtime, что удобно для вывода недавно изменённых файлов вперёд.
- find означает необходимость идти через инструмент bash, а значит, возможны ошибки экранирования и сложная семантика, неудобная для распознавания пользователем.
Словом, для такого сверхчастого сценария, как glob, использование специализированного инструмента явно даёт гораздо больше выгоды.
GREP
В основе grep тоже rg. Но в отличие от glob инструмент grep инкапсулирует все параметры rg. По сути, программа rg напрямую отдаётся модели.
Почему бы не отдать программу модели напрямую, чтобы она её вызывала, или не позволить модели идти через bash? Ответ: для этого частого сценария внутри нужно выполнить некоторую обработку для подстраховки и оптимизации, чтобы обеспечить эффективность и гладкость процесса.
- Параметры фактически — это параметры rg. Поэтому сохраняются все возможности rg, но структурированные параметры предотвращают инъекции и ошибки экранирования.
- Вывод ограничен и урезан: по умолчанию выдаются только имена файлов, чтобы не переполнить контекст.
- Инкапсулирована пагинация. Внизу она и так поддерживается, здесь делается обёртка, чтобы явно отдать модели возможность пагинации и дать явный сигнал об усечении: show results with pagination. Семантика яснее.
- Добавлена страховка безопасности: если pattern, заданный моделью, начинается с -, добавляется -e для защиты от инъекции.
Вопрос: параметры уже описаны, зачем ещё в описании инструмента повторять, как использовать различные параметры?
Философия проектирования одного инструмента
Если посмотреть на промпт инструмента grep, может возникнуть вопрос: о схеме инструмента, то есть о том, как использовать и что означают параметры, уже есть в описании схемы. Почему же в промпте самого инструмента так много всего этого? А в подсказке инструмента edit такого описания параметров нет — там больше о сценариях использования самого инструмента.
Отсюда вытекает философия и принципы проектирования инструмента:
- Системный промпт агента: управляет частью между инструментами, например различиями между инструментами, разграничением сценариев использования и т. д.
- Описание инструмента описывает рабочие сценарии и способы использования инструмента: когда и как использовать.
- Схема управляет смыслом параметров, типами и значениями, исключительными ситуациями и т. д.
Для модели: инструмент выбирается по описанию, а параметры заполняются по аннотациям.
Но если существует режим deferr, то есть изначально отправляется только описание инструмента (у Claude такое есть), а инструмент при этом довольно сложный: различия некоторых параметров влияют на сценарий использования инструмента. Например, в инструменте grep использование параметра glob или его отсутствие соответствует разным ситуациям. Тогда эту часть описания необходимо добавить в описание инструмента.
Ещё один случай — когда речь идёт о связях между несколькими параметрами, описание параметров тоже нужно поднять в описание инструмента, например этот фрагмент: "By default patterns match within single lines".
Словом, всё, что касается того, как и когда использовать этот инструмент, должно быть поднято в описание инструмента.
Об agent search
В промпте есть фрагмент: Use ${AGENT_TOOL_NAME} tool for open-ended searches requiring multiple rounds. Так не возникнет ли циклическое делегирование? И как Claude подстраховывает такую ситуацию?
На самом деле, если не ограничивать, я считаю, такая ситуация вполне вероятна: агент порождает потомка, используя системный промпт с добавленными инструментами grep и agent. Тогда агент, получив задачу поиска, тоже считает её сложным поиском и по подсказке продолжает порождать агентов — бесконечный цикл.
Посмотрим, как это предотвращает Claude.
- Во-первых, explore agent: в его определении сразу отключён agent tool, поэтому он просто не может больше порождать агентов.
- В промпте If you ARE the fork — execute directly; do not re-delegate. Это объявление для самого агента, мягкое ограничение.
- В данных телеметрии есть depth: каждый добавленный уровень глубины фиксируется телеметрией — это подстраховка на потом.
Итог
Подведём итог по некоторым ключевым принципам и моментам, на которые стоит обратить внимание:
- Инструментализировать ключевые бизнес-операции и заключить с основным промптом модели контракт, одновременно управляя границами поведения и читаемостью модели и инструментов, — так формируется экосистема под бизнес (возможно, это и есть harness).
- Для частых сценариев следует абстрагировать специализированные инструменты.
- Для инструментов нужно понимать различные границы через их внутренние механизмы и сценарии применения. На границах строить защиту.
- Обращайте внимание на очень мелкое аномальное поведение: модель может выдать что угодно, вполне вероятно похожее на правильное, но с тонкими отличиями — процесс верный, но на результат влияет.
- Обязательно выстраивайте систему телеметрии: статистика и аудит по сценариям, вызовам инструментов, промежуточным ошибкам — только так можно узнать, где именно в реальной работе возникают ошибки и каковы частые результаты.
- Для аномального поведения инструментов обычно есть трёхуровневая стратегия подстраховки: мягкий уровень — ограничения в промпте; жёсткий уровень — проверка фактического ввода, вывода и выполнения инструмента; ловящий уровень — телеметрия, захват и анализ поведения и результатов, регулярная оптимизация, A/B-тестирование.
Источник: Juejin · Популярное об ИИ за неделю · juejin.cn