# Контекст и харнесс: AGENTS.md, спеки, sensors

> Промпт — верхушка айсберга: как устроены артефакты, из которых агент собирает контекст, и как замкнуть обратную связь

_Источник: https://sii.sergeivolchkov.ru/materials/agent/context_



Результат агента определяется в основном тем, что ему доступно **до**
промпта. Поэтому работа смещается с сочинения промптов на подготовку
артефактов, из которых контекст собирается сам.

<AgentHarness />

Формула простая: **агент = модель + харнесс**. Модель одна и та же у всех;
разница в харнессе — том, что подаётся вперёд (guides) и что возвращается
назад (sensors).

Если читать про агентов один текст, то
[Building effective agents](https://www.anthropic.com/engineering/building-effective-agents)
— он и разводит понятия, которые в разговорах слиплись: **workflow** —
заранее прописанный маршрут вызовов модели, **агент** — система, которая
сама решает, что делать дальше. Разница практическая: маршрут отлаживается
и воспроизводится, агент — нет, зато справляется там, где шаги заранее
неизвестны. Большинству студенческих задач хватает первого, а берут сразу
второе — и потом чинят недетерминированность там, где её можно было
не создавать. Тот же порядок усложнения мы держим в
[работе с моделью](/materials/ai/working-with-model): промпт, потом
поиск, и только потом агент.

## AGENTS.md — память проекта [#agentsmd--память-проекта]

Файл в корне репозитория, который агент читает перед работой. Смысл не в
формате, а в наблюдении: агент раз за разом совершает одни и те же ошибки —
путает термины, лезет в миграции, выдумывает версии API. Каждая такая
ошибка — не повод объяснять заново в чате, а повод записать правило в
репозиторий. Имя `AGENTS.md` понимают Claude Code, Codex, Cursor, Vibe и ещё
десятки инструментов — [это открытый
формат](https://agents.md/), с осени 2025 живущий под Linux Foundation.
Но работает здесь не имя, а привычка выносить повторяющееся в текст.

```markdown title="AGENTS.md"
## Проект
Тренажёр к экзамену: студент загружает материалы, получает вопросы по ним.
Python 3.13, uv, FastAPI, Postgres. Поднимается целиком: `docker compose up`.
Use cases — `docs/use-cases/`, диаграммы — `docs/diagrams/`, решения — `docs/adr/`.

## Команды
uv sync                     # окружение из lock-файла
uv run ruff check --fix     # линт и формат
uv run ty check             # типы
uv run pytest               # тесты
uv run pytest evals/        # качество ответов модели
npx aact@beta check         # архитектура против диаграммы

## Границы
- Миграции в `alembic/versions/` не трогай без явной просьбы.
- Секреты только из `.env`: ни в коде, ни в примерах, ни в тестах.
- Новую зависимость сначала предложи, не ставь молча.
- Диаграммы правь в `.puml` и перегенерируй; `.svg` руками не редактируй.

## Глоссарий
- **Материал** — загруженный студентом файл курса.
- **Набор** — сгенерированные по теме вопросы (не «тест» и не «квиз»).
- **Проверка** — сверка ответа студента с фрагментом источника.

## Грабли
- Langfuse тянет шесть контейнеров; на слабой машине берём облако.
- Модель выдумывает вопросы не по материалу — требуй ссылку на фрагмент.
- `ty` спотыкается на зависимостях FastAPI: пиши тип явно, а не `type: ignore`.

## Всегда
- Непонятен API или версия — ищи в интернете, не угадывай.
- Меняешь поведение — сначала use case, потом тест, потом код.
```

Что здесь важнее формата.

**Раздел «Команды» — самый рабочий.** Агент, который знает, чем себя
проверить, запускает проверку сам и приходит с уже починенным кодом.
Без этого раздела он пишет вслепую и приносит результат на разбор
человеку — то есть тратит твоё время вместо своего.

**Правило, которое умеет проверять машина, сюда не пишут.** Ему место
в pre-commit hook или тесте: в файле оно соблюдается через раз, в
хуке — всегда. `AGENTS.md` держит то, что машиной не проверишь:
термины, намерения, пройденные грабли.

**Файл не генерируется — он растёт.** Сгенерированный агентом
`AGENTS.md` — это страница общих советов, которые модель и так знает,
и она честно тратит на них контекст. Каждая строчка настоящего файла
оплачена пойманной ошибкой, поэтому нормальный размер — десятки строк,
а не сотни. Anthropic советует держать такие файлы в пределах двухсот
строк, и причина техническая: чем длиннее файл, тем хуже соблюдается
каждое отдельное правило.

Три раздела дают эффект сразу: **глоссарий** (агент перестаёт называть
одну сущность тремя словами), **грабли** (перестаёт повторять уже
пройденное) и **границы** (перестаёт лезть туда, где ломает молча).
Про первый — отдельно в [едином языке
команды](/materials/use-cases/glossary): здесь достаточно короткой
выжимки, полный список терминов живёт рядом с use cases.

## Спеки вместо вайб-кодинга [#спеки-вместо-вайб-кодинга]

Следующий уровень — **Specs Driven Development**: источник истины не код,
а спецификация. Изменение продукта начинается с правки спеки, из неё
следуют тесты и код.

Что это даёт на практике: проект передаётся другому человеку и другому
агенту без «расскажи, как оно тут устроено»; маленькое контекстное окно
перестаёт быть проблемой (агент читает нужный фрагмент, а не весь репозиторий);
стейкхолдер видит требования, а не диффы.

Держится это на треугольнике: **спеки ↔ тесты ↔ код**. Разъехалась любая
сторона — расхождение чинится в том же PR, а не «потом». У нас это уже
встроено: из use cases пишутся evals, и только потом код, а `aact check`
следит, чтобы
диаграмма не врала.

## Progressive disclosure: не вываливай всё сразу [#progressive-disclosure-не-вываливай-всё-сразу]

Промпт не должен содержать весь контекст — он должен **ссылаться** на
артефакты: спеку use case, `AGENTS.md`, нужный файл, заметки. Агент
«ныряет» глубже только там, где ему это действительно нужно.

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

## Sensors: обратная связь без человека [#sensors-обратная-связь-без-человека]

Guides подаются вперёд, sensors возвращаются назад. И вот здесь главное
свойство, ради которого всё строится: **модель недетерминирована, а
среда вокруг неё — нет**. Один и тот же промпт даёт разный ответ; один и
тот же `pytest` даёт один и тот же вердикт. Поэтому доверие к результату
берётся не из того, насколько уверенно модель его подала, а из того, что
о нём сказали детерминированные инструменты.

Та же мысль в [безопасности](/materials/quality/security): границы задаёт
не модель, а среда, в которой её вызвали. Здесь — то же самое, только про
качество вместо прав доступа.

Sensors — это всё, что даёт агенту машинный вердикт о его же работе:

| Sensor          | Что ловит                                      |
| --------------- | ---------------------------------------------- |
| `ruff`, `ty`    | Стиль и типы — до того, как это увидит человек |
| Тесты и evals   | Регрессию поведения и качества ответов модели  |
| `aact check`    | Архитектуру, разъехавшуюся с диаграммой        |
| pre-commit hook | Всё вышеперечисленное — до коммита, а не в CI  |
| Ревью-агент     | Системные проблемы, которые не ловит линтер    |

Ключевой принцип, общий с [мультиагентными
системами](/materials/architecture/multi-agent): **жёсткое ограничение —
это код, а не абзац в промпте**. «Не добавляй зависимости» в промпте
соблюдается через раз; тот же запрет в pre-commit — всегда.

### Сенсор часто дешевле написать, чем найти [#сенсор-часто-дешевле-написать-чем-найти]

Готовым инструментом среда не заканчивается. Под конкретную проверку
сенсор пишется за пару минут — и дальше отвечает на вопрос «я это не
сломал?» столько раз, сколько нужно:

* прогнать все внешние ссылки материала и напечатать коды ответов —
  вместо «вроде рабочие»;
* отрендерить диаграмму в картинку и посмотреть на неё, а не на исходник:
  наложения подписей в коде не видно;
* сходить в API репозитория и убедиться, что файл, на который ты
  ссылаешься, там действительно есть.

Разница между «посмотри, всё ли нормально» и «запусти и покажи вывод» —
это разница между мнением и фактом. Агент, который приносит вывод
команды, проверяем; агент, который приносит уверенность, — нет.

## База знаний для ресёрча [#база-знаний-для-ресёрча]

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

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