MCP и навыки в AI-агентах: интеграция внешних баз знаний (продолжение)

опубликовано: ⏰ 9

В прошлой статье был пример подключения навыка (skill) для работы с внешней базой знаний. Но это не всё, что можно сделать с MCP и агентами. Есть более удобный способ управления поведением через описание своих агентов.

Введение

Если ранее необходимо было явно указывать, какой навык нужно применить, либо надеяться, что LLM поймёт, что его нужно определить по контексту задачи, то в этот раз будет использоваться специальный агент. Это будет агент с заранее заданным поведением, задачами и действиями, которые он должен выполнять. Главный плюс использования агента с заранее описанным поведением — это возможность работать в рамках заданных правил безусловно, то есть это приоритетные правила, которые будут применены к каждому запросу.

Для примера возьму всё тот же OpenCode, который поддерживает кастомные агенты. У него есть несколько встроенных агентов, которые можно выбирать прямо в консоли (plan, build) и несколько скрытых. При этом можно создавать свои кастомные агенты, что и понадобится далее.

Применение агента – опять же интеграция с внешней базой знаний через MCP-сервер. В данном случае, как и в предыдущем примере, будет использовать tekBlueprint.kbase.

Общая схема взаимодействия

Чем-то похоже на предыдущую схему, но теперь агент сам может содержать или подгружать необходимые навыки.

AGENT.md – это описание самого агента, создание и описание которого будет приведено ниже.

Поток данных опять же похож на предыдущий пример, но с небольшими отличиями:

  1. При старте подгружается агент и его поведение (AGENT.md) + навыки (SKILLS.md).
  2. Пользователь задает вопрос в чате с агентом (AI Agent).
  3. Агент анализирует запрос, активирует навык (SKILLS.md), если есть, и понимает, что нужно обратиться к базе знаний.
  4. Через клиент (MCP Client) агент отправляет запрос на сервер (MCP Server) (например, tools/call для поиска или resources/read для чтения).
  5. Сервер (MCP Server) принимает запрос, аутентифицирует его и преобразует в понятный для внутреннего API (Internal API) запрос.
  6. Internal API выполняет обработку запроса или запрашивает данные из базы (Databases) через REST, gRPC или прямой SQL/векторный запрос.
  7. Сервер базы знаний (Databases) находит релевантные документы/факты и возвращает их обратно по цепочке Internal API → MCP Server.
  8. Сервер (MCP Server) упаковывает результат в формат MCP и передает обратно агенту (AI Agent).
  9. Агент (AI Agent) обогащает свой контекст полученными данными и формирует финальный ответ пользователю.

Работа с агентом с помощью MCP

В качестве демонстрационного примера возьму задачу на создание всеми надоевшего ToDo менеджера на React с UI на PrimeReact. Но перед этим потребуется выполнить несколько подготовительных шагов:

  1. Создать агента в OpenCode с инструкциями по работе с MCP.
  2. Создать в базе знаний агента PrimeReact Frontend Developer от лица которого будем генерировать приложение.

Создание нового агента

AGENT.md – это обычный текстовый файл с frontmatter, с кратким описанием агента и некоторыми параметрами. В случае использования OpenCode создать всё достаточно просто: выполняем команду и отвечаем на вопросы.

Shell
opencode agent create

Описание агента лучше формулировать достаточно подробно. На его основе OpenCode через LLM сгенерирует полное описание агента, которое будет использоваться далее.

Небольшой пример описания для понимания, как это выглядит в случае использования внешнего MCP.

Markdown
---
description: >-
  Use this agent when a user requests an action or task and specifies a
  particular role (e.g., "Can you help me with coding as the code reviewer?",
  "Execute this as the project planner", "Handle this like a devops engineer
  would"). The agent must fetch role-specific instructions from the external
  knowledge base using the tB.kbase skill, then follow those retrieved
  to complete the requested action. This is appropriate when the
  user's request implicitly requires fetching how that role operates, what their
  responsibilities are, or what specific steps they would take. 
  **Carefully read your instructions.**
mode: all
---

You are a role-based instruction follower agent. Your core function is to fetch role-specific instructions
from an external knowledge base and apply them to complete user requests.

## Your Workflow

1. **Identify the Role**: When a user requests an action and specifies a role (explicitly or implicitly),
   extract the role from their request. Examples of role references to include: "role: [role]", "as a [role]",
   "like a [role]", "[role]-style", or simply mentioning a role title.
2. **Fetch Instructions**: Always use the `tB.kbase` skill to retrieve the agent/role description from the
   external knowledge base by using `search-agents` and `get-agent-by-uri`. The knowledge base contains 
   detailed instructions, responsibilities, and methodologies for each role.
3. **Follow Retrieved Instructions**: Apply the fetched instructions to complete the user's requested action. 
   This may involve:
    - Following specific decision-making frameworks outlined in the role description
    - Applying the role's code standards and patterns
    - Executing methodologies as prescribed by that role
    - Making judgments consistent with the role's established practices
4. **Execute the Task**: Complete the user's request using the approach and standards defined in the retrieved
   role instructions.

## Important Guidelines

- Always **fetch the role instructions** first before responding or taking action
- Do not assume how a role operates - retrieve their explicit instructions from the knowledge base
- If the user request is ambiguous about which role, ask for clarification
- If the knowledge base does not contain instructions for the specified role, inform the user and ask for 
  an alternative role or confirmation to proceed with general best practices
- Maintain fidelity to the fetched role instructions - do not deviate from their prescribed methodologies
  unless the user explicitly requests otherwise

## Output Format

When you complete the task, provide your response in the format appropriate to the role whose instructions you 
followed, as specified in the retrieved description.

Большая часть описания будет сгенерирована, если что-то в описании некорректно, то можно исправить вручную.

База знаний

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

Для примера сделал в базе знаний простого агента для разработки веб-приложений с использованием PrimeReact, который содержит:

  • Инструкции по работе.
  • Навыки и опыт.
  • Чеклисты.
  • Примеры артефактов.
  • Правила активации.

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

Генерация приложения

Ниже сам процесс генерации. Видно, что были прочитаны требуемые инструкции и в результате сгенерировал проект с нужной структурой и использованием компонентов от PrimeReact.

Лог выполнения
Shell
⚙ kbase_get-spec-by-uri [arg0=kb://ai-agent/staff-it:webdev-primereact:1.0]

Thinking: Now I have the PrimeReact developer instructions. Let me also get the related library specs for reference and then implement the app. Let me check what libraries/skills are referenced to understand the full tooling:
- React 19 
- PrimeReact 10
- PrimeFlex 3
- PrimeIcons 7
- TypeScript
- Vite
- Vite
- Biome (linting)

The instructions say:
- Use functional components with TypeScript
- Keep components under 300 lines
- Use TypeScript interfaces
- Prefer PrimeReact controls over creating new ones
- Organize by domain
- Extract reusable logic into hooks
- Use hooks for state management
- Import PrimeReact styles properly
- Biome (linting)

The instructions say:
- Use functional components with TypeScript
- Keep components under 300 lines
- Use TypeScript interfaces
- Prefer PrimeReact controls over creating new ones
- Organize by domain
- Extract reusable logic into hooks
- Use hooks for state management
- Import PrimeReact styles properly

...

Project Structure

todo/
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts
└── src/
    ├── main.tsx              # Entry point — imports PrimeReact themes & styles
    ├── App.tsx               # Root layout: Panel, ProgressBar, Toast wiring
    ├── features/
    │   └── todo/
    │       ├── useTodos.ts   # Custom hook with localStorage persistence & filter logic
    │       └── TodoList.tsx  # Filtered list with filter tabs, stats, empty state
    └── shared/
       └── ui/
            ├── TodoInput.tsx  # Add-todo form using InputText + Button
            └── TodoItem.tsx   # Individual item: Checkbox, text, Delete button

PrimeReact Components Used
    Panel — main card with toggle functionality
    Button — add button, filter tabs, delete & clear-completed (with severity)
    InputText — todo input field
    Checkbox — per-item completion toggle
    Message — empty-state messaging
    ProgressBar — completion progress bar
    Toast — notification popups

Генерация ToDo App

В итоге получается вот такое безобразие и даже работает без ошибок.

todo-1.webp

todo-2.webp

Возможные проблемы

Как указывал выше, здесь не очень оптимально используется база знаний, так как выполняется подгрузка агента из агента (сон во сне). В идеале лучше написать специализированного агента, который будет сразу получать инструкции из базы знаний, а также знать, как их применять наиболее оптимально, в процессе работы по необходимости подгружая дополнительную информацию. То есть вместо OpenCode запускается какой-нибудь tekblueprint.agent, который заточен на работу с tekBlueprint.kbase.

Здесь тоже может потребоваться экономия токенов на генерацию: где-то можно TOONS применить, а вместо JSON использовать Markdown. Есть ещё небольшой хак с использованием определённых правил формирования ответа для LLM, который, по некоторым оценкам, может снизить количество токенов на 46%. Один из примеров – навыки caveman.

Не всегда LLM следует инструкциям, особенно на малых квантах. Если явно указать, то возвращается к нормальной генерации.

Заключение

Если используются агенты вроде Claude Code, OpenCode, Qwen Code, то можно создавать специализированных агентов, которые опираются на обновляемую информацию из общей базы знаний. Это заметно упрощает поддержку окружения разработки или аналитики. Плюс, такой подход неплохо ложится на решения оркестрации агентов вроде Agent Swarm.

Ai Mcp Agents Llm Genai