Skip to main content
The Kernel provides a shared key-value store to all running plugins. A plugin can use it for small pieces of state that must be read or updated through the Kernel, such as cached values, plugin state, or data shared with another plugin. KV values are raw bytes. The Kernel does not assign a data format to them, so you can encode a value as JSON, text, a binary structure, or any other format your plugin understands.

Storage model

The store has a two-level layout:
For example:
The KV store belongs to the Kernel, not to an individual plugin instance. All plugins connected to the same Kernel use the same store. A plugin namespace is an organizational convention; it is not a permission boundary. In the current implementation, a plugin can read and write another plugin’s namespace unless that namespace is read-only. Use a namespace owned by your plugin by convention, usually derived from the plugin name. If multiple plugins intentionally share a namespace, document the key names and value format they agree to use.

Operations

The operations are defined by the Protobuf host contract. See Protobuf for the shared transport definition.

Read a value

The read request contains: The response contains a found boolean and a value byte sequence. A missing key is not an error: found is false and no value is returned. Reading a value does not create its namespace or key.

Write a value

The write request contains the same namespace and key fields plus: Writing an existing key replaces its value. The operation returns an error string when the write is rejected, for example when the namespace is read-only.

Delete a value

The delete request contains namespace and key. Deleting an existing key removes its value. Deleting a key that does not exist succeeds without changing the store. The operation returns an error string when deletion is rejected, including an attempt to delete from a read-only namespace.

List keys

The list request contains a namespace field:
  • When namespace is non-empty, the response contains the keys currently present in that namespace.
  • When namespace is empty, the response contains the names of all namespaces currently present in the store.
The returned names are sorted by the Kernel. Listing does not return values.

Lifecycle and persistence

The Kernel creates the KV store when it creates the plugin manager. The store is in memory:
  • stopping or restarting a plugin does not clear its KV values;
  • loading a new version of the same plugin does not clear its KV values; and
  • restarting the Kernel creates a new empty store and clears all values.
KV is therefore not a durable database. Persist data elsewhere when it must survive a Kernel restart, and treat KV as runtime state or a shared cache.

Concurrency and value ownership

The Kernel synchronizes individual KV operations. Reads, writes, deletes, and lists are safe when multiple plugin calls happen concurrently. There is no transaction or compare-and-swap operation. A sequence such as “read, modify, write” is not atomic with respect to another plugin. If several plugins update the same key, coordinate ownership or design the value so that lost updates do not corrupt the application state. The Kernel copies byte values when storing and reading them. Mutating a byte buffer after a write does not change the stored value, and mutating a returned buffer does not change the value in the store.

The sys namespace

sys is a Kernel-managed, read-only namespace. Plugins can read and list it, but writes and deletes through the plugin host boundary return an error. The Kernel uses this namespace for host-managed state, including plugin registry information. Do not write to sys, and do not depend on undocumented system keys unless the Kernel documentation explicitly defines them.

Backend behavior

WASM and gRPC plugins use the same KV contract:
  • a WASM plugin reaches the store through the generated host bindings; and
  • a gRPC plugin reaches the store through the Kernel’s host callback channel.
The storage semantics are the same for both backends. The backend changes how the request crosses the plugin boundary, not how the Kernel stores or returns the value. Use a predictable namespace and key scheme:
Keep values small enough for the calling path and define their encoding before other components consume them. Check the found result before decoding a value, handle write and delete errors, and avoid treating a successful write as durable persistence.