Перейти к основному содержимому

Исполняющие среды

Плагин объявляет в манифесте одну или несколько исполняющих сред — способов, которыми ядро может с ним взаимодействовать:

[plugin]
runtime = "in_process" # одна среда
# или
runtime = ["in_process", "mcp_stdio"] # плагин работает в нескольких средах

Ядро выбирает подходящий адаптер при загрузке и общается с плагином через него. Для потребителя (кода, который получает плагин из реестра и вызывает его методы) разница между средами невидима — все адаптеры возвращают единый прокси-объект.

Три среды

in_process — нативный вызов в том же процессе

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

Когда использовать:

  • Плагин написан на том же языке, что и ядро.
  • Плагин не требует изоляции (доверенный код).
  • Производительность критична (вызовы миллионы раз в секунду).

Ограничения:

  • Плагин должен быть в пакете, импортируемом ядром.
  • Падение плагина (segfault в C-extension, утечка памяти, deadlock) = падение ядра.

mcp_stdio — подпроцесс через stdio

Плагин запускается как отдельный процесс; общение — через stdin/stdout по MCP-протоколу (JSON-RPC 2.0 поверх line-delimited JSON).

Когда использовать:

  • Плагин написан на другом языке (Python-ядро, Go-плагин).
  • Нужна изоляция (сторонний плагин из untrusted-источника).
  • Плагин имеет тяжёлые зависимости (C-extension, ML-модель), которые не хочется тянуть в основной процесс.

Ограничения:

  • Все входы/выходы обязаны быть JSON-сериализуемыми (инвариант 2 из ADR-0003).
  • Overhead на каждый вызов — spawn процесса (один раз на lifetime плагина) и JSON-сериализация (на каждый вызов). Не подходит для hot-path с жёсткими требованиями к latency.

mcp_http — удалённый HTTP-сервис

Плагин развёрнут как отдельный сервис, доступный по HTTP. Ядро делает MCP-запросы через HTTP.

Когда использовать:

  • Плагин — внешний сервис (SaaS, корпоративный микросервис).
  • Плагин требует специальной инфраструктуры (GPU-инстанс, scaled-horizontally worker-пул).
  • Вы хотите обновлять плагин без перезапуска ядра.

Ограничения:

  • Сеть — дополнительная точка отказа (таймауты, transient errors).
  • Все ограничения mcp_stdio плюс свои — auth-токены, TLS, CA-bundles.
  • Overhead на каждый вызов = network roundtrip + JSON-сериализация.

Таблица сравнения

Свойствоin_processmcp_stdiomcp_http
Разные языки ядра и плагина
Изоляция от основного процесса✓ (subprocess)✓ (отдельный хост)
Latency вызова~μs~10-100μs~ms
Serialization required✗ (нативные объекты)✓ (JSON)✓ (JSON)
Сетевые ошибкиневозможныневозможнывозможны
Deploy независим от ядра
Подходит для live-stream большого трафика

Множественный runtime в одном плагине

Плагин может декларировать несколько runtime-адаптеров:

runtime = ["in_process", "mcp_stdio"]

Это значит: ядро может запустить плагин в любом из указанных режимов, выбор — на стороне хоста. Типичный сценарий:

  • in_process — когда ядро на Python и плагин тоже на Python: прямой импорт.
  • mcp_stdio — когда ядро на TypeScript, плагин только на Python: запуск subprocess.

Каждый binding ответственен за реализацию адаптера для поддерживаемых runtime-адаптеров.

Декларация runtime для своего плагина

Минимальный случай — один runtime:

[plugin]
name = "openai_compatible"
kind = "llm"
runtime = "in_process"
core_version = ">=0.1.0,<1.0.0"

Множественный — массив:

[plugin]
name = "semantic_search"
kind = "tool"
runtime = ["in_process", "mcp_stdio", "mcp_http"]
core_version = ">=0.1.0,<1.0.0"

Runtime-specific поля манифеста

Для каждого runtime-адаптера могут быть специфичные поля. Отдельный groupId от таб-блоков с языковыми примерами, чтобы выбор «мой язык» не перепутался с выбором «какой runtime обсуждаем».

[plugin]
runtime = "in_process"
entry_point = "plugin:OpenAIPlugin" # REQUIRED для in_process

Полная схема полей каждого runtime-адаптера — в spec-репозитории.

Когда какой runtime выбирать — flowchart

┌─ Плагин на том же языке, что и ядро?

├─ Да → нужна ли изоляция?
│ │
│ ├─ Нет, и производительность важна
│ │ → in_process
│ │
│ └─ Да, плагин из untrusted-источника
│ → mcp_stdio

└─ Нет (разные языки):

├─ Плагин — внешний сервис (SaaS, корп. микросервис)
│ → mcp_http

└─ Плагин — локальный, нужна локальная установка
→ mcp_stdio

Последствия выбора runtime для кода плагина

Инвариантin_processmcp_stdiomcp_http
Serializable boundaries (ADR-0003 §2)рекомендуетсяобязательнообязательно
Resources через DIобязательнообязательнообязательно
Чистота от внешнего состояния средыобязательнообязательнообязательно
execution_model имеет значениеданет (process boundary)нет (network boundary)

Ключевое наблюдение: все три runtime-адаптера требуют одинаковых runtime-инвариантов. Это делает миграцию плагина с in_process на mcp_stdio (например, когда нужно выделить его в подпроцесс для изоляции) механической — код плагина не меняется, меняется только манифест.

См. также