Developers · Go SDK + CLI

One-line AgentSmack from Go, GitHub Actions, or any CI pipeline.

go install …/cmd/agentsmack ships the typed client + standalone CLI in one repo. Wire-compatible with the TypeScript SDK and the Python SDK — same shapes, same verb names, same exit codes. Swap languages without changing your pipeline.

Install

# cli binary

go install github.com/shivemind/agentsmack/packages/sdk-go/cmd/agentsmack@latest

# library

go get github.com/shivemind/agentsmack/packages/sdk-go@latest

# homebrew (planned)

brew install shivemind/tap/agentsmack # planned

Go 1.22+. Tested against 1.22 - 1.26 on Linux, macOS, and Windows. Ships cmd/agentsmack as the CLI entry point and the top-level package as the library.

What it gives you

  • agentsmack.Client

    Wraps POST /api/submissions + GET /api/submissions/[slug] with typed Go structs, header injection, and polling. No interface{} at the boundary.

  • Three submission modes

    Structured paste, raw text (any of JSON/YAML/Markdown), or a public URL — populate AnalyzeRequest.SystemPrompt / Text / URL respectively.

  • Offline pack verification

    Pure-Go crypto/ed25519 + content-address re-derivation. Cross-language deterministic — a pack signed by the TS or Python SDK verifies in Go byte-for-byte (and vice versa).

  • CI/CD friendly

    `agentsmack analyze --wait --fail-on critical` returns non-zero so your pipeline fails the build on triggered probes. Same exit codes as the TS + Python CLIs.

  • Deterministic

    Injectable http.RoundTripper + injectable polling Sleep. Pin the SDK in your replay tests — same input, same call sequence, byte-for-byte.

  • Type-safe

    Typed errors (HTTPError, NetworkError, PollingTimeoutError, FindingsExceededError) with `errors.As`. `go vet ./...` clean. ed25519 verify is constant-time per the stdlib contract.

SDK quickstart

package main

import (
	"context"
	"fmt"
	"os"

	agentsmack "github.com/shivemind/agentsmack/packages/sdk-go"
)

func main() {
	c := agentsmack.NewClient(os.Getenv("AGENTSMACK_API_KEY"), "")
	// (api key is optional — anonymous submissions are allowed.)

	ctx := context.Background()
	result, err := c.Analyze(ctx, agentsmack.AnalyzeRequest{
		SystemPrompt: "You are a helpful assistant.",
		ToolList: []agentsmack.ToolDefinition{
			{Name: "search_web", Description: "Search the web"},
		},
		Model: "gpt-4o",
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	fmt.Println(result.PublicReportURL)

	// Block until honeypot + underground probes finish:
	final, err := c.WaitForCompletion(ctx, result.PublicSlug, agentsmack.PollingOptions{})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	fmt.Printf("honeypot blocked: %d/%d\n",
		final.Probes.Honeypot.Blocked, final.Probes.Honeypot.Total)
}

Fail the build on findings

Client.AnalyzeAndWait returns a typed *FindingsExceededError when any honeypot triggers or underground probe breaches at the chosen severity. Drop it into your CI step and the pipeline fails for you.

package main

import (
	"context"
	"errors"
	"fmt"
	"os"

	agentsmack "github.com/shivemind/agentsmack/packages/sdk-go"
)

func main() {
	c := agentsmack.NewClient("", "")
	_, err := c.AnalyzeAndWait(context.Background(), agentsmack.AnalyzeAndWaitOptions{
		Request: agentsmack.AnalyzeRequest{SystemPrompt: "..."},
		Wait:    true,
		FailOn:  agentsmack.SeverityHigh,
	})

	var findingsErr *agentsmack.FindingsExceededError
	if errors.As(err, &findingsErr) {
		fmt.Fprintf(os.Stderr, "Triggered %d probe(s) at %s\n",
			findingsErr.TriggeredCount, findingsErr.Threshold)
		os.Exit(1)
	}
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

Offline pack verification

Every paid-tier submission produces a signed governance pack (content-addressed packId + Ed25519 signature). The Go verifier is cross-language deterministic — a pack signed by the TS or Python SDK verifies in Go and vice versa, byte-for-byte. The cross-language anchor lives at packages/sdk-go/tests/cross_language_pin_test.go.

package main

import (
	"fmt"
	"os"

	agentsmack "github.com/shivemind/agentsmack/packages/sdk-go"
)

func main() {
	packBytes, _ := os.ReadFile("pack.json")
	sigHex, _ := os.ReadFile("pack.sig")
	pubHex, _ := os.ReadFile("workspace.pub")

	verdict := agentsmack.VerifyPack(agentsmack.VerifyPackInput{
		PackJSON:     packBytes,
		SignatureHex: string(sigHex),
		PublicKeyHex: string(pubHex),
	})

	if !verdict.Valid {
		fmt.Fprintf(os.Stderr, "AgentSmack pack invalid: %s\n", verdict.Reason)
		os.Exit(1)
	}
	fmt.Println(verdict.PackID, verdict.BundleDigest)
}

CLI

Same module, single static binary. The exit-code matrix matches the TS + Python CLIs exactly so a pipeline switching languages keeps the same gating logic. Credentials live in the same ~/.agentsmack/config.json file — log in once with any SDK, use all three.

Login

agentsmack login --api-key "$AGENTSMACK_API_KEY"

Analyze a local file

agentsmack analyze ./agent.json

CI/CD — fail the build

agentsmack analyze ./agent.json \
  --wait --fail-on high

Read from stdin

cat .cursorrules | agentsmack analyze -

Verify a downloaded governance pack

agentsmack verify ./pack.json \
  --signature-file ./pack.sig \
  --public-key-file ./workspace.pub

Next

  • /developers/sdk — same SDK in TypeScript / Node. Wire-compatible with this one.
  • /developers/sdk-python — same SDK in Python. Wire-compatible with this one.
  • /developers/mcp — register AgentSmack as an MCP server in Claude Desktop / Cursor.
  • /pricing — Pro-tier features include signed governance packs and the full honeypot battery.