Архитектура AI-агентов: planner, executor, stateful memory, MCP инструменты | AiManual
AiManual Logo Ai / Manual.
29 Дек 2025 Гайд

Как спроектировать современного AI-агента: от planner/executor до stateful memory

Полное руководство по проектированию современных AI-агентов: от архитектуры planner/executor до реализации stateful memory и работы с инструментами.

Почему простые LLM-агенты не работают в продакшене

Если вы уже пробовали создавать AI-агентов на базе простых промптов или наивного RAG, то наверняка столкнулись с классическими проблемами: агент "галлюцинирует", теряет контекст в длинных диалогах, не умеет планировать сложные задачи и восстанавливаться после ошибок. Эта проблема особенно хорошо знакома тем, кто читал нашу статью "Production-ready AI-агент с нуля".

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

Современный AI-агент — это не просто "умный промпт". Это сложная система, состоящая из нескольких компонентов, каждый из которых решает свою задачу. В этой статье мы разберём архитектурный паттерн, который используют ведущие компании для создания продакшен-готовых агентов.

Архитектура современного AI-агента

В основе любой серьёзной агентной системы лежит три фундаментальных компонента:

Компонент Роль Примеры технологий
Planner (Планировщик) Разбивает цель на подзадачи, выбирает стратегию Chain of Thought, Tree of Thoughts, ReAct
Executor (Исполнитель) Выполняет конкретные действия, использует инструменты MCP, LangChain Tools, AutoGen
Stateful Memory (Память с состоянием) Хранит контекст, историю, знания Vector DB, SQLite, Redis, Chroma

1 Planner: мозг агента, который думает наперёд

Планировщик — это компонент, который отвечает на вопрос "Как решить эту задачу?". В отличие от простых LLM, которые пытаются сразу дать ответ, планировщик разбивает сложную цель на последовательность простых шагов.

💡
Планировщик не должен выполнять действия! Его единственная задача — генерировать план. Разделение планирования и исполнения — ключевой принцип, который делает агента устойчивым к ошибкам.

Пример простого планировщика на Python:

class Planner:
    def __init__(self, llm):
        self.llm = llm
        
    def create_plan(self, goal: str, available_tools: list) -> dict:
        """Создаёт план достижения цели"""
        prompt = f"""
        Цель: {goal}
        Доступные инструменты: {', '.join(available_tools)}
        
        Разбей цель на последовательность шагов.
        Каждый шаг должен:
        1. Быть конкретным и выполнимым
        2. Использовать только доступные инструменты
        3. Иметь чёткий критерий успеха
        
        Ответ в формате JSON:
        {{
            "steps": [
                {{"action": "название действия", "tool": "инструмент", "params": {{}}}}
            ]
        }}
        """
        
        response = self.llm.generate(prompt)
        return json.loads(response)

2 Executor: руки агента, которые делают работу

Исполнитель получает план от планировщика и выполняет его шаг за шагом. Ключевая особенность хорошего исполнителя — умение работать с инструментами (tools) и обрабатывать ошибки.

Современный стандарт для работы с инструментами — MCP (Model Context Protocol). Это открытый протокол, который позволяет безопасно подключать внешние инструменты к LLM. В отличие от самописных интеграций, MCP обеспечивает:

  • Единый интерфейс для всех инструментов
  • Безопасное выполнение (инструменты работают в изолированной среде)
  • Автоматическую документацию и обнаружение
  • Поддержку streaming и асинхронных операций
class Executor:
    def __init__(self, tools_registry):
        self.tools = tools_registry
        self.memory = []  # История выполнения
        
    def execute_step(self, step: dict) -> dict:
        """Выполняет один шаг плана"""
        try:
            tool_name = step["tool"]
            params = step["params"]
            
            if tool_name not in self.tools:
                return {
                    "status": "error",
                    "error": f"Инструмент {tool_name} не найден"
                }
            
            # Выполняем инструмент через MCP
            result = self.tools[tool_name].execute(params)
            
            # Сохраняем в память
            self.memory.append({
                "step": step,
                "result": result,
                "timestamp": datetime.now()
            })
            
            return {
                "status": "success",
                "result": result
            }
            
        except Exception as e:
            # Восстановление после ошибки
            return {
                "status": "error",
                "error": str(e),
                "suggestion": self._suggest_recovery(step, e)
            }

3 Stateful Memory: долговременная память агента

Самая критичная часть архитектуры — память. Как мы писали в статье "Agent Skills: как заставить ИИ-агента не тупить", контекстное окно LLM ограничено, и агент "забывает" всё, что не помещается в текущий контекст.

Stateful Memory решает эту проблему, предоставляя несколько типов памяти:

  1. Краткосрочная память — текущий диалог и контекст выполнения
  2. Долгосрочная память — векторная база знаний, документы, инструкции
  3. Процедурная память — история выполненных действий и их результатов
  4. Рабочая память — промежуточные вычисления и состояния
class StatefulMemory:
    def __init__(self):
        self.short_term = []  # Ограниченный размер
        self.long_term = ChromaVectorStore()  # Vector DB
        self.procedural = SQLiteStore()  # SQLite для структурированных данных
        
    def remember(self, key: str, query: str, limit: int = 5) -> list:
        """Извлекает релевантные воспоминания"""
        # Ищем в долгосрочной памяти (векторный поиск)
        vector_results = self.long_term.similarity_search(query, k=limit)
        
        # Ищем в процедурной памяти (SQL запрос)
        procedural_results = self.procedural.query(
            "SELECT * FROM memories WHERE key LIKE ?", 
            [f"%{key}%"]
        )
        
        # Объединяем и ранжируем
        return self._rank_and_merge(vector_results, procedural_results)
        
    def learn(self, experience: dict):
        """Сохраняет новый опыт"""
        # Сохраняем в краткосрочную память
        self.short_term.append(experience)
        
        # Если опыт важен — сохраняем в долгосрочную
        if self._is_important(experience):
            self.long_term.add(
                text=experience["summary"],
                metadata=experience["metadata"]
            )
            
        # Сохраняем в процедурную память
        self.procedural.insert("memories", experience)

Полная архитектура: как компоненты взаимодействуют

Теперь соберём все компоненты в единую систему. Современный агент работает в цикле наблюдение-планирование-действие-рефлексия:

class ModernAIAgent:
    def __init__(self, llm, tools, memory_config):
        self.planner = Planner(llm)
        self.executor = Executor(tools)
        self.memory = StatefulMemory(**memory_config)
        self.max_iterations = 10
        
    def run(self, goal: str) -> dict:
        """Основной цикл выполнения агента"""
        
        # 1. Загружаем релевантный контекст из памяти
        context = self.memory.remember("similar_goals", goal)
        
        # 2. Создаём начальный план
        available_tools = list(self.executor.tools.keys())
        plan = self.planner.create_plan(goal, available_tools, context)
        
        results = []
        
        # 3. Цикл выполнения
        for iteration in range(self.max_iterations):
            for step in plan["steps"]:
                # Выполняем шаг
                result = self.executor.execute_step(step)
                
                # Сохраняем результат
                results.append(result)
                
                # Если ошибка — перепланируем
                if result["status"] == "error":
                    new_plan = self.planner.replan(
                        goal, 
                        current_state=results,
                        error=result["error"]
                    )
                    plan = new_plan
                    break
                    
                # Рефлексия: анализируем результат
                reflection = self._reflect_on_result(result, step)
                if reflection["needs_adjustment"]:
                    plan = self._adjust_plan(plan, reflection)
                    
            # Проверяем, достигнута ли цель
            if self._goal_achieved(results, goal):
                break
                
        # 4. Сохраняем опыт в память
        self.memory.learn({
            "goal": goal,
            "results": results,
            "success": self._goal_achieved(results, goal),
            "summary": self._generate_summary(goal, results)
        })
        
        return {
            "success": self._goal_achieved(results, goal),
            "results": results,
            "iterations": iteration + 1
        }

Практические рекомендации по реализации

Выбор моделей для разных компонентов

Не используйте одну и ту же модель для всех задач! Планировщик нуждается в моделях с сильным reasoning, исполнитель — в моделях, которые хорошо следуют инструкциям. Обратите внимание на топ-5 open-source моделей для агентов.

Компонент Рекомендуемые модели Почему
Planner Claude 3.5 Sonnet, GPT-4o, DeepSeek Coder Сильное reasoning, умение разбивать задачи
Executor Gemini Flash, Llama 3.1 8B, Mixtral Быстрое выполнение, точное следование инструкциям
Reflection GPT-4, Claude 3 Opus Глубокий анализ, критическое мышление

Реализация MCP-инструментов

MCP (Model Context Protocol) — это будущее работы с инструментами. Вот как создать простой MCP-сервер:

# mcp_server.py
from mcp import Server, StdioServerTransport
import asyncio

class CalculatorTool:
    @staticmethod
    def add(a: float, b: float) -> float:
        return a + b
    
    @staticmethod
    def multiply(a: float, b: float) -> float:
        return a * b

async def main():
    # Создаём сервер MCP
    server = Server("calculator-server")
    
    # Регистрируем инструменты
    @server.list_tools()
    async def handle_list_tools():
        return [
            {
                "name": "add",
                "description": "Складывает два числа",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "a": {"type": "number"},
                        "b": {"type": "number"}
                    }
                }
            },
            {
                "name": "multiply",
                "description": "Умножает два числа",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "a": {"type": "number"},
                        "b": {"type": "number"}
                    }
                }
            }
        ]
    
    # Запускаем сервер
    async with StdioServerTransport() as transport:
        await server.run(transport)

if __name__ == "__main__":
    asyncio.run(main())

Распространённые ошибки и как их избежать

Ошибка 1: Слишком сложный план
Планировщик генерирует план из 50 шагов для простой задачи. Решение: Ограничивайте максимальное количество шагов, добавьте проверку сложности плана.

Ошибка 2: Бесконечные циклы
Агент зацикливается на одном шаге. Решение: Добавьте счётчик итераций и механизм принудительного выхода.

Ошибка 3: Переполнение памяти
Stateful memory растёт бесконечно. Решение: Реализуйте механизм забывания, приоритетное хранение, компрессию старых воспоминаний.

Ошибка 4: Небезопасные инструменты
Агент получает доступ к опасным операциям. Решение: Используйте MCP с sandbox-режимом, добавляйте approval-шаги для критических операций.

Продвинутые техники

Иерархическое планирование

Для очень сложных задач используйте иерархическое планирование: высокоуровневый планировщик разбивает задачу на подзадачи, каждая подзадача обрабатывается своим специализированным агентом. Это похоже на то, как работают AI-агенты как сотрудники в организации.

Мультимодальная память

Современные агенты должны работать не только с текстом. Добавьте в Stateful Memory поддержку:

  • Векторные эмбеддинги изображений
  • Транскрипты аудио и видео
  • Структурированные данные (JSON, таблицы)
  • Временные ряды и метрики

Обучение на опыте (Learning from Experience)

Лучшие агенты учатся на своих ошибках. Реализуйте механизм, который:

  1. Анализирует неудачные выполнения
  2. Извлекает уроки ("не использовать инструмент X в ситуации Y")
  3. Обновляет инструкции и промпты планировщика
  4. Создаёт шаблоны для похожих задач в будущем

Заключение

Проектирование современного AI-агента — это не магия, а инженерная дисциплина. Разделение ответственности на planner, executor и stateful memory позволяет создавать системы, которые:

  • Масштабируются — можно улучшать каждый компонент независимо
  • Надёжны — ошибки в одном шаге не ломают всю систему
  • Обучаемы — агент накапливает опыт и становится умнее
  • Контролируемы — вы всегда понимаете, что делает агент и почему

Следующий шаг после освоения базовой архитектуры — изучение продвинутых тем: распределённые агенты, мультиагентные системы, reinforcement learning для оптимизации поведения. Если вы хотите углубиться в тему, рекомендую бесплатный курс по разработке AI-агентов.

🚀
Главный секрет успеха — начать с простого. Создайте минимальную работающую версию с базовым planner, 2-3 инструментами и простой памятью. Затем постепенно добавляйте сложность, основываясь на реальных потребностях вашего проекта.