> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arupa.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Protobuf

> Understand how Protobuf defines the contract between the Kernel and plugins.

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:

```text theme={null}
Kernel ── lifecycle context, requests, and events ──▶ Your plugin
Kernel ◀─ typed requests for shared capabilities ─── Your plugin
```

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`](https://github.com/knqyf263/go-plugin), which
generates Go interfaces and hides the raw WASM communication behind the SDK.

Follow the development model described in the
[guide](https://github.com/knqyf263/go-plugin): 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.
