Инвариант
Полезно различать три объекта:
proposed_args — что выдала модель
effective_args — что после валидации реально получил обработчик
observed_result — что вернулось модели и в audit log
Идеальный путь сохраняет proposed_args == effective_args. Если это невозможно, преобразование становится частью явного контракта: runtime сообщает, что изменил, почему и какое значение исполнил. Молчаливое расхождение запрещено.
Это относится не только ко входу. Результат тоже нельзя незаметно урезать, переформатировать или подменять успешной заглушкой: агент должен отличать полный вывод, bounded preview, сохранённый внешний артефакт и отказ (Bounded Tool Output, Unknown Not A Value).
Где теряется точность
| Слой | Типичный сдвиг |
|---|---|
| сериализация | escaping, Unicode normalization, перевод реальных newline в литералы или обратно |
| schema adapter | неявное coercion строки в число, удаление неизвестных полей, подстановка default |
| policy gateway | переписывание пути, команды или target; добавление scope/tenant/флага |
| SDK / shell wrapper | дополнительное quoting, environment expansion, скрытые CLI-аргументы |
| tool implementation | нормализация регистра, пробелов, кавычек или кодировки |
| result adapter | truncation, redaction или «починка» ошибки без маркировки |
Особенно разрушителен exact-match интерфейс. Модель читает строку с типографскими кавычками, передаёт её как old_string, adapter меняет кавычки, а инструмент закономерно отвечает no match. Повторное чтение снова показывает исходную строку, поэтому модель не может увидеть слой, где возникло расхождение, и зацикливается.
Не всякое преобразование запрещено
Нормализация и добавленные runtime-поля иногда необходимы. Запрещена не трансформация, а её невидимость и смешение владельцев.
- Проверка типов и отказ предпочтительнее «догадливого» coercion.
actor_id,tenant_id, permission scope и idempotency key задаёт доверенный runtime, а не модель. Они хранятся отдельнымpolicy_context, не маскируются под предложенные ею аргументы (Tool Gateway).- Канонизация пути или Unicode допустима, если schema обещает её, ответ показывает effective value, а destructive operation требует проверки результата.
- Redaction секрета показывается как redaction, а не как исходное значение; в аудите можно хранить хэш или ссылку на защищённый payload.
- Автоматический retry не вправе менять смысл аргументов. Если стратегия изменилась, это новый вызов с отдельной записью.
Пример ответа адаптера:
{
"status": "executed_with_transformations",
"proposed_args_hash": "sha256:…",
"effective_args": {"path": "/workspace/a.txt", "encoding": "utf-8"},
"transformations": [
{"field": "path", "kind": "workspace_resolution", "from": "a.txt", "to": "/workspace/a.txt"}
],
"result": {"bytes_written": 418}
}
Для опасного изменения безопаснее вернуть needs_confirmation с preview effective arguments и исполнить только после подтверждения, чем сначала переписать запрос, а потом объяснять результат.
Как тестировать adapter
- Round-trip corpus: пробелы, реальные newline, обратные слеши, кавычки, combining Unicode, emoji,
null, нулевой байт и длинные значения проходят весь путь model-shaped JSON → handler. - Differential test: прямой вызов обработчика и вызов через каждый adapter получают одинаковые effective arguments либо ожидаемый, описанный diff.
- Unknown-field test: лишнее поле отклоняется явно, а не исчезает.
- Default test: каждый подставленный default присутствует в effective arguments и tool result.
- Mutation test: намеренное скрытое преобразование должно ломать контрактный тест.
- Read-after-write: для записи проверяется фактическое состояние внешней системы, а не только
successот wrapper. - Trace localization: сохраняются хэши или безопасные представления на границах
model output → parser → gateway → handler, чтобы найти первый diverging layer (Trajectory Prefix Evals).
Ведущая метрика — не доля валидного JSON, а semantic argument fidelity: совпало ли исполненное намерение с тем, которое видел и подтвердил агент. Для exact-copy инструментов добавляются byte/code-point exact match и позиция первого расхождения.
Наблюдаемость без утечки
Полный raw payload нельзя безусловно писать в обычный лог: там могут быть токены, PII и содержимое файлов. Audit record хранит:
- версию schema и adapter;
- хэш исходных аргументов;
- redacted effective arguments;
- список преобразований и их причины;
- policy context отдельно от model-proposed fields;
- идентификатор защищённого полного payload при необходимости расследования;
- фактический результат или явный отказ.
Так сохраняется возможность найти слой порчи, но observability не превращается в канал утечки.
Границы
- Fidelity не означает «исполнять всё буквально»: политика безопасности может и должна отклонить запрос.
- Прозрачность преобразования не делает его правильным — schema и policy всё равно требуют ревью.
- Read-after-write обнаруживает расхождение после действия, но не предотвращает необратимый вред; для него нужен preview и confirmation.
- Книжные примеры про конкретные IDE не подтверждены независимым issue или changelog; переносится класс отказа, а не обвинение продукта.
Связано с
- Tool Calling — общий цикл от JSON-запроса до результата
- Tool Gateway — проверка и policy context до побочного эффекта
- Agent Failure Modes — повторяемый отказ без видимой для модели причины
- Agent Audit Log — границы, на которых сохраняется provenance вызова
- Trajectory Prefix Evals — локализация первого слоя, где значение разошлось