惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Security Blog
Microsoft Security Blog
S
Secure Thoughts
酷 壳 – CoolShell
酷 壳 – CoolShell
S
SegmentFault 最新的问题
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
美团技术团队
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
V
Visual Studio Blog
腾讯CDC
小众软件
小众软件
有赞技术团队
有赞技术团队
博客园 - 聂微东
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
IT之家
IT之家
C
CERT Recently Published Vulnerability Notes
大猫的无限游戏
大猫的无限游戏
T
Threat Research - Cisco Blogs
SecWiki News
SecWiki News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Hacker News
The Hacker News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Troy Hunt's Blog
月光博客
月光博客
雷峰网
雷峰网
T
Tor Project blog
I
Intezer
S
Securelist
罗磊的独立博客
The Register - Security
The Register - Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
NISL@THU
NISL@THU
Google Online Security Blog
Google Online Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cisco Talos Blog
Cisco Talos Blog
云风的 BLOG
云风的 BLOG
www.infosecurity-magazine.com
www.infosecurity-magazine.com
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
Lohrmann on Cybersecurity
The Cloudflare Blog
Attack and Defense Labs
Attack and Defense Labs
P
Privacy International News Feed
W
WeLiveSecurity
Forbes - Security
Forbes - Security
量子位
Last Week in AI
Last Week in AI

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
OpenWebUI: System Prompt vs Skills vs MCP Tools — разбираем на живом примере валидации URL
akdengi (HOS · 2026-04-29 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение7 мин

Охват и читатели291

Обзор

Автор: Александр Казанцев, руководитель отдела документации и контента

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

AI-платформа

Готовые серверы с LLM и инструментами для ИИ и машинного обучения.

Узнать больше

Казалось бы, простая задача — всего лишь нужно написать в системном промте: «Проверяй ссылки перед отправкой». Но модель не умеет делать HTTP-запросы. Она — текстогенератор, а не браузер. Поэтому встал вопрос:

«Как гарантировать, что сгенерированная ссылка действительно работает, а не ведёт на 404?»

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

  1. System Prompt — инструкция для LLM

  2. Skills — пост-процессоры ответа

  3. MCP Tools — исполняемый код для действий «в реальном мире»

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

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

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

Каждый слой решает свою задачу. Давайте разберём их по порядку.

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

System Prompt — это текстовый контекст, который «настраивает» поведение языковой модели до генерации ответа. Это не код, не конфигурация — это естественный язык, который модель интерпретирует как правила поведения. В нашем случае это правила для поиска информации в базе знаний, ее интерпретация, форматирование.

Кратко стартовый блок и блок формирования ссылок выглядят вот так:

<role>
ИИ-ассистент техподдержки HOSTKEY. Задача: помогать по серверам, 
панели Invapi и документации hostkey.ru.
</role>

<rules>
### 🌐 ЯЗЫК (приоритет №1)
- Отвечай ТОЛЬКО на русском, независимо от языка вопроса.

### 🔗 ССЫЛКИ — АЛГОРИТМ (строго)
Файл в базе: `<раздел>@<тема>@ru.md`
Преобразование:
1. Убрать `@ru.md` → `faq@network_settings`
2. Разбить по `@` → `["faq","network_settings"]`
3. Собрать URL: `https://hostkey.ru/documentation/faq/network_settings/`
</rules>

Что делает System Prompt в данном случае:

  • Задаёт роль, тон и тематику ответов;

  • Обучает модель правильно формировать ссылки по бизнес-алгоритму;

  • Запрещает нежелательные действия (код, выдуманные URL);

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

  • Не проверяет, существует ли ссылка на самом деле;

  • Не делает сетевые запросы;

  • Не знает о существовании инструмента url_fetch_mcp — для модели это «магия».

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

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

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

  • Парсить и анализировать текст ответа

  • Вызывать внешние инструменты (MCP Tools)

  • Модифицировать вывод перед отправкой пользователю

Если системный промт привязан к конкретной модели, то Skills могут вызываться и использоваться различными моделями совместно. Достаточно указать их при создании кастомной модели в Workspace. Мы реиспользуем этот Skills, например, в переводчиках, чтобы не было «битых» ссылок.

В нашем случае нам нужен валидатор ссылок, то есть Skill url-validator-with-mcp.

---
name: url-validator-with-mcp
description: Validates URLs via url_fetch_mcp, removes invalid ones, 
             and ensures proper formatting for valid links.
version: "2.0"
tags: [validation, urls, links, mcp, formatting, self-check]
requires_tools: ["url_fetch_mcp"]
---
# 🔗 URL Validator Skill (MCP-backed + Format Enforcement)

## 🎯 Purpose
After generating a response containing URLs:
1. **Validate accessibility** using `url_fetch_mcp`
2. **Remove entirely** invalid/unreachable links (text + URL)
3. **Enforce proper formatting** for valid links
4. Output ONLY the cleaned, validated response — no logs, no commentary

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

Разберемся, как же работает наш Skill:

  1. Он находит URL в сгенерированном ответе (выполняет его парсинг);

  2. Вызывает MCP Tools url_fetch_mcp передавая его последовательно найденные URL;

  3. Применяет бизнес-правила: удалять битые ссылки, форматировать рабочие;

  4. Возвращает «чистый» ответ без мета комментариев.

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

  • Не учит модель, как строить ссылки (это задача системного промта);

  • Не заменяет логику бизнес-правил;

  • Не работает автономно и требует подключённого MCP Tool, так как сам он не может пройти по ссылке и проверить ответ от сервера.

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

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

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

В нашем случае у нас есть уже специальный сервер mcpo (MCP over HTTP) от тех же разработчиков, на котором расположен инструментарий работы с Invapi, поэтому добавить туда еще один было не проблемой. Но никто не запрещает тот же код реализовать через внутренние Tools OpenWebUI. 

По факту сам инструмент — это простой fastmcp-сервер и код на питоне, который и проверяет ссылки. mcpo же в данном случае — это «переводчик» между миром локальных CLI-инструментов (MCP) и миром веб-приложений (OpenWebUI). 

Плюсом mcpo будет интерактивная документация в swagger-формате, доступная в /docs.

Наш MCP инструмент носит имя check_url()

from __future__ import annotations
import logging, re, sys, time
from dataclasses import asdict, dataclass
from typing import Optional
from urllib.parse import urlparse
import requests

logging.basicConfig(
    stream=sys.stderr,
    level=logging.INFO,
    format='%(asctime)s [URL_FETCH] %(levelname)s: %(message)s'
)
logger = logging.getLogger(__name__)

DEFAULT_TIMEOUT = 5.0
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."

@dataclass
class URLCheckResult:
    valid: bool
    url: str
    normalized_url: Optional[str] = None
    status_code: Optional[int] = None
    response_time_ms: Optional[float] = None
    error: Optional[str] = None
    content_type: Optional[str] = None
    final_url: Optional[str] = None
    ssl_valid: Optional[bool] = None
    
    def to_dict(self) -> dict:
        return {k: v for k, v in asdict(self).items() if v is not None}

def check_url(
    url: str,
    timeout: float = DEFAULT_TIMEOUT,
    follow_redirects: bool = True,
    check_ssl: bool = True
) -> dict:
    """MCP Tool: Проверка доступности URL"""
    logger.info(f"MCP call: check_url(url='{url}')")
    
    # 1. Валидация формата
    is_valid, err = _validate_url_format(url)
    if not is_valid:
        return URLCheckResult(valid=False, url=url, error=err).to_dict()
    
    # 2. HTTP-запрос с обработкой ошибок
    try:
        response = requests.head(url, timeout=timeout, 
                                allow_redirects=follow_redirects,
                                verify=check_ssl)
        # ... анализ ответа ...
        return URLCheckResult(valid=True, status_code=response.status_code, 
                             response_time_ms=...).to_dict()
                             
    except requests.exceptions.Timeout:
        return URLCheckResult(valid=False, error="Таймаут").to_dict()
    except requests.exceptions.SSLError:
        return URLCheckResult(valid=False, error="SSL-ошибка").to_dict()
    # ... другие исключения ...

Что наш валидатор делает:

  • Реально «стучится» по ссылке (сетевой запрос);

  • Возвращает структурированный результат: status_code, response_time_ms, error;

  • Обрабатывает исключения: таймауты, SSL-ошибки, редиректы;

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

Но так как это просто код на Python, то он не знает контекст диалога (кто пользователь, о чём вопрос), не принимает решений: «удалять ссылку или нет», так как это логика Skill, и не форматирует финальный ответ, а отдает только данные в json формате.

После этого остается только прописать наш MCP Tools в OpenWebUI.

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

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

Давайте проследим, как работает вся цепочка на реальном сценарии.

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

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

Шаг 1: Model + System Prompt

  1. LLM получает вопрос + системный промт;

  2. Находит в базе документ: controlpanel@network_interface@ru.md;

  3. Применяет алгоритм: 

    "убрать @ru.md" → ["controlpanel","network_interface"] > "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. Парсит текст, находит 1 ссылку;

  3. Вызывает MCP Tool: 

 url_fetch_mcp(url="https://.../network_interface/")

  1. Получает результат:

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

  1. Проверяет формат: Markdown - Да, HTTPS - Да, текст ≠ вопрос - Да ;

  2. Возвращает ответ без изменений (всё валидно).

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

  1. MCP Tool вернул:

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

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

  2. Выдает ответ без ссылки:

   "Откройте панель Invapi → 'Сеть' → 'Интерфейсы'.

    Точной инструкции не нашёл. Для помощи: 

    [Техподдержка](https://hostkey.ru/customer-care/)."

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

Так что-же лучше? System Prompt, Skill или MCP Tools. Свели все основные критерии в такую таблиц, чтобы вы могли выбрать наиболее подходящий вам инструмент.

Критерий

System Prompt

Skill

MCP Tool

Когда выполняется

До генерации ответа

После генерации

По вызову из Skill

Язык реализации

Естественный язык

Markdown + логика

Python/JS код

Доступ к сети

Нет

Только через Tools

Да

Контекст диалога

Полный

Ответ модели

Только параметры

Основная задача

Поведение, правила

Пост-обработка, координация

Конкретное действие

Гибкость

Высокая (текст)

Средняя (шаблон)

Низкая (код)

Сложность поддержки

Низкая

Средняя

Высокая

Заключение

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

  • System Prompt —  отвечает за поведение ассистента, правила, бизнес-логику, «Знай, как надо»;

  • Skill — на нем пост-обработка и координация, «Проверь, что сделано»;

  • MCP Tool — выполняет конкретные действия «в мире», «Сделай и доложи».

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

Полезные ссылки

AI-платформа

Готовые серверы с LLM и инструментами для ИИ и машинного обучения.

Узнать больше