English · Русский
Чтобы ИИ понимал, как код исполняется
Модель, читающая исходник, рассуждает о том, что должно происходить. Модель, читающая записи о вызовах, знает, что происходило.
Разница не в объёме сведений, а в том, какой вопрос вообще имеет ответ. По исходнику видно, что может случиться: ветви, которые там написаны, доводы, которые там объявлены. По записям видно другое — какие ветви исполнялись, какие доводы встретились на самом деле, какие вызовы зависли и какие бросили исключение. Второго в исходнике нет ни в каком виде, и вывести его чтением нельзя.
Обратное тоже верно, и это надо держать рядом: записи не скажут, что код неправильный. Они скажут, что он делает. Вывод «а должно быть иначе» остаётся человеку.
Что для этого сделать
- Поставить инструмент — Установка.
Дописать в настройку клиента один блок:
{ "mcpServers": { "ouroboros": { "type": "stdio", "command": "ouroboros-mcp" } } }
- Проверить, что у агента появились инструменты с именами
wrap_file,read_trace,trace_statsи остальные — всего семнадцать. - Дать задание. Готовая формулировка — ниже.
Семнадцать инструментов, четыре группы
Сервер выкладывает операции напрямую, без промежуточного слоя выбора: агент видит все семнадцать имён и зовёт их по имени.
Дописать запись о вызовах
| инструмент | что делает |
|---|---|
wrap_code_snippet | обмазывает переданную строку кода, ничего не сохраняя |
wrap_file | обмазывает файл на месте |
wrap_functions | обмазывает только названные функции — для горячих и больших файлов |
Прочитать записи
| инструмент | что делает |
|---|---|
read_trace | записи с отбором и чтением частями |
trace_stats | сводка: сколько раз звали, сколько бросили, сколько шло |
Черновик
| инструмент | что делает |
|---|---|
create_project | заводит черновик с историей изменений |
write_file | обмазывает до сохранения; неразбираемое отвергает |
read_file, list_files | посмотреть, что в черновике |
execute | запускает команду, сам подставляя путь к debug.info |
finish | копирует черновик в чистовик; обмазку не снимает |
C и C++ через clangd — выбрать, что обмазывать, в большом дереве
| инструмент | что делает |
|---|---|
lint_file | разбор clang-tidy |
symbol_search | найти имя по всему дереву |
document_symbols | что определено в одном файле |
references | кто зовёт |
call_hierarchy | кто зовёт кого, по цепочке |
describe_symbol | где определено и с какой подписью |
У каждого инструмента проставлено, что он делает с файлами: читающие помечены как безопасные, wrap_file и finish — как переписывающие, execute — как запускающий произвольную команду. Клиент видит это до первого вызова (ouroboros/mcp/server.py:668).
Таблицы выше — краткий пересказ. Полный справочник снят с живого сервера: Справочник средств MCP — на каждое из семнадцати средств заголовок, описание, схема доводов, схема ответа и настоящий ответ на настоящий вызов. Он не написан руками, а напечатан из docs/mcp-tools.json, который снимается разговором с сервером командой scripts/probe/build-reference.sh. Если пересказ здесь и справочник разойдутся — верен справочник.
Как это выглядит на самом деле
Вызов wrap_file через сервер MCP:
{
"ok": true,
"path": "/srv/tmp/ouro-work/mcpdemo/stats.py",
"language": "python",
"functions_wrapped": 3,
"runtime_header": "/srv/tmp/ouro-work/mcpdemo/ouroboros_runtime.py"
}После прогона программы — trace_stats по тому же черновику:
{
"ok": true,
"calls_parsed": 5,
"malformed": 0,
"total_calls": 5,
"by_function": [
{ "name": "parse_line", "count": 3, "result": 3, "raised": 0, "unknown": 0,
"duration_seconds": { "min": 1e-06, "max": 2e-06, "mean": 2e-06, "total": 5e-06, "count": 3 } },
{ "name": "average", "count": 1, "result": 1, "raised": 0, "unknown": 0,
"duration_seconds": { "min": 2e-06, "max": 2e-06, "mean": 2e-06, "total": 2e-06, "count": 1 } },
{ "name": "report", "count": 1, "result": 1, "raised": 0, "unknown": 0,
"duration_seconds": { "min": 0.000351, "max": 0.000351, "mean": 0.000351, "total": 0.000351, "count": 1 } }
]
}Это настоящий обмен с сервером, а не образец.
Порядок работы
create_project → write_file → execute → read_trace → finish
черновик обмазывает запускает читаем переносим
при записи записи наружуИли короче, без черновика: wrap_file → агент сам запускает программу → read_trace.
Горячие файлы. wrap_file на файле с миллионом вызовов в секунду топит нужные записи в шуме. Агент, которому не сказали иного, скорее возьмёт wrap_file — поэтому на горячем файле имя wrap_functions называют в задании прямо.
Формулировка для задания агенту
Годится как есть:
Разберись, как на самом деле исполняется
<файл>. Возьми уроборос: заведи черновик, обмажь<файл>(на горячем файле —wrap_functions, назови функции), прогони на настоящих данных, прочитай записи.В отчёте назови: сколько вызовов записано, какие функции исполнялись и с какими доводами, что вернулось, что бросило исключение и что не вернулось (
in_flight). Отдельно — сколько строк не разобралось (malformed).Выводов о правильности программы не делай: записи говорят, что код сделал, а не что он должен был сделать. Если увидишь странность — назови её вопросом ко мне, а не утверждением.
Что агент обязан проверить, а не принять на веру
Что вообще что-то записалось. calls_parsed: 0 значит, что обмазанный код не исполнялся, а не что всё чисто. Это первое, на что стоит смотреть.
Испорченные строки. malformed больше нуля — часть записей не разобралась, и выводы сделаны по неполной картине.
Невернувшиеся вызовы. in_flight — это вход без выхода: зависание, падение или жёсткий выход. Пустой список хорошо, непустой требует объяснения.
Покрытие. Ветвь, в которую не зашли, записей не даст и не пожалуется. Утверждать по трассе что-либо о неисполнявшемся коде нельзя.
Что именно записано. Запись утверждает «на этом входе вышло вот это». Она не утверждает, что так правильно. Агент, подающий трассу как доказательство правильности, ошибается — и это самая частая ошибка при работе с инструментом.
Длительность — не цена. Поле d измеряет обмазанный прогон. Читать его как стоимость обычного прогона нельзя.
Навык
В хранилище лежит навык skill/SKILL.md — короткое описание инструмента для агента: что поставить, как подключить сервер, все семнадцать средств, порядок работы и границы с замеренными числами. Он описывает этот инструмент и ничего сверх него.