Почему ваш AI-агент для кода — это не чат-бот, а вы этого не знаете
Вы наверняка видели демки, где нейросеть пишет код за пару секунд. Выглядит как магия. Пока не попробуешь сделать что-то сложнее калькулятора. Агент зависает, генерирует бесконечные циклы, забывает, что только что сделал. Потому что под капотом — не просто промпт к GPT, а сложная система. И если вы не понимаете её архитектуру, вы не сможете ни починить, ни улучшить.
Готовые решения вроде GitHub Copilot или Cursor — чёрные ящики. Они работают, пока работают. А когда сломаются или перестанут отвечать вашим нуждам, вы останетесь с кучей технического долга, о котором я уже писал. Пора заглянуть внутрь.
Забудьте про «просто подключим API». AI-агент для кода — это мини-операционная система. Со своими процессами, памятью и системными вызовами. Если собрать её на скотче, она развалится на первом же рефакторинге.
Из чего на самом деле состоит агент: пять обязательных компонентов
Представьте, что вы дирижёр оркестра. У вас есть партитура (задача), музыканты (инструменты) и память о том, как звучало предыдущее исполнение. AI-агент работает так же. Вот его ядро:
| Компонент | Аналог в разработке | Что ломается, если его нет |
|---|---|---|
| Оркестратор (Ядро) | Event Loop или Message Bus | Агент не понимает, какой инструмент вызвать следующим. Тупит. |
| Память (Краткосрочная и долгая) | База данных + кэш | Забывает контекст через 5 минут. Повторяет одни и те же ошибки. |
| Инструменты (Tools) | API или системные вызовы | Может только болтать, но не может выполнить действие (запустить тест, прочитать файл). |
| Планировщик (Scheduler) | Менеджер задач | Не может разбить большую задачу ("сделай мне CRM") на шаги. Пытается сделать всё сразу. |
| Безопасность (Sandbox) | Контейнер или виртуальная машина | Стирает вашу файловую систему, пытаясь "очистить кэш". |
1 Оркестратор: мозг, который решает, что делать дальше
Это не просто роутер, который передаёт запросы туда-сюда. Оркестратор — это конечный автомат. Он получает задачу, анализирует текущий контекст (что уже сделано, что в памяти), выбирает следующий инструмент и передаёт ему управление. Потом ждёт результат, оценивает его и решает, продолжать или откатиться.
В 2026 году самые продвинутые оркестраторы используют графы исполнения (execution graphs), а не линейные цепочки. Это позволяет агенту ветвить логику, работать над несколькими подзадачами параллельно и откатывать только неудачные ветки. Инструменты вроде LangChain или собственные решения крупных компаний уже поддерживают это.
# Упрощённая схема оркестратора на Python
class Orchestrator:
def __init__(self, tools, memory):
self.tools = tools # Словарь инструментов
self.memory = memory # Объект памяти
self.execution_graph = {} # Граф выполненных шагов
def decide_next_step(self, current_state, goal):
"""Решает, какой инструмент вызвать следующим."""
# Анализ памяти: что уже пробовали, что сработало
history = self.memory.get_recent_actions()
# Выбор инструмента на основе истории и цели
# Здесь может быть сложная логика с использованием LLM
next_tool_name = self._call_planner_llm(goal, history)
return self.tools[next_tool_name]
def execute(self, goal):
"""Главный цикл исполнения."""
current_state = {}
while not self._is_goal_achieved(current_state, goal):
tool = self.decide_next_step(current_state, goal)
result = tool.execute(current_state)
self.memory.store_action(tool, result)
current_state.update(result)
# Возможность отката при ошибке
if result.get("status") == "error":
self._rollback_last_step()
return current_state
2 Память: чем она отличается от кэша и почему её не хватает
Память агента — это не просто массив последних сообщений. Это структурированное хранилище, которое должно отвечать на вопросы: "Что мы уже пробовали для этой задачи?", "Какие ошибки возникали?", "Какие файлы мы уже читали?".
Есть три уровня:
- Кратковременная (рабочая): Контекст текущей сессии. Обычно это окно токенов LLM (например, 128K у Claude 3.7 Sonnet или 1M у некоторых open-source моделей 2026 года). Но тупо запихнуть всё в промпт — дорого и неэффективно.
- Долговременная (векторная + графовая): База знаний агента. Сюда пишутся успешные решения, связи между сущностями (например, "файл X использует функцию Y из модуля Z"). Современные подходы, как GraphRAG в архитектуре AAF, комбинируют векторный поиск с графами для точного восстановления контекста.
- Эпизодическая: Записи о completed tasks с метаданными (время, результат, использованные инструменты). Позволяет агенту учиться на прошлом опыте без тонкой настройки модели.
Самая частая ошибка — хранить память в формате, неудобном для поиска. Если агент каждый раз ищет "как исправить ошибку Y" во всей истории диалога, он тратит токены и время. Нужна индексация.
3 Инструменты: как дать агенту руки, не отдав ему нож
Инструмент — это любое действие, которое агент может выполнить во внешнем мире. От чтения файла до запуска тестов и отправки HTTP-запроса. Описываются они через чёткий API: имя, описание, входные параметры (схема), выходные данные.
В 2026 году стандартом де-факто стал OpenAI Tools format (бывший Function Calling), который поддерживают почти все LLM, включая локальные, как Llama 3.2 90B или Command R 7B. Но формат — это просто синтаксис. Суть в безопасности.
Никогда не давайте агенту инструмент `execute_shell(command)` без валидации. Даже если вы доверяете модели. Потому что модель может ошибиться, быть скомпрометирована промптом-инжекцией или просто решить, что `rm -rf /` — это хороший способ освободить место. Используйте инструменты с явными параметрами: `run_tests(file_path)`, `search_in_files(pattern)`.
Пример набора инструментов для код-агента:
[
{
"type": "function",
"function": {
"name": "read_file",
"description": "Read the contents of a file",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Absolute path to the file"
}
},
"required": ["path"]
}
}
},
{
"type": "function",
"function": {
"name": "write_file",
"description": "Write content to a file. Will overwrite existing content.",
"parameters": {
"type": "object",
"properties": {
"path": { "type": "string" },
"content": { "type": "string" }
},
"required": ["path", "content"]
}
}
}
]
Для локальных агентов, которые работают прямо на вашем компьютере, архитектура инструментов должна включать контроль доступа. Подробнее об этом в гайде по архитектуре локальных агентов.
4 Главный цикл: тот самый тик-ток, который всё двигает
Вот где магия превращается в инженерную дисциплину. Главный цикл — это бесконечный (пока задача не выполнена) процесс: Восприятие -> Размышление -> Действие -> Оценка (ReAct pattern на стероидах).
- Восприятие: Агент смотрит в память и текущее состояние системы (например, вывод последней команды, содержимое файла).
- Размышление: Решает, что делать дальше. Здесь может работать планировщик (разбивает крупную цель на шаги) или сама LLM ("исходя из ошибки компиляции, мне нужно исправить синтаксис в строке 42").
- Действие: Вызывает выбранный инструмент с конкретными параметрами.
- Оценка: Анализирует результат. Успех? Ошибка? Нужно ли повторить с другими параметрами? Результат пишется в память.
Звучит просто. Но дьявол в деталях. Что если действие заняло 30 секунд, а контекст LLM ограничен? Нужно асинхронное исполнение с колбэками. Что если результат действия — это 10 МБ логов? Нужна суммаризация или выборочное сохранение. Именно здесь многие фреймворки ломаются, когда выходишь за рамки туториала.
Собираем своего агента: пошаговый план на 2026 год
Теория без практики — это просто болтовня. Вот как начать строить, не утонув в сложности.
Шаг 0: Выберите модель (локальную или облачную)
В 2026 году выбор огромен. Для код-генерации по-прежнему лидируют специализированные модели вроде DeepSeek Coder 33B Instruct (обновлённая версия) или CodeLlama 2 70B. Но для сложной логики и планирования нужны модели с большим контекстом и хорошим reasoning. Присмотритесь к Claude 3.7 Sonnet (если бюджет позволяет) или open-source альтернативам вроде Qwen 2.5 72B или Mixtral 2 8x22B.
Критерий прост: модель должна стабильно поддерживать вызов инструментов (function calling) и иметь контекст хотя бы 32K токенов для сложных задач. Для локального запуска на одной видеокарте смотрите на квантованные 7B-20B модели.
Шаг 1: Определите инструменты (начните с минимального набора)
Не пытайтесь охватить всё. Вашему агенту для работы с кодом достаточно:
- Чтение файла
- Запись в файл
- Поиск по файлам (grep)
- Выполнение команды в shell (строго ограниченной, например, только `npm test`, `pytest`, `go build`)
- Поиск в интернете (через безопасный API, типа Serper или SearxNG)
Каждый инструмент должен иметь чёткую схему валидации входных данных. Используйте Pydantic для Python или Zod для TypeScript.
Шаг 2: Реализуйте простую память (сначала — просто список)
Не лезьте сразу в векторные базы. Создайте класс Memory, который хранит последние N шагов в формате (действие, результат). Добавьте метод поиска по ключевым словам. Этого хватит для первых экспериментов. Когда упрётесь в ограничения, переходите на ChromaDB, Qdrant или Weaviate с интеграцией GraphRAG, как в архитектуре AAF.
Шаг 3: Напишите оркестратор (самую простую версию)
Ваш первый оркестратор может быть тупым: он просто передаёт управление LLM на каждом шаге, предоставляя ей список инструментов и историю. Используйте шаблон ReAct. Подключите вызов инструментов через native function calling выбранной модели.
# Псевдокод главного цикла
async def main_loop(task_description, max_steps=20):
memory = []
for step in range(max_steps):
# 1. Сформируем промпт с историей и доступными инструментами
prompt = build_react_prompt(task_description, memory, available_tools)
# 2. Отправим запрос к LLM
llm_response = await llm.chat(prompt, tools=tool_schemas)
# 3. Извлечём решение о действии из ответа LLM
action_to_take = parse_llm_response(llm_response)
# 4. Выполним действие (вызов инструмента)
result = await execute_tool(action_to_take)
# 5. Сохраним шаг в память
memory.append({"action": action_to_take, "result": result})
# 6. Проверим, выполнена ли задача
if task_completed(result):
break
return memory
Шаг 4: Добавьте планировщик (когда простой цикл не справляется)
Когда задачи становятся сложными ("добавь авторизацию в моё приложение"), агент теряется. Нужен планировщик — отдельный модуль (часто это тоже LLM), который разбивает цель на подзадачи и создаёт граф исполнения. Посмотрите на HuggingGPT или AutoGPT старых версий, но учтите их ошибки. В 2026 году планировщики стали умнее: они оценивают ресурсы (время, стоимость API) и могут параллелить независимые задачи.
Где всё ломается: пять фатальных ошибок новичков
- Бесконечные циклы из-за плохой оценки состояния. Агент не понимает, что задача выполнена, и продолжает делать одно и то же. Лечение: чёткие критерии остановки (например, все тесты проходят) и лимит шагов.
- Переполнение контекста. Вы пихаете в промпт всю историю, и через 10 шагов модель "забывает" начало. Лечение: агрессивная суммаризация прошлых шагов, использование долговременной памяти с поиском.
- Небезопасные инструменты. Дали агенту `subprocess.run` — он удалил node_modules и решил, что так надо. Лечение: песочница (Docker-контейнеры) для выполнения кода и инструменты только с явными параметрами.
- Игнорирование ошибок. Агент видит, что тесты падают, но продолжает писать новый код вместо исправления. Лечение: заставьте оркестратор анализировать статус результата инструмента и явно обрабатывать ошибки ("при ошибке компиляции — вызови инструмент fix_error").
- Отсутствие обучения. Агент каждый раз начинает с чистого листа. Лечение: сохраняйте успешные траектории выполнения задач в векторную БД. Перед новой задачей ищите похожие решения и загружайте их в контекст. Это тот самый паттерн обучения, который отличает продвинутого разработчика.
Когда одного агента мало: намёк на мульти-агентность
Если ваш агент стал слишком сложным, он делает и планирование, и код-ревью, и тестирование — пора разделять ответственность. Мульти-агентная система, где есть специализированные агенты (архитектор, кодер, тестировщик, ревьюер), часто эффективнее. Они общаются через общую шину событий (Event Bus) или через менеджера. Переход на такую архитектуру — тема для отдельного разговора, но критерии просты: когда один агент постоянно путается в противоречивых подзадачах или когда задачи требуют экспертизы в разных областях. Подробнее о переходе читайте в этом материале.
Неочевидный совет: Самый ценный компонент в архитектуре AI-агента — не модель и не инструменты, а логирование. Записывайте каждый шаг, каждый выбор оркестратора, каждый ответ LLM в структурированном виде (JSON). Когда что-то сломается (а это случится), вы сможете не гадать, а проанализировать лог и понять, где агент сошёл с ума. Это сэкономит вам недели отладки.
Архитектура AI-агентов для кода — это не про волшебство. Это про инженерный компромисс между гибкостью и надёжностью. Соберите сначала простую, но понятную систему. Потом итерируйте. И помните, что даже самый умный агент — всего лишь инструмент в руках разработчика, который всё ещё должен понимать, что происходит. Иначе технический долг накроет с головой, и вы даже не поймёте, откуда он взялся.