Алексей Синяев
Навигация по странице статьи
Статьи 9 мин чтения June 21, 2026

Как понять, что AI-агент потерял контекст: state-canary в AGENTS.md и CLAUDE.md

State-canary — простой observability-паттерн для AI coding agents: одна строка состояния в каждом ответе помогает раньше заметить context drift, потерю scope и забытые ограничения.

Прев'ю статті про state-canary для AI-агентів: термінал із маркером стану task, scope і constraint, що допомагає помітити втрату контексту.
Содержание

TL;DR

  • Заставьте агента печатать одну строку состояния в начале каждого ответа: [state: task=…; scope=…; constraint=…]. Пока строка корректна — у вас есть признак, что ключевые инструкции и task-state ещё удерживаются.
  • Когда поле становится unknown, scope расширяется сам собой или task подменяется — это видимый сигнал context drift, который вы замечаете до того, как агент напишет неверный код.
  • State-canary — это observability-сигнал, а не антигаллюцинационная магия. Он ловит потерю инструкций и дрейф задачи, но не ловит уверенную ложь по фактам. Сработал — сбрасывайте сессию и восстанавливайтесь из markdown.

Самая дорогая ошибка AI-агента — не та, на которой он спотыкается и просит помощи. Дорогая ошибка — та, которую он делает уверенно: ссылается на функцию, которой нет, «вспоминает» ограничение, которого вы не давали, переписывает то, что пять ходов назад договорились не трогать. Тон ответа не меняется. Меняется только качество — а вы об этом узнаёте на ревью, когда уже потратили час.

Я несколько раз ловил себя на одном и том же: агент в длинной сессии начинал придумывать пути к файлам, которые сам же читал двадцать ходов назад. Корень почти всегда один — потерянный рабочий контекст, а не «глупая модель». Проблема в том, что потеря невидима: нет момента, когда экран краснеет и пишет «контекст деградировал».

Эта статья — про дешёвый приём наблюдаемости (observability), который делает такую потерю видимой: state-canary — строка состояния, которую агент печатает в начале каждого ответа прямо по инструкции из AGENTS.md или CLAUDE.md. После статьи у вас будет copy-paste блок, который можно положить в проект сегодня, и протокол действий на случай, когда канарейка сработала.

Если базовая память агента у вас ещё не выстроена, начните с AI-агентов в рабочем процессе разработчика — там разобран паттерн AGENTS.md/CLAUDE.md, на котором стоит всё дальнейшее.

Кому это полезно — и когда не стоит заморачиваться

Приём не универсальный, и честнее сразу очертить, где он окупается.

Особенно полезно, если вы

ведёте длинные многоэтапные задачи с AI coding agents; храните task-state в markdown; работаете с Claude Code, Codex или Cursor; и регулярно ловите уверенные ошибки после долгих сессий.

И наоборот — не тратьте на это время, когда:

  • задаёте короткий разовый вопрос или решаете задачу на 5–10 минут;
  • агент вообще не меняет код (объяснение, ревью, поиск);
  • важнее проверить факты, чем отследить контекст, — там работает не канарейка, а тесты и источники.

Проблема: агент уверен, но уже не помнит договорённости

Опасна не сама ошибка, а её невидимость. Агент держит ровный тон независимо от того, опирается он на актуальный контекст или на его обрывки. Значит, нужен внешний индикатор — что-то дешёвое и всегда на виду, что ломается раньше, чем ломается результат.

Хорошая новость: агент уже умеет подхватывать проектные инструкции из AGENTS.md и похожих файлов. Эту же механику можно использовать как датчик — попросить его постоянно показывать, что именно он сейчас удерживает в рабочем состоянии.

Почему теряется рабочий контекст

Современные модели Claude и Codex могут хорошо работать, когда нужный контекст физически находится в окне. Но часть уверенных ошибок в длинных сессиях возникает не из-за «глупости модели», а из-за того, что рабочий контекст вытеснен, размыт или стал хуже использоваться. Механизмов несколько.

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

Компакция и суммаризация. Claude Code сжимает длинную историю — командой /compact или автоматически при заполнении окна. Здесь нужна точность, потому что обобщение «/compact теряет CLAUDE.md» неверно. Project-root CLAUDE.md переинъектируется после компакции; а вот вложенные CLAUDE.md в подкаталогах сами не возвращаются, пока агент снова не прочитает файл в этой директории. И главное — инструкции, которые жили только в разговоре, и детали текущей задачи могут выпасть из эффективного рабочего состояния, даже когда корневая память перечитана. Поэтому активную задачу я держу не в чате, а в отдельном markdown-файле и перечитываю его после reset или compact.

Context rot. Даже без жёсткого обрезания точность падает по мере роста контекста — документация Anthropic по контекстному окну прямо описывает деградацию recall при увеличении объёма. Падение плавное: нет точки, где «всё сломалось», и поэтому глазом его не поймать.

Lost in the middle. Инструкция может физически быть в окне, но стоять в его середине. Модели надёжнее воспроизводят то, что в начале и в конце контекста, чем зажатое посередине, — это эффект, описанный в исследовании «Lost in the Middle». Важное правило, окружённое большим объёмом текста, соблюдается хуже.

Уровень 1. Простейшая canary

В шахтах держали канареек: птица реагировала на опасный воздух раньше людей. Здесь та же идея — дешёвый индикатор, который ломается первым.

Положите в AGENTS.md инструкцию, которую легко проверить глазом, которая не влияет на результат задачи и достаточно специфична, чтобы случайно не совпасть:

Markdown
## Output format

Start every response with: "Алексей,"
No exceptions, even for one-line answers.

Пока обращение на месте — верхние инструкции файла ещё соблюдаются. Вот как выглядит срыв на практике:

Code
Ход 4:  Алексей, обновил роуты, вот дифф...
Ход 19: Готово. Поправил конфиг, перегенерировал кэш...
         ^ обращение исчезло — повод проверить, что ещё уехало

Важно: держите эту инструкцию короткой. Codex собирает цепочку инструкций из нескольких AGENTS.md-файлов, и у project guidance есть ограничение размера. Canary должна быть одной строкой, а не отдельным регламентом.

Этого уже достаточно, чтобы насторожиться. Но префикс с именем фиксирует только факт сбоя, а не его содержание.

Почему имя — только первый уровень

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

Уровень 2. State-canary: task / scope / constraint

Пусть агент печатает одну строку, отражающую активный контекст:

Prompt
Before answering, print exactly one line:

[state: task=<task-slug>; scope=<allowed-area>; constraint=<main-constraint>]

If any field is unclear, write "unknown".
Do not invent missing state.

Три поля выбраны не случайно: task отвечает на «над чем мы», scope — «где можно трогать код», constraint — «чего делать нельзя». Вот как это читается в реальной задаче:

Code
[state: task=paywall-refactor; scope=WordPress/Timber templates only; constraint=no vendor patching]

Нашёл место, где paywall-логика всё ещё завязана на vendor override...

Если на следующем ходу constraint станет unknown или scope вырастет сам собой — вы увидите это раньше, чем агент полезет править код вендора. Правило Do not invent missing state здесь ключевое: пусть лучше честно напишет unknown, чем нарисует правдоподобное поле по инерции.

Нормальный ход:

Code
[state: task=paywall-refactor; scope=WordPress/Timber templates only; constraint=no vendor patching]

Проверяю только шаблоны Timber, vendor не трогаю.

Подозрительный ход:

Code
[state: task=paywall-refactor; scope=unknown; constraint=unknown]

Я могу поправить vendor-файл напрямую...

Вот это и есть момент остановки: агент ещё говорит уверенно, но маркер уже показывает, что рабочие границы задачи потеряны.

Почему не turn counter

Соблазнительно добавить в маркер счётчик ходов — выглядит аккуратно и «наблюдаемо». Я его не использую: модель может продолжать счёт механически, сбрасывать его или подгонять, и при этом контекст уже деградировал. task, scope и constraint подделать по инерции труднее — поэтому их диагностическая ценность выше, чем у красивой цифры.

Как читать сигнал

Ценность state-canary в том, что разные поломки маркера значат разное и требуют разных действий.

СимптомЧто это может значитьЧто делать
Пропал маркер целикомАгент перестал следовать верхней инструкцииНе продолжать вслепую, проверить state
task сменился без командыАгент смешал задачиВернуть task-slug или начать новую сессию
constraint=unknownАгент не уверен в текущем ограниченииПеречитать task-md и scope
Маркер корректен, но факты неверныЭто factual hallucination, а не context driftПроверять через tools, tests, источники
Агент начал придумывать путиПотерял карту проектаЗаставить сделать find/ls/read, не верить памяти

Что canary ловит, а что нет

State-canary — инженерный датчик, а не доказательство. Граница простая и её важно держать в голове:

  • Ловит context drift, instruction drift и потерю task-state — то есть случаи, когда инструкции уехали из эффективного контекста.
  • Не ловит factual hallucination: если агент уверенно врёт при корректном маркере, источник ошибки — обучающий приор модели, а не потеря контекста.
  • Не заменяет тесты, инструменты, проверку источников и code review. Это ранний сигнал поверх них, а не вместо них.
Класс отказаCanary помогает?
Переполнение окна, старые инструкции вытесненыДа
Дрейф после компакции/суммаризацииДа
Context rot (плавная деградация recall)Частично
Lost in the middle (инструкция есть, но игнорируется)Частично
Factual hallucination при корректном маркереНет
Неверно понятое требование с самого началаНет

Когда нужен не canary, а hook

Если правило должно не просто отображаться в ответе, а гарантированно выполняться в конкретный момент — например, запускать тесты перед коммитом или запрещать запись в определённые файлы, — используйте hooks или автоматические проверки. Canary показывает, что агент помнит ограничение; hook заставляет среду выполнить действие независимо от того, что агент «помнит».

Уровень 3. Протокол восстановления

Маркер пропал, сменился сам собой или показал unknown. Главное, чего я не делаю, — не пытаюсь починить длинную сессию ещё одним длинным промптом: это лишь добавляет токены, не убирая деградацию. Вместо этого — сброс и восстановление из markdown:

Prompt
If the state marker disappears, changes unexpectedly, or shows "unknown":
1. Stop the current task.
2. Summarize current state into docs/analysis/<task>.md.
3. Start a fresh session.
4. Re-read AGENTS.md/CLAUDE.md and the task markdown.
5. Continue from the last verified step.

Поэтому активные задачи у меня лежат в docs/analysis/<task-slug>.md: файл служит и исходным анализом, и точкой восстановления. После /clear агент перечитывает его и поднимает нить за один ход — без переигрывания всей переписки.

Готовый блок для AGENTS.md / CLAUDE.md

Скопируйте в корневой AGENTS.md или CLAUDE.md и подставьте свои значения:

Markdown
## Agent state canary

At the start of every response, print exactly one line:

[state: task=<current-task>; scope=<allowed-area>; constraint=<main-constraint>]

Rules:
- Keep it to one line.
- Use "unknown" if unsure.
- Do not invent missing state.
- If the user changes task, update the task field.

If the marker disappears, changes unexpectedly, or shows "unknown":
1. Stop the current task.
2. Summarize state into docs/analysis/<task>.md.
3. Start a fresh session.
4. Re-read this file and the task markdown.
5. Continue from the last verified step.

FAQ

Не сломает ли маркер ответы агента?

Нет, если это одна строка. Агент печатает её первой, дальше отвечает как обычно. Вы либо не замечаете строку, либо сразу видите аномалию.

Работает ли это вне Claude — с Codex или Cursor?

Да, если инструмент регулярно подхватывает проектные инструкции из AGENTS.md, CLAUDE.md или аналога. Это не system-level гарантия: например, Claude Code сам пишет, что CLAUDE.md — не системный промпт, а инструкция, которую модель старается соблюдать. Поэтому canary и нужна как наблюдаемый сигнал, а не как жёсткая защита.

А если агент «ленится» и пропускает маркер при целом контексте?

Бывает. Поэтому одиночный пропуск — повод насторожиться, а не сбрасывать сессию. Сигнал — маркер, пропавший на два-три хода подряд или ставший unknown.

Нужна ли канарейка в коротких сессиях?

Нет. На 20–30 ходах в небольшом проекте деградация маловероятна. Ценность растёт на длинных многоэтапных задачах.

Как отличить потерю контекста от обычной ошибки?

По паттерну: агент перестал следовать сразу нескольким правилам, переспрашивает решённое, путает пути к файлам. Три-четыре сигнала вместе — уже не случайность.

Источники и дальше почитать

Похожие статьи

Поделиться статьей

LinkedIn X Email

Связаться

Работаете над похожей задачей? Давайте обсудим.

Открыт к обсуждению архитектуры, Laravel, WordPress, производительности и практических инженерных задач.

Связаться Смотреть кейсы

Смотрите также

Статьи

June 14, 2026

Часть 3. Месяц с AI-дневником: как искать связи между сном, стрессом и тренировками

Как анализировать AI-дневник после первого месяца: исправление распознавания, честная рефлексия с источниками, Obsidian, стоимость…
Статьи

June 14, 2026

Часть 2. Hermes Agent + DeepSeek на Ubuntu: полный мануал AI-дневника в Telegram

Пошаговый мануал: Hermes Agent и DeepSeek на Ubuntu, Telegram-бот с закрытым доступом, локальный faster-whisper,…
Статьи

June 14, 2026

Часть 1. Как я превратил старый игровой ноутбук в AI-дневник самочувствия

Как старый Xiaomi Mi Gaming Laptop стал домашним AI-сервером: Hermes Agent, DeepSeek, Telegram и…