Главная / Статьи

Глубокие агенты с SKILL.md: оркестратор LangChain, загружающий навыки

Создать универсального глубокого агента на LangChain, который сканирует папку с навыками, направляет действия по описаниям в SKILL.md, обменивается памятью из AGENTS.md и приобретает новые способности без изменений кода.

Издатель: REACTAPP.TOP8 мин чтения1811 слов

Источники: Building Deep Agents + SKILL.md with Langchain

Что, если у агента не будет фиксированного списка способностей, и он сможет узнать, что может делать, только осматриваясь вокруг? Именно такой подход используется здесь: рабочий глубокий агент в LangChain, который загружает файлы SKILL.md по мере необходимости для ответов на запросы. Здесь нет жестко заданных цепочек обработки и никаких пользовательских маршрутизаторов. Есть только универсальный оркестратор, папка с навыками и библиотека deepagents, отвечающая за основную работу.

Проблема фиксированных наборов инструментов

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

Альтернатива — это оркестратор, который не знает, что он может сделать, пока не проведет проверку. Во время выполнения он сканирует каталог skills/, сначала читает только метаданные, а полные инструкции загружает тогда, когда та или иная навык соответствует запросу. Вместо того чтобы жестко задавать «этот агент исследует и пишет», вы помещаете файлы research/SKILL.md и writer/SKILL.md в папку, и агент сам определяет остальное. Завтра вы можете добавить навык code-reviewer, и он будет использоваться без необходимости изменять хотя бы одну строку кода. Именно так применяется шаблон SKILL.md в LangChain.

Как все соединяется

Четыре принципа определяют работу файла agent.py:

  1. Сначала происходит планирование. Оркестратор всегда составляет план, преобразуя общую цель пользователя в конкретные технические шаги.
  • Делегирование остается общим. Вместо специалистов, работающих в конкретных ролях, задачи передаются универсальному подагенту с теми же инструментами и таким же доступом к библиотеке навыков.
  • Знания предоставляются по мере необходимости. Ни оркестратор, ни подагент не знают специализированных рабочих процессов с момента запуска. Они находят их через SkillsMiddleware, который постепенно раскрывает навыки, и загружают полную документацию только тогда, когда это необходимо.
  • Рабочее пространство строго контролируется. Инструменты и действия, основанные на навыках, хранятся в каталоге ./workspace/ для сохранения данных, в то время как корневой каталог остается видимым для настройки и хранения навыков.
  • Весь проект компактен, и всю реальную работу выполняют три файла.

    Шаг 1: настройка проекта

    Зависимости указаны в файле pyproject.toml:

    # pyproject.toml
    [project]
    name = "deep-agents-langchain"
    version = "0.1.0"
    requires-python = ">=3.12"
    dependencies = [
        "deepagents>=0.4.12",
        "langchain-anthropic>=1.4.0",
        "langchain-openai>=1.1.12",
        "python-dotenv>=1.2.2",
        "streamlit>=1.55.0",
        "tavily-python>=0.7.23",
    ]
    

    Основной инструмент — это deepagents, библиотека с открытым исходным кодом от LangChain, которая формализует паттерн глубоких агентов. Сразу после установки она предоставляет возможности планирования с помощью write_todos, инструменты для работы с файловой системой, создание подагентов через task, сжатие контекста, а также, что особенно важно, загрузку навыков.

    Шаг 2: определение инструментов

    В файле agent.py единственным пользовательским инструментом является стандартный обёрток для поиска Tavily:

    import os
    from typing import Literal
    from dotenv import load_dotenv
    from langchain_anthropic import ChatAnthropic
    from langchain_openai import ChatOpenAI
    from tavily import TavilyClient
    from deepagents import create_deep_agent
    from deepagents.backends import FilesystemBackend
    load_dotenv()
    # --- Generic Tools ---
    tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
    def internet_search(
        query: str,
        max_results: int = 5,
        topic: Literal["general", "news", "finance"] = "general",
    ):
        """Search the web for current information."""
        return tavily.search(query, max_results=max_results, topic=topic)
    

    Все остальное, включая планирование, работу с файлами, использование подагентов и загрузку навыков, реализовано в библиотеке deepagents.

    Шаг 3: фабрика агентов

    Именно здесь всё объединяется:

    def get_deep_agent():
        model = ChatAnthropic(
            model="claude-3-5-sonnet-20240620",
            temperature=0,
        )
    return create_deep_agent(
            model=model,
            system_prompt="""You are a generic Deep Agent orchestrator.
    1. Use `write_todos` to plan complex requests.
    2. You have access to skills in the `skills/` directory.
       - You ONLY see names and descriptions initially.
       - For specialized tasks, load the matching SKILL.md first.
    3. Use the `task` tool to delegate to subagents.
    4. ALL outputs go to `./workspace/` exclusively.""",
            tools=[internet_search],
            skills=["./skills"],          # <-- This is the magic line
            memory=["./AGENTS.md"],
            backend=FilesystemBackend(root_dir="."),
            name="generic_deep_agent",
        )
    

    Три параметра заслуживают более внимательного рассмотрения.

    skills=[“./skills”] указывает deepagents на необходимость сканирования этой директории, парсинга YAML-метаданных каждого файла SKILL.md, который он находит, и включения каталога навыков в системный промпт. Агент видит что-то вроде этого:

    Available Skills:
    - research: "Conducts comprehensive web research on any topic..."
    - writer: "Specialized in writing high-quality content..."
    

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

    memory=["./AGENTS.md"] загружает правила проекта в системный промпт. Он служит общим контекстом для основного агента и всех подагентов, своего рода страницей «как у нас здесь всё делается» для команды.

    backend=FilesystemBackend(root_dir=".") предоставляет агенту инструменты для работы с файлами (read_file, write_file, edit_file) с корневой папкой проекта, так что файловая система становится постоянной рабочей областью агента.

    Шаг 4: написание навыков

    Намеренно простой исследовательский навык:

    ---
    name: research
    description: >
      Conducts comprehensive web research on any topic using search APIs
      and web scraping. Use when the user asks for research, information
      gathering, competitive analysis, or needs current data from the web.
    license: MIT
    compatibility: Requires internet access and Tavily API key
    allowed-tools: internet_search Read Write
    ---
    # Web Research Skill
    ## Instructions
    1. Parse the research query to identify key topics.
    2. Use the `internet_search` tool to gather initial results.
    3. If results are insufficient, try alternative search queries.
    4. Synthesize findings into a structured summary.
    5. Save detailed findings to `./workspace/` as a markdown file.
    

    И навык писателя:

    ---
    name: writer
    description: >
      Specialized in writing high-quality, creative, and technical content.
      Use when the user needs a blog post, report, technical guide,
      or any form of structured writing.
    license: MIT
    ---
    # Creative Writer Skill
    ## Instructions
    1. Review the input notes or research data provided.
    2. Define an outline (Introduction, Body, Conclusion).
    3. Use a tone appropriate for the target audience.
    4. Ensure all claims are backed by provided data.
    5. Save the final draft to `./workspace/`.
    

    Каждый файл содержит YAML-фронтматтер, который служит своего рода удостоверением личности навыка, а за ним следует тело в формате Markdown, выполняющее роль инструкции по использованию. Агент видит фронтматтер на уровне 1, а тело — только на уровне 2. Это соответствует спецификации, опубликованной на agentskills.io.

    Шаг 5: общая память в AGENTS.md

    Этот файл загружается всегда. В нем указано, кто что делает и как работает команда:

    # Project Context: Deep Agents Demo
    ## Conventions
    - Skills are stored as directories under `skills/`.
    - Every skill must have a `SKILL.md` file.
    - Subagents should be used for complex, multi-step tasks.
    - All intermediate work goes to `./workspace/`.
    ## Known Entities
    - **Main Agent**: The orchestrator who plans and delegates.
    - **Researcher**: Specialized in web search and data aggregation.
    - **Writer**: Specialized in formatting and synthesizing information.
    

    Как на самом деле работает маршрутизация

    Маршрутизатора и классификатора не существует, поскольку маршрутизацию выполняет сама большая языковая модель. Когда библиотека формирует системный промпт, она добавляет текст примерно в таком виде:

    You have access to a library of skills in the `skills/` directory.
    You ONLY see names and descriptions initially.
    For any specialized task, look for matching skills and use
    `read_file` to load the SKILL.md before executing.
    Available skills:
    - research: "Conducts comprehensive web research..."
    - writer: "Specialized in writing high-quality content..."
    

    Модель читает сообщение пользователя и описания навыков, затем решает, вызывать ли read_file("skills/research/SKILL.md") или ничего не делать. Весь процесс принятия решения происходит во время выполнения алгоритма трансформера без использования внешней логики. Другими словами, описание навыка служит механизмом направления действий, и достаточно хорошо написанного описания с ключевыми словами и границами, определяющими допустимый контекст.

    Фронтенд Streamlit

    app.py оборачивает всё в интерфейс Streamlit, который отображает процесс мышления агента в реальном времени. Функция LangGraph stream("updates") генерирует событие для каждой операции над узлом, и приложение преобразует их в вызовы инструментов, сигналы загрузки навыков, обновления плана действий и окончательный ответ.

    Добавление навыка без изменений в коде

    Предположим, вам нужен навык для ревью кода. Создайте папку для него рядом с другими папками:

    skills/
    ├── research/
    │   └── SKILL.md
    ├── writer/
    │   └── SKILL.md
    └── code-reviewer/
        └── SKILL.md
    

    Затем напишите его SKILL.md:

    ---
    name: code-reviewer
    description: >
      Reviews code for bugs, security issues, and best practices.
      Use when the user asks for a code review, security audit,
      or wants feedback on code quality. Do NOT use for writing
      new code or debugging runtime errors.
    license: MIT
    allowed-tools: Read Write
    ---
    # Code Review Skill
    ## Instructions
    1. Read the target file using `read_file`.
    2. Analyze for: bugs, security issues, performance, readability.
    3. Write a structured review to `./workspace/review.md`.
    

    Перезапустите приложение — теперь агент умеет анализировать код. Файл agent.py остался нетронутым, как и системное сообщение. Вы просто добавили папку, больше ничего. Такой подход позволяет создавать более сложных глубоких агентов.

    Уроки, извлеченные из этого

    • Описания навыков важнее, чем инструкции к ним. Если описание слабое, навык так и не будет использоваться. Настройка поля description, включая ключевые слова и ограничения вида «Не использовать для...», заняла больше времени, чем написание самого текста навыка, поскольку именно этот текст обеспечивает логику работы.
    • Файловая система недооценивается. Во многих учебниках по агентам всё хранится в истории сообщений, что подходит для простых задач, но не справляется с многоэтапной работой. Сохранение промежуточных результатов в папку ./workspace/ и возможность для подагентов их читать позволяют элементам правильно сочетаться друг с другом.
  • AGENTS.md объединяет все элементы воедино. Без него оркестратор и его подагенты работают по отдельности. С его наличием они используют общие правила, знают структуру проекта и избегают дублирования усилий — это небольшой файл с огромным влиянием.
  • Начните с универсального решения и постепенно специализируйтесь с помощью навыков. Может возникнуть искушение включить специфические знания области прямо в системный промпт, но сохранение универсальности оркестратора и размещение всех специализаций в файлах SKILL.md делает систему модульной и поддающейся тестированию. Навыки можно менять без вмешательства в агентов.
  • Что добавила бы производственная версия

    Это приложение сознательно минималистично. В реальном варианте развертывания, скорее всего, будут использоваться постоянные данные в памяти через LangMem для воспроизведения информации в разных сессиях, интеграция с MCP для корпоративных инструментов вроде Slack, Jira и баз данных, контрольные точки с участием человека с использованием механизма прерывания LangGraph, компрессия контекста для длительных исследовательских задач, а также дополнительные навыки — каждый из которых представляет собой просто папку с файлом SKILL.md.

    Направление развития кажется ясным. Создание агентов сводится не столько к написанию большего количества кода, сколько к созданию более качественных файлов SKILL.md. Фреймворк занимается техническими аспектами, навыки содержат экспертизу, а большая языковая модель определяет, когда использовать тот или иной навык.