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.
mkdir plugin_example && cd plugin_example
go mod init github.com/yourname/plugin_example
go get github.com/mlund01/squadron-sdkCreate main.go:
package main
import (
"context"
"fmt"
squadron "github.com/mlund01/squadron-sdk"
)
type GreetInput struct {
Name string `json:"name" jsonschema:"required,description=The name to greet"`
}
func main() {
app := squadron.New()
var greeting string
app.Configure(func(settings map[string]string) error {
greeting = settings["greeting"]
if greeting == "" {
greeting = "Hello"
}
return nil
})
squadron.Tool(app, "greet", "Greet someone by name",
func(ctx context.Context, in GreetInput) (string, error) {
return fmt.Sprintf("%s, %s!", greeting, in.Name), nil
})
app.Serve()
}The schema is reflected from GreetInput's struct tags via
github.com/invopop/jsonschema. Use
the standard jsonschema: tag keys (required, description=...,
enum=...,enum=..., minimum=N, maximum=N, default=..., pattern=...,
etc.). For descriptions that need commas, use the dedicated
jsonschema_description: tag instead.
Pass struct{} as the input type for tools that take no parameters.
mkdir -p ~/.squadron/plugins/example/local
go build -o ~/.squadron/plugins/example/local/plugin .Or use the Squadron CLI:
squadron plugin build example .plugin "example" {
version = "local"
settings = {
greeting = "Hey there"
}
}
agent "assistant" {
model = models.anthropic.claude_sonnet_4
tools = [plugins.example.greet]
}# 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]There are two ways to write a plugin:
A typed, generics-driven API. The schema is derived from the input struct, the payload is unmarshaled and the result marshaled automatically:
app := squadron.New()
app.Configure(func(settings map[string]string) error { ... })
squadron.Tool(app, name, description, func(ctx, in InputType) (Output, error) { ... })
app.Serve()Behind the scenes this builds a ToolProvider (see below) that ships full
JSON Schema bytes — enum, default, minimum/maximum, $defs, etc. all
flow through to the LLM verbatim.
The underlying contract, useful when tools are dynamic or the typed API doesn't fit:
type ToolProvider interface {
Configure(settings map[string]string) error
Call(ctx context.Context, toolName string, payload string) (string, error)
GetToolInfo(toolName string) (*ToolInfo, error)
ListTools() ([]*ToolInfo, error)
}ToolInfo.RawSchema (a json.RawMessage) ships verbatim and overrides the
typed Schema if both are set — use it to hand-write rich JSON Schema.
The entry point is squadron.Serve(provider) (or app.Serve(), which is
the same thing).
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.
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).
To distribute your plugin, set up GoReleaser with GitHub Actions. Squadron auto-downloads published plugins on first use.
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_examplename: 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 }}git tag v0.0.1
git push origin v0.0.1GoReleaser 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.
| 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 |
MIT