Runtime
Runtime providers manage where executable plugins and hosted agent providers run.
A runtime provider is not the plugin itself, and it is not a host provider like
authentication, IndexedDB, or workflow. Instead, it is a control-plane backend
that lets gestaltd create a plugin runtime session, bind host-local services
into that session, start the plugin process there, and dial the plugin back
over gRPC.
Scope
Runtime providers apply to executable plugins under plugins.<name> and agent
providers under providers.agent.<name> when they opt into hosted execution.
They do not replace host-local infrastructure providers such as
authentication, authorization, IndexedDB, cache, S3, secrets, or workflow.
Those providers still live on the gestaltd host. A runtime provider only
changes where the configured plugin or agent provider process runs.
Mental model
By default, executable plugins and agent providers run on the same machine as
gestaltd. A provider only uses a runtime provider when it opts in with
execution.mode: hosted. Use execution.mode: hosted with
execution.runtime; legacy plugins.<name>.runtime and
providers.agent.<name>.runtime fields are no longer accepted.
When a provider does opt in, Gestalt selects a backend from runtime.providers,
reads the backend’s support profile, starts a runtime session, waits for that
session to become ready, binds any required host-local services, starts the
provider process inside the session, then dials it back over gRPC. From that
point on, the hosted provider behaves like any other configured provider from
the caller’s point of view. Gestalt stops the runtime session during shutdown
or after a bootstrap failure.
That is why the runtime interface is bigger than a single StartPlugin call:
Gestalt needs an explicit lifecycle boundary, not just a fire-and-forget launch
RPC.
Configuring a runtime provider
Runtime providers are configured under top-level runtime.providers:
runtime:
providers:
modal:
source:
path: ./vendor/gestalt-providers/runtime/modal/manifest.yaml
default: true
config:
app: gestalt-runtime
environment: main
server:
runtime:
defaultHostedProvider: modal
plugins:
support:
source: ./plugins/support/manifest.yaml
execution:
mode: hosted
runtime:
image: ghcr.io/example/support-plugin:2026-04-21
template: python-dev
metadata:
environment: productionSelection is intentionally two-step. runtime.providers defines named
backends, while execution.mode: hosted opts a specific plugin or agent
provider into hosted execution. server.runtime.defaultHostedProvider is only
a default selector for providers that already opted into hosted execution.
Runtime profiles
Runtime backends are not interchangeable, but the compatibility check is meant
to read in terms of behavior, not implementation details. Gestalt asks whether
the runtime can host plugins, how hosted plugins reach Gestalt-owned services,
and whether the runtime can preserve hostname-based egress.allowedHosts.
Host-service access is reported as none, relay, or direct. direct
means the runtime can expose guest-local service sockets inside the session.
relay means the current host deployment can provide those services through
Gestalt’s public relay path. Egress support is separate: a runtime must preserve
Gestalt’s hostname-based policy model before plugins with egress.allowedHosts
or a default-deny egress policy can run there.
The admin inspection API exposes both sides of that decision. GET /admin/api/v1/runtime/providers includes profile.advertised, which is what
the runtime reports, and profile.effective, which is what this gestaltd
deployment can actually provide after relay and public proxy prerequisites are
considered.
Host services and hosted plugins
Plugins do not talk directly to host-local services over the public network.
gestaltd starts those services on the host and then gives the runtime one of
two integration paths. A runtime with direct host-service access can bind
guest-local sockets straight into the session. A runtime without that direct
path can still use relay-backed bindings, in which case the hosted plugin talks
back to gestaltd over a scoped public relay target and gestaltd forwards
the request to the real host-local service.
That same split shows up in hostname-based egress. A runtime may preserve
egress.allowedHosts internally, or it may preserve it by routing hosted
HTTP(S) traffic through Gestalt’s public egress proxy. Either way, the contract
is that the meaning of egress.allowedHosts stays the same from the plugin’s
point of view.
The runtime provider is also responsible for the plugin’s own listener endpoint.
StartPlugin must start the plugin, allocate or inject its provider listener,
and return a host-reachable dial_target. Gestalt currently supports
unix://, tcp://, and tls:// dial targets.
Local vs hosted backends
Today there are two main runtime choices:
| Backend | Type | Notes |
|---|---|---|
local | Built-in driver | Runs the plugin on the same machine as gestaltd. Supports host-path execution and the existing host-local runtime behavior. |
modal | Installable kind: runtime provider | Runs the plugin in a hosted Linux sandbox. Requires runtime.providers.<name>.config.app and plugins.<name>.execution.runtime.image. When the host is configured for the public relay and proxy path, Modal can run plugins that need Gestalt-owned services and hostname-based egress. |
Provider images
Hosted runtime providers run prebuilt provider images. Gestalt does not upload provider bundles into those sessions. Instead, the configured image must contain the provider package at the image working directory and preserve the release package layout. Gestalt starts the manifest entrypoint path from that working directory and passes the manifest entrypoint args.
plugins:
support:
source: https://artifacts.example.com/support/v0.1.0/provider-release.yaml
execution:
mode: hosted
runtime:
provider: modal
image: ghcr.io/example/support-plugin@sha256:...This is why plugins.<name>.execution.runtime.image, template,
imagePullAuth, and metadata are forwarded to the runtime backend: they are
runtime-specific session hints, not universal plugin semantics. For private OCI
images, imagePullAuth.dockerConfigJson carries Docker config JSON, matching
the registry auth material used by Docker and Kubernetes image pull secrets.
Keep the manifest release and image digest in sync; Gestalt does not inspect the
image to prove that the manifest entrypoint exists inside it.
What to read next
For the config fields, see Configuration and Config File. For plugin-side opt-in, see Plugin. For the execution boundary, see Security. To build a runtime backend, see Custom Providers > Runtime.