About Language Binding Plugins
A language-binding plugin is application code that registers a stable plugin kind with the Relay runtime already loaded by Rust, Python, or Node.js. It has no manifest, shared library, worker process, integrity digest, or separately managed environment. That makes it the most direct choice for behavior owned and deployed by one application.
The checked examples/language-binding-plugin project implements one
documentation-plugin in all three bindings. Every version follows the same sequence:
- Validate the same JSON-compatible component settings.
- Install equivalent event and request behavior.
- Print the activation report and exercise managed tool, model, stream, and event paths.
- Clear registrations and deregister the kind.
The Smallest Useful Language-Binding Plugin
These complete programs contain the same boundary in each binding: the plugin validates
component-local JSON, installs component-owned middleware, the host activates a
PluginConfig, and cleanup tears the behavior down.
Python
Node.js
Rust
The host passes only {"tag": "documentation"} to both hooks. register does not
receive the surrounding document, enabled, or another component’s settings. Relay
records the registration against this component, which is why clearing configuration
can remove it without the plugin keeping a global deregistration handle.
How the Bindings Differ
Configuration keys remain snake_case in all three examples. Only Node.js API methods
such as listKinds or registerLlmRequestIntercept use camelCase.
Follow the Complete Workflow
Follow these pages in order to build, activate, exercise, and remove the same plugin in each language binding:
- Validate Configuration turns wrong types, unsupported modes, unknown fields, and disabled-invalid components into stable diagnostics before runtime state changes.
- Register Behavior connects valid feature groups to component-owned registrations and verifies rollback.
- Advanced Configuration covers multiple instances, host policy, reports, activation close, deregistration, and async lifecycle differences.
- Runnable Examples gives the clean commands and expected output for Rust, Python, and Node.js.
Success means the same operator intent produces the same visible behavior in each binding: invalid configuration is inert, valid configuration reports activation, representative calls show the plugin effect, and teardown removes both active behavior and future kind lookup when requested.