Skip to content

Plugin SDKs

RoboDev provides SDK helper libraries and build tooling for three languages. The protobuf definitions in proto/ are the source of truth. Generated stubs are not checked into the repository — you generate them locally with make sdk-gen before using the SDKs.

What's in the repository

Language Directory What's included
Go sdk/go/ Helper scaffolding and examples; no generated stubs
Python sdk/python/ plugin.py base class helpers; proto stub dirs are empty until you run make sdk-gen
TypeScript sdk/typescript/ plugin.ts base class helpers; proto stub dirs are empty until you run make sdk-gen

Generating stubs

Run the following Make target to regenerate all three SDKs from the proto sources:

make sdk-gen

This invokes buf generate with the appropriate configuration for each language. You will need buf installed and available on your PATH. Install it with:

# macOS / Linux
brew install bufbuild/buf/buf

# Or download a release binary from https://github.com/bufbuild/buf/releases

Individual languages can also be generated directly:

buf generate proto/                                    # Go stubs
buf generate proto/ --template buf.gen.python.yaml    # Python stubs
buf generate proto/ --template buf.gen.ts.yaml        # TypeScript stubs

Go SDK (sdk/go/)

The Go stubs are a module importable by any Go plugin. They provide the generated protobuf types and gRPC service definitions. Combine them with the pkg/plugin/ interfaces and hashicorp/go-plugin to build a built-in or third-party plugin.

import (
    v1 "github.com/unitaryai/robodev/proto/v1"
)

func (b *MyBackend) Handshake(
    ctx context.Context,
    req *v1.HandshakeRequest,
) (*v1.HandshakeResponse, error) {
    return &v1.HandshakeResponse{
        InterfaceVersion: 1,
        PluginName:       "my-backend",
        PluginVersion:    "1.0.0",
    }, nil
}

See Writing a Plugin for a complete walkthrough.

Python SDK (sdk/python/)

The Python stubs are generated by buf using the protoc-gen-python and protoc-gen-grpc-python plugins. They provide the message classes and service stub classes needed to implement a gRPC server.

A minimal ticketing plugin skeleton:

import grpc
from concurrent import futures
from robodev.v1 import ticketing_pb2, ticketing_pb2_grpc, common_pb2

class MyTicketingBackend(ticketing_pb2_grpc.TicketingBackendServicer):
    def Handshake(self, request, context):
        return common_pb2.HandshakeResponse(
            interface_version=1,
            plugin_name="my-backend",
            plugin_version="1.0.0",
        )

    def PollReadyTickets(self, request, context):
        # Call your issue tracker API here.
        return ticketing_pb2.PollReadyTicketsResponse(tickets=[])

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    ticketing_pb2_grpc.add_TicketingBackendServicer_to_server(
        MyTicketingBackend(), server
    )
    server.add_insecure_port("[::]:50051")
    server.start()
    server.wait_for_termination()

if __name__ == "__main__":
    serve()

Refer to the example Jira plugin at examples/plugins/example-jira-python/ for a complete implementation including pyproject.toml and a Dockerfile.

TypeScript SDK (sdk/typescript/)

The TypeScript stubs are generated by buf using protoc-gen-grpc-web or protoc-gen-ts. They provide typed message interfaces and service client stubs compatible with Node.js gRPC.

A minimal notifications plugin skeleton:

import * as grpc from '@grpc/grpc-js';
import {
  NotificationChannelService,
  INotificationChannelServer,
} from './generated/notifications_grpc_pb';
import {
  HandshakeRequest,
  HandshakeResponse,
} from './generated/common_pb';

class TeamsNotificationChannel implements INotificationChannelServer {
  handshake(
    call: grpc.ServerUnaryCall<HandshakeRequest, HandshakeResponse>,
    callback: grpc.sendUnaryData<HandshakeResponse>,
  ): void {
    const response = new HandshakeResponse();
    response.setInterfaceVersion(1);
    response.setPluginName('teams');
    response.setPluginVersion('1.0.0');
    callback(null, response);
  }

  // ... implement notify, notifyStart, notifyComplete ...
}

const server = new grpc.Server();
server.addService(NotificationChannelService, new TeamsNotificationChannel());
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
  server.start();
});

Refer to the example Teams plugin at examples/plugins/example-teams-ts/ for a complete implementation including package.json, tsconfig.json, and a Dockerfile.

Interface versioning

All generated stubs carry the interface_version constant from their respective proto package. This version must match what the controller expects (currently 1 for all services). See the Plugin gRPC API reference for the full versioning rules.