New request
#3383: RFC: Subprocess-isolated plugin backend API bridge
We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.
Issue
enhancementtracking
Summary
Add a plugin backend API system where each plugin runs in its own subprocess, communicating with WebUI via stdin/stdout JSON. This replaces the need for standalone HTTP servers per plugin and avoids the security risks of running plugin code in-process.
Motivation
From PR #2622 discussion:
- No viable in-process sandbox — CPython has no reliable in-process sandbox (
ctypesbypasses everything). Running third-party plugin code viaexec_module()is unsafe for public plugin use. - Standalone servers are heavy — port allocation, process lifecycle, CORS boilerplate per plugin adds unnecessary complexity.
- Interest from reviewers — both nesquena-hermes and AJV20 agree subprocess isolation is the right direction.
Proposed Design
Plugin JS (sandboxed iframe, from PR #2622)
│ fetch('/api/plugins/<name>/<sub_route>')
▼
WebUI (proxy layer)
│ serialize request → JSON, write to subprocess stdin
▼
Plugin subprocess (isolated, resource-limited)
│ run handler, serialize response → JSON, write to stdout
▼
WebUI wraps JSON → HTTP response
Key properties:
- stdin/stdout JSON-line protocol (one line per request/response)
- Each plugin gets its own subprocess (crash isolation)
- Resource limits via
setrlimit(512MB RAM, 5min CPU, 256 files) - Minimal environment passed to plugin (no API tokens)
CompatHandlermimicsBaseHTTPRequestHandlerso existing plugin code needs minimal changes- Controlled by
HERMES_WEBUI_PLUGIN_MODE=subprocess(defaults to in-process)
Guardrails (from review discussion)
- Manifest contract — plugin manifest declares backend command/args, supported methods, timeout
- Minimal env — explicit passthrough only; no ambient secrets
- Bounded protocol — structured request/response with id, method, params, timeout, error shape
- Lifecycle ownership — WebUI owns start/stop/restart/health; plugin is a sidecar, not an extension
- Permission model — manifest declares capabilities; UI surfaces them
- Failure isolation tests — hung process, invalid JSON, crash, oversized response, stderr leaks
Scope
- Start with one minimal read-only demo endpoint to validate the protocol/lifecycle
- Keep PR #2622 focused on iframe/frontend isolation
- Follow-up RFC/PR for the subprocess backend bridge
Related
- PR #2622: Dashboard plugin system with iframe isolation
- Discussion: https://github.com/nesquena/hermes-webui/pull/2622#issuecomment-4561187464
Assessmentadvisory
feature●●● hard90% confidence
Architectural addition of a subprocess-isolated plugin bridge spanning API routing, process lifecycle management, and frontend proxy integration.
Likely files
- entry/api/server.py
- entry/api/plugin_bridge.py
- entry/bootstrap.py
- static/plugin-proxy.js
- infra/config/plugin-manifest.schema.json
- infra/unknown/test_plugin_bridge.py
Create the request