Skip to content
Spice Framework on GitHub

RFC 0005: Runtime Tool Plugin Protocol

agentMaturity: experimentalSource: spice-agent@4726fb8Exact reviewed source
  • Status: draft
  • Initial package: plugin/v1
  • Transport: one local gRPC connection per process generation

Purpose

Runtime plugins support tools whose executable implementation is not part of the compiled application. They are the only dynamic extension graph. The protocol does not recreate static Spice composition and never registers compiled stages, providers, or native UI code.

Identity and launch

Configuration includes a canonical absolute executable path, expected SHA-256, plugin name, startup/call/drain bounds, and approved capabilities. The host opens the verified file, detects path/digest drift as far as the operating system permits, launches with a random single-use handshake secret, and bounds stderr. PATH lookup and ambient directory scanning are forbidden.

Initialize exchanges protocol/build identity, manifest, tool definitions, capabilities, limits, and the launch-secret proof. A candidate is not visible to runs until all facts validate.

Generation lifecycle

Candidate activation is atomic and affects future runs only. Starting a run leases the current generation and snapshots its identity/tool definitions. Old processes remain alive until all leases release, then receive bounded drain and shutdown. A failed candidate or drain never mutates the active generation.

Host restart is bounded and applies only to future calls. A call interrupted by crash is failed. A mutating call with uncertain outcome is never automatically replayed. Cancellation propagates through RPC then process-tree cleanup; failure to confirm termination is observable.

Initial tool API

ListTools returns immutable bounded definitions. Execute accepts one validated call and streams bounded progress followed by exactly one result or typed failure. Call/progress IDs must match. Unknown capabilities, duplicate names, oversized schemas/payloads, post-terminal messages, and stdout protocol contamination fail the candidate or call according to phase.

Compatibility and language neutrality

Buf lint/breaking checks govern plugin/v1. Additive optional fields follow the engine-protocol rules. Go and Python 3.12+ fixtures must pass the same black-box conformance suite. Generated client code is permitted; importing host-private Go packages is not.

Trust model

Digest pinning provides provenance/change detection, not sandboxing. The process runs with the daemon user’s privileges unless a later launcher/policy extension provides real isolation. Capability declarations are mandatory metadata but not security theater: help/status must state whether an enforcing decorator exists.

Acceptance before freeze

Conformance covers wrong digest, path replacement, handshake replay, old/new versions, unknown fields, duplicate tools, malformed/oversized traffic, bounded stderr, crash at every lifecycle phase, cancellation, uncertain mutation, activation races, generation leases, drain timeout, and clean Windows/Unix process-tree shutdown.