Skip to main content
Messages provide synchronous, point-to-point communication between plugins running in the same Kernel. A sending plugin names one target plugin, sends a topic and a byte payload, and waits for the target to return a reply. Use messages when one plugin needs another plugin to perform an operation or return data. Use KV storage when the data should be shared as state instead of delivered as a request.

Message envelope

The message is the Protobuf PluginMessage defined by the Protobuf contract: The target receives a PluginMessageReply: The Kernel does not interpret topic, payload, or message. Define their format between the participating plugins. You can use JSON, Protobuf, text, or another encoding, but the sender and target must agree on it.

Send a message

To send a message:
  1. choose the registered name of the target plugin;
  2. choose a stable topic name;
  3. encode the request into payload; and
  4. send the envelope through the generated host binding for your backend.
The sender waits while the Kernel dispatches the message to the target’s plugin message handler. A successful reply contains the target’s message value. The source plugin cannot choose or override its identity; the Kernel replaces the source field with the authenticated name of the calling plugin.

Receive a message

The target plugin receives the same envelope, including the Kernel-provided source. It should:
  1. verify that the source plugin is allowed to request the operation;
  2. route the message by topic;
  3. decode and validate payload; and
  4. return either a result or an error.
The Kernel does not provide topic subscriptions or automatic dispatch inside the plugin. The target’s message handler receives messages for that plugin and is responsible for interpreting the topic.

Errors and delivery

Messages are delivered only to a currently running target plugin. The send fails when:
  • target is empty;
  • the target plugin is not running;
  • the target handler returns a transport or execution error; or
  • the target reply contains a non-empty error field.
The target’s error value is returned to the sender as an error. A message is not delivered to another plugin when the target is unavailable. Messages are not queued, retried, broadcast, or persisted. There is no durable delivery guarantee. If the target stops while a message is in flight, the call context is canceled with the target plugin’s lifecycle.

Backend behavior

The message semantics are identical for both plugin backends:
  • a WASM plugin sends through generated host bindings; and
  • a gRPC plugin sends through the Kernel’s host callback channel.
The Kernel then invokes the target plugin through its selected backend and converts the target’s reply back into the sender’s backend-specific response type.

Identity and authorization

The Kernel authenticates the source plugin at the host boundary. A plugin cannot impersonate another plugin by writing a different source value into a send request. There is no Kernel-level access policy for individual topics. Any running plugin can address another running plugin by name, so the target must enforce authorization in its own handler when a topic or payload represents a privileged operation. Treat topic as routing information, not as an access control mechanism.

Design a message contract

Keep a message contract explicit and versionable:
Document the payload schema, required fields, response format, and error meaning for every topic. Validate untrusted payloads before using them, and return an explicit error for unknown or malformed topics. Use a stable target name and topic namespace. If a request can be safely repeated, make the operation idempotent because the sender may need to retry it at the application level after a temporary target failure.