---
name: TypeSafe
description: Use when building AI-powered software that needs structured decisions: routing requests, classifying content, scoring severity or sentiment, detecting patterns, or validating outputs. Reach for TypeSafe when you need typed answers and confidence scores instead of generated text, and when you want code to remain in control of the workflow.
metadata:
    mintlify-proj: typesafe
    version: "1.0"
---

# TypeSafe Skill

## Product summary

TypeSafe is a System One model platform for making fast, structured decisions in software. Jev is TypeSafe's flagship model. Send a `state` (text, JSON object, or array) and typed `questions` to the API endpoint `POST https://api.typesafe.ai/v1/systemone`; get back structured `answers` with probabilities and confidence scores. Use the Python SDK (`typesafe-sdk`), JavaScript SDK (`@typesafe-ai/sdk`), or HTTP API directly. Set `TYPESAFE_API_KEY` in your environment. The primary documentation is at https://docs.typesafe.ai.

## When to use

Use TypeSafe when your code needs to make a judgment about unstructured or semi-structured data and you want:

- **Typed, constrained answers** instead of generated text — route a ticket to a department, classify a document type, score severity on a scale you define.
- **Probability distributions and confidence** to decide when to act automatically, ask for confirmation, or escalate to a human.
- **Parallel evaluation** — ask many independent questions about the same input in one request without serial round trips.
- **Code in control** — keep your workflow deterministic and let the model handle only the judgment calls.

Specific tasks:

- **Intent routing**: Classify what a user is asking for and route to the right handler.
- **Ticket triage**: Classify department, score urgency/frustration, detect escalation signals.
- **Content classification**: Detect spam, phishing, PII, sentiment, topic, language.
- **Validation**: Check if extracted data is correct, if a tool call matches a request, if citations are supported.
- **Scoring**: Rate bug severity, customer satisfaction, candidate skill level, startup pitch quality.
- **Confidence-gated decisions**: Act automatically on high-confidence answers, ask for review on medium confidence, escalate low-confidence cases.

## Quick reference

### Question types

| Type | Use when | Returns | Example |
|------|----------|---------|---------|
| **Noul** | Yes/no judgment | `noul` (0–1 probability) | "Does this message request a refund?" |
| **Choice** | Pick one from a fixed set | `choice`, `probabilities`, `confidence` | "Which team: billing, technical, sales?" |
| **Score** | Position on an ordered spectrum | `score`, `legend`, `probabilities`, `confidence` | "Frustration level: calm, frustrated, angry?" |

### API request structure

```json
{
  "state": "string, object, or array of text",
  "model": "jev-latest",
  "questions": {
    "question_id": {
      "type": "noul|choice|score",
      "instructions": "Your question here",
      "criteria": { ... }
    }
  }
}
```

### Python SDK quick start

```python
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

with TypeSafeClient() as client:
    response = client.system_one(
        state="Your text or JSON object",
        questions={
            "is_urgent": Noul(instructions="Is this urgent?"),
            "department": Choice(
                instructions="Which team?",
                criteria={"billing": "...", "technical": "..."}
            ),
            "frustration": Score(
                instructions="How frustrated?",
                criteria=["calm", "frustrated", "angry"]
            ),
        },
    )

print(response.answers["is_urgent"].noul)
print(response.answers["department"].choice)
print(response.answers["frustration"].score)
```

### JavaScript SDK quick start

```javascript
import { TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient();
const response = await client.systemOne({
  state: "Your text or JSON object",
  questions: {
    is_urgent: { type: "noul", instructions: "Is this urgent?" },
    department: {
      type: "choice",
      instructions: "Which team?",
      criteria: { billing: "...", technical: "..." },
    },
  },
});

console.log(response.answers.is_urgent.noul);
console.log(response.answers.department.choice);
```

### Confidence thresholds

| Confidence | Action |
|------------|--------|
| < 0.5 | Route to human; model is genuinely uncertain |
| 0.5–0.8 | Proceed with caution; ask for confirmation or flag for review |
| > 0.8 | Act automatically; model has a clear read |

Adjust thresholds per action based on risk. High-stakes actions (approving transfers) need higher confidence than low-stakes ones (showing a screen).

## Decision guidance

### When to use Noul vs Choice vs Score

| Scenario | Type | Why |
|----------|------|-----|
| Yes/no judgment with no middle ground | Noul | Probability directly answers the question |
| Pick one from a known set of options | Choice | Options are unordered; you need the selected one |
| Position on a spectrum you can describe | Score | Levels are ordered; you need a position along them |
| Skill level (no experience → deep expertise) | Score | Ordered progression; can fall between levels |
| Refund requested (yes/no) | Noul | Clear binary; probability is the signal |
| Which category (A, B, or C) | Choice | Unordered options; one winner |

### When to ask one request vs multiple requests

| Scenario | Approach | Why |
|----------|----------|-----|
| Questions use the same state | One request | Parallel evaluation; barely slower; cheaper |
| Second question depends on first answer | Two requests | Need the first answer to build the second state or pick options |
| Speculative questions (only some matter) | One request | Ask all; let code ignore irrelevant answers |
| Many independent judgments | One request | Batch them; questions run in parallel |

### When to use structured state vs string

| Scenario | Format | Example |
|----------|--------|---------|
| Simple single text | String | `"My card was charged twice."` |
| Multiple related pieces | Object | `{"message": "...", "order_id": "A-104", "policy": "..."}` |
| Conversation or sequence | Array | `["Hi", "My issue is...", "Please help"]` |

Use objects for most requests so each part has a descriptive name.

## Workflow

### Typical task: build a ticket triage system

1. **Understand the input**: What data do you have? (ticket message, customer history, policies)

2. **Decompose the judgment**: Break broad decisions into atomic questions. Instead of "triage this ticket," ask: Is it urgent? Which department? How frustrated is the customer? Is it a phishing attempt?

3. **Structure the state**: Build a JSON object with only the context needed for the questions. Include the ticket message, relevant policies, customer plan, open orders — nothing more.

4. **Define questions**: Write one question per judgment. Use Noul for yes/no, Choice for routing, Score for severity/sentiment.

   ```python
   questions = {
       "is_urgent": Noul(instructions="Does the message convey urgency?"),
       "department": Choice(
           instructions="Which team should handle this?",
           criteria={"billing": "...", "technical": "...", "account": "..."}
       ),
       "frustration": Score(
           instructions="How frustrated is the customer?",
           criteria=["calm", "frustrated", "very angry"]
       ),
   }
   ```

5. **Make one request**: Send all questions together. They run in parallel.

   ```python
   response = client.system_one(state=state, questions=questions)
   ```

6. **Inspect answers**: Check the `choice`, `score`, and `noul` values. Check `confidence` on Choice and Score.

7. **Route by confidence**: Use confidence to decide whether to act automatically or escalate.

   ```python
   if response.answers["department"].confidence < 0.7:
       route_to_human(ticket)
   else:
       route_to_handler(response.answers["department"].choice, ticket)
   ```

8. **Combine signals in code**: If you need a composite score, weight the individual answers yourself.

   ```python
   priority = (
       0.5 * response.answers["is_urgent"].noul
       + 0.3 * (response.answers["frustration"].score / 2)
       + 0.2 * (1 if response.answers["department"].confidence > 0.8 else 0)
   )
   ```

## Common gotchas

- **Asking one question per request**: Questions run in parallel; batching them saves cost and time. Ask all questions that use the same state in one request.

- **Asking broad questions**: "Triage this ticket" hides multiple judgments. Decompose into atomic questions: Is it urgent? Which department? How frustrated? Combine answers in code.

- **Ignoring confidence**: Confidence tells you when the model is uncertain. Use it to decide whether to act automatically or escalate. Different actions need different thresholds.

- **Putting all context in state**: Include only what the questions need. Irrelevant context adds tokens and can distract the model.

- **Rewriting questions when priorities shift**: If you need to weight factors differently, change the weights in code, not the questions. Ask all factors as separate questions.

- **Treating Noul like a Score**: A Noul of 0.5 means the model is unsure, not that the answer is "medium." Use a Score if you need ordered levels.

- **Forgetting to reference nested state fields**: When state is a JSON object, point questions at specific fields using backtick paths: `"Does `ticket.message` request a refund?"` instead of relying on the model to find the right part.

- **Not handling rate limits**: The SDKs retry automatically with backoff. If calling the HTTP API directly, implement exponential backoff on `429 Too Many Requests` and `529 Overloaded`.

- **Sending images, audio, or video**: Jev accepts text only. Pre-process non-text inputs into text or structured fields.

- **Assuming English-only accuracy**: English is the primary training language. Other languages are supported but with lower accuracy; test on your own data.

## Verification checklist

Before submitting work with TypeSafe:

- [ ] Questions are atomic and specific, not broad or multi-part
- [ ] State includes only context needed for the questions
- [ ] All questions that use the same state are in one request
- [ ] Confidence thresholds are set per action based on risk
- [ ] Code handles low-confidence answers (route to human or escalate)
- [ ] Probabilities sum to 1 for each answer (sanity check)
- [ ] Choice criteria are mutually exclusive and exhaustive (or include "other")
- [ ] Score levels are ordered and clearly defined
- [ ] Noul questions are phrased as yes/no, not as scales
- [ ] API key is set in `TYPESAFE_API_KEY` environment variable
- [ ] Retry logic is in place (automatic with SDKs; manual for HTTP API)
- [ ] Response model field matches expected version or alias

## Resources

- **Full documentation**: https://docs.typesafe.ai/llms.txt — comprehensive page-by-page navigation for agents
- **API Reference**: https://docs.typesafe.ai/api — request/response shapes, error codes, rate limits
- **How to build with TypeSafe**: https://docs.typesafe.ai/concepts/how-to-build-with-system-one — workflow design, decomposition, confidence routing
- **Patterns**: https://docs.typesafe.ai/patterns — speculative fan-out, confidence-gated routing, composite scoring, intent routing

---

> For additional documentation and navigation, see: https://docs.typesafe.ai/llms.txt