Синтетический кейс

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

Agent session cache reuse — синтетический кейс

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

Автор — Сергей НотевскийСинтетический кейсПроверено

Задача кейса

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

Доказательная граница кейса

Кейс проверяет только порядок инструментов в двух JSON-файлах; он не запускает модель или кэш, не использует рабочий трафик и не измеряет попадания в кэш, задержку, стоимость или качество.

Синтетический кейс. Оба запроса созданы специально для этой публичной демонстрации. В них нет журналов рабочей системы, пользовательских данных, внутренней архитектуры или измерений реальной системы.

Кейс проверяет небольшой участок пути агентного запроса. Системное и пользовательское сообщения, модель, определения инструментов и схема ответа одинаковы. Во втором JSON меняется только порядок двух инструментов. Закреплённая версия layout_linter.py должна принять стабильный алфавитный порядок и вернуть AP-2 для перестановки.

Это доказательство на уровне входных файлов. Модель не вызывается, сеть провайдера не используется, состояние кэша не создаётся. Узкий тест воспроизводимо доказывает один факт о форме входа и не выдаёт себя за сквозное измерение.

Контекст

Agent runtime часто собирает tools из registry на каждом шаге. Плагины загружаются асинхронно, permissions фильтруют действия, а язык программирования не всегда обещает нужный порядок после объединения нескольких источников. В результате одинаковый смысловой набор способен сериализоваться по-разному.

Для prefix cache порядок существенен. Runtime сравнивает токенизированный префикс или его block hashes, а не множество tools как математический set. Если tool schemas расположены раньше пользовательской динамики, перестановка меняет префикс до всей последующей истории.

Это техническая гипотеза, а не утверждение о конкретном provider hit. Чтобы проверить реальный cache path, понадобились бы documented usage fields, route evidence и повторный вызов в одном cache domain. В кейсе такой информации нет.

Наблюдаемый симптом

Репозиторий содержит два файла:

  • evidence/v3/agent-session-cache-reuse/step-stable.json перечисляет lookup_policy, затем write_file;
  • evidence/v3/agent-session-cache-reuse/step-drift.json перечисляет write_file, затем lookup_policy.

Все остальные поля эквивалентны. Оба набора данных используют Chat-style messages, одно и то же имя модели, одинаковые описания функций и одну JSON Schema. В ранних сообщениях нет метки времени, идентификатора запроса или другого намеренно изменчивого поля.

Симптом здесь — не падение hit rate. Наблюдаемое различие состоит только в order массива tools. Его можно увидеть обычным diff и затем проверить правилом AP-2.

Решение и ограничения

Для демонстрации выбран deterministic order по имени функции. Это подходит нашим синтетическим tools, потому что порядок не несёт отдельной семантики. В реальном агенте сортировать автоматически безопасно не всегда: некоторые adapters или prompts способны придавать первому инструменту значение. Перед изменением команда проверяет API contract и качество tool selection.

Запросы намеренно не содержат credentials, tenant identifiers и текст пользователей. Названия функций описывают чтение публичной policy и запись синтетического audit artifact. Evidence хранится рядом с контентом и проходит обычный code review.

Анализатор закреплён за публичным релизом v0.1.3 и коммитом cbf216e73b0b49064e44e7a9ed1a174d1c5dbd23. Данные GitHub Latest Release API и копия репозитория проверены 22 июля 2026 года. Одного тега для такой фиксации недостаточно: тег может сменить целевой коммит. Перед запуском кейс сверяет origin, точный тег на HEAD и полный SHA коммита.

Закреплённые команды

Запускайте команды из корня локальной копии этого сайта. Сначала создайте свежую копию анализатора. Защитное условие перед git clone вернёт ненулевой код, если целевой каталог уже существует:

test ! -e .evidence-tools/audit-prompt-caching-v0.1.3 && \
  git clone --depth 1 --branch v0.1.3 \
  https://github.com/sernote/audit-prompt-caching.git \
  .evidence-tools/audit-prompt-caching-v0.1.3

Существующую копию можно использовать повторно только после всех трёх проверок. Каждая команда вернёт ненулевой код при любом несовпадении:

git -C .evidence-tools/audit-prompt-caching-v0.1.3 remote get-url origin | \
  grep -Fx 'https://github.com/sernote/audit-prompt-caching.git'
git -C .evidence-tools/audit-prompt-caching-v0.1.3 describe --tags --exact-match HEAD | \
  grep -Fx 'v0.1.3'
git -C .evidence-tools/audit-prompt-caching-v0.1.3 rev-parse HEAD | \
  grep -Fx 'cbf216e73b0b49064e44e7a9ed1a174d1c5dbd23'

Только после этого проверьте стабильный файл из репозитория сайта:

python3 .evidence-tools/audit-prompt-caching-v0.1.3/audit-prompt-caching/scripts/layout_linter.py \
  evidence/v3/agent-session-cache-reuse/step-stable.json

Проверка стабильного файла завершилась с кодом 0. JSON-результат содержит:

{
  "status": "ok",
  "findings": [],
  "clean_checks": ["AP-1", "AP-2"]
}

Файл с перестановкой проверяется той же версией скрипта:

python3 .evidence-tools/audit-prompt-caching-v0.1.3/audit-prompt-caching/scripts/layout_linter.py \
  evidence/v3/agent-session-cache-reuse/step-drift.json

Этот запуск ожидаемо завершился с кодом 1. Для анализатора это найденное нарушение, а не ошибка чтения файла. JSON-результат:

{
  "rule_id": "AP-2",
  "severity": "high",
  "category": "tool-schema-stability",
  "issue": "tool definitions are not sorted by stable name",
  "evidence": "tools order is ['write_file', 'lookup_policy']"
}

В исходном коде этой версии файлы находятся по путям evidence/v3/agent-session-cache-reuse/step-stable.json, evidence/v3/agent-session-cache-reuse/step-drift.json и evidence/v3/agent-session-cache-reuse/layout-linter-output.json. Машинный снимок сохраняет исходные команды, отдельный переносимый рецепт с проверками origin, тега и HEAD, ожидаемые и полученные коды завершения и оба JSON-результата.

Гипотезы после finding

AP-2 подтверждает layout drift, но оставляет несколько следующих гипотез. Первая: tool registry выдаёт элементы в недетерминированном порядке. Вторая: permissions меняют состав tools между шагами. Третья: разные adapters сериализуют один объект по-разному. Четвёртая: route drift или eviction мешают reuse даже после стабилизации payload.

Этот кейс проверяет только первую наблюдаемую форму: порядок двух известных tools. Состав не меняется. Adapter и tokenizer не запускаются. Route, cache residency и provider usage отсутствуют. Остальные гипотезы требуют новых evidence artifacts.

Изменение

Минимальное изменение для такого входа — формировать массив инструментов детерминированно до сериализации и покрыть его snapshot-тестом. Стабильный fixture показывает ожидаемый порядок. Следующий защитный шаг — добавить закреплённую версию анализатора в CI, чтобы будущая проверка останавливала изменение при повторном появлении AP-2.

В production code одного сортировщика мало. Нужно закрепить источник identity, schema revision и permissions profile. Если tool становится недоступен по политике, это осознанное изменение префикса, а не drift. Лог или trace должен отличать эти события.

Валидация

Успех локальной проверки определяется узко:

  1. stable input возвращает exit 0, status ok, AP-1/AP-2 в clean_checks;
  2. otherwise-equivalent drift input возвращает exit 1, status findings;
  3. finding имеет rule_id: AP-2 и category: tool-schema-stability;
  4. evidence сообщает observed order write_file, lookup_policy;
  5. оба запуска используют один commit и один script path.

Все пять условий зафиксированы 22 июля 2026 года. Если release, fixture или правило изменятся, evidence нужно получить заново; редактировать только prose недостаточно.

Что этот кейс доказывает

  • Два source-controlled JSON различаются порядком tools при одинаковых остальных полях.
  • layout_linter.py из commit cbf216e… принимает стабильный порядок без AP-1/AP-2 findings.
  • Тот же linter воспроизводимо возвращает AP-2 для переставленных tools.
  • Finding относится к категории tool-schema-stability и содержит фактический observed order.
  • Такой тест пригоден как регрессионный guard для rendered request layout.

Чего не доказывает

  • Кейс не доказывает cache hit или miss у OpenAI, Claude, vLLM, SGLang либо другого runtime.
  • Не измеряет cached tokens, time to first token, end-to-end latency, throughput и стоимость.
  • Не показывает production incident, результат production-системы или реальный агентный traffic.
  • Не подтверждает, что сортировка улучшит качество tool selection либо безопасна для любого API.
  • Не проверяет route locality, replica affinity, KV pressure, eviction и tenant isolation.
  • Не сравнивает модели, providers и продукты.

Следующее проверочное действие

В реальном расследовании после AP-2 сохраните два запроса из одного сценария, очищенных от чувствительных данных, сравните их байтовые или токенные префиксы и добавьте документированное поле чтения кэша вместе с идентификатором маршрута. Затем повторите холодный и прогретый запуски на закреплённой конфигурации. До появления этих данных честный вывод остаётся прежним: изменение найдено, влияние на среду исполнения не измерено.

Связанные материалы: Prefix Cache, audit-prompt-caching и каноническая статья «Короткий промпт ≠ дешёвый промпт: как оптимизация ломает prefix cache в LLM-агентах»Внешняя ссылка, откроется в новой вкладке.

Проверка материала

Применимость

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

Ограничения

Кейс проверяет только порядок инструментов в двух JSON-файлах; он не запускает модель или кэш, не использует рабочий трафик и не измеряет попадания в кэш, задержку, стоимость или качество.

Связанные материалы