ИИ-агенты в разработке: как устроен Claude Code
- О чём это занятие
- Кодинг-агент изнутри: чем агент отличается от чата и автодополнения, как устроен агентный цикл и зачем вокруг него «обвязка» — права доступа, память, сжатие контекста. Разбираемся на примере Claude Code, но принципы переносятся на любой современный агент — а пользоваться ими вы будете весь курс, в собственном проекте.
- Аннотация
- Занятие начинается с разграничения трёх инструментов — автодополнение, чат, агент — и правила, когда какой уместен. Затем вскрывается сердце любого агента: цикл из пятнадцати строк «запрос → модель → вызов инструмента → результат → снова модель», прослеженный по шагам на реальной трассировке. Дальше главный инженерный сюжет: голый цикл в работе не выживает, и всё, что делает агента пригодным — ворота прав, ретраи, сжатие контекста, журнал сессии, — живёт в обвязке-харнессе вокруг неизменного цикла. Разбираются инструменты и система прав (в тренажёре вы сами поработаете этими воротами), память проекта CLAUDE.md и режим планирования, механизмы расширения — команды, хуки, суб-агенты, MCP. Финал прикладной: как применять агента в вашем учебном проекте — пять рабочих рецептов, шаблон файла памяти и правила честного использования, за которые спросится на защите.
- Пререквизиты
- Занятие 1 (постановка задачи, выбор траектории и проекта). Базовые навыки работы в терминале. Полезно вперёд: на занятиях 10–11 вы будете составлять задания и файлы правил для LLM — сегодняшняя механика объяснит, почему они работают.
- Мотивация
- Почти каждый из вас уже просил нейросеть написать кусок кода. Разница между «просить чат» и «работать с агентом» — как между советом по телефону и напарником за соседним столом: агент сам читает ваш проект, запускает тесты, видит ошибки и правит, пока не станет зелёным. В проекте практики это умножитель скорости — но только для того, кто понимает, что происходит под капотом: откуда агент берёт контекст, почему он вдруг «забывает» начало сессии, что он имеет право сделать без спроса. Непонимание здесь стоит дорого: от впустую потраченных часов до снесённых файлов.
1. Автодополнение, чат, агент: кто есть кто
Обычный чат с моделью — это «вопрос → ответ»: модель только генерирует текст и ничего не может сделать. Агент отличается ровно одним: у него есть инструменты (читать файлы, запускать команды, искать) и цикл — после каждого действия он смотрит на результат и решает, что дальше, пока задача не выполнена.
ЧАТ: вопрос → ответ (один шаг) АГЕНТ: вопрос → [подумать → действие → результат]* → ответ (шагов сколько нужно)
Три инструмента разработчика решают разные задачи — путаница между ними — частая причина разочарований («агент слишком медленный», «автодополнение слишком глупое»):
| Автодополнение | Чат с моделью | Агент | |
|---|---|---|---|
| что делает | достраивает строку/блок | отвечает текстом | действует в цикле до результата |
| видит проект | текущий файл | что вы вставили | читает файлы сам |
| запускает код | нет | нет | да: тесты, сборка, git |
| итерирует | нет | вы вручную | сам: правка → тест → правка |
| лучшее применение | быстрый набор | понять, спросить | многошаговые задачи |
| цена/скорость | мгновенно | быстро | медленнее и дороже |
Практическое правило: автодополнение — когда вы сами пишете и знаете что; чат — когда нужно понять; агент — когда задача требует нескольких шагов с обратной связью («почини тест», «разберись в баге»). Не гоняйте агента ради однострочника — это как вызывать эвакуатор, чтобы переставить машину на метр.
2. Сердце: агентный цикл
В основе любого кодинг-агента — очень простая конструкция. Вся история диалога лежит в массиве сообщений; модель на каждом обороте либо отвечает текстом, либо просит вызвать инструмент:
Пользователь → messages[] → Claude API → ответ
│
stop_reason == "tool_use"?
да ↙ ↘ нет
выполнить инструмент, вернуть текст —
добавить tool_result цикл завершён
и снова в API
Вот и весь «магический» агент: модель + инструменты + цикл. Посмотрите, как он отрабатывает реальную задачу «найди все файлы .py в src/, посчитай строки и покажи самый большой» — три оборота цикла:
ВИТОК 1 → API: messages=[задача], tools=[read_file, bash]
← stop_reason=tool_use → bash("find src -name '*.py'")
→ tool_result: "src/app.py\nsrc/db.py\nsrc/utils.py"
ВИТОК 2 ← stop_reason=tool_use → bash("wc -l src/app.py src/db.py src/utils.py")
→ tool_result: "120 app.py · 64 db.py · 38 utils.py"
ВИТОК 3 ← stop_reason=end_turn
← текст: "Найдено 3 файла. Самый большой — src/app.py (120 строк)."
Обратите внимание: последовательность «сначала найти, потом посчитать, потом сделать вывод» никто не программировал — она возникла сама как следствие цикла. И главная мысль, которую стоит унести с занятия: цикл не меняется, сколько бы возможностей мы ни добавляли. Инструментов может быть 3 или 300 — структура остаётся той же; всё усложнение живёт вокруг.
3. Харнесс: почему голый цикл не выживает
Цикл из раздела 2 умещается в 15 строк, и его действительно можно собрать за вечер.
Но в реальной работе он долго не живёт: не знает про права и радостно выполнит
rm -rf, если так «попросил» прочитанный файл; падает от первой же ошибки
сети; забывает начало разговора при переполнении контекста; теряет всё при сбое процесса.
Харнесс (агентная обвязка) — это всё, что оборачивает цикл, превращая
игрушку в рабочий инструмент. Если модель — двигатель, а цикл — коленвал, то харнесс —
кузов, ремни, приборная панель и тормоза.
| Проблема голого цикла | Слой харнесса |
|---|---|
| выполняет любую команду вслепую | ворота прав + deny-правила (раздел 4) |
| падает при ошибке API или таймауте | ретраи с нарастающей паузой, таймауты |
| забывает начало при переполнении | сжатие контекста (раздел 5) |
| теряет всё при сбое процесса | журнал сессии на диске, восстановление |
| непонятно, что и почему сделал | логи и трейсинг каждого витка |
Отсюда второй девиз занятия: сложность агента — не в цикле, а в обвязке. Дальше мы пройдём по главным слоям этой обвязки — тем, с которыми вы будете сталкиваться каждый день.
4. Инструменты и ворота прав
Инструменты агента делятся на понятные категории: файлы (чтение, правка), поиск по кодовой базе, выполнение команд в терминале, веб, делегирование суб-агентам. Важное инженерное свойство: инструменты только для чтения безопасны и могут выполняться параллельно пачками — а всё, что меняет файлы или состояние, идёт строго последовательно и через проверку прав.
Права — главный механизм безопасности. Перед выполнением каждый вызов проходит
«ворота»: пользовательские хуки → правила allow/deny из
настроек → интерактивный вопрос, если правила молчат. Правила задаются один раз в
settings.json проекта:
{
"permissions": {
"allow": ["Bash(npm run test:*)", "Read(src/**)"],
"deny": ["Bash(rm -rf *)", "Read(.env)", "Bash(git push --force*)"]
}
}
Так тесты и чтение исходников идут без вопросов, а разрушительные команды и чтение
секретов запрещены навсегда — что бы ни «попросила» модель. Есть и целые режимы прав:
default (спрашивать про опасное), plan (только читать и
планировать), acceptEdits (правки без вопросов) и
bypassPermissions — без вопросов вообще.
bypassPermissions на рабочей машине, «чтобы не мешал вопросами».
Этот режим — только для изолированной песочницы или контейнера, где нечего ломать.
Второй вариант той же ошибки — слепо жать «разрешить», не читая, какую команду агент
собрался выполнить. Ворота прав работают, только пока вы в них смотрите.
5. Память и контекст: CLAUDE.md, сжатие, план
Контекстное окно модели конечно, и им нужно управлять — это вторая по частоте причина «странного» поведения агента после прав.
CLAUDE.md — файл памяти проекта: агент читает его в начале работы и подчиняется написанному. Это не документация, а шпаргалка: стек, команды сборки и тестов, правила и запреты. Вот шаблон под ваш проект практики — положите его в корень репозитория и поддерживайте:
# Проект: <название вашего проекта практики> ## Стек - <язык, фреймворк, БД — из вашей главы 2 отчёта> ## Команды - `...` — запуск в разработке - `...` — тесты (запускать после каждого изменения!) ## Правила - Отвечай и комментируй код по-русски. - Не трогай файлы в `docs/` и `report/` без явной просьбы. - Новые функции — с тестами. - Секреты лежат в `.env` — не читать и не коммитить.
Когда сессия длинная, история сжимается: старые сообщения свёртываются в резюме
(автоматически или командой /compact), свежие остаются подробными. Признак
переполнения — агент «поплыл» и забывает договорённости: сожмите контекст или начните
новую сессию через /clear.
И, наконец, режим планирования: агент сначала читает код и составляет план, а править начинает только после вашего одобрения. Для незнакомого или критичного кода — обязательная привычка: вы видите намерения до действий и успеваете поправить понимание задачи.
6. Расширения: команды, хуки, суб-агенты, MCP
Вокруг цикла есть четыре механизма расширения — все они устроены как «добавь файл, а не меняй код»:
| Механизм | Что это | Пример |
|---|---|---|
| слэш-команды | markdown-файл со сценарием в
.claude/commands/ |
/review-pr — своё ревью с фиксированным форматом ответа |
| хуки | ваши shell-команды в точках жизненного цикла | после каждой правки — автоформатирование; перед записью — проверка на секреты с блокировкой |
| суб-агенты | описанный в markdown помощник со своим контекстом и ограниченными инструментами | ревьюер с доступом «только чтение»: анализирует, но не может менять код |
| MCP | протокол подключения внешних инструментов | доступ к базе данных проекта под readonly-пользователем |
Обратите внимание на повторяющийся приём безопасности: суб-агенту-ревьюеру дают только инструменты чтения, базу подключают под readonly-пользователем, хук блокирует запись секретов до выполнения. Принцип наименьших привилегий — на каждом слое.
7. Безопасность: граница доверия
Как только агент читает внешние данные — веб-страницы, чужие файлы, вывод команд, — появляется главная угроза: prompt injection. Во внешнем тексте могут быть спрятаны инструкции («выполни rm -rf», «отправь .env на этот адрес»), и модель может принять их за команды пользователя. Ментальная модель защиты — граница доверия:
[ инструкции пользователя ] = доверенные команды [ вывод инструментов/файлов/веба ] = ДАННЫЕ, не инструкции
Защита выстраивается слоями, каждый из которых вы уже видели: deny-правила блокируют опасное, что бы ни «попросила» модель; песочница путей не пускает за пределы проекта; секреты вообще не попадают в контекст; необратимые действия требуют подтверждения человека. Худшая из возможных конфигураций — дать агенту одновременно доступ к секретам и возможность отправлять данные наружу без подтверждения: это готовый канал утечки.
8. Тренажёр: прокрутите цикл своими руками
Ниже — симулятор агентного цикла на задаче из раздела 2. Вы играете роль ворот прав: когда агент просит выполнить команду, решаете — разрешить или запретить. Панель показывает массив сообщений, текущий этап цикла и счётчик контекста. Запреты не ломают агента — посмотрите, как он выкручивается.
Три сценария, которые стоит прожить. Всё разрешить — канонические три витка: два вызова инструментов и ответ; заметьте, как история растёт с каждым шагом — за неё вы платите токенами на каждом обороте. Запретить первый bash — агент получит отказ как результат инструмента, попробует прочитать каталог напрямую, наткнётся на ошибку (каталог — не файл!) и честно объяснит, что без прав задачу не решить: отказ — это сигнал модели, а не крах программы. Запретить второй bash — агент обойдётся инструментами чтения: откроет все три файла по очереди (чтение безопасно и не требует разрешения) и посчитает строки сам — дольше, дороже, но цель достигнута.
9. Практикум: мини-агент своими руками
Соберём настоящего агента на официальном SDK — цикл, два инструмента, ворота прав.
Этого достаточно, чтобы исследовать проект, запускать тесты и чинить ошибки; именно так
в основе устроен любой кодинг-агент. Обратите внимание на четыре продакшн-детали, которые
отличают скелет от игрушки: таймаут на команды, обрезка длинного вывода (токены — деньги),
флаг is_error в результате (агент понимает, что инструмент упал, и пробует
иначе) и блок-лист опасных команд, срабатывающий раньше вопроса пользователю.
Полный код: рабочий мини-агент (Python + Anthropic SDK, один файл)
import subprocess, json from anthropic import Anthropic client = Anthropic() # ключ берётся из ANTHROPIC_API_KEY # 1) описания инструментов для модели (JSON Schema) TOOL_SCHEMAS = [ {"name": "read_file", "description": "Прочитать текстовый файл по пути и вернуть содержимое.", "input_schema": {"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]}}, {"name": "bash", "description": "Выполнить shell-команду, вернуть stdout/stderr/код.", "input_schema": {"type": "object", "properties": {"cmd": {"type": "string"}}, "required": ["cmd"]}}, ] # 2) реализация инструментов def read_file(path): with open(path, encoding="utf-8") as f: return f.read()[:10000] # обрезаем: не раздуваем контекст def bash(cmd): r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=30) tail = lambda s: s[-2000:] # только хвост длинного вывода return json.dumps({"stdout": tail(r.stdout), "stderr": tail(r.stderr), "code": r.returncode}) IMPL = {"read_file": lambda a: read_file(a["path"]), "bash": lambda a: bash(a["cmd"])} # 3) ворота прав: опасное блокируем, остальное спрашиваем DENY = ("rm -rf", "git push --force", ":(){", "mkfs", "dd if=") def check_permission(name, args): if name == "bash": cmd = args.get("cmd", "") if any(bad in cmd for bad in DENY): return False return input(f"Выполнить `{cmd}`? [y/N] ").strip().lower() == "y" return True # чтение безопасно # 4) главный агентный цикл def run(prompt): messages = [{"role": "user", "content": prompt}] while True: resp = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=2048, tools=TOOL_SCHEMAS, messages=messages) messages.append({"role": "assistant", "content": resp.content}) if resp.stop_reason != "tool_use": print(next(b.text for b in resp.content if b.type == "text")) return results = [] for block in resp.content: if block.type != "tool_use": continue if not check_permission(block.name, block.input): out, err = "Отказано пользователем", True else: try: out, err = IMPL[block.name](block.input), False except Exception as e: out, err = f"Ошибка инструмента: {e}", True results.append({"type": "tool_result", "tool_use_id": block.id, "content": str(out), "is_error": err}) messages.append({"role": "user", "content": results}) if __name__ == "__main__": run("Найди все файлы .py в src/, посчитай строки и покажи самый большой")
Дальнейший путь наращивания — в порядке боли: сначала ворота прав (иначе опасно), потом ретраи и таймауты (иначе падает), затем сохранение сессии (иначе теряете работу), и только потом сжатие контекста и трейсинг. Пять шагов — и вы повторите путь от учебного скрипта до архитектуры уровня Claude Code.
10. Агент в вашем проекте практики
Теперь главное — как применять это в курсе. Пять рецептов, покрывающих типовые ситуации семестра:
| Ситуация | Приём |
|---|---|
| получили чужой/шаблонный код | сгенерировать файл памяти командой /init, затем: «опиши архитектуру
проекта и точки входа» |
| упал тест | «запусти тесты, найди упавший, объясни причину и предложи фикс» — сначала диагноз, потом правка |
| рискованная правка | режим планирования + коммит до запуска: план читаете и одобряете, откат — одной командой git |
| перед коммитом | /review: проверка незакоммиченных изменений на баги и стиль |
| нужны тесты на модуль | «сначала перечисли граничные случаи, потом напиши тесты и запусти» — список случаев успеваете поправить |
Заметьте общий паттерн рецептов: сначала локализуй и объясни — потом правь. Фразы «объясни причину», «не меняй ничего, пока не подтвержу», «перечисли случаи» держат агента в режиме анализа и дают вам точку контроля. И четыре привычки, которых хватает на 90% повседневной работы: файл памяти в начале проекта, режим планирования для рискованного, сжатие контекста, когда «поплыло», и deny-правила для опасного.
10.1. Правила честного использования в курсе
Агент в этом курсе — разрешённый и поощряемый инструмент, как компилятор или отладчик. Но ответственность за результат — на вас, и на защите это проявится буквально:
- не сдавайте то, чего не понимаете: любой фрагмент кода проекта вы должны уметь объяснить строку за строкой — «это написал агент» ответом не является;
- ревьюйте код агента как чужой: читайте диффы перед коммитом; агент уверенно ошибается — особенно там, где не хватает контекста;
- коммитьте часто и мелко — это и защита от неудачных правок, и честная история работы в git, которую видно на контрольных точках;
- использование агента описывается в отчёте: чем пользовались и для чего — как описывают любой инструмент разработки (см. справку по структуре отчёта).
Контрольные вопросы
-
У агента есть инструменты (чтение файлов, команды, поиск) и цикл: после каждого действия он видит результат и решает, что дальше, до выполнения задачи. Чат только генерирует текст по вставленному контексту; автодополнение достраивает код в текущем файле. Выбор: автодополнение — набор, чат — понять/спросить, агент — многошаговые задачи с обратной связью.
-
История лежит в messages[]; она уходит в API со списком инструментов. Если stop_reason == "tool_use" — выполняем запрошенный инструмент, кладём tool_result в историю и снова вызываем API; иначе это финальный текст. Цикл не меняется от количества инструментов — вся сложность в обвязке вокруг.
-
Обвязка вокруг цикла, делающая агента пригодным к работе: ворота прав (иначе выполнит опасное), ретраи и таймауты (иначе падает от сетевых ошибок), сжатие контекста (иначе забывает начало), журнал сессии на диске (иначе теряет всё при сбое), логи и трейсинг (иначе непонятно, что и почему сделал).
-
Перед выполнением вызов проходит: хуки → правила allow/deny из settings.json → интерактивный вопрос. Отказ возвращается агенту как tool_result с ошибкой — для модели это данные, она пробует другой путь (в тренажёре: после запрета bash агент считал строки чтением файлов). Правила позволяют раз и навсегда запретить rm -rf и чтение .env.
-
Файл памяти проекта: стек, команды сборки и тестов, правила и запреты — агент читает его и подчиняется. Короткий и конкретный: это шпаргалка для агента, а не документация; длинный файл съедает контекст и снижает качество. Генерируется командой /init, поддерживается руками.
-
Для незнакомого и критичного кода, рискованных массовых правок. Агент читает и составляет план, но ничего не меняет до одобрения: вы видите намерения до действий, успеваете поправить понимание задачи, а в связке с коммитом до запуска любая неудача откатывается одной командой.
-
История диалога отправляется в модель на каждом витке и растёт с каждым шагом; главный пожиратель — вывод инструментов. При переполнении старые сообщения сжимаются в резюме (/compact автоматически или вручную); признак — агент «плывёт» и забывает договорённости. Для новой темы — /clear.
-
Понимать каждую сданную строку (на защите «это написал агент» — не ответ); ревьюить код агента как чужой, читая диффы; коммитить часто и мелко; описать использование инструмента в отчёте. Единица работы — узкая проверяемая задача, а не «сделай проект целиком».
-
Инструкции, спрятанные во внешних данных (файл, веб-страница, вывод команды), которые модель может принять за команды пользователя. Граница доверия: инструкции пользователя — доверенные; всё прочитанное инструментами — данные, не команды. Защита слоями: deny-правила, песочница путей, изоляция секретов, подтверждение необратимого. Худшее сочетание — доступ к секретам плюс свободная отправка данных наружу.
-
Вывод инструментов попадает в messages[] и перечитывается моделью на каждом витке: тысячи строк лога — это токены и «утопленный» контекст, поэтому отдают только хвост. Флаг is_error отличает «результат» от «падения инструмента» — модель понимает, что путь не сработал, и пробует другой, вместо того чтобы строить выводы на сообщении об ошибке.
Источники
- Claude Code — Anthropic Documentation : [сайт]. — URL: https://docs.anthropic.com/en/docs/claude-code (дата обращения: 09.07.2026).
- Model Context Protocol : [сайт]. — URL: https://modelcontextprotocol.io (дата обращения: 09.07.2026).
- Building Effective Agents — Anthropic : [сайт]. — URL: https://www.anthropic.com/research/building-effective-agents (дата обращения: 09.07.2026).