Skip to content
Get API key

SDKs and compatibility

POST https://api.mouse.dev/v1/decisions is our primary neutral endpoint, and POST https://api.mouse.dev/v1/systemone is served as an identical alias that is wire-compatible with the TypeSafe System One request and response specification. You can call either route with zero dependencies using fetch / requests / httpx, or point an existing @typesafe-ai/sdk (TypeScript/JavaScript) or typesafe-sdk (Python) client at https://api.mouse.dev.

Every standard System One request and response field works unchanged:

  • Request fields: model ("mouse-1" or "mouse"), state (string, JSON object, or array), and questions (choice, noul, score with string or structured JSON instructions and criteria).
  • Response fields: answers keyed by your question IDs, returning choice / noul / score, probabilities, confidence, and legend, plus model and usage.
  • Mouse extensions (safely ignored by existing SDKs):
    • Request: optional calibration ("calp1.<kid>.<blob>") from POST /v1/calibrations.
    • Request: optional order_invariant: true (server-side permutation averaging for choice), and OpenAI Decisions field names (input, array questions, predicate, choices, levels) accepted as aliases.
    • Answer: logits and mouse: { calibrated, p_top, abstain, confidence_winning, confidence_normalized } on every answer; noul answers also carry probabilities: { false, true }.
    • Usage: itemized state_tokens, question_tokens, framing_tokens, cached_tokens, and cost_usd alongside input_tokens and output_tokens.
    • Top-level: id ("dec_..."), object ("systemone.response"), latency_ms, and optional warnings.

Because /v1/systemone is a single non-streaming JSON endpoint that completes in ~40–100 ms, a 15-line fetch or httpx helper gives you full access to both System One answers and Mouse calibration fields (mouse.abstain, usage.cost_usd):

export interface MouseMeta {
calibrated: boolean;
p_top: number;
abstain: boolean | null;
}
export async function decide<T extends Record<string, unknown>>(
state: unknown,
questions: T,
options?: { calibration?: string; signal?: AbortSignal },
) {
const res = await fetch("https://api.mouse.dev/v1/systemone", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MOUSE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "mouse-1",
state,
questions,
...(options?.calibration ? { calibration: options.calibration } : {}),
}),
signal: options?.signal ?? AbortSignal.timeout(3_000),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err?.error?.message ?? `Mouse HTTP ${res.status}`);
}
return res.json();
}
import os
import httpx
_client = httpx.Client(
base_url="https://api.mouse.dev",
headers={"Authorization": f"Bearer {os.environ['MOUSE_API_KEY']}"},
timeout=3.0,
)
def decide(state, questions: dict, calibration: str | None = None) -> dict:
payload = {"model": "mouse-1", "state": state, "questions": questions}
if calibration:
payload["calibration"] = calibration
res = _client.post("/v1/systemone", json=payload)
res.raise_for_status()
return res.json()

Using @typesafe-ai/sdk (TypeScript / JavaScript)

Section titled “Using @typesafe-ai/sdk (TypeScript / JavaScript)”

Install @typesafe-ai/sdk (Node.js 20+) and set baseURL to "https://api.mouse.dev" and defaultModel to "mouse-1":

npm install @typesafe-ai/sdk
import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient({
apiKey: process.env.MOUSE_API_KEY,
baseURL: "https://api.mouse.dev",
defaultModel: "mouse-1",
timeout: 3_000,
retry: { maxRetries: 1 },
});
const result = await client.systemOne({
state: {
task: "Rename parseToken to verifyToken in src/auth.ts",
command: "pnpm test",
},
questions: {
tool: choice("Which tool should run next?", {
edit: "Modify source code",
search: "Search repository",
ask: "Ask the user for clarification",
}),
safe: noul("Is `command` safe to run without user approval?"),
risk: score("How risky is `command`?", [
"Read-only or local test command",
"Modifies local workspace files",
"Pushes to remote or mutates external state",
]),
},
});
// Answer types are inferred from the question map:
// result.answers.tool.choice has type "edit" | "search" | "ask"
console.log(result.answers.tool.choice, result.answers.tool.confidence);
console.log(result.answers.safe.noul);
console.log(result.answers.risk.score);

Install typesafe-sdk (Python 3.10+) and pass base_url="https://api.mouse.dev" and model="mouse-1":

pip install typesafe-sdk
import os
from typesafe_sdk import AsyncTypeSafeClient, Choice, Noul, Score, TypeSafeClient
with TypeSafeClient(
api_key=os.environ["MOUSE_API_KEY"],
base_url="https://api.mouse.dev",
model="mouse-1",
) as client:
response = client.system_one(
state="Customer says: my card was charged twice for order #1042.",
questions={
"intent": Choice(
instructions="Which team should handle this?",
criteria={
"billing": "Duplicate charges, invoices, or refunds",
"shipping": "Delivery status or tracking",
"account": "Login or profile settings",
},
),
"refund_requested": Noul(
instructions="Does the customer ask for a refund?",
),
},
)
print(response.answers["intent"].choice, response.answers["intent"].confidence)
print(response.answers["refund_requested"].noul)

For async Python services (FastAPI, asyncio workers), use AsyncTypeSafeClient with the same base_url="https://api.mouse.dev" and model="mouse-1" parameters.