RLM архитектура для LLM-агентов: решение Goal Drift и Context Rot | AiManual
AiManual Logo Ai / Manual.
20 Янв 2026 Гайд

RLM: практическое руководство по созданию LLM-агентов без контекстного дрейфа и потери цели

Полное практическое руководство по созданию LLM-агентов на архитектуре RLM. Устраняем контекстный дрейф и потерю цели с помощью рекурсивных вызовов. Примеры код

Почему ваши LLM-агенты сходят с ума через 10 минут работы

Вы запускаете агента с четкой задачей: "проанализируй 100 документов и составь отчет". Первые 15 минут все идет идеально. Агент систематизирует данные, находит закономерности, генерирует умные выводы. А потом происходит что-то странное.

Агент внезапно начинает обсуждать погоду. Или повторяет один и тот же анализ трижды. Или полностью меняет тему, забыв исходную цель. Это не баг - это фундаментальный провал архитектуры.

Goal Drift (потеря цели) и Context Rot (контекстный дрейф) - две главные причины, почему 80% продвинутых LLM-агентов разваливаются на сложных задачах. Традиционные подходы - цепочки мыслей, ReAct, даже продвинутые планировщики - не решают проблему рекурсивной деградации контекста.

Классические агенты работают по принципу "все в одном контексте". Каждое новое сообщение добавляется в историю, контекст разбухает, ключевые инструкции тонут в шуме. Через 20-30 итераций агент забывает, зачем начал работу.

RLM: архитектура, которая не забывает

Recursive Language Model - не новая модель, а архитектурный паттерн. Суть в том, что главный агент (orchestrator) не выполняет работу сам. Он разбивает задачу на подзадачи и создает для каждой специализированного суб-агента с чистым контекстом.

Каждый суб-агент получает:

  • Конкретную микрозадачу
  • Только релевантный контекст
  • Четкие критерии завершения
  • Нулевой исторический багаж

После выполнения суб-агент уничтожается вместе со своим контекстом. Orchestrator собирает результаты и принимает решение: задача решена или нужно углубиться рекурсивно.

💡
RLM похож на работу опытного руководителя: он не пытается делать все сам, а нанимает специалистов под конкретные задачи, дает им четкие инструкции, а потом собирает результаты. Каждый специалист работает в своем "чистом помещении" без отвлечений.

Как работает RLM под капотом

Представьте, что вам нужно проанализировать кодбазу из 500 файлов. Классический агент загрузит все в контекст (или будет использовать RAG) и начнет анализ. Через час он будет обсуждать стиль кодирования в файле A, забыв, что искал security vulnerabilities.

RLM подход:

  1. Orchestrator анализирует общую задачу: "найди уязвимости в коде"
  2. Создает суб-агента для анализа структуры проекта
  3. Получает список потенциально опасных модулей
  4. Для каждого модуля создает нового суб-агента с задачей "проанализируй модуль X на уязвимости"
  5. Собирает все отчеты, проверяет полноту
  6. Если нужно углубиться - запускает рекурсивно суб-агентов для конкретных функций
Компонент Роль Жизненный цикл
Orchestrator Держит цель, управляет суб-агентами Существует всю задачу
Суб-агент Выполняет конкретную подзадачу Создается и уничтожается за 1 цикл
Контекстный менеджер Изолирует контексты, предотвращает утечки Постоянный

Пошаговая реализация на Python (2026 год)

Сейчас, в 2026 году, у нас есть выбор: использовать готовые фреймворки вроде LangChain 0.2.x (который наконец-то починили после провального 0.1) или писать на чистом API. Я покажу оба подхода, но предупрежу: готовые фреймворки часто добавляют свою магию, которая ломает изоляцию контекста.

1 Настройка среды и базовых классов

Сначала определим базовые классы. В 2026 году OpenAI GPT-5 уже вышел, но архитектура RLM работает с любой современной LLM - Claude 3.5, Gemini 2.0, или локальными моделями вроде Llama 3.2 400B.

from dataclasses import dataclass
from typing import List, Dict, Any, Optional
from enum import Enum
import json

class AgentStatus(Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"

@dataclass
class SubTask:
    id: str
    description: str
    context: Dict[str, Any]
    max_depth: int = 3
    current_depth: int = 0

@dataclass
class AgentResult:
    task_id: str
    status: AgentStatus
    output: Any
    next_subtasks: List[SubTask] = None
    error: Optional[str] = None

2 Реализация Context Manager - сердце RLM

Context Manager - самый критичный компонент. Он должен гарантировать, что контексты суб-агентов никогда не смешиваются. В 2026 году появились специализированные векторные БД с изоляцией на уровне тенантов, но для простоты используем in-memory подход.

class ContextManager:
    def __init__(self):
        self.contexts = {}  # task_id -> context
        self.isolation_boundary = set()
    
    def create_isolated_context(self, task_id: str, parent_context: Optional[Dict] = None) -> Dict:
        """Создает полностью изолированный контекст для суб-агента"""
        # Копируем только необходимые данные из родительского контекста
        base_context = {
            "task_id": task_id,
            "created_at": "2026-01-20T10:00:00Z",  # Актуальная дата
            "llm_config": {
                "model": "gpt-5-turbo",  # Самая новая модель на 2026 год
                "temperature": 0.1,
                "max_tokens": 2000
            }
        }
        
        if parent_context:
            # Берем только явно разрешенные поля
            allowed_keys = ["goal", "constraints", "output_format"]
            for key in allowed_keys:
                if key in parent_context:
                    base_context[key] = parent_context[key]
        
        self.contexts[task_id] = base_context
        self.isolation_boundary.add(task_id)
        return base_context
    
    def destroy_context(self, task_id: str):
        """Уничтожает контекст после завершения агента"""
        if task_id in self.contexts:
            del self.contexts[task_id]
            self.isolation_boundary.remove(task_id)
    
    def enforce_isolation(self, task_id: str, query: Dict) -> bool:
        """Проверяет, не пытается ли агент выйти за свои границы"""
        # Запрещаем доступ к контекстам других агентов
        referenced_tasks = self._extract_references(query)
        for ref_task in referenced_tasks:
            if ref_task != task_id and ref_task in self.isolation_boundary:
                return False
        return True

3 Суб-агент с самоуничтожением

Ключевая фишка RLM - суб-агенты живут ровно один цикл выполнения. После завершения задачи они должны быть уничтожены со всем своим контекстом.

class SubAgent:
    def __init__(self, task: SubTask, context_manager: ContextManager):
        self.task = task
        self.context_manager = context_manager
        self.context = None
        self.llm_client = None  # Инициализация клиента LLM
        
    def initialize(self):
        """Создает изолированный контекст"""
        parent_context = self.task.context if self.task.current_depth > 0 else {}
        self.context = self.context_manager.create_isolated_context(
            self.task.id, 
            parent_context
        )
        
        # В 2026 году большинство LLM API поддерживают session-based изоляцию
        self.llm_client = OpenAIClient(
            model=self.context["llm_config"]["model"],
            session_id=self.task.id  # Критически важно для изоляции
        )
    
    def execute(self) -> AgentResult:
        try:
            self.initialize()
            
            # Выполняем задачу в изолированном контексте
            prompt = self._build_isolated_prompt()
            response = self.llm_client.generate(prompt)
            
            # Анализируем результат, определяем нужны ли deeper суб-задачи
            parsed_result = self._parse_response(response)
            
            # Проверяем глубину рекурсии
            next_tasks = []
            if self.task.current_depth < self.task.max_depth:
                next_tasks = self._extract_subtasks(parsed_result)
            
            return AgentResult(
                task_id=self.task.id,
                status=AgentStatus.COMPLETED,
                output=parsed_result,
                next_subtasks=next_tasks
            )
            
        except Exception as e:
            return AgentResult(
                task_id=self.task.id,
                status=AgentStatus.FAILED,
                output=None,
                error=str(e)
            )
        finally:
            # ВСЕГДА уничтожаем контекст
            self.context_manager.destroy_context(self.task.id)
            self.llm_client = None
            self.context = None

4 Orchestrator - мозг системы

Orchestrator не делает работу, он только управляет. Его контекст содержит только цель и общие инструкции, но не детали выполнения.

class RLOrchestrator:
    def __init__(self, main_goal: str):
        self.main_goal = main_goal
        self.context_manager = ContextManager()
        self.completed_results = []
        self.failed_tasks = []
        
        # В 2026 году появились специализированные модели для планирования
        self.planner_model = "claude-3.5-sonnet-planning"
        
    def run(self) -> Dict:
        """Основной рекурсивный цикл выполнения"""
        # Шаг 1: Разбиваем главную цель на подзадачи
        initial_tasks = self._plan_initial_subtasks()
        task_queue = initial_tasks
        
        iteration = 0
        max_iterations = 50  # Защита от бесконечной рекурсии
        
        while task_queue and iteration < max_iterations:
            current_task = task_queue.pop(0)
            
            # Шаг 2: Запускаем суб-агента
            agent = SubAgent(current_task, self.context_manager)
            result = agent.execute()
            
            # Шаг 3: Обрабатываем результат
            if result.status == AgentStatus.COMPLETED:
                self.completed_results.append(result)
                
                # Если агент предложил deeper задачи, добавляем в очередь
                if result.next_subtasks:
                    for subtask in result.next_subtasks:
                        subtask.current_depth = current_task.current_depth + 1
                        task_queue.append(subtask)
            else:
                self.failed_tasks.append(result)
            
            iteration += 1
            
            # Шаг 4: Проверяем, достигнута ли главная цель
            if self._is_goal_achieved():
                break
        
        return self._compile_final_report()
    
    def _plan_initial_subtasks(self) -> List[SubTask]:
        """Используем LLM для планирования, но результат кэшируем"""
        # В реальной реализации здесь вызов к planner_model
        # Для примера возвращаем фиктивные задачи
        return [
            SubTask(
                id="analyze_structure",
                description="Проанализировать структуру задачи и выделить основные компоненты",
                context={"goal": self.main_goal},
                max_depth=3
            )
        ]

Типичные ошибки, которые сломают ваш RLM

Ошибка 1: Утечка контекста через глобальные переменные

Самая частая ошибка. Вы создаете изолированный контекст, но потом суб-агент обращается к глобальному кэшу или shared memory. В 2026 году многие фреймворки имеют hidden global state - проверяйте документацию.

Ошибка 2: Рекурсия без ограничения глубины

Суб-агент создает суб-задачу, та создает еще одну, и так до бесконечности. Всегда устанавливайте max_depth и отслеживайте current_depth. В production добавьте circuit breaker.

Ошибка 3: Orchestrator микроменеджмент

Если orchestrator начинает проверять каждое решение суб-агента - вы теряете преимущества изоляции. Orchestrator должен проверять только конечные результаты и общую цель.

RLM vs другие архитектуры: что выбрать в 2026

Архитектура Плюсы Минусы Когда использовать
RLM Нет Goal Drift, масштабируется, стабилен Сложнее реализовать, overhead на создание агентов Сложные многошаговые задачи, анализ больших данных
ReAct Простой, хорош для инструментов Теряет цель после 10+ шагов Простые задачи с 3-5 действиями
Agent Skills Модульность, переиспользование Контекст все равно накапливается Повторяющиеся бизнес-процессы
Planner/Executor Четкое разделение План устаревает при выполнении Задачи с predictable workflow

Практический пример: анализ кодовой базы без потери фокуса

Допустим, мы хотим проанализировать репозиторий на security issues. Вот как это выглядит в RLM:

# Инициализируем orchestrator с главной целью
orchestrator = RLOrchestrator(
    main_goal="Найти все security vulnerabilities в репозитории ~/project, "
              "сгенерировать отчет с приоритетами и рекомендациями по фиксу"
)

# Запускаем выполнение
report = orchestrator.run()

# В процессе:
# 1. Создается суб-агент для анализа структуры проекта
# 2. Он возвращает список suspicious modules
# 3. Для каждого модуля создается суб-агент
# 4. Каждый модульный агент работает в изоляции
# 5. Если находит сложную уязвимость - создает deeper агента для анализа
# 6. Все результаты собираются в финальный отчет

Частые вопросы (FAQ)

RLM замедляет выполнение из-за создания агентов?

Да, overhead есть. Но в 2026 году создание LLM-контекста оптимизировано. Плюс, вы экономите время на дебаггинге Goal Drift. Для реальных задач разница 10-20%, а надежность вырастает в разы.

Можно ли комбинировать RLM с Agent Skills?

Абсолютно. Фактически, это лучшая комбинация. Каждый суб-агент может использовать специфические skills для своей задачи. В нашей предыдущей статье "Agent Skills: как заставить ИИ-агента не тупить" мы подробно разбирали этот подход.

Как обрабатывать зависимости между суб-задачами?

Orchestrator должен отслеживать зависимости. В реализации выше это упрощено, но в production нужно добавить DAG (Directed Acyclic Graph) для управления workflow. Новые фреймворки 2026 года, как LangChain 0.2.x, имеют встроенную поддержку task dependencies.

Какие модели лучше всего подходят для RLM?

Для orchestrator - модели с сильными planning способностями (Claude 3.5 Sonnet, GPT-5 Planning). Для суб-агентов - специализированные под задачу. В 2026 году появились "экспертные" модели на 10-50B параметров, которые дешевле и эффективнее для узких задач.

Что будет дальше с RLM

К 2027 году я ожидаю появления hardware-accelerated context isolation. Специализированные AI чипы будут создавать аппаратно изолированные контексты для суб-агентов, уменьшая overhead до нуля.

Сейчас RLM кажется сложным. Через год это будет стандартом для production LLM-систем. Начинайте внедрять сейчас, пока ваши конкуренты все еще дебаггит Goal Drift в монолитных агентах.

Главный урок: если ваш агент начинает обсуждать погоду вместо анализа данных - это не проблема промптов. Это проблема архитектуры. RLM решает ее на фундаментальном уровне.