Agent Skills: Архитектура LLM-агентов, промпты и RAG для стабильной работы | AiManual
AiManual Logo Ai / Manual.
29 Дек 2025 Гайд

Agent Skills: как заставить ИИ-агента не тупить и помнить все инструкции

Полное руководство по созданию ИИ-агентов, которые не забывают инструкции. Архитектура, промпты, RAG, инструменты и практические шаги для разработчиков.

Проблема: почему ИИ-агенты "тупят" и забывают инструкции?

Вы создали умного ИИ-агента, который вчера прекрасно справлялся с задачами, а сегодня ведёт себя как будто его перезагрузили. Он забывает базовые инструкции, путает контекст, делает элементарные ошибки. Знакомая ситуация? Это не баг — это фундаментальная проблема архитектуры большинства LLM-агентов.

Ключевая проблема: Контекстное окно LLM ограничено. Даже модели с 128K токенов не могут хранить все инструкции, историю диалога и внешние данные одновременно. Агент "забывает" то, что не помещается в текущий контекст.

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

  • Работать с большими объёмами данных
  • Выполнять сложные многошаговые задачи
  • Поддерживать длинные диалоги
  • Использовать внешние инструменты и API

...системный промпт становится неподъёмным, а производительность падает.

Решение: архитектура Agent Skills с динамической памятью

Вместо монолитного промпта мы строим модульную систему, где каждая "скилл" (навык) — это независимый модуль с собственной памятью, инструментами и инструкциями. Агент динамически выбирает, какие навыки активировать в зависимости от задачи.

💡
Архитектура Agent Skills похожа на микросервисы в DevOps: каждый навык независим, имеет чёткий интерфейс и может масштабироваться отдельно. Это позволяет создавать сложных агентов, которые остаются стабильными при росте функциональности.

Ключевые компоненты архитектуры

Компонент Назначение Технологии
Orchestrator Определяет, какие навыки активировать LLM с function calling, классификаторы
Skills Registry Реестр доступных навыков с описаниями JSON/YAML конфиги, векторная БД
Memory System Хранит контекст и историю RAG, векторные БД, SQLite
Tools Interface Интерфейс для внешних инструментов REST API, MCP (Model Context Protocol)

Пошаговый план: создаём агента с устойчивой памятью

1 Проектируем архитектуру навыков

Начните с декомпозиции задач агента на независимые навыки. Каждый навык должен иметь:

  • Чёткое название и описание
  • Список необходимых инструментов
  • Шаблон промпта с заполнителями
  • Требования к входным данным
  • Формат выходных данных
# Пример структуры навыка в Python
skill_registry = {
    "data_analysis": {
        "description": "Анализ данных с использованием pandas и визуализация",
        "tools": ["pandas", "matplotlib", "seaborn"],
        "prompt_template": """
        Ты — аналитик данных. Твоя задача: {task}
        
        Доступные данные: {data_summary}
        Требуемый формат вывода: {output_format}
        
        Инструкции:
        1. Проверь качество данных
        2. Выполни анализ согласно методологии
        3. Создай визуализации
        4. Сформулируй выводы
        """,
        "input_schema": {
            "task": "string",
            "data_path": "string",
            "output_format": "string"
        }
    },
    "code_review": {
        "description": "Проверка кода на качество и безопасность",
        "tools": ["pylint", "bandit", "black"],
        "prompt_template": "..."
    }
}

2 Реализуем систему памяти с RAG

RAG (Retrieval-Augmented Generation) — это не только для документов. Используйте его для хранения:

  • Истории диалогов
  • Инструкций и политик
  • Результатов предыдущих выполнений
  • Контекста пользователя
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter

class AgentMemory:
    def __init__(self):
        self.embeddings = OpenAIEmbeddings()
        self.vectorstore = Chroma(
            embedding_function=self.embeddings,
            persist_directory="./memory_db"
        )
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=1000,
            chunk_overlap=200
        )
    
    def store_conversation(self, user_input, agent_response, skill_used):
        # Сохраняем контекст с метаданными
        text = f"User: {user_input}\nAgent ({skill_used}): {agent_response}"
        chunks = self.text_splitter.split_text(text)
        
        metadatas = [{
            "type": "conversation",
            "skill": skill_used,
            "timestamp": datetime.now().isoformat()
        } for _ in chunks]
        
        self.vectorstore.add_texts(chunks, metadatas)
    
    def retrieve_relevant_context(self, query, k=5):
        # Ищем релевантный контекст
        docs = self.vectorstore.similarity_search(query, k=k)
        return "\n\n".join([doc.page_content for doc in docs])
💡
Для эффективного RAG важно правильно настроить чанкинг и метаданные. Используйте разные коллекции для разных типов данных: инструкции, диалоги, результаты. Это улучшит релевантность поиска.

3 Создаём оркестратор с динамической загрузкой навыков

Оркестратор анализирует запрос пользователя и решает, какие навыки применить. Ключевые подходы:

class SkillOrchestrator:
    def __init__(self, llm, memory):
        self.llm = llm
        self.memory = memory
        self.skills = self.load_skills()
    
    def load_skills(self):
        # Динамическая загрузка навыков из директории
        skills = {}
        skills_dir = "skills"
        for file in os.listdir(skills_dir):
            if file.endswith(".yaml") or file.endswith(".json"):
                with open(os.path.join(skills_dir, file), 'r') as f:
                    skill_data = yaml.safe_load(f) if file.endswith('.yaml') else json.load(f)
                    skills[skill_data['name']] = skill_data
        return skills
    
    def select_skill(self, user_query):
        # Используем LLM для выбора навыка
        skill_descriptions = "\n".join([
            f"{name}: {skill['description']}"
            for name, skill in self.skills.items()
        ])
        
        prompt = f"""
        Пользователь запросил: {user_query}
        
        Доступные навыки:
        {skill_descriptions}
        
        Выбери наиболее подходящий навык. Ответь только названием навыка.
        """
        
        selected = self.llm.invoke(prompt).strip()
        return self.skills.get(selected)
    
    def execute_skill(self, skill_name, user_query, context):
        skill = self.skills[skill_name]
        
        # Загружаем релевантную память
        relevant_memory = self.memory.retrieve_relevant_context(
            f"{user_query} {skill_name}"
        )
        
        # Формируем финальный промпт
        full_prompt = skill["prompt_template"].format(
            task=user_query,
            context=context,
            memory=relevant_memory
        )
        
        # Выполняем навык
        response = self.llm.invoke(full_prompt)
        
        # Сохраняем в память
        self.memory.store_conversation(
            user_query, response, skill_name
        )
        
        return response

4 Интегрируем внешние инструменты через MCP

Model Context Protocol (MCP) — это стандарт для подключения инструментов к LLM. Вместо того чтобы описывать каждый API в промпте, используйте MCP для динамического обнаружения инструментов.

# Пример интеграции с MCP сервером
import mcp

class ToolManager:
    def __init__(self, mcp_server_url="http://localhost:8000"):
        self.client = mcp.Client(mcp_server_url)
        self.tools = self.discover_tools()
    
    def discover_tools(self):
        # Получаем список доступных инструментов от MCP сервера
        response = self.client.list_tools()
        return {
            tool.name: tool
            for tool in response.tools
        }
    
    def execute_tool(self, tool_name, **kwargs):
        tool = self.tools[tool_name]
        return self.client.call_tool(tool_name, arguments=kwargs)

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

Нюансы и частые ошибки

1. Переоптимизация промптов

Ошибка: Создание гигантских, переоптимизированных промптов для каждого навыка.

Решение: Используйте шаблоны с заполнителями. 80% промпта должны быть общими для всех навыков, 20% — специфичными.

2. Игнорирование контекстного истощения

Ошибка: Отправка всего контекста в каждый запрос, что приводит к переполнению токенов.

Решение: Реализуйте стратегию суммирования контекста:

def summarize_context(context, max_tokens=2000):
    """Суммируем длинный контекст, сохраняя ключевые моменты"""
    if len(context) <= max_tokens:
        return context
    
    # Разделяем на важные и второстепенные части
    important_parts = extract_important_segments(context)
    summary = llm.invoke(f"Суммаризируй: {context[:5000]}")
    
    return f"Важные детали: {important_parts}\n\nОбщая сводка: {summary}"

3. Отсутствие валидации выходных данных

Ошибка: Доверие к выходным данным LLM без проверки.

Решение: Добавьте валидаторы для каждого навыка:

class SkillValidator:
    def validate_output(self, skill_name, output, expected_schema):
        if skill_name == "data_analysis":
            return self.validate_json(output, expected_schema)
        elif skill_name == "code_generation":
            return self.validate_code(output)
        
    def validate_code(self, code):
        # Проверяем синтаксис
        try:
            ast.parse(code)
            return True
        except SyntaxError:
            return False

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

Задача Рекомендуемый подход Инструменты
Быстрый прототип LangChain + простой RAG ChromaDB, OpenAI
Продакшен система Кастомная архитектура + MCP PostgreSQL + pgvector, FastAPI
Мультимодальный агент Специализированные навыки для каждого типа данных CLIP для изображений, Whisper для аудио

Важно: Выбор LLM имеет критическое значение. Для разных задач подходят разные модели. Ознакомьтесь с гидом по лучшим opensource LLM, чтобы выбрать оптимальную модель для вашего агента.

FAQ: ответы на частые вопросы

Q: Сколько навыков может эффективно обрабатывать один агент?

A: Оптимально — 5-15 навыков. При большем количестве эффективность оркестратора падает. Решение: создавайте иерархию агентов или используйте микросервисную архитектуру.

Q: Как тестировать таких агентов?

A: Используйте A/B тестирование с разными архитектурами, юнит-тесты для каждого навыка и интеграционные тесты для оркестратора. Автоматизируйте тестирование с помощью инструментов вроде pytest.

Q: Можно ли использовать эту архитектуру с локальными моделями?

A: Да, абсолютно. Архитектура Agent Skills не зависит от конкретной LLM. Вы можете использовать локальные opensource модели, что особенно важно для проектов с требованиями к конфиденциальности данных.

Q: Как обучать команду работе с такой архитектурой?

A: Рекомендую начать с бесплатного курса по разработке AI-агентов, а затем углубляться в конкретные технологии: LangChain, LlamaIndex, MCP.

Заключение

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

Ключевые преимущества подхода:

  1. Масштабируемость: Новые навыки добавляются без переписывания всей системы
  2. Стабильность: Проблема в одном навыке не ломает всего агента
  3. Эффективность: Динамическая загрузка только необходимых инструкций
  4. Поддерживаемость: Каждый навык можно тестировать и улучшать отдельно

Начните с малого: выделите 2-3 ключевых навыка вашего агента, реализуйте для них отдельные модули с RAG-памятью, и вы сразу увидите улучшение стабильности работы. По мере роста сложности агента архитектура будет масштабироваться вместе с вашими требованиями.

🚀
Помните: лучший агент — не тот, который знает всё, а тот, который точно знает, что он знает, и умеет это эффективно применять. Архитектура Agent Skills даёт именно эту способность.