TypeSafe API SDK

September 20, 2026 · View on GitHub

TypeSafe API SDK

Hex.pm HexDocs GitHub License

TypeSafe API SDK

Building with System One semantics? New application code should use system_one_sdk, the provider-neutral Elixir/BEAM SDK. typesafe_api_sdk is the TypeSafe-specific API/provider SDK used by its built-in TypeSafe provider.

Fast, reliable, and strongly typed Elixir client for TypeSafe AI's System One API.

Instead of writing fragile string prompts, wrestling with token limits, or parsing unstructured JSON out of an LLM, typesafe_api_sdk gives you direct, probabilistic machine intelligence over structured data:

  1. Provide your application state (a customer message, document, or structured map).
  2. Ask targeted questions using typed primitives (Noul, Choice, and Score).
  3. Receive validated Elixir structs with exact probabilities and answers.

Execution is powered by Pristine for rock-solid HTTP/2 connection pooling, automatic retries with exponential backoff, and cooperative request cancellation.


Quick Example

# 1. Initialize your client
client = TypeSafeAPISDK.new_client(api_key: System.fetch_env!("TYPESAFE_API_KEY"))

# 2. Define questions with native wire primitives
questions = %{
  billing: TypeSafeAPISDK.noul(
    instructions: "Is this inquiry primarily about billing, invoices, or payment methods?"
  ),
  routing: TypeSafeAPISDK.choice(
    %{
      "tier1" => "Standard questions, password resets, basic FAQ",
      "engineering" => "Bug reports, API failures, infrastructure outages",
      "finance" => "Charge disputes, refunds, tax inquiries"
    },
    instructions: "Which team is best equipped to resolve this?"
  ),
  urgency: TypeSafeAPISDK.score(
    ["low", "medium", "critical"],
    instructions: "How urgent is the customer's request?"
  )
}

# 3. Query the model with your context
{:ok, response} = TypeSafeAPISDK.system_one(
  client,
  "Customer reports: 'Our production webhook endpoint received 500s during checkout.'",
  questions
)

# 4. Access typed answers directly
response.answers["billing"].noul           #=> false
response.answers["routing"].choice         #=> "engineering"
response.answers["urgency"].score          #=> "critical"
response.usage.input_tokens                #=> 42

Key Highlights

  • Typed Wire Primitives: First-class structs for every question type (Noul, Choice, Score) and answer type (NoulAnswer, ChoiceAnswer, ScoreAnswer). No string extraction or schema guessing.
  • Production-Ready HTTP Substrate: Executes on Pristine using Finch connection pools, HTTP/2 multiplexing, and jittered exponential backoff.
  • Resilient Retry Handling: Automatic handling of transient 429 rate limits, 5xx server errors, and explicit server Retry-After headers.
  • Cooperative Cancellation: Full integration with Pristine.Cancellation tokens so you can safely cancel running requests when client timeouts fire or callers disconnect.
  • Committed OpenAPI Code Generation: Core operations and schemas are generated from reviewed TypeSafe OpenAPI specifications for exact wire fidelity.

Installation

Add typesafe_api_sdk to your list of dependencies in mix.exs:

def deps do
  [
    {:typesafe_api_sdk, "~> 0.1.0"}
  ]
end

Before Hex publication or in local development, use a path dependency:

def deps do
  [
    {:typesafe_api_sdk, path: "../typesafe_api_sdk"}
  ]
end

Question Types

TypeSafe System One answers questions probabilistically over your input state. Three fundamental primitives cover virtually any operational decision:

1. Noul (Boolean / Binary Decision)

Use noul/1 when you need a definitive yes/no or true/false answer:

question = TypeSafeAPISDK.noul(
  instructions: "Does this message contain a request to cancel an account?"
)

2. Choice (Categorical Routing)

Use choice/2 when selecting one category from a defined set of options:

question = TypeSafeAPISDK.choice(
  %{
    "en" => "English language text",
    "es" => "Spanish language text",
    "fr" => "French language text"
  },
  instructions: "What language is this text written in?"
)

3. Score (Ordered Spectrum)

Use score/2 when evaluating quality, urgency, or sentiment along an ordered scale:

question = TypeSafeAPISDK.score(
  ["minor", "moderate", "severe"],
  instructions: "Assess the severity of the reported issue."
)

Discovering Models

TypeSafe regularly updates and optimizes its System One models. You can query available models at runtime:

{:ok, catalog} = TypeSafeAPISDK.list_models(client)

for model <- catalog.models do
  IO.puts("#{model.name}: #{model.description} (released: #{model.release_date})")
end

By default, the SDK targets the jev-latest alias. You can override the default model on the client or per-request.


Configuration

Clients can be configured with an explicit options keyword list or via application environment:

client = TypeSafeAPISDK.new_client(
  api_key: "ts_live_...",
  base_url: "https://api.typesafe.ai",    # default
  model: "jev-latest",                   # default
  timeout_ms: 10_000,                     # 10s default
  retry: [max_retries: 2]                 # 2 retries default
)

Environment Variables

When running as the root Mix application, config/runtime.exs automatically picks up:

VariableDescriptionDefault
TYPESAFE_API_KEYYour TypeSafe bearer API keyRequired
TYPESAFE_BASE_URLRoot URL for the TypeSafe APIhttps://api.typesafe.ai
TYPESAFE_DEFAULT_MODELDefault model aliasjev-latest
TYPESAFE_LOG_LEVELLogger level for API operations:info

Runtime Controls & Resiliency

Every API call accepts per-request overrides for timeouts, custom retries, and cancellation:

# Create a cancellation token
cancellation = Pristine.Cancellation.new()

# Execute request with custom overrides
task = Task.async(fn ->
  TypeSafeAPISDK.system_one(
    client,
    order_data,
    questions,
    model: "jev-latest",
    timeout_ms: 3_000,
    retry: [max_retries: 1],
    extra_headers: %{"X-Trace-ID" => "req_abc123"},
    cancellation: cancellation
  )
end)

# Cooperatively cancel if needed
# Pristine.Cancellation.cancel(cancellation)
result = Task.await(task)

Architecture & Ecosystem Role

typesafe_api_sdk is intentionally designed as a lean, focused provider client. It sits directly on the Pristine runtime:

       ┌──────────────────────────────┐
       │      Application / Domain    │
       └──────────────┬───────────────┘


       ┌──────────────────────────────┐
       │   system_one_sdk (Planned)   │  ◄── Orchestration, batching, OTP workflows
       └──────────────┬───────────────┘


 ┌──────────────────────────────────────────┐
 │             typesafe_api_sdk             │  ◄── Wire models, bearer auth,
 │  ┌────────────────────────────────────┐  │      OpenAPI schemas, status normalization
 │  │        Pristine HTTP Engine        │  │
 │  └─────────────────┬──────────────────┘  │
 └────────────────────┼─────────────────────┘


         [ TypeSafe System One API ]
  • typesafe_api_sdk owns: TypeSafe OpenAPI operations, schemas, bearer authentication, wire structs (Noul, Choice, Score), response decoding, and status normalization.
  • Higher-level libraries own: Domain-specific decision workflows, evaluation harnesses, speculative fan-out, batch pipelines, and OTP GenServers.

Live Verification

The real-service matrix deliberately separates official TypeSafe credentials from alternate-deployment credentials:

export TYPESAFE_API_KEY='...'
bash scripts/live_qc.sh official

The official matrix exercises both /v1/models and /v1/systemone, Noul, Choice, Score, tuple and bang APIs, explicit/default model selection, request metadata, and safe per-call controls. A separate opt-in alternate matrix verifies arbitrary TypeSafe-compatible API roots (including deployment path prefixes) with a credential issued for that exact root.

export TYPESAFE_LIVE_ALT_BASE_URL='https://provider.example/deployment/root'
export TYPESAFE_LIVE_ALT_API_KEY='...'
bash scripts/live_qc.sh alternate

See guides/live-verification.md for the complete coverage matrix, including which failure/control paths are tested deterministically rather than manufactured against a billable production service.


Development & Maintenance

Clone the repository and fetch dependencies:

mix deps.get
mix test

Running the Quality Gate

The quality gate validates formatting, strict Credo linter rules, Dialyzer types, documentation generation, and Hex packaging:

bash scripts/check_handoff.sh

OpenAPI Refresh & Codegen

Generated code is committed directly to source control. To regenerate or verify the OpenAPI definitions against Pristine's codegen tools:

source scripts/ensure_tooling.sh
mix typesafe_api.verify --project-root .

License

typesafe_api_sdk is open source software released under the MIT License.