Building against TypeSafe's Jev: the /v1/systemone HTTP API, the Python (`typesafe-sdk`) and JS (`@typesafe-ai/sdk`) SDKs, Noul/Choice/Score request and answer shapes, model ids and pinning, limits, pricing, retries, errors, gateways, and the framework integrations (Pydantic AI `TypeSafeModel`, LangChain `TypeSafeClassifier`, Vercel AI SDK, OpenRouter, LiteLLM, DSPy). USE WHEN: code imports `typesafe_sdk`, `@typesafe-ai/sdk`, `langchain_typesafe`, `@ai-sdk/typesafe-ai`, or uses `typesafe:jev...
Pro scans all 5 files and shows the line behind each finding
Scanned 10/3/2026
npx -y skills add claude-dev-suite/claude-dev-suite --skill typesafe-jev --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Typesafe Jev?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/claude-dev-suite-typesafe-jev)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: typesafe-jev
description: |
Building against TypeSafe's Jev: the /v1/systemone HTTP API, the Python
(`typesafe-sdk`) and JS (`@typesafe-ai/sdk`) SDKs, Noul/Choice/Score request
and answer shapes, model ids and pinning, limits, pricing, retries, errors,
gateways, and the framework integrations (Pydantic AI `TypeSafeModel`,
LangChain `TypeSafeClassifier`, Vercel AI SDK, OpenRouter, LiteLLM, DSPy).
USE WHEN: code imports `typesafe_sdk`, `@typesafe-ai/sdk`, `langchain_typesafe`,
`@ai-sdk/typesafe-ai`, or uses `typesafe:jev-latest`, `client.system_one`,
`client.systemOne`, `TYPESAFE_API_KEY`, `api.typesafe.ai`; user asks how to
call Jev, write Noul/Choice/Score questions, or wire Jev into an agent.
DO NOT USE FOR: deciding *whether* a typed decision model fits (load
`typed-decision-models`) or fitting/validating its probabilities (load
`decision-model-calibration`).
allowed-tools: Read, Grep, Glob, Write, Edit, Bash, WebFetch
---
# TypeSafe Jev — integration reference
Verified against docs.typesafe.ai, the OpenAPI spec, PyPI, npm and the
integration docs on **2026-10-03**. Versions at that date: `typesafe-sdk` 0.7.2,
`@typesafe-ai/sdk` 0.6.0, model `jev-1.13.0`, Pydantic AI 2.53.0,
`@ai-sdk/typesafe-ai` 3.0.12, `langchain-typesafe` 0.0.1a3 (alpha).
The SDKs are pre-1.0 and have shipped breaking changes in minor releases —
pin them.
Deeper material:
| File | Covers |
|---|---|
| `quick-ref/python-sdk.md` | sync/async clients, `response_model`, retries, exceptions, HTTP/2, logging, gateways |
| `quick-ref/javascript-and-http.md` | JS/TS SDK, raw HTTP with curl, OpenAPI quirks |
| `quick-ref/framework-integrations.md` | Pydantic AI, LangChain, Vercel AI SDK, OpenRouter, LiteLLM, DSPy, others |
| `quick-ref/question-design.md` | writing questions and state, the documented patterns and failure modes |
## Mental model
One request = one `state` (what is judged) + a map of named `questions` (what
is asked about it). Every question is answered independently against the same
state, in parallel. The question keys are yours and **are not sent to the
model** — only `instructions` and `criteria` are.
```
POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer $TYPESAFE_API_KEY
```
```json
{
"state": "Help! My payouts have been failing for 3 days.",
"model": "jev-latest",
"questions": {
"is_urgent": {"type": "noul", "instructions": "Does this convey urgency?",
"criteria": {"true": "Explicitly time-sensitive", "false": "No urgency expressed"}},
"department": {"type": "choice", "instructions": "Which team should handle this?",
"criteria": {"billing": "Payments, invoicing, refunds",
"technical": "Bugs, outages, integrations",
"sales": "Pricing, upgrades, new accounts"}},
"frustration": {"type": "score", "instructions": "How frustrated is the customer?",
"criteria": ["Calm", "Frustrated", "Very angry"]}
}
}
```
| Question | `criteria` | Answer fields |
|---|---|---|
| `noul` | optional `{"true": …, "false": …}` | `noul` (P(yes)) |
| `choice` | **required** map option → description or `null`; ≤ 255 options | `choice`, `probabilities` (option → float), `confidence` |
| `score` | **required** ordered array of level descriptions; 2–10 levels | `score` (float, can land between levels), `legend` ("0" → text), `probabilities` ("0" → float), `confidence` |
`state`, `instructions` and each criterion accept a string, object or array.
Response top level: `model` (the versioned id that answered), `answers`,
`usage.input_tokens`, `usage.output_tokens`. Request id: `x-typesafe-request-id`.
## Python quickstart
```bash
pip install typesafe-sdk # Python >= 3.10; extra: typesafe-sdk[http2]
export TYPESAFE_API_KEY=...
```
```python
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
client = TypeSafeClient()
state = "I was charged twice. Please help ASAP."
questions = {
"billing": Noul(instructions="Is this about billing?"),
"tone": Choice(
instructions="What is the tone?", criteria={"calm": None, "angry": None}
),
"urgency": Score(
instructions="How urgent is this?", criteria=["low", "medium", "high"]
),
}
result = client.system_one(state, questions)
print(
result.nouls["billing"].noul,
result.choices["tone"].choice,
result.scores["urgency"].score,
)
```
`result.answers[key]` holds every answer; `.nouls`, `.choices`, `.scores` are
typed views. In the SDK, `ScoreAnswer.probabilities` and `.legend` are keyed by
**int**; on the wire they are strings. `AsyncTypeSafeClient` has the same
surface. Full detail in `quick-ref/python-sdk.md`.
## JavaScript / TypeScript quickstart
```bash
npm install @typesafe-ai/sdk # Node.js 20+; ESM + CJS + .d.ts
```
```ts
import { choice, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient();
const response = 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,
}),
},
});
console.log(response.answers.category.choice);
```
Helpers: `noul(instructions?, criteria?)`, `choice(instructions, criteria)`,
`score(instructions, criteria)` (criteria typed as a tuple of ≥ 2). Answer types
are inferred from the questions. Browser use is refused unless
`dangerouslyAllowBrowser: true` — keep the key server-side.
## Models and pinning
| id | resolves to | meaning |
|---|---|---|
| `jev-latest` | `jev-1.13.0` | latest stable; SDK default |
| `jev-preview` | `jev-1.13.0` | latest build, official or not |
| `jev-1.13.0` | — | pinned |
The vendor's own rule: *"If you have tuned confidence thresholds against a
specific version, pin that version's ID instead of the alias."* Log
`response.model` on every call so an alias move is visible in your traces.
`GET /v1/models` lists aliases only; versioned ids are accepted regardless.
## Limits and pricing (as of 2026-10-03 — re-check, they move)
| Item | Value |
|---|---|
| Price | $0.042 per million **input** tokens; output tokens free |
| Rate limits | 100K tokens/s, 80 requests/s (was 40 req/s two weeks earlier); 429 on either |
| Context | 64k tokens for state + all questions; 32k for state + the single longest question |
| Choice | ≤ 255 options |
| Score | 2–10 levels (the OpenAPI spec and Python SDK enforce only "non-empty") |
| Input | text only; English primary, CJK "handled but not equally well" |
| Streaming | none |
| Sampling | none — no temperature/top_p |
| Hosting | US; no self-hosting; zero data retention for enterprise via sales |
| Training on your data | no (docs + privacy policy) |
The vendor states it cannot prove the price is not subsidised. Budget for it
going up.
## Errors and retries
| Status | Meaning |
|---|---|
| 401 | missing/invalid key |
| 422 | body failed validation; FastAPI-style `detail[]` names the field |
| 429 | rate limited — honour `retry-after` |
| 529 | overloaded — retry with backoff |
Both SDKs retry 408, 429 and 5xx twice by default with jittered exponential
backoff (0.5 s → 5 s) and honour `retry-after`. Python's `RetryPolicy.timeout`
(30 s) is a **total** budget; JS has a per-attempt timeout (10 s) and no total
budget — put an `AbortSignal` on latency-critical paths.
## Rules that prevent most bugs
1. **The prompt is the state; the question goes in `instructions`.** A question
written into the state is judged as text, not answered.
2. **One judgement per question.** Combine in code.
3. **Every Choice gets a catch-all** (`other` / `none of the above`) unless the
options are provably exhaustive — the model must pick something.
4. **Never threshold `choice` alone.** Read `confidence`/`probabilities`; for
Noul, the probability *is* the uncertainty.
5. **Keep arithmetic, counting and date comparison in code.** Ask Jev to
extract or pick; compute yourself.
6. **Treat state as attacker-controlled.** Prompt injection through the state
is documented as live. A Noul gating a destructive action is not an
authorization layer — pair it with human approval.
7. **Test option order** on any Choice that matters (the model leans toward the
first option). `decision-model-calibration` has a one-request rotation check.
8. **Don't send secrets in state** — it leaves your infrastructure.
## Official resources
- Docs: https://docs.typesafe.ai — full dump at `/llms-full.txt` (can lag the
live pages; append `.md` to any page path for its current markdown)
- OpenAPI: https://api.typesafe.ai/openapi.json · console: https://console.typesafe.ai
- Limitations: https://docs.typesafe.ai/model-jaggedness/jev-1.13
- Official agent skill: `claude plugin marketplace add typesafe-ai/skills`
- `typesafe-ai/system-one-adapter-python`: a drop-in `TypeSafeClient` backed by
ordinary LLM APIs — useful for comparing like-for-like through the same code
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!