OpenWebUI: System Prompt vs Skills vs MCP Tools — разбираем на живом примере валидации URL

OpenWebUI: System Prompt vs Skills vs MCP Tools — разбираем на живом примере валидации URL

В последних версиях OpenWebUI появились Skills, и я решил сразу применить их на практике. Одной из задач стало валидация ссылок, которые чат-бот техподдержки возвращает в ответах: модель должна корректно формировать URL на документацию и не генерировать несуществующие эндпоинты.

Карта территории: три слоя архитектуры

В экосистеме OpenWebUI выделяют три уровня абстракции:

  • System Prompt — инструкция для LLM;
  • Skills — пост-обработка ответа;
  • MCP Tools — выполнение кода во внешнем мире.

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

Уровень 1: System Prompt — «Должностная инструкция»

System Prompt — это текстовый контекст, который задаёт поведение модели до генерации ответа. Он использует естественный язык, а не код, и определяет правила: роль, тон, формат ответа, запрет на выдуманные данные.

В нашем случае он:

  • определяет, как строить ссылки по бизнес-логике;
  • запрещает генерировать код и несуществующие URL.

Чего он не может:

  • проверить, существует ли ссылка;
  • выполнить HTTP-запрос;
  • знать о существовании инструмента url_fetch_mcp — для модели это «магия».

System Prompt — это должностная инструкция сотрудника. Он знает, как писать отчёт, но не может выйти в поле и проверить данные.

Уровень 2: Skills — «Редактор с лупой»

Skills в OpenWebUI — это декларативные скрипты в формате Markdown с YAML-метаданными. Они выполняются после генерации ответа и могут:

  • анализировать текст;
  • вызывать MCP Tools;
  • модифицировать вывод.

Skills не привязаны к одной модели — их можно использовать совместно в разных моделях. Например, мы применяем url-validator-with-mcp в переводчиках, чтобы избежать «битых» ссылок.

Как работает наш Skill:

  1. находит URL в ответе;
  2. вызывает MCP Tool url_fetch_mcp для каждой ссылки;
  3. применяет бизнес-правила: удаляет нерабочие ссылки, форматирует рабочие;
  4. возвращает чистый ответ без технических комментариев.

Чего Skill не делает:

  • не обучает модель строить ссылки — это задача System Prompt;
  • не заменяет бизнес-логику;
  • не работает автономно — требует подключённый MCP Tool.

Skill — это редактор, который проверяет черновик. Он не пишет за автора, но исправляет ошибки, удаляет нерабочие ссылки и приводит текст к стандарту.

Уровень 3: MCP Tools — «Курьер с прибором»

MCP Tools (Model Context Protocol) — это внешний исполняемый код (Python/Node.js), выполняющий реальные действия: API-запросы, проверка URL, работа с файлами.

В нашем случае используется специальный сервер mcpo (MCP over HTTP), на котором размещён инструмент check_url(). Это fastmcp-сервер на Python, который:

  • выполняет HTTP-запрос по ссылке;
  • возвращает структурированный результат: status_code, response_time_ms, error;
  • обрабатывает таймауты, SSL-ошибки, редиректы.

Инструмент можно использовать не только в этом Skill, но и в других или напрямую в моделях.

Однако он не знает контекста диалога, не принимает решений «удалять или оставить ссылку» — это логика Skill. Он просто возвращает данные в JSON.

MCP Tool — это курьер с прибором учёта. Он не решает, куда ехать и что писать в отчёте. Он только измеряет: «Доставлено/не доставлено, время в пути, причина сбоя».

Полный цикл: от вопроса до ответа

Рассмотрим реальный сценарий.

Вход: пользователь спрашивает

«Как настроить сетевой интерфейс в панели Invapi?»

Шаг 1: Model + System Prompt

  1. LLM получает вопрос и системный промт;
  2. находит документ controlpanel@network_interface@ru.md;
  3. преобразует имя в URL: https://hostkey.ru/documentation/controlpanel/network_interface/;
  4. генерирует черновик:

«Откройте панель Invapi → 'Сеть' → 'Интерфейсы'. Подробнее: [Настройка сетевого интерфейса](https://hostkey.ru/documentation/controlpanel/network_interface/)»

Шаг 2: Skill (url-validator-with-mcp)

  1. Skill получает ответ и находит ссылку;
  2. вызывает url_fetch_mcp с этим URL;
  3. получает ответ:

{"valid": true, "status_code": 200, "response_time_ms": 342}

  1. проверяет формат (HTTPS, Markdown, не совпадает с вопросом);
  2. возвращает ответ без изменений — всё валидно.

Шаг 3: А если ссылка не валидна?

  1. MCP Tool возвращает:

{"valid": false, "error": "HTTP 404"}

  1. Skill удаляет конструкцию [текст](ссылка);
  2. возвращает:

«Откройте панель Invapi → 'Сеть' → 'Интерфейсы'. Точной инструкции не нашёл. Для помощи: [Техподдержка](https://hostkey.ru/customer-care/)»

Сравнение подходов

Сводная таблица по ключевым критериям:

Компонент Когда выполняется Язык реализации Доступ к сети Контекст диалога Основная задача Уровень абстракции Сложность поддержки
System Prompt До генерации ответа Естественный язык Нет (только через Tools) Полный Поведение, правила Высокая Низкая
Skill После генерации Markdown + логика Через MCP Tools Ответ модели Пост-обработка, координация Средняя Средняя
MCP Tool По вызову из Skill Python/JS код Да Только параметры Конкретное действие Низкая Высокая

Заключение

Создание надёжного ИИ-ассистента — это не только про «умную модель», но и про правильную архитектуру. Каждый компонент должен выполнять свою задачу:

  • System Prompt — задаёт поведение и правила: «Знай, как надо»;
  • Skill — отвечает за пост-обработку и координацию: «Проверь, что сделано»;
  • MCP Tool — выполняет действия в реальном мире: «Сделай и доложи».

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

Читать оригинал