Skip to content

plugin development

Thomas Mangin edited this page Apr 8, 2026 · 1 revision

Pre-Alpha. This page describes behavior that may change.

This is the plugin author's section. The audience is different from the operator section: you are writing code that registers with the engine, reacts to events, and possibly emits events of its own. Read the Plugins overview first if you want context on what kinds of plugins already exist.

There are two paths and you should pick one before you start writing code.

Go plugins

A Go plugin lives in the Ze repo and is compiled into the binary. Infrastructure plugins (such as fib-kernel, fib-p4, iface-dhcp, and sysrib) register in internal/plugins/, while BGP plugins register in internal/component/bgp/plugins/. The engine wires it up directly. Latency is the lowest of any path, the type system catches most mistakes at compile time, and it has access to the in-process Go SDK without going through a serialisation layer.

You write a Go plugin when:

  • You are extending Ze's BGP behaviour and want the plugin shipped with the binary.
  • You need the lowest latency possible (fib-kernel, the RIB, the route selection policy).
  • You want compile-time type checking.

Go plugins is the next page.

External plugins

An external plugin is a separate process. Ze launches it, sets a small set of environment variables, and the plugin connects back over a single TLS connection (or stdin/stdout for the standalone debug case) and speaks the line protocol. Languages do not matter: any language that can read and write text and parse JSON can implement an external plugin.

You write an external plugin when:

  • You want a language other than Go.
  • You want crash isolation (the plugin can die without taking the daemon down).
  • You want to ship and version it independently of Ze.
  • You are migrating an ExaBGP process script through the bridge.

The External plugins page covers the wire protocol, the startup flow, and the practicalities of writing one in a language that is not Go. The in-tree plugin protocol guide is the canonical reference.

What both kinds can do

Whichever path you pick, the capabilities are the same.

  • Receive BGP events (UPDATE, OPEN, peer state, NOTIFICATION, EOR, RPKI) as JSON.
  • Provide commands callable from the CLI, the API, MCP, and other plugins.
  • Encode and decode NLRI for custom address families.
  • Extend the configuration tree with their own YANG schemas.
  • Verify or apply config diffs at reload time.
  • Inject capabilities into outgoing OPEN messages.
  • Validate incoming OPEN messages.
  • Emit events that other plugins consume.
  • Dispatch commands through the engine to other plugins.

The 5-stage startup protocol

Whichever surface a plugin uses, the startup is the same five-stage handshake.

  1. declare-registration: the plugin tells the engine which families, commands, and schemas it provides.
  2. configure: the engine sends the plugin its configuration sections.
  3. declare-capabilities: the plugin tells the engine which BGP capabilities to inject into OPEN messages.
  4. share-registry: the engine shares the full command registry with the plugin.
  5. ready: the plugin enters its runtime event loop.

After ready, the engine can deliver-batch (BGP events) and execute-command to the plugin, and the plugin can update-route and emit-event to the engine. Shutdown is bye.

Pages

  • Go plugins. Skeleton, registration, lifecycle, schema, handlers, tests.
  • External plugins. Wire protocol, startup flow, writing one in another language.
  • YANG schema. Authoring a schema for a plugin.
  • Handlers. The On* callbacks the SDK gives you.
  • Commands. Declaring and serving commands.
  • Testing. net.Pipe test pair, fuzz targets, functional tests.

See also

Adapted from main/docs/plugin-development/README.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally