В последних версиях 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:
- находит URL в ответе;
- вызывает MCP Tool url_fetch_mcp для каждой ссылки;
- применяет бизнес-правила: удаляет нерабочие ссылки, форматирует рабочие;
- возвращает чистый ответ без технических комментариев.
Чего 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
- LLM получает вопрос и системный промт;
- находит документ
controlpanel@network_interface@ru.md; - преобразует имя в URL:
https://hostkey.ru/documentation/controlpanel/network_interface/; - генерирует черновик:
«Откройте панель Invapi → 'Сеть' → 'Интерфейсы'. Подробнее: [Настройка сетевого интерфейса](https://hostkey.ru/documentation/controlpanel/network_interface/)»
Шаг 2: Skill (url-validator-with-mcp)
- Skill получает ответ и находит ссылку;
- вызывает url_fetch_mcp с этим URL;
- получает ответ:
{"valid": true, "status_code": 200, "response_time_ms": 342}
- проверяет формат (HTTPS, Markdown, не совпадает с вопросом);
- возвращает ответ без изменений — всё валидно.
Шаг 3: А если ссылка не валидна?
- MCP Tool возвращает:
{"valid": false, "error": "HTTP 404"}
- Skill удаляет конструкцию
[текст](ссылка); - возвращает:
«Откройте панель Invapi → 'Сеть' → 'Интерфейсы'. Точной инструкции не нашёл. Для помощи: [Техподдержка](https://hostkey.ru/customer-care/)»
Сравнение подходов
Сводная таблица по ключевым критериям:
| Компонент | Когда выполняется | Язык реализации | Доступ к сети | Контекст диалога | Основная задача | Уровень абстракции | Сложность поддержки |
|---|---|---|---|---|---|---|---|
| System Prompt | До генерации ответа | Естественный язык | Нет (только через Tools) | Полный | Поведение, правила | Высокая | Низкая |
| Skill | После генерации | Markdown + логика | Через MCP Tools | Ответ модели | Пост-обработка, координация | Средняя | Средняя |
| MCP Tool | По вызову из Skill | Python/JS код | Да | Только параметры | Конкретное действие | Низкая | Высокая |
Заключение
Создание надёжного ИИ-ассистента — это не только про «умную модель», но и про правильную архитектуру. Каждый компонент должен выполнять свою задачу:
- System Prompt — задаёт поведение и правила: «Знай, как надо»;
- Skill — отвечает за пост-обработку и координацию: «Проверь, что сделано»;
- MCP Tool — выполняет действия в реальном мире: «Сделай и доложи».
Когда зоны ответственности чётко разделены, система становится предсказуемой, тестируемой и легко масштабируемой. А пользователь получает точный ответ с рабочими ссылками.