squadron

package module
v0.0.30 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 2, 2026 License: MIT Imports: 8 Imported by: 0

README

Squadron SDK

Go SDK for building Squadron plugins.

Plugins extend Squadron agents with custom tools — browser automation, database queries, API integrations, or anything else you can write in Go. Each plugin is a standalone binary that Squadron manages as a subprocess, communicating over gRPC.

Quick Start

1. Create a new Go module
mkdir plugin_example && cd plugin_example
go mod init github.com/yourname/plugin_example
go get github.com/mlund01/squadron-sdk
2. Implement the plugin

Create main.go:

package main

import (
    "encoding/json"
    "fmt"

    squadron "github.com/mlund01/squadron-sdk"
)

var tools = map[string]*squadron.ToolInfo{
    "greet": {
        Name:        "greet",
        Description: "Greet someone by name",
        Schema: squadron.Schema{
            Type: squadron.TypeObject,
            Properties: squadron.PropertyMap{
                "name": {
                    Type:        squadron.TypeString,
                    Description: "The name to greet",
                },
            },
            Required: []string{"name"},
        },
    },
}

type Plugin struct {
    greeting string
}

func (p *Plugin) Configure(settings map[string]string) error {
    if v, ok := settings["greeting"]; ok {
        p.greeting = v
    }
    return nil
}

func (p *Plugin) Call(toolName string, payload string) (string, error) {
    switch toolName {
    case "greet":
        var params struct {
            Name string `json:"name"`
        }
        if err := json.Unmarshal([]byte(payload), &params); err != nil {
            return "", fmt.Errorf("invalid payload: %w", err)
        }
        greeting := p.greeting
        if greeting == "" {
            greeting = "Hello"
        }
        return fmt.Sprintf("%s, %s!", greeting, params.Name), nil
    default:
        return "", fmt.Errorf("unknown tool: %s", toolName)
    }
}

func (p *Plugin) GetToolInfo(toolName string) (*squadron.ToolInfo, error) {
    info, ok := tools[toolName]
    if !ok {
        return nil, fmt.Errorf("unknown tool: %s", toolName)
    }
    return info, nil
}

func (p *Plugin) ListTools() ([]*squadron.ToolInfo, error) {
    result := make([]*squadron.ToolInfo, 0, len(tools))
    for _, info := range tools {
        result = append(result, info)
    }
    return result, nil
}

func main() {
    squadron.Serve(&Plugin{})
}
3. Build and install locally
mkdir -p ~/.squadron/plugins/example/local
go build -o ~/.squadron/plugins/example/local/plugin .

Or use the Squadron CLI:

squadron plugin build example .
4. Use it in your config
plugin "example" {
  version = "local"
  settings = {
    greeting = "Hey there"
  }
}

agent "assistant" {
  model = models.anthropic.claude_sonnet_4
  tools = [plugins.example.greet]
}
5. Test it
# List available tools
squadron plugin tools example

# Call a tool directly
squadron plugin call example greet '{"name": "World"}'

# Use all tools from the plugin
# tools = [plugins.example.all]

Interface

Every plugin implements the ToolProvider interface:

type ToolProvider interface {
    Configure(settings map[string]string) error
    Call(toolName string, payload string) (string, error)
    GetToolInfo(toolName string) (*ToolInfo, error)
    ListTools() ([]*ToolInfo, error)
}
Method Purpose
Configure Receive settings from HCL config. Use this to initialize connections, set options, etc.
Call Handle a tool invocation. payload is a JSON string matching the tool's schema.
GetToolInfo Return metadata and schema for a specific tool.
ListTools Return metadata for all tools the plugin provides.

The entry point is always squadron.Serve(&YourPlugin{}) in main().

Schema Types

Tool parameters are defined using JSON Schema types:

squadron.TypeString   // "string"
squadron.TypeNumber   // "number"
squadron.TypeInteger  // "integer"
squadron.TypeBoolean  // "boolean"
squadron.TypeArray    // "array"
squadron.TypeObject   // "object"

Nested objects and arrays are supported:

Schema: squadron.Schema{
    Type: squadron.TypeObject,
    Properties: squadron.PropertyMap{
        "query": {
            Type:        squadron.TypeString,
            Description: "SQL query to execute",
        },
        "options": {
            Type:        squadron.TypeObject,
            Description: "Query options",
            Properties: squadron.PropertyMap{
                "timeout": {Type: squadron.TypeInteger, Description: "Timeout in seconds"},
                "limit":   {Type: squadron.TypeInteger, Description: "Max rows to return"},
            },
        },
        "tags": {
            Type:        squadron.TypeArray,
            Description: "Tags for the query",
            Items:       &squadron.Property{Type: squadron.TypeString},
        },
    },
    Required: []string{"query"},
},

Settings

Plugins receive settings from the HCL config via Configure():

plugin "example" {
  version = "local"
  settings = {
    api_url  = "https://api.example.com"
    timeout  = "30"
    headless = "true"
  }
}

All values are strings — parse them in Configure() as needed.

Local Development

During development, use version = "local" to point Squadron at your local build:

# Build to the local plugin path
mkdir -p ~/.squadron/plugins/myplugin/local
go build -o ~/.squadron/plugins/myplugin/local/plugin .

# Or use the CLI shorthand
squadron plugin build myplugin .

# Reference in config
# plugin "myplugin" { version = "local" }

The plugin binary must be named plugin (or plugin.exe on Windows) and placed at:

~/.squadron/plugins/<name>/<version>/plugin

Plugin processes are managed by Squadron — they start when first referenced and persist for the duration of the mission (so state like database connections or browser sessions is maintained across tasks).

Releasing

To distribute your plugin, set up GoReleaser with GitHub Actions. Squadron auto-downloads published plugins on first use.

.goreleaser.yml
version: 2

project_name: plugin_example

builds:
  - id: plugin
    binary: plugin
    main: .
    goos:
      - darwin
      - linux
      - windows
    goarch:
      - amd64
      - arm64
    ldflags:
      - -s -w

archives:
  - format: tar.gz
    format_overrides:
      - goos: windows
        format: zip
    name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"

checksum:
  name_template: "checksums.txt"
  algorithm: sha256

release:
  github:
    owner: yourname
    name: plugin_example
.github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - "v*"

permissions:
  contents: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-go@v5
        with:
          go-version: "1.23"

      - uses: goreleaser/goreleaser-action@v6
        with:
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Publish a release
git tag v0.0.1
git push origin v0.0.1

GoReleaser builds cross-platform binaries, generates checksums, and creates a GitHub release. Users reference your plugin by source and version:

plugin "example" {
  source  = "github.com/yourname/plugin_example"
  version = "v0.0.1"
}

Squadron downloads the correct binary for the user's platform, verifies the checksum, and installs it automatically.

Existing Plugins

Plugin Description
plugin_playwright Browser automation (navigate, click, screenshot, aria snapshots)
plugin_pinger Minimal example plugin (ping/pong/echo)
plugin_databricks_sql Databricks SQL queries and schema exploration

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Handshake = plugin.HandshakeConfig{
	ProtocolVersion:  1,
	MagicCookieKey:   "SQUAD_PLUGIN",
	MagicCookieValue: "squadron-tool-plugin-v1",
}

Handshake is the handshake config for plugins

View Source
var PluginMap = map[string]plugin.Plugin{
	"tool": &ToolPluginGRPCPlugin{},
}

PluginMap is the map of plugins we can dispense

Functions

func Serve

func Serve(impl ToolProvider)

Serve starts the plugin server with the given ToolProvider implementation. This is the main entry point for plugin binaries. It also monitors the parent process and exits if the parent dies, preventing orphaned plugin processes.

Types

type GRPCClient

type GRPCClient struct {
	// contains filtered or unexported fields
}

GRPCClient is the gRPC client implementation of ToolProvider

func (*GRPCClient) Call

func (c *GRPCClient) Call(ctx context.Context, toolName string, payload string) (string, error)

func (*GRPCClient) Configure

func (c *GRPCClient) Configure(settings map[string]string) error

func (*GRPCClient) GetToolInfo

func (c *GRPCClient) GetToolInfo(toolName string) (*ToolInfo, error)

func (*GRPCClient) ListTools

func (c *GRPCClient) ListTools() ([]*ToolInfo, error)

type GRPCServer

type GRPCServer struct {
	pb.UnimplementedToolPluginServer
	Impl ToolProvider
}

GRPCServer is the gRPC server implementation that wraps a ToolProvider

func (*GRPCServer) Call

func (s *GRPCServer) Call(ctx context.Context, req *pb.CallRequest) (*pb.CallResponse, error)

func (*GRPCServer) Configure

func (s *GRPCServer) Configure(ctx context.Context, req *pb.ConfigureRequest) (*pb.ConfigureResponse, error)

func (*GRPCServer) GetToolInfo

func (*GRPCServer) ListTools

func (s *GRPCServer) ListTools(ctx context.Context, req *pb.ListToolsRequest) (*pb.ListToolsResponse, error)

type Property

type Property struct {
	Type        PropertyType `json:"type"`
	Description string       `json:"description,omitempty"`
	Items       *Property    `json:"items,omitempty"`      // For array types
	Properties  PropertyMap  `json:"properties,omitempty"` // For nested objects
	Required    []string     `json:"required,omitempty"`   // For nested objects
}

Property defines a single property in a JSON Schema

type PropertyMap

type PropertyMap map[string]Property

PropertyMap is a map of property names to their definitions

type PropertyType

type PropertyType string

PropertyType represents a JSON Schema type

const (
	TypeString  PropertyType = "string"
	TypeNumber  PropertyType = "number"
	TypeInteger PropertyType = "integer"
	TypeBoolean PropertyType = "boolean"
	TypeArray   PropertyType = "array"
	TypeObject  PropertyType = "object"
)

type Schema

type Schema struct {
	Type       PropertyType `json:"type"`
	Properties PropertyMap  `json:"properties"`
	Required   []string     `json:"required,omitempty"`
}

Schema represents a JSON Schema for tool parameters

func (Schema) String

func (s Schema) String() string

String returns the JSON representation of the schema

type ToolInfo

type ToolInfo struct {
	Name        string
	Description string
	Schema      Schema
}

ToolInfo contains metadata about a tool

type ToolPluginGRPCPlugin

type ToolPluginGRPCPlugin struct {
	plugin.Plugin
	Impl ToolProvider
}

ToolPluginGRPCPlugin is the plugin.GRPCPlugin implementation

func (*ToolPluginGRPCPlugin) GRPCClient

func (p *ToolPluginGRPCPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error)

func (*ToolPluginGRPCPlugin) GRPCServer

func (p *ToolPluginGRPCPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error

type ToolProvider

type ToolProvider interface {
	// Configure passes settings from HCL config to the plugin
	Configure(settings map[string]string) error

	// Call invokes a tool with the given JSON payload.
	// Implementations should respect context cancellation for long-running operations.
	Call(ctx context.Context, toolName string, payload string) (string, error)

	// GetToolInfo returns metadata about a specific tool
	GetToolInfo(toolName string) (*ToolInfo, error)

	// ListTools returns info for all tools this plugin provides
	ListTools() ([]*ToolInfo, error)
}

ToolProvider is the interface that all tool plugins must implement

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL