Devsy
Developing Providers

Runtime Protocol v1

Contract for external runtime driver authors using the Devsy Runtime SDK.

The SDK foundation is available. Devsy host integration and the full runtime conformance suite are still in development. This guide does not describe an available agent.driver: external configuration.

The canonical protobuf schema is maintained in the Devsy Runtime SDK. The module path is github.com/devsy-org/devsy-runtime-sdk; the logical plugin name is devsy-runtime. HashiCorp application protocol 1 and Info API major 1/minor 0 are separate version checks. Same-major newer minor versions are accepted. Unknown mount/recreate enum values are rejected because they control host behavior.

Runtime boundary

Info, Preflight, ProvisioningPreflight, Find, TargetArchitecture, RunImage, Start, Stop, Delete, Exec, and Logs are the v1 RPC surface. Runtime state persists in the backend across plugin processes. Plugins do not own image build/tag/push, registry credentials, Compose, IDE configuration, snapshots, provider machine lifecycle, or updates.

RunImage receives resolved intent. Its empty response acknowledges completion; Find queries state. image_built_locally is an image-origin hint, not permission to build. Optional privileged/init flags distinguish absent from explicit false. Environment and mounts may contain secrets and must not appear in diagnostic logs.

Runtime name, driver name/version, and capabilities are required in Info. Runtime version may be empty when a backend cannot report it without expensive setup. An empty mount list means no supported mount types. ProvisioningPreflight may be a no-op when its capability is false. Logs may return Unimplemented when its capability is false. Reprovision means RunImage can update an existing workspace with complete resolved intent; it does not imply that an empty request is safe. The host adapter must reconcile Devsy's existing nil-options reprovision path before enabling that capability.

TargetArchitecture returns canonical amd64 or arm64. A runtime may require an existing workspace to answer; hosts must not require pre-start architecture discovery from such runtimes.

Lifecycle

Find returns found=false for ordinary absence, without a NotFound RPC error. A found response includes container details with normalized state running or stopped. Transport, permission, and backend errors remain errors.

Start on an already running workspace succeeds; missing returns NotFound. Stop on an already stopped workspace succeeds; missing may return NotFound. Delete normalizes missing state to success for cleanup. Provisioning compatibility checks must precede destructive teardown.

Exec and Logs

The first client frame is exactly one ExecStart containing argv. Later frames contain stdin bytes or exactly one CloseStdin; the client then closes its send side. Data after CloseStdin, repeated Start, unset payloads and empty stdin data frames, and unexpected EOF before CloseStdin are InvalidArgument. v1 Devsy callers use tty=false; runtimes reject unsupported TTY requests.

Each side uses one send pump and one receive loop. Data chunks should be at most 32 KiB. Empty input is represented by CloseStdin with no preceding data frames. Stdout/stderr are separate byte streams, with no text decoding or PTY. The receiver drains output before exactly one terminal ExecExit. Command success requires exit_code == 0 and an empty signal. A nonempty signal means command failure regardless of exit_code, including its protobuf default of zero. Ordinary nonzero or signal-terminated command exit is carried in ExecExit and the RPC succeeds. Setup/transport/backend failures are RPC errors; stream EOF without an exit is not command success. Context cancellation/deadlines terminate the operation and release its resources. Plugins that launch children must ensure child cleanup. The SDK server bootstrap does not own those children; hosts can opt into the SDK supervisor to own a leased plugin process tree. Unix descendants must remain in its process group and retain signalable privileges. Detached sessions, elevated commands, and independently managed runtime services require a separate owner.

Logs uses merged binary OutputChunk frames. Output buffering must remain bounded. Do not call Send concurrently from stdout and stderr copiers.

Errors and trust

Use canonical gRPC status and attach RuntimeError details for stable categories, actionable messages, optional backend diagnostics, retryability, and structured context. Raw backend diagnostics must be redacted before display. Unknown detail fields remain forward-compatible; callers must not parse messages to classify errors.

The plugin binary is trusted provider code. The future host resolves it from checksum-verified Agent.Binaries, rather than PATH discovery. The host also verifies a separately distributed supervisor executable, or runs the helper entry point in its own trusted executable. The SDK runner requires absolute executable paths, but it does not download binaries or establish checksum trust. Before creating the client, the future host must require a nonempty expected checksum for each provider-distributed runtime or supervisor and verify the resolved executable against it, including cached and local absolute paths. The existing provider downloader supports optional checksums, so a successful DownloadBinaries call or an Agent.Binaries path alone does not establish this trust. Reject missing checksums and failed verification; enforcing this requirement is a host-integration prerequisite. Reuse successful checksum verification from the distribution path when it covers the executable being launched; a redundant second pass immediately after that verified download is not required. The magic cookie is an identity check, not authentication or sandboxing. go-plugin's SecureConfig verifies a Cmd path and cannot be used with the supervisor's custom RunnerFunc.

Plugin process environment

The default policy is to inherit the host environment when starting a trusted runtime plugin. This preserves the built-in MicroSandbox client's behavior rather than introducing a hidden allowlist during externalization. This is the environment of the plugin and its runtime CLI children, separate from the workspace environment carried in RunImage or ExecStart.

Hosts must preserve settings used by the existing runtime and image clients:

SettingsCompatibility requirement
HTTP(S) proxy and NO_PROXYPreserve proxy configuration, credentials, and bypass rules
Custom CA bundle/directoryPreserve certificate locations for runtime HTTPS clients
HOME and XDG directoriesPreserve access to existing user and runtime configuration
Docker context, endpoint, and configPreserve daemon selection and credential/config locations
Temporary directoriesPreserve platform temp-directory settings
PATH and runtime-specific variablesPreserve child CLI resolution and settings not known to the host

SDK supervisor.Options.Env supplies overrides on top of the environment selected by the go-plugin client. Merely listing a few variables there does not remove other inherited values. A standalone SDK consumer can deliberately disable host inheritance with ClientConfig.SkipHostEnv = true and then supply its chosen variables through Options.Env. That is an explicit compatibility change, not the default Devsy policy or a sandbox: the trusted supervisor itself still inherits the host environment, and the OS may require additional variables such as Windows SYSTEMROOT.

Client-assigned handshake cookie, protocol versions, port range, certificate, broker multiplexing, and socket metadata take precedence over provider overrides. Preserve empty overrides as empty values. Never log the full environment or secret-bearing runtime arguments; redact backend diagnostics before exposing them to users.

The SDK's real-transport regression probes check inherited settings and explicit overrides in both the plugin and an absolute-path child executable. They also check deliberate reduced inheritance, protected transport metadata, and secret canaries in diagnostics. These probes validate forwarding, not whether a real runtime correctly uses a corporate proxy, custom CA, Docker credentials, or XDG config. Before external MicroSandbox cutover, exercise those behaviors with the extracted runtime under inherited and deliberately reduced environments. That runtime experiment and the supervisor startup comparison remain integration gates; the probes do not select session reuse.

Current implementation

The SDK provides generated Go bindings, the shared plugin handshake, server helpers, Info validation, a fake runtime with reusable lifecycle conformance, and an opt-in process supervisor. Its executable probes cover process ownership and 100 MiB duplex streaming on Linux, macOS, and Windows. Devsy host integration, real-runtime compatibility, and runtime cutover remain later stages.

For SDK development commands and package usage, see the SDK README.

On this page