vgi.serve
Module overview
Zero-boilerplate CLI for serving VGI workers.
Loads any Worker by module reference and serves it — stdio by default
(matching vgi-rpc’s run_server()), --http for cloud deployment.
Usage:
# Stdio (default) — for subprocess/pipe use by vgi-client or DuckDBvgi-serve my_worker.pyvgi-serve my_app.workers:ProductionWorker
# HTTP — for cloud deploymentvgi-serve my_worker.py --httpvgi-serve my_worker.py --http --host 0.0.0.0 --port 8080Programmatic API:
from vgi.serve import create_app, load_worker_class
app = create_app(load_worker_class("my_app:MyWorker"))# Use with gunicorn: gunicorn app -w 4 -b 0.0.0.0:8080function create_app
Section titled “function create_app”create_app(
worker_cls: type[Worker],
,
prefix: str = ‘’,
cors_origins: str = ‘’,
describe: bool = True,
signing_key: bytes | None = None,
log_level: int = logging.INFO,
authenticate: Callable[[falcon.Request], AuthContext] | None = None,
proxy_proof_required: bool | None = None,
oauth_resource_metadata: Any = None,
otel_config: OtelConfig | None = None,
max_stream_response_bytes: int | None = None,
max_externalized_response_bytes: int | None = None,
introspect_principals: Iterable[str] | None = None,
introspect_rate_limit: int | None = None,
) -> falcon.App[Any, Any]
Create a WSGI app for a VGI worker.
Returns a standard WSGI app usable with gunicorn, uwsgi, waitress, or any WSGI server.
function export_serve_config
Section titled “function export_serve_config”export_serve_config(
*,
worker_ref: str,
prefix: str,
cors_origins: str,
describe: bool,
log_level: int,
max_stream_response_bytes: int | None,
max_externalized_response_bytes: int | None,
) -> None
Publish the parent’s serve configuration for worker processes to read.
function load_worker_class
Section titled “function load_worker_class”load_worker_class(reference: str) -> type[Worker]
Load a Worker subclass from a module reference string.
Accepts several reference formats:
module:ClassName— import module and return ClassNamemodule— import module and auto-discover the singleWorkersubclass./path/to/file.pyorpath.py— load from file path./path/to/file.py:ClassName— load from file path, return ClassName
Auto-discovery finds Worker subclasses defined in the module (ignores
imported ones by checking __module__).
function main
Section titled “function main”main() -> None
CLI entry point for vgi-serve.
function resolve_shared_signing_key
Section titled “function resolve_shared_signing_key”resolve_shared_signing_key(
*,
propagate_to_children: bool,
) -> tuple[bytes, bool]
Resolve the signing key every process in this deployment must agree on.
The key seals HTTP state tokens and catalog opaque data. Every process
that might serve a continuation for a stream has to hold the same one:
a token sealed by one key fails the AEAD check under another, and the
failure is load-dependent rather than deterministic. A client whose
connection stays pinned to one process never notices; one that reconnects
mid-stream – seek_to_token, a load balancer, a respawned worker –
hits an intermittent 400 that looks like flakiness.
Resolution:
VGI_SIGNING_KEYset: use it. Tokens survive restarts and are valid across every process configured with the same value. This is the only correct setting for a load-balanced or multi-instance deployment, because nothing here can reach a peer we did not start.- Unset: mint a random key for this deployment. Tokens are then valid for the life of these processes and clients re-ATTACH after a restart.
function wsgi_app_factory
Section titled “function wsgi_app_factory”wsgi_app_factory() -> Any
Build the WSGI app from the environment — the pre-fork worker entry point.
Granian is pointed at vgi.serve:wsgi_app_factory and calls this once
per worker process. Everything it needs was published by
:func:export_serve_config in the parent, plus VGI_SIGNING_KEY, which
the parent minted and exported so every worker seals state tokens with the
same key.