typesafe-sdk-go

September 21, 2026 · View on GitHub

ci Go Reference Docs License: MIT

An unofficial Go SDK for TypeSafe. Full docs: typesafe-sdk-go.mintlify.site.

typesafe-sdk-go gives Go applications access to the same SystemOne question-answering workflow that exists in the official Python and JavaScript SDKs: typed choice, score, and noul questions, a typed answer union, and model discovery.

Why This Exists

TypeSafe ships official SDKs for Python and JavaScript, but there is no first-class Go SDK today. This project fills that gap with a Go-native client, built to the same wire contract as the other two.

This project is unofficial and is not affiliated with or endorsed by TypeSafe. If an official Go SDK lands upstream, this repo should ideally become unnecessary.

Status

This project is in beta.

  • Both API endpoints (/v1/systemone, /v1/models) are implemented.
  • go test ./... passes against local fixtures with no network access.
  • A live test (live_test.go) is verified against the real API and runs in CI when TYPESAFE_API_KEY is set.
  • The SDK is checked against the upstream OpenAPI spec, committed at openapi.json.

Requirements

  • Go 1.21+
  • A TypeSafe API key

Installation

go get github.com/atharvamhaske/typesafe-sdk-go

See the quickstart for a walkthrough.

Quickstart

export TYPESAFE_API_KEY=sk-...
package main

import (
	"context"
	"fmt"
	"log"

	typesafe "github.com/atharvamhaske/typesafe-sdk-go"
)

func main() {
	client, err := typesafe.NewClient() // reads TYPESAFE_API_KEY
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.SystemOne(context.Background(),
		"I was charged twice. Please refund the duplicate charge today.",
		map[string]typesafe.Question{
			"category": typesafe.Choice{
				Instructions: "Categorize the message",
				Criteria:     map[string]string{"billing": "Billing issue", "technical": "Technical issue"},
			},
			"urgency": typesafe.Score{
				Instructions: "Rate urgency",
				Criteria:     []string{"Can wait", "Needs attention"},
			},
			"is_dupe": typesafe.Noul{
				Instructions: "Is this a duplicate charge?",
				Criteria:     map[string]string{"true": "Duplicate", "false": "Not a duplicate"},
			},
		})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.Choices()["category"].Choice) // "billing"
	fmt.Println(resp.Scores()["urgency"].Score)    // 1.7
	fmt.Println(resp.Nouls()["is_dupe"].Noul)      // 0.98
}

Feature Coverage

SystemOne

  • Typed Choice, Score, and Noul question builders
  • Typed answer union, decoded from the API's discriminated response
  • Per-call model override with WithRequestModel
  • Token usage on every response

Models

  • List available models with ListModels

Package Overview

For full API documentation, see the docs site, api.md, or pkg.go.dev.

The public surface is organized around one handle:

  • Client for both SystemOne and ListModels, configured with functional options

Configuration

OptionEnv varPurpose
WithAPIKeyTYPESAFE_API_KEYAPI key, required
WithBaseURLTYPESAFE_BASE_URLAPI base URL, defaults to https://api.typesafe.ai
WithModelTYPESAFE_DEFAULT_MODELDefault model, defaults to jev-latest
WithHTTPClientUnderlying *http.Client
WithMaxRetriesRetries for network errors, 429s, and 5xxs, honoring Retry-After. Default 3
WithCacheOpt-in in-memory cache for SystemOne responses, keyed by request body. Disabled by default

Error Handling

Non-2xx responses return *typesafe.Error:

FieldPurpose
StatusCodeHTTP status code
DetailValidation detail, when the API returns one
BodyRaw response body

Examples

Runnable examples live in examples/ and are walked through on the examples page:

TYPESAFE_API_KEY=... go run ./examples/systemone
TYPESAFE_API_KEY=... go run ./examples/listmodels
TYPESAFE_API_KEY=... go run ./examples/spamfilter   # Noul spam/moderation classifier
TYPESAFE_API_KEY=... go run ./examples/prlabel      # Choice-based PR/diff labeler
TYPESAFE_API_KEY=... go run ./examples/gamemove     # Choice-based game move picker

Verified Against the Live API

The raw endpoint via curl:

$ curl -s https://api.typesafe.ai/v1/systemone \
    -H "Authorization: Bearer $TYPESAFE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"state":"I was charged twice. Please refund the duplicate charge today.",
         "model":"jev-latest",
         "questions":{"category":{"type":"choice","instructions":"Categorize the message",
           "criteria":{"billing":"Billing issue","technical":"Technical issue"}}}}'
{
  "model": "jev-1.13.0",
  "answers": {
    "category": {
      "type": "choice",
      "choice": "billing",
      "confidence": 1.0,
      "probabilities": {"billing": 1.0, "technical": 0.0}
    }
  },
  "usage": {"input_tokens": 319, "output_tokens": 31}
}

The same call through the SDK:

$ TYPESAFE_API_KEY=... go run ./examples/systemone
category: billing (confidence 1.00)
urgency:  1.00
is_dupe:  0.66
usage:    381 in / 64 out

SystemOne and ListModels examples running against the live TypeSafe API

Use with Braintrust

trace/contrib/typesafe automatically traces every SystemOne call through typesafe.WithHTTPClient, matching the span shape the official Python and JS TypeSafe integrations use. It is not merged upstream yet, so install it from the fork branch:

go get github.com/atharvamhaske/braintrust-sdk-go/trace/contrib/typesafe@feat/typesafe-tracing

See the Use with Braintrust docs page for the field reference, and examples/braintrust for a full runnable example. That example has its own go.mod, so braintrust-sdk-go and OpenTelemetry stay out of the core SDK's dependency graph.

cd examples/braintrust
BRAINTRUST_API_KEY=... TYPESAFE_API_KEY=... go run .

Testing

go test ./...                                    # fixture tests, no network
TYPESAFE_API_KEY=... go test ./...               # includes the live API test

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md.

If you want to extend surface area or align behavior with the upstream SDKs, opening an issue first is helpful so the API shape can stay coherent.

Relationship to Upstream

This repository exists because there is no official Go SDK at the time of writing. If the TypeSafe team decides to ship or adopt one upstream, aligning this project with that effort would be the best long-term outcome.

References

License

MIT. See LICENSE.