Skip to content
SONOEDocs
EspañolESConsole

SDKs and clients

Sonoe doesn't need its own SDK: TypeSafe's official SDKs work with it unchanged, and any HTTP client works too.

TypeSafe's SDKs

Both SDKs read their configuration from the environment. To use Sonoe, set the base URL and a Sonoe key:

export TYPESAFE_BASE_URL="https://api.sonoeai.com"
export TYPESAFE_API_KEY="sk_sonoe_..."
export TYPESAFE_DEFAULT_MODEL="sonoe-latest"   # optional: the SDKs default to jev-latest, which Sonoe also accepts

Python

pip install typesafe-sdk
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

client = TypeSafeClient()  # or TypeSafeClient(api_key=..., base_url="https://api.sonoeai.com")
result = client.system_one(
    "I was charged twice. Please help ASAP.",
    {
        "refund": Noul(instructions="Does the customer want their money back?"),
        "tone": Choice(instructions="What is the tone?", criteria={"calm": None, "angry": None}),
        "urgency": Score(instructions="How urgent is this?", criteria=["low", "medium", "high"]),
    },
)
print(result.nouls["refund"].noul, result.choices["tone"].choice, result.scores["urgency"].score)
print(result.usage.input_tokens, result.request_id)

JavaScript and TypeScript

npm install @typesafe-ai/sdk
import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient(); // or new TypeSafeClient({ apiKey, baseURL: "https://api.sonoeai.com" })
const { answers, usage } = await client.systemOne({
  state: { document: "I was charged twice. Please fix this ASAP." },
  questions: {
    category: choice("What is this ticket about?", { billing: null, technical: null, other: null }),
    urgent: noul("Is it urgent?"),
    anger: score("How angry is the customer?", ["calm", "annoyed", "furious"]),
  },
});
console.log(answers.category.choice, answers.urgent.noul, answers.anger.score, usage);

What works

Tested with typesafe-sdk 0.7.5 and @typesafe-ai/sdk 0.7.0:

  • Noul, Choice and Score questions, and typed answers.
  • Sync and async clients (Python), withResponse() and request ids (JavaScript).
  • models.list().
  • zstd-compressed request bodies (the SDKs compress from 1 KiB on).
  • Automatic retries on 429 and 5xx, following Retry-After.
  • Errors as the SDKs' own exception classes (AuthenticationError, UnprocessableEntityError, RateLimitError…).

Images (image(), withAssets, box()) aren't supported: Sonoe reads text only and returns 422.

Any HTTP client

The API is plain JSON over HTTPS. Send Authorization: Bearer <key> and Content-Type: application/json:

import os
import requests

r = requests.post(
    "https://api.sonoeai.com/v1/systemone",
    headers={"Authorization": f"Bearer {os.environ['SONOE_API_KEY']}"},
    json={
        "model": "sonoe-latest",
        "state": "Help! My payouts have been failing for 3 days.",
        "questions": {"urgent": {"type": "noul", "instructions": "Is this urgent?"}},
    },
    timeout=10,
)
if r.status_code == 429:
    wait = int(r.headers.get("Retry-After", "10"))
r.raise_for_status()
print(r.json()["answers"]["urgent"]["noul"])

When you write your own client:

  • Retry 429 and 503 after Retry-After seconds (or a short backoff). Don't retry other 4xx.
  • Log the x-request-id header; it identifies the request if you need help.
  • Call Sonoe from your server only. The key must never reach a browser or an app.