Jinba: превращаем описание бизнес-процесса в API и MCP-сервер

Jinba: превращаем описание бизнес-процесса в API и MCP-сервер
Temporary fallback cover; replace in editorial pass.

Уровень: средний · Чтение: до 12 минут ·

Типичная ситуация: процесс уже описан словами («получить заявку, проверить поля, классифицировать, отправить ответ»), а нужен работающий сервис, который можно вызвать из кода и подключить к агенту. В этой статье мы соберём небольшой workflow в Jinba, посмотрим на него как на граф и как на YAML, проверим конфигурацию локально и опубликуем один сценарий — через HTTP API и как MCP-сервер.

Самое важное из мира AI — в канале MAX AgentLabОтдельные разборы, инструменты и практические схемы Читайте Agent Lab в Telegram Разборы, кейсы и новости о практических AI-агентах без лишней воды.

Что получится в итоге

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

  • сохраним описание workflow как YAML-файл в репозитории и проверим его синтаксис локально;
  • запустим workflow на тестовом входе;
  • опубликуем его как API-эндпоинт и вызовем через curl;
  • подключимся к тому же сценарию как к MCP-инструменту через MCP Inspector.

Важно про примеры. Названия полей YAML, пункты меню и формат URL ниже — иллюстрация подхода, а не точная спецификация. Интерфейс и схема Jinba меняются; сверяйтесь с актуальной документацией продукта и с тем YAML, который экспортирует ваш собственный workflow. Мы не приводим цены, лимиты тарифов и отзывы клиентов — их нужно уточнять у поставщика.

Почему граф и YAML вместе — это удобно

Идея Jinba в том, что один и тот же workflow существует в двух представлениях. Визуальный граф удобен, чтобы обсуждать процесс с аналитиком или владельцем продукта: видно шаги, ветвления и данные между ними. YAML удобен инженеру: его можно положить в Git, сравнить в code review, откатить и сгенерировать заново.

Практическое правило: источником истины выбирайте что-то одно. Если команда правит в графе, YAML в репозитории — это экспорт для истории изменений. Если правит в YAML, граф — это только просмотр. Параллельные правки в обоих местах — самый частый источник «потерянных» изменений.

Шаг 1. Опишите процесс словами

Начните с короткого и проверяемого описания. Чем конкретнее входы и выходы, тем меньше ручной правки после генерации. Пример описания, которое можно дать генератору workflow:

Процесс: первичная разметка обращений в поддержку.
Вход: поле "message" (строка, до 2000 символов).
Шаги:
1. Проверить, что message не пустое.
2. Классифицировать обращение в одну из категорий:
   billing, bug, feature_request, other.
3. Вернуть JSON: {"category": ..., "summary": ... (не длиннее 200 символов)}.
Если message пустое — вернуть ошибку "empty_message", LLM не вызывать.

Обратите внимание: мы заранее зафиксировали формат выхода и поведение на ошибке. Это потом пригодится и для API-контракта, и для описания MCP-инструмента.

Шаг 2. Сгенерируйте и проверьте граф

Вставьте описание в редактор Jinba и сгенерируйте workflow. В графе проверьте три вещи:

  1. Вход — один параметр message со строковым типом.
  2. Ветвление — пустое сообщение уходит в ветку ошибки до вызова модели.
  3. Выход — именно два поля, category и summary, без лишних служебных данных.

Если генератор добавил лишние шаги (например, «отправить письмо»), удалите их сейчас: публиковать стоит минимальный сценарий, который вы понимаете целиком.

Шаг 3. Экспортируйте YAML и положите в репозиторий

Экспортируйте конфигурацию и сохраните её, например, в workflows/support-triage.yaml. Условный вид такого файла (структура упрощена для читаемости):

# workflows/support-triage.yaml — условный пример, схема может отличаться
name: support-triage
inputs:
  message:
    type: string
    required: true
steps:
  - id: validate
    type: condition
    if: "{{ inputs.message | length == 0 }}"
    then: return_error
  - id: classify
    type: llm
    prompt: |
      Классифицируй обращение в одну категорию:
      billing, bug, feature_request, other.
      Верни JSON с полями category и summary (до 200 символов).
      Обращение: {{ inputs.message }}
  - id: return_error
    type: output
    value: { error: "empty_message" }
outputs:
  category: "{{ steps.classify.output.category }}"
  summary: "{{ steps.classify.output.summary }}"

Секретов в этом файле быть не должно: ключи моделей и токены публикации храните в настройках окружения Jinba или в менеджере секретов, а не в YAML.

Шаг 4. Локальная проверка конфигурации

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

# Синтаксис YAML (нужен установленный yamllint)
yamllint workflows/support-triage.yaml

# Альтернатива без yamllint: распарсить файл через Python
python3 -c "import yaml,sys; d=yaml.safe_load(open(sys.argv[1])); print(sorted(d))" \
  workflows/support-triage.yaml

# Быстрая проверка, что в файл не попали похожие на секреты строки
grep -nEi "(api[_-]?key|secret|token|password)\s*:" workflows/support-triage.yaml \
  || echo "Похожих на секреты полей не найдено"

Это проверяет только форму файла, а не логику: корректный YAML может описывать неправильный процесс. Логику проверяем запуском.

Шаг 5. Тестовый запуск

Запустите workflow из редактора (или тем способом выполнения, который доступен в вашей версии Jinba) на трёх подготовленных входах. Сохраните их рядом с YAML, например в workflows/support-triage.cases.json:

[
  {"message": "Списали деньги дважды за один месяц"},
  {"message": "Кнопка экспорта падает с ошибкой 500"},
  {"message": ""}
]

Ожидания: первый случай — billing, второй — bug, третий — empty_message без вызова модели. Классификация LLM недетерминирована, поэтому для первых двух проверяйте не дословный summary, а категорию и формат ответа.

Шаг 6. Публикация как API

В настройках публикации включите HTTP API для этого workflow. Вы получите URL эндпоинта и токен доступа. Не вставляйте их в команды и скрипты напрямую — передавайте через переменные окружения:

export JINBA_API_URL="<URL эндпоинта из настроек публикации>"
export JINBA_API_TOKEN="<токен из настроек публикации>"

curl -sS -X POST "$JINBA_API_URL" \
  -H "Authorization: Bearer $JINBA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message": "Кнопка экспорта падает с ошибкой 500"}'

Схема аутентификации и формат тела запроса могут отличаться — ориентируйтесь на пример запроса, который показывает сам Jinba на странице публикации. Чтобы токен не оседал в истории shell, можно читать его из файла с ограниченными правами или из менеджера секретов.

Шаг 7. Публикация как MCP-сервер

Тот же workflow можно отдать агентам как MCP-инструмент. Включите MCP-публикацию и скопируйте адрес сервера. Затем проверьте его официальным отладчиком протокола — MCP Inspector:

npx @modelcontextprotocol/inspector

В открывшемся интерфейсе выберите HTTP-транспорт, укажите адрес MCP-сервера и, если требуется, заголовок авторизации. Дальше:

  1. Откройте список инструментов — там должен быть инструмент, соответствующий support-triage.
  2. Проверьте схему входа: один обязательный строковый параметр message.
  3. Вызовите инструмент с теми же тремя тестовыми входами и сравните ответы с результатами шага 6.

Обратите внимание на описание инструмента: именно его прочитает модель-агент, решая, когда вызывать workflow. Короткое и точное описание («классифицирует обращение в поддержку по четырём категориям») работает лучше, чем пересказ всего процесса.

Как проверить результат

  • YAML проходит локальную проверку и лежит в Git без секретов.
  • Все три тестовых случая дают ожидаемые категории или ошибку.
  • Ответы через API и через MCP совпадают по формату для одинаковых входов.
  • Пустой вход не вызывает модель (это видно в логах выполнения workflow).
  • Запрос без токена или с неверным токеном отклоняется.

Типовые ошибки

  • Правки «разъехались». Изменили граф, а в репозитории старый YAML. Решение — договориться об одном источнике истины и экспортировать после каждой правки.
  • Нестрогий выход. Модель иногда возвращает текст вокруг JSON. Явно задайте формат в промпте и, если платформа позволяет, схему выхода.
  • Токен в команде или файле. Он попадает в историю shell, логи CI или Git. Используйте переменные окружения и менеджер секретов.
  • Слишком широкий MCP-инструмент. Если workflow делает побочные действия (отправка писем, запись в CRM), агент может вызвать их неожиданно. Публикуйте через MCP только то, что безопасно вызывать автоматически.
  • Проверка дословного текста LLM. Тесты, которые сравнивают summary побуквенно, будут нестабильны. Проверяйте структуру и категорию.

Ограничения подхода

  • Генерация workflow из текста — это черновик. Ответственность за логику, ветки ошибок и права доступа остаётся на команде.
  • Локально мы проверили только форму конфигурации; полноценное выполнение зависит от того, какие режимы запуска доступны в вашей версии и тарифе Jinba.
  • Публикованный эндпоинт — внешний сервис: учитывайте задержки, квоты и доступность платформы, если встраиваете его в критичный процесс.
  • Наши три теста — пример, а не оценка качества. Для реального процесса нужен набор обращений из вашей предметной области.

Что дальше

Следующий логичный шаг — добавить в репозиторий скрипт, который прогоняет файл с тестовыми случаями через API после каждой публикации, и подключить MCP-инструмент к своему агенту. Другие практические разборы ищите в разделе гайдов, а термины из статьи — в глоссарии.