Read in:
Русский

Хорошая инструкция для MCP помогает дешёвой модели быстрее находить ответы

О чём это: замеренный A/B на двух дешёвых моделях. Я подключил Claude Haiku и GPT-5.4-nano к базе документации trip2g через MCP и задал каждой по восемь вопросов. Сначала с короткой заметкой-инструкцией в контексте, потом без неё. Те же инструменты, те же вопросы. С заметкой Haiku искал на 26% быстрее и на 41% реже выгружал заметки целиком. А nano, который и сам по себе бережлив, в ней почти не нуждался. Читать, если вы держите базу знаний за MCP и не уверены, окупается ли инструкция.

Короткий ответ: хорошая инструкция не делает дешёвую модель умнее. Она исправляет расточительное поведение по умолчанию. Загвоздка в том, что не всякая дешёвая модель расточительна. На Haiku заметка дала явный выигрыш. На nano, который и без подсказки читает аккуратно, заметка почти ничего не дала и даже стоила токенов. Обе истории ниже, потому что честный вывод как раз в контрасте.

Выгода, в цифрах

Я прогнал claude-haiku-4.5 по живому MCP-эндпоинту trip2g. Семь поисковых вопросов, по три раза каждый, в двух вариантах: с заметкой-инструкцией в системном промпте и с простой строкой «у тебя есть инструменты, пользуйся ими» вместо неё. Инструменты работали по-настоящему, против реальной документации.

Метрика С заметкой Без заметки Разница
Вызовов инструментов 4.00 5.43 на 26% меньше
Токенов 17 265 18 696 на 8% меньше
Выгрузок заметки целиком 0.95 1.62 на 41% меньше
Доля чтения по секциям 71% 29% +43 п.п.
Правильный ответ найден 100% 100% поровну

Главное тут — последняя строка вместе со всеми остальными. Точность одинаковая. Заметка покупает не правильность, а эффективность: меньше обращений до того же ответа, и куда реже эти обращения кончаются выгрузкой всей заметки.

Именно последняя метрика волнует меня больше всего. «Выгрузка» — это когда модель читает заметку целиком вместо одной нужной секции. На этой базе секция это несколько сотен токенов, а целая заметка — до пятнадцати тысяч символов. Без инструкции Haiku выгружал заметку в среднем 1,6 раза на вопрос. С инструкцией — меньше одного. Заметка учит модель читать секцию, и модель слушается.

Вторая модель показала другое

Потом я прогнал ровно тот же A/B на gpt-5.4-nano. И по главной для стоимости метрике направление перевернулось.

Метрика С заметкой Без заметки Разница
Вызовов инструментов 5.14 6.05 на 15% меньше
Токенов 16 143 11 694 на 38% БОЛЬШЕ
Выгрузок заметки целиком 0.52 0.52 без изменений
Доля чтения по секциям 100% 95% +5 п.п.
Правильный ответ найден 100% 100% поровну

nano почти не выигрывает, потому что nano и так делал всё правильно. Без всякой заметки он читал по секциям в 95% случаев и выгружал заметку целиком вдвое реже, чем Haiku добивался даже с заметкой. Расточительности, которую заметке нужно было бы убрать, почти не было. Поэтому главным эффектом заметки стало то, что она добавила свои несколько сотен токенов к каждому шагу и подтолкнула nano исследовать чуть больше, а это подняло токены, а не снизило.

Вывод не «заметка плоха». Вывод в том, что заметка — это исправление расточительного поведения по умолчанию, а у nano его не было. Haiku, предоставленный сам себе, читает заметки целиком для верности; заметка это чинит. nano читает по секциям инстинктивно; чинить нечего, а контекст она всё равно ест. Если бы вы могли выбрать модель, для аккуратной вы бы заметку пропустили. Но модель, которая подключается к публичному эндпоинту, вы обычно не выбираете, так что отдать заметку всё равно правильно: она ограничивает ущерб от расточительных моделей и стоит аккуратным пары сотен токенов.

Пара специфичных для nano привычек. Он переуказывает вызовы: передаёт около семи аргументов в note_html (все поля-идентификаторы плюс match_id плюс toc_path разом) там, где Haiku передаёт два. Безвредно, сервер разрешает любой один идентификатор, но видно, что nano не пытается ужать сам вызов. И на expand nano опирался чаще Haiku, больше навигируя по структуре, прежде чем читать.

Сколько это стоит в деньгах

Токены — это механизм, но платите вы по счёту, а вход и выход тарифицируются по-разному. Я брал Claude Haiku 4.5 по 1,00 доллара за миллион входных токенов и 5,00 за миллион выходных (опубликованный прайс Anthropic), а gpt-5.4-nano — по 0,05 за вход и 0,40 за выход (тариф OpenRouter на момент прогона).

Модель $/1k без $/1k с заметкой Δ
Haiku 4.5 $22,05 $20,37 −8% (дешевле)
nano $0,78 $1,00 +29% (дороже)

(На запрос: Haiku $0,0220 без и $0,0204 с заметкой; nano $0,00078 без и $0,00100 с заметкой.)

Две вещи меня здесь удивили, и обе стоит сказать прямо.

Первое: счёт определяет вход, а не выход. В этой нагрузке входные токены — около 80% стоимости, хотя выход стоит в пять–восемь раз дороже за токен. Причина структурная: каждая прочитанная секция или заметка возвращается входом на следующем шаге, так что большое чтение — это большой входной счёт, а ответы самой модели коротки. Деньги двигают число обращений и то, сколько каждое чтение сваливает в контекст, — ровно то, чем управляет заметка.

Второе: сама заметка — это повторяющаяся входная стоимость. Она едет в контексте на каждом вызове, так что настоящий вопрос в том, перебивает ли экономия на вызове стоимость её ношения. У Haiku перебивает: срезав четверть вызовов инструментов, вы убираете больше входа, чем добавляет заметка, так что прогон с заметкой примерно на 8% дешевле — около 1,68 доллара меньше на тысячу запросов. У nano не перебивает: nano и так бережлив, заметка убирает мало, зато добавляет собственный вес, и прогон с ней стоит примерно на 29% больше — около 22 центов больше на тысячу запросов.

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

Как заметка попадает в модель

Одна честная граница у всего сказанного: этот тест кладёт заметку прямо в системный промпт модели. Он не запускает настоящее рукопожатие MCP-клиента. Так что строго я измерял «заметка в контексте», а не «реальный клиент её получил и показал модели».

Это честная замена — из-за того, куда заметка попадает в реальной схеме. initialize.instructions — стандартное поле протокола MCP: совместимый клиент забирает инструкции подключённого сервера во время рукопожатия и сам подаёт их в контекст модели. Никто не вставляет заметку в промпт вручную — это делает клиент при подключении. trip2g возвращает заметку базы документации ровно в этом поле (internal/case/mcp/resolve.go:154). Вставить заметку в системный промпт для A/B — это смоделировать то, что делает нормальный клиент.

Этот механизм я придумал довольно давно и, к стыду своему, ни разу не проверял, что реальный клиент действительно забирает это поле. Поэтому я запустил канарейку. На Claude Code на плоской подписке (перед запуском сбросить ANTHROPIC_API_KEY, иначе он идёт по платному консольному пути и падает на кончившемся балансе) я зарегистрировал базу как HTTP-сервер MCP и спросил его, ничего не вставляя в промпт: «какие инструкции подключения дал тебе сервер trip2g-docs при старте?» Он процитировал заметку дословно, под заголовком, который сам назвал «MCP Server Instructions»: строку идентичности, четырёхшаговый цикл поиска и разобранный пример с федерацией — слово в слово из docs/_mcp_initialize.md. Раз я этот текст в промпт не клал, единственный способ, которым он попал к модели, — клиент сам показал initialize.instructions. Механизм работает. (Одна гонка, которую стоит учесть: на холодном headless-старте сервер может ещё подключаться на первом же шаге, и тогда модель верно сообщает, что инструкций пока нет. Сначала форсируйте подключение одним вызовом инструмента или дайте прогреться.)

И он ведёт цикл до конца, а не просто цитирует. На вопросе «как настроить федерацию с приватным пиром через HMAC-секрет» след вызовов был: search("federation private peer HMAC secret setup"), затем note_html(pid=658, toc_path=["Adding a private peer (two-step exchange)"]). Это ровно тот цикл, которому учит заметка: поиск указателя, потом чтение одной секции по её toc_path, без выгрузки заметки целиком. Он ответил верно и сослался на заметку.

Значит, путь доставки реален, а не предположён: канарейка доказывает, что клиент сам показывает заметку, а след с федерацией — что модель затем ей следует на живой базе. A/B остаётся той частью, что измеряет величину эффекта: насколько заметка сдвигает поведение по сравнению с моделью, предоставленной самой себе (вариант без заметки выше показывает, что она и сама иногда дробит). Доставка подтверждена вживую; величина измерена через A/B. (Codex я не трогал: headless он медленный и прожорливый по токенам, а ограниченная проверка — не место, чтобы его настраивать.)

За счёт чего это работает

Заметка учит одному циклу, и весь фокус в этом цикле:

  1. search(query) возвращает указатели, а не документы. У каждого попадания есть toc_path — хлебная крошка до конкретной секции, которая совпала.
  2. note_html(pid=N, toc_path=[...]) читает только эту секцию. Несколько сотен токенов вместо всего файла.
  3. expand(pid=N) обходит оглавление по одному уровню, когда указатель нечёткий, чтобы модель дошла до нужной секции, а не гадала.
  4. Целиком заметку читаем только тогда, когда expand показал, что дробить в ней нечего.

Голая модель с теми же инструментами обычно делает search, а потом на всякий случай читает верхний результат целиком. Это работает и стоит дорого. Заметка меняет привычку по умолчанию: сначала тяни секцию, а целая заметка это крайний случай. На вопросе про федерацию модель с заметкой ответила за 2,7 вызова и ни разу не выгрузила заметку целиком; голая заняла 5,3 вызова и выгружала почти каждый раз.

Вторая половина заметки — это ограничители, написанные из того, как инструменты ломаются на самом деле. На этой базе неверный toc_path не выдаёт ошибку. Он молча возвращает всю заметку. Поэтому заметка говорит модели: если чтение по секции вернулось намного длиннее секции, значит указатель промахнулся, вызови expand, прочитай настоящий заголовок и не повторяй вслепую. Одна эта фраза превращает молчаливую ошибку на 15 000 символов в дешёвое восстановление.

Где я честен

Заметка не волшебная, и притворяться иначе — только тратить ваше время.

Голая модель не была беспомощной. Сама по себе она читала по секции примерно в трети случаев. Haiku знает про toc_path, как только видит схему; заметка лишь делает точное чтение привычкой, а не исключением.

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

Один вопрос с заметкой обошёлся дороже, чем без неё. На «как опубликовать хранилище» модель с инструкцией продолжала доискиваться точной секции (7+ вызовов), а голая раньше останавливалась на более грубом ответе. Уклон в точное чтение секций иногда стоит лишнего вызова. Это настоящий размен, небольшой, и он окупается сокращением выгрузок на всех остальных вопросах.

И один вопрос оказался ничьёй по построению, по крайней мере для Haiku: «что делает expand» оба варианта Haiku ответили по памяти, потому что модель и так знает, что значит «expand» вообще. Вопрос на общее знание — это не проверка поиска, так что я посчитал его отдельно. nano, к слову, даже на нём предпочёл поиск, а не память.

Каждая база знаний своя — опишите свою

Единственно верного способа искать по базе знаний нет. Моя — гибрид ключевых слов и векторов с циклом дробления по секциям, но ваша может быть чистым RAG по векторным чанкам, wikiLLM, обходящим граф wiki-ссылок, обычным полнотекстом или смесью всего этого. Каждая устроена по-своему и вознаграждает свою технику поиска. Агент, подключившийся вхолодную, не может знать, на что он смотрит, поэтому гадает, а из гадания и берутся лишние токены и неверные ответы.

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

И доставляется это бесплатно. Как показано выше, совместимый клиент сам показывает эту инструкцию через поле MCP initialize.instructions при подключении, так что каждый агент, который заговорит с вашей базой, стартует с вашим руководством уже в контексте. Если вы держите базу, практические шаги — в dev-заметке docs/dev/mcp_instructions_guide.md («How to write good MCP instructions for your base»), а заметка, которую тестировал этот прогон, — разобранный пример в docs/_mcp_instructions.md.

Почему дешёвым моделям Claude это заходит

Гипотеза, а не доказанное утверждение, о том, почему даже Haiku без заметки так часто читает по секциям. В работе Anthropic Contextual Retrieval перед эмбеддингом к каждому чанку добавляется его ситуирующий контекст — секция и заголовок, — и в референсной реализации этот контекст порождала Claude 3 Haiku. То есть «этот абзац живёт под этим заголовком в этом документе» — форма, которую модели Claude учили и производить, и потреблять. trip2g выдаёт ровно это как хлебную крошку toc_path в каждом совпадении поиска. Догадка: toc_path — знакомая опора в тот же миг, как модель Claude видит схему, поэтому она дробит по секциям, даже когда её об этом не просят. Инструкция не учит чужому приёму, она делает уже знакомый ход поведением по умолчанию, а не исключением.

Метод, чтобы повторить

Модели: claude-haiku-4.5 и gpt-5.4-nano через OpenRouter, инструменты — живые MCP search, note_html, expand, similar. Системным промптом варианта A была заметка docs/_mcp_initialize.md без фронтматтера, ровно то, что отдаёт MCP-ответ initialize. У варианта B — одна общая строка. Восемь вопросов по разным темам: федерация, публикация, контроль доступа, инструменты токен-экономии, Telegram; по три прогона; сорок восемь прогонов на модель. «Выгрузка» — это ответ note_html длиннее 6000 символов. Всего потрачено около 0,92 доллара на Haiku и 0,04 доллара на nano.

Полные таблицы, разбивка по вопросам, сырые прогоны и сам скрипт лежат в dev-заметках: 2026-07-02_mcp_haiku_ab.md, 2026-07-02_mcp_haiku_ab_results.json и 2026-07-02_mcp_nano_ab_results.json.

Напишите свою

Если вы держите базу на trip2g, дайте ей собственную заметку initialize. Начните с того, что это за база, научите циклу «search, потом toc_path, потом expand», покажите один разобранный пример с реальным id заметки и напишите ограничители из реальных сбоев ваших инструментов. Держите коротко: дешёвая модель тонет в стене текста. Полный рецепт, с подводными камнями затенения и чек-листом проверки на живом эндпоинте, лежит в dev-заметке docs/dev/mcp_instructions_guide.md (она идёт вместе с самой заметкой-инструкцией).

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