DocsUse it from
Frameworks
LangChain, the Vercel AI SDK, n8n, TanStack AI and Pipecat, each checked against a running server: what to set, and what to know.
Five third-party integrations of TypeSafe’s wire format were run against a decisio server (Gemma 4 31B, decisio 0.9.0, from a Mac through an SSH tunnel, 2026-10-08); every check passed. They are plumbing checks: the client sends a request, the server answers, the client parses it. They say nothing about accuracy, and each is written and maintained by someone else.
Figure · Frameworks
Five integrations, each checked against a running server.
- LangChain0.0.1a342 of 42 checks passedbase URL has no
/v1 - Vercel AI SDKai 7.0.131, @ai-sdk/typesafe-ai 3.0.1542 of 42 checks passedbase URL ends in
/v1 - n8nn8n 2.35.7, n8n-nodes-jev 0.2.344 of 44 checks passedbase URL has no
/v1 - TanStack AI@tanstack/ai 0.65.1, @tanstack/ai-typesafe 0.1.839 of 39 checks passedbase URL has no
/v1 - Pipecatpipecat-ai 1.12.039 of 39 checks passedbase URL has no
/v1
They are plumbing checks of the wire format, not of accuracy.
Source: the README's "Works with" table, and each integration's README in decisio-examples.
Every integration needs the same three things, in its own spelling:
base URL http://127.0.0.1:8000 (the Vercel AI SDK's provider wants http://127.0.0.1:8000/v1)API key any string (every integration requires one; the server ignores it)model decisio-gemma-4-31b-it-letters (the name GET /v1/models lists; the server ignores it)A shape to fill in, not a command to run.
| Word | Meaning |
|---|---|
| integration | a package written and maintained by someone else that speaks System One |
| plumbing check | a run that sends requests and parses answers, to see that the pieces fit; it does not measure accuracy |
| abstention | a server run with --abstain-option can answer the best of the other options when its “can’t tell” option is the likeliest; most of the integrations drop the two fields that say so (n8n with Simplify Output off, and Pipecat’s client, pass them through), and that was emulated, not seen on a real abstaining server |
1. LangChain
Section titled “1. LangChain”Python 3.12; langchain-typesafe, 0.0.1a3: 42 of 42 checks passed against a running server (the check and its record). It uses TypeSafeClassifier.
- Base URL
- no /v1: the class appends it; the base_url argument or TYPESAFE_BASE_URL
- API key
- required: a dummy one works (ValueError without)
- If the server answers 422
- TypeSafeUnprocessableEntityError, status 422, the server's detail on its body; not retried
- Timeout and retries
- 30 seconds, no retries
from langchain_typesafe import TypeSafeClassifier
classifier = TypeSafeClassifier(base_url="http://127.0.0.1:8000", api_key="unused")A shape to fill in, not a command to run.
Nothing broke. The class marks itself beta and logs a warning when built. It checks a question before sending (a choice with no options never reaches the server), and it drops the abstention fields, so a caller cannot tell that a server abstained.
2. Vercel AI SDK
Section titled “2. Vercel AI SDK”Node 22; ai + @ai-sdk/typesafe-ai, ai 7.0.131, @ai-sdk/typesafe-ai 3.0.15: 42 of 42 checks passed against a running server (the check and its record). It uses createTypeSafeAi(...).decisionModel(...) with experimental_decide.
- Base URL
- must end in /v1 (http://host:port/v1); TYPESAFE_AI_BASE_URL is read when the provider is created
- API key
- required: apiKey or TYPESAFE_AI_API_KEY (LoadAPIKeyError without)
- If the server answers 422
- APICallError, statusCode 422, not retryable; the message is the server's detail as JSON
- Timeout and retries
- none set (Node's fetch defaults apply); maxRetries 2 for retryable failures
import { createTypeSafeAi } from "@ai-sdk/typesafe-ai";
const typesafe = createTypeSafeAi({ baseURL: "http://127.0.0.1:8000/v1", apiKey: "unused" });const model = typesafe.decisionModel("decisio-gemma-4-31b-it-letters");A shape to fill in, not a command to run.
The one real difference from the other integrations is that baseURL needs /v1; without it the call fails loudly with a 404. The decision function throws if the chosen option is not the most probable one, which a server run with --abstain-option can produce; that case was emulated, not seen on a real abstaining server.
3. n8n
Section titled “3. n8n”Node 22 (n8n 2.42 and later need Node 24 and were not run); n8n-nodes-jev, n8n 2.35.7, n8n-nodes-jev 0.2.3: 44 of 44 checks passed against a running server (the check and its record). It uses the community node's credential and its decision nodes.
- Base URL
- the credential's Base URL, with no /v1; its default is the hosted address, so a self-hosted server changes it
- API key
- required in the credential: any string
- If the server answers 422
- a NodeApiError with httpCode 422 and the server's detail; with Continue on Error the detail is only in the item's error object
- Timeout and retries
- none unless added under Options; retries only on 429 and 529
Nothing broke. Simplify Output is on by default and returns one flat value per question, so probabilities, legend and usage are dropped; turn it off to get the server's response unchanged.
4. TanStack AI
Section titled “4. TanStack AI”Node 22; @tanstack/ai + @tanstack/ai-typesafe, @tanstack/ai 0.65.1, @tanstack/ai-typesafe 0.1.8: 39 of 39 checks passed against a running server (the check and its record). It uses createTypesafeDecider(...) with decide().
- Base URL
- no /v1: the adapter posts to {baseURL}/v1/systemone; there is no environment variable for it
- API key
- required: createTypesafeDecider takes it directly, typesafeDecider reads TYPESAFE_API_KEY
- If the server answers 422
- an Error whose message starts "TypeSafe evaluate request failed: 422 Unprocessable Entity" and carries the body; not retried
- Timeout and retries
- none set (Node's fetch defaults apply); no retries
import { createTypesafeDecider } from "@tanstack/ai-typesafe";
const adapter = createTypesafeDecider("decisio-gemma-4-31b-it-letters", "unused", { baseURL: "http://127.0.0.1:8000" });A shape to fill in, not a command to run.
Nothing broke. A base URL ending in /v1 posts to /v1/v1/systemone and fails with a 404, the opposite of the Vercel AI SDK's provider. The adapter drops the abstention fields and the x-decisio response headers.
5. Pipecat
Section titled “5. Pipecat”Python 3.12; pipecat-ai[jev], pipecat-ai 1.12.0: 39 of 39 checks passed against a running server (the check and its record). It uses JevClient and JevClassifier in pipecat.classifiers.jev.
- Base URL
- no /v1; always pass base_url, because the default is the hosted address
- API key
- required: JevClient(api_key="") raises ValueError
- If the server answers 422
- ClassifierError "HTTP 422"; the server's detail is discarded
- Timeout and retries
- 10 seconds; 3 retries, on 429 and 529 only
from pipecat.classifiers.jev import JevClient
client = JevClient(api_key="unused", base_url="http://127.0.0.1:8000")A shape to fill in, not a command to run.
Nothing broke. A 422 loses its reason (only "HTTP 422" is raised), the default timeout is short at 10 seconds, and the classifier's results leave out the abstention fields.
What next
Section titled “What next”- System One clients: the differences that matter once a client is pointed at the server.
- Python and JavaScript and TypeScript: the same call without a framework.
- The HTTP API: every route, request field and response field.