Python SDK
Package name vibex-plugin, source sdk/python. Author environments and the Host Isolated interpreter require CPython 3.12 or newer. The Host locks CPython 3.12.11 (python-build-standalone install_only). Template python-worker writes runtime/worker.py and pyproject.toml. entrypoints.worker.runtime is python, protocol 1.1.
The Host launches the locked CPython executable plus entrypoints.worker.path (default runtime/worker.py). That file must call run_stdio_plugin_worker under __main__.
[project]
name = "my-plugin"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["vibex-plugin>=1.0.0"]
[tool.vibex.plugin]
worker = "runtime/worker.py"Constants: PLUGIN_API_VERSION = "1.0", PLUGIN_PROTOCOL_VERSION = "1.1", PLUGIN_SDK_VERSION = "1.0.0".
Worker
from vibex_plugin import define_plugin_worker, run_stdio_plugin_worker
def setup(registrar, environment):
def hello(value, env):
env.log.info("hello", {"input": value})
return {"ok": True, "input": value}
registrar.handle("hello", hello)
if __name__ == "__main__":
run_stdio_plugin_worker(define_plugin_worker(setup))The async entry is run_stdio_plugin_worker_async. define_plugin_worker(setup) accepts a synchronous setup(registrar, environment). A handler may be a plain function or a coroutine; the SDK uses inspect to decide whether to await.
Handler id regex matches TypeScript. Duplicate registrar.handle(id, fn) throws PluginSdkError("handler_duplicate"). registrar.on_dispose(fn) runs in reverse.
environment.context is an attribute dict: plugin_id, plugin_version, generation, package_class, granted_capabilities. Underlying keys are camelCase (pluginId and the rest), aligned with the protocol.
environment.host.call(capability, operation, input=None) is async. Use an async handler, or put I/O in Full Trust helpers.
environment.log provides debug / info / warn / error. environment carries a cancellation flag and aborts on dispose.
activate_plugin_worker is for tests. Error type: PluginSdkError(code, message, details=None).
Full Trust local I/O
HostClient.call is the only Host RPC. files.* returns files_root_denied until a workspace root is bound. Full Trust also ships local helpers:
from vibex_plugin import fetch_url, read_local_file, write_local_file
raw = read_local_file("/path/on/host")
write_local_file("/path/on/host", "text")
result = fetch_url("https://example.com", method="GET", timeout=30.0)Isolated Worker:
from vibex_plugin.isolated import define_plugin_workerUnder Isolated builds, the OS sandbox denies filesystem, network, and subprocess. Manifest version and packageClass: Plugin architecture.
Testing
from vibex_plugin import (
create_worker_harness,
create_generation_harness,
MemoryHostClient,
define_plugin_worker,
)
async def test_hello():
worker = await create_worker_harness(define_plugin_worker(setup))
result = await worker.invoke("hello", {"n": 1})
await worker.dispose()create_worker_harness, invoke, and dispose are coroutines and must be awaited. MemoryHostClient records call. create_generation_harness checks candidate switches. In-package tests live under sdk/python/tests/: stdio, protocol fixtures, worker, testing.
init --template python-worker default tests check manifestVersion on plugin.json. Authors add business handler tests.

