Pilot

Pilot Go SDK

Go client for the Cuitty Pilot API — manage playbooks, runs, and providers with idiomatic Go error handling.

Pilot Go SDK

github.com/cuitty/pilot-sdk-go is a Go client for the Pilot API. It requires Go 1.22+ and has zero external dependencies beyond the standard library.

Install

go get github.com/cuitty/pilot-sdk-go

Quick start

package main

import (
	"encoding/json"
	"fmt"
	"log"

	pilot "github.com/cuitty/pilot-sdk-go"
)

func main() {
	client := pilot.NewClient("http://localhost:4320", "your-auth-token")

	// List all playbooks
	playbooks, err := client.ListPlaybooks("")
	if err != nil {
		log.Fatal(err)
	}
	for _, pb := range playbooks {
		fmt.Printf("%s: %s\n", pb.ID, pb.Title)
	}

	// Start a run
	inputs, _ := json.Marshal(map[string]string{
		"zone":        "example.com",
		"record_name": "app",
		"ip_address":  "1.2.3.4",
	})
	resp, err := client.StartRun(&pilot.StartRunRequest{
		PlaybookID: "cloudflare.dns.add-a-record",
		Mode:       "autonomous",
		Inputs:     inputs,
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Run started: %s (%s)\n", resp.ID, resp.Status)
}

NewClient

Creates a new Pilot API client. Pass an empty string for authToken to skip authentication.

// With auth
client := pilot.NewClient("http://localhost:4320", "ey...")

// Without auth
client := pilot.NewClient("http://localhost:4320", "")

The Client struct exposes BaseURL, AuthToken, and HTTP (*http.Client) fields for customization.

MethodReturnsDescription
Health()*HealthStatus, errorCheck server health
ListPlaybooks(target)[]PlaybookSummary, errorList playbooks; pass "" for all
GetPlaybook(id)*Playbook, errorGet playbook by ID (latest version)
CreatePlaybook(req)*CreatePlaybookResponse, errorCreate a new playbook
UpdatePlaybook(id, req)*UpdatePlaybookResponse, errorUpdate (version-bump) a playbook
DeletePlaybook(id)*DeletePlaybookResponse, errorDelete all versions
StartRun(req)*StartRunResponse, errorStart a new run
ListRuns(opts)[]Run, errorList runs with optional filters
GetRun(id)*Run, errorGet run details including steps
AbortRun(id)*AbortRunResponse, errorAbort a running or queued run
ApproveRun(id, req)*ApproveResponse, errorSubmit approval decision for a step
ListProviders()[]Provider, errorList all provider profiles

Playbooks

// List all
playbooks, err := client.ListPlaybooks("")

// Filter by target
cfPlaybooks, err := client.ListPlaybooks("cloudflare")

// Get one
pb, err := client.GetPlaybook("cloudflare.dns.add-a-record")

// Create
resp, err := client.CreatePlaybook(&pilot.CreatePlaybookRequest{
	Target:     "cloudflare",
	Title:      "Add CNAME record",
	YAML:       playbookYAML,
	AuthoredBy: "human",
})

// Update
resp, err := client.UpdatePlaybook("cloudflare.dns.add-cname",
	&pilot.UpdatePlaybookRequest{YAML: updatedYAML})

// Delete
resp, err := client.DeletePlaybook("cloudflare.dns.add-cname")

Runs

// Start a run
inputs, _ := json.Marshal(map[string]string{
	"zone": "example.com",
	"record_name": "api",
	"ip_address": "1.2.3.4",
})
resp, err := client.StartRun(&pilot.StartRunRequest{
	PlaybookID:        "cloudflare.dns.add-a-record",
	Mode:              "interactive",
	Inputs:            inputs,
	ProviderProfileID: "cf-prod",
})

// Get run with steps
run, err := client.GetRun(resp.ID)
for _, step := range run.Steps {
	fmt.Printf("%s: %s\n", step.StepID, step.Status)
}

// List runs with filters
runs, err := client.ListRuns(&pilot.ListRunsOptions{
	Status: "running",
	Limit:  10,
})

// Abort
resp, err := client.AbortRun(runID)

// Approve a step
resp, err := client.ApproveRun(runID, &pilot.ApproveRequest{
	StepID:   "save",
	Decision: "approve",
})

Types

Core types

TypeKey fields
PlaybookID, Version, Target, Title, DocumentYAML, AuthoredBy, CreatedAt
PlaybookSummaryID, Version, Target, Title, AuthoredBy
RunID, ProjectID, PlaybookID, Mode, Status, InputsJSON, OutputsJSON, Steps []RunStep
RunStepID, RunID, StepID, Action, Status, AIUsed, DurationMs *int, ErrorMessage *string
ProviderID, ProjectID, Provider, Label, BaseURL, LastAuthenticated, ExpiresAt
HealthStatusStatus, Database, DriverPool, ProviderSessions, LastChecked

Request types

TypeFields
StartRunRequestPlaybookID, Version *int, Mode, Inputs json.RawMessage, ProviderProfileID, ProjectID
CreatePlaybookRequestTarget, Title, YAML, AuthoredBy
UpdatePlaybookRequestYAML, Target, Title, AuthoredBy
ApproveRequestStepID, Decision
ListRunsOptionsStatus, PlaybookID, Limit int

Error handling

The SDK returns *APIError for non-2xx responses. All other errors are standard Go errors from net/http or encoding/json.

import (
	"errors"
	pilot "github.com/cuitty/pilot-sdk-go"
)

resp, err := client.StartRun(&req)
if err != nil {
	var apiErr *pilot.APIError
	if errors.As(err, &apiErr) {
		fmt.Printf("API error %d: %s\n", apiErr.StatusCode, apiErr.Message)
	} else {
		fmt.Printf("Network error: %v\n", err)
	}
}
TypeFieldsWhen
*APIErrorStatusCode int, Message stringNon-2xx HTTP response
errorstandardNetwork, JSON, or other failure

See also