Date: 2026-04-16
- Core launches plugin as a side process.
- Core writes protocol messages to plugin
stdin. - Core reads protocol messages from plugin
stdout. - Messages are JSON objects.
- Framing is line-delimited JSON (one complete JSON object per line).
- Core expects exactly one handshake response line after startup.
- Core then sends one execute request line and expects one execute response line.
- Anything that cannot be decoded as one full JSON object is malformed protocol output.
- Handshake request:
PluginHandshakeRequest - Handshake response:
PluginHandshakeResponseincluding explicitmanifest- required manifest fields:
plugin_idplugin_versionprotocol_versionexposed_tools
- capability declaration:
capabilities- required when the core-bound
PluginSpecgrants plugin capabilities - each value is a capability/resource the plugin explicitly requests
- every requested value must exist in the core-owned allow-list for that plugin binding
- empty, whitespace-padded and duplicate values are rejected
- required when the core-bound
- required manifest fields:
- Execute request:
PluginRequest - Execute response:
PluginResponse - Error payload:
PluginError
- Invocation timeout is owned by core (plugin-specific timeout or runtime default).
- Timeout is a hard execution failure.
- Timeout never maps to implicit success.
- Plugin exit before a valid response is treated as execution failure.
- Malformed handshake or response payload is treated as execution failure.
- Core does not silently fallback to success when protocol exchange is invalid.
Core classifies plugin-runtime failures with explicit codes:
launch_failedhandshake_failedtimeoutcrashedmalformed_responsetool_not_exposedprotocol_version_mismatchcapability_not_declaredcapability_not_allowed
Additional contract checks tied to this taxonomy:
- handshake
manifest.protocol_versionmust match requested protocol - requested runtime tool must exist in
manifest.exposed_tools - if
PluginSpec.Capabilitiesis non-empty, handshakemanifest.capabilitiesmust explicitly declare the plugin's requested capabilities - handshake
manifest.capabilitiesmust be a subset of the core-ownedPluginSpec.Capabilitiesallow-list; the plugin never self-grants power by naming a capability