Skip to main content
As a plugin developer, you use Protobuf as the contract between your plugin and the Arupa Kernel. The contract defines the messages your plugin receives, the responses it returns, and the shared operations it can request from the Kernel. Generated code turns that contract into the typed SDK used by your plugin. You implement your feature on top of this SDK. You do not need to write the binary serialization, process communication, or WASM host bindings yourself. Protobuf only defines the boundary; your plugin still owns the feature logic and the data structures that do not cross that boundary.

What crosses the plugin boundary

The protocol carries two kinds of communication:
When the Kernel starts your plugin, it gives the plugin its configuration and a chance to declare the resources it provides. Later, incoming requests and events are converted into Protobuf messages before they reach your handlers. Your handlers return Protobuf messages, which the Kernel converts back into the corresponding application response. If your feature needs a capability owned by the Kernel, use the generated host bindings. The Kernel performs the operation and returns a typed result to your plugin. Keep feature-specific state and behavior in your plugin; use the host boundary for shared application capabilities.

Choose a backend

Choose the backend according to the language and runtime you want to use. Both backends use the same Protobuf contract, but their implementation requirements are different.

gRPC

You can implement a gRPC plugin in any language with Protobuf and gRPC support. The plugin runs as a separate process and communicates with the Kernel through the gRPC form of the Protobuf contract. Use your language’s Protobuf and gRPC tooling to generate or implement the contract types, then set Type: grpc in the plugin manifest.

WASM

Arupa currently supports Go for WASM plugins. Use the Go SDK generated for the Arupa Protobuf contract and compile the plugin to WASM. The WASM integration is based on knqyf263/go-plugin, which generates Go interfaces and hides the raw WASM communication behind the SDK. Follow the development model described in the guide: define or consume the Protobuf contract, generate the Go bindings, implement the generated plugin interface, and compile the implementation as a WASM module. Set Type: wasm in the plugin manifest. The transport changes, but the message types and their meaning stay the same. Choose the SDK and build process that match the Type in your plugin manifest.

Use the generated SDK

The .proto schema is the source of truth for the plugin contract. The SDK generated from it contains the message types and backend bindings your plugin uses during compilation. Treat generated files as build artifacts. Do not edit them by hand. If you need to use a newly added message or field, regenerate the SDK from the matching schema and rebuild your plugin. Set ContractVersion in info.yaml to the protocol version used by your plugin. The version must be supported by the Kernel that will load the package. The manifest version and the generated SDK should always be updated together. Using the generated SDK gives your plugin:
  • typed request and response values;
  • consistent serialization with the Kernel;
  • transport-specific communication handled by the runtime; and
  • one programming model for the plugin contract.

Keep your plugin compatible

When you consume a newer contract, remember that Protobuf identifies fields by number, not only by name:
  • keep existing field numbers assigned to their original meaning;
  • do not reuse the number of a removed field;
  • add new fields with new numbers; and
  • allow your plugin to ignore fields it does not need when the change is backward-compatible.
Do not change the meaning or type of an existing field in your plugin’s local assumptions. If a change is not backward-compatible, use the corresponding new contract version and rebuild the plugin against it.

Typical development flow

Use this workflow when developing a plugin:
  1. Choose WASM or gRPC and use the matching generated SDK.
  2. Implement the plugin contract and your feature logic with the SDK types.
  3. Declare the resources your plugin provides during registration.
  4. Use host bindings whenever your feature needs a Kernel-owned capability.
  5. Set the matching ContractVersion in the plugin manifest.
  6. Build and package the plugin, then load it with a Kernel that supports that contract version.
The important boundary is simple: your plugin implements behavior, while Protobuf and the generated SDK carry typed data between your code and the Kernel.