MODULE_02 · УРОК 2.1

Описания, которые работают

С тремя инструментами короткие WHEN TO USE / WHEN NOT TO USE ещё тянут. Добавите четвёртый, пятый, а потом ещё и субагентов... и модель снова поплывёт: полезет в bash там, где хватило бы read. Лекарство то же: описания. Просто их нужно сделать жёстче и полнее.

ЧТО ПОЛУЧИТСЯ У каждого инструмента — однотипный «контракт» из пяти блоков. На неоднозначных фразах модель стабильнее выбирает read / grep / bash.

Слова, которые встретятся

  • Контракт описания — фиксированный шаблон текста у инструмента. Все tools пишутся одинаково, модели проще сравнивать.
  • Мягкий запрет (WHEN NOT TO USE) — «лучше возьми другой tool».
  • Жёсткий запрет (DO NOT USE FOR) — «этим вообще не решают задачу X». Да, похоже на мягкий. Намеренно: модели нужно сказать дважды.
  • Bash gravity — привычка модели хвататься за терминал, как за швейцарский нож. Наша задача — отговорить её вежливым, но упорным текстом.

Быстрый путь

  1. Расширьте docstring каждого tool до пяти секций.
  2. Добавьте USAGE (ограничения параметров) и EXAMPLES (конкретные вызовы).
  3. Оставьте оба негатива: WHEN NOT TO USE и DO NOT USE FOR.

Упражнение 2.1

Приведите описания read, grep и bash к полному контракту.

  • Первая строка — что делает tool и что возвращает.
  • WHEN TO USE — 2–4 сценария словами из реальных промптов.
  • WHEN NOT TO USE — мягко указать другой инструмент по имени.
  • DO NOT USE FOR — жёсткие границы («никогда не для поиска / не для cat»).
  • USAGE — лимиты, дефолты, то, чего не видно из типов аргументов.
  • EXAMPLES — 2–3 конкретных набора аргументов.

Зачем два «не делай так»

Кажется, что WHEN NOT TO USE и DO NOT USE FOR дублируют друг друга. Так и есть. Под нагрузкой (неясный промпт, много tools) модель «забывает» мягкий намёк и снова тянется к bash. Второй запрет — ремень безопасности. Сказал один раз — может проскочить. Сказал два — почти всегда держится.

Полный контракт на примере

docstring для grep

"""Поиск по содержимому файлов через regex. Строки с путями к файлам.

WHEN TO USE: паттерны по многим файлам, определения функций,
  импорты, TODO, сообщения об ошибках.

WHEN NOT TO USE: чтение уже известного файла (используй read).
  Запуск команд (используй bash).

DO NOT USE FOR: чтение файлов (read), список каталогов (bash),
  правка файлов (edit / write — появятся позже).

USAGE: pattern — строка regex. glob — маска вроде "*.py".
  Результат обрезается на 50 совпадениях.

EXAMPLES:
  - TODO: pattern "TODO" glob "*.py"
  - определения функций: pattern "def \\w+" glob "*.py"
  - импорт пакета: pattern "from pydantic_ai" glob "*.py"
"""

docstring для read

"""Прочитать файл проекта. Возвращает пронумерованные строки.

WHEN TO USE: просмотр содержимого, конфигов, исходников,
  кусок файла через offset/limit.

WHEN NOT TO USE: поиск по многим файлам (используй grep).
  Запуск команд (используй bash).

DO NOT USE FOR: поиск по коду (grep), выполнение в shell (bash),
  изменение файлов (edit / write).

USAGE: path — относительно рабочей директории.
  offset и limit необязательны. Вывод не больше 500 строк.
"""

docstring для bash

"""Выполнить shell-команду в рабочей директории.

WHEN TO USE: сборка, установка пакетов, тесты, git, список файлов.

WHEN NOT TO USE: чтение файла (используй read).
  Поиск по паттерну (используй grep).

DO NOT USE FOR: чтение файлов (read), поиск по коду (grep).

USAGE: command — одна строка shell. Команды вне белого списка
  блокируются и возвращают понятное сообщение.

EXAMPLES:
  - список файлов: command "ls -la"
  - статус git: command "git status"
  - тесты: command "pytest"   # если добавите в белый список
"""
Секция Зачем
Первая строка Что делает и что отдаёт
WHEN TO USE Сценарии и слова из промптов пользователя
WHEN NOT TO USE Мягкий редирект на другой tool
DO NOT USE FOR Жёсткая граница, повтор
USAGE Лимиты и дефолты, которых нет в типах
EXAMPLES Конкретные вызовы «скопируй как образец»

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

Проверьте

По одному промпту на каждый «характер» инструмента:

uv run python main.py . "Найди все TODO-комментарии в проекте"
uv run python main.py . "Прочитай pyproject.toml"
uv run python main.py . "Перечисли файлы в этой директории"

Ожидание: TODO → grep, файл → read, список → bash с ls. Смешанные фразы вроде «покажи содержимое pyproject через cat» могут уйти и в read, и в bash — это размытый промпт, не обязательно баг маршрутизации.

Готово, если:

  • У всех трёх tools есть все пять секций описания
  • Поиск TODO уходит в grep
  • Чтение файла уходит в read
  • Список файлов уходит в bash
  • (бонус) Убрали EXAMPLES — и поймали, где маршрутизация впервые ломается
ЭКСПЕРИМЕНТ Сломайте самое любимое описание по секциям: EXAMPLES → DO NOT USE FOR → USAGE. После каждого выреза прогоните три тестовых промпта. Где DeepSeek первым делом свалится в «давайте просто в bash»?