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

Типичная ситуация: процесс уже описан словами («получить заявку, проверить поля, классифицировать, отправить ответ»), а нужен работающий сервис, который можно вызвать из кода и подключить к агенту. В этой статье мы соберём небольшой workflow в Jinba, посмотрим на него как на граф и как на YAML, проверим конфигурацию локально и опубликуем один сценарий — через HTTP API и как MCP-сервер.
Что получится в итоге
Мы соберём агентный 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. В графе проверьте три вещи:
- Вход — один параметр
messageсо строковым типом. - Ветвление — пустое сообщение уходит в ветку ошибки до вызова модели.
- Выход — именно два поля,
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-сервера и, если требуется, заголовок авторизации. Дальше:
- Откройте список инструментов — там должен быть инструмент, соответствующий
support-triage. - Проверьте схему входа: один обязательный строковый параметр
message. - Вызовите инструмент с теми же тремя тестовыми входами и сравните ответы с результатами шага 6.
Обратите внимание на описание инструмента: именно его прочитает модель-агент, решая, когда вызывать workflow. Короткое и точное описание («классифицирует обращение в поддержку по четырём категориям») работает лучше, чем пересказ всего процесса.
Как проверить результат
- YAML проходит локальную проверку и лежит в Git без секретов.
- Все три тестовых случая дают ожидаемые категории или ошибку.
- Ответы через API и через MCP совпадают по формату для одинаковых входов.
- Пустой вход не вызывает модель (это видно в логах выполнения workflow).
- Запрос без токена или с неверным токеном отклоняется.
Типовые ошибки
- Правки «разъехались». Изменили граф, а в репозитории старый YAML. Решение — договориться об одном источнике истины и экспортировать после каждой правки.
- Нестрогий выход. Модель иногда возвращает текст вокруг JSON. Явно задайте формат в промпте и, если платформа позволяет, схему выхода.
- Токен в команде или файле. Он попадает в историю shell, логи CI или Git. Используйте переменные окружения и менеджер секретов.
- Слишком широкий MCP-инструмент. Если workflow делает побочные действия (отправка писем, запись в CRM), агент может вызвать их неожиданно. Публикуйте через MCP только то, что безопасно вызывать автоматически.
- Проверка дословного текста LLM. Тесты, которые сравнивают
summaryпобуквенно, будут нестабильны. Проверяйте структуру и категорию.
Ограничения подхода
- Генерация workflow из текста — это черновик. Ответственность за логику, ветки ошибок и права доступа остаётся на команде.
- Локально мы проверили только форму конфигурации; полноценное выполнение зависит от того, какие режимы запуска доступны в вашей версии и тарифе Jinba.
- Публикованный эндпоинт — внешний сервис: учитывайте задержки, квоты и доступность платформы, если встраиваете его в критичный процесс.
- Наши три теста — пример, а не оценка качества. Для реального процесса нужен набор обращений из вашей предметной области.
Что дальше
Следующий логичный шаг — добавить в репозиторий скрипт, который прогоняет файл с тестовыми случаями через API после каждой публикации, и подключить MCP-инструмент к своему агенту. Другие практические разборы ищите в разделе гайдов, а термины из статьи — в глоссарии.