DocsUse it from
JavaScript and TypeScript
Call a server from Node with fetch, in JavaScript or TypeScript, with no package.
A server is a JSON API, and fetch is built into Node 22, so JavaScript needs no package either.
The same script is shown in TypeScript, with the shape of an answer typed.
Figure · A JavaScript client
One POST out, one JSON answer back; the rest is reading it.
The numbers are the recorded decision's; a server on another base answers with its own.
Recorded decision: Gemma 4 31B, decisio 0.9.0, RTX PRO 6000 at 600 W, 2026-10-08; record 1 of 60 of decisio-examples' support-routing run; the probabilities are rounded to two places.
With a server running (Get started starts one), save this as ask.mjs and run node ask.mjs; it sends the recorded support ticket and prints each question’s likeliest option:
const body = { "state": "I was charged twice for October. Both charges are 49.00 EUR, same day. Please refund one.", "questions": { "urgent": { "type": "noul", "instructions": "Does this ticket need a response within the hour?" }, "queue": { "type": "choice", "instructions": "Which team should handle this ticket?", "criteria": { "billing": "Invoices, payments, refunds, prices, VAT", "access": "Login, passwords, two-factor, SSO, permissions, invitations, account security", "bug": "The product behaves wrongly: errors, crashes, wrong numbers, lost data", "feature": "A request for something the product does not do yet", "cancellation": "Cancelling, pausing or closing an account, deleting data", "other": "Press, partners, jobs, sales pitches, wrong address, thanks, general questions" } }, "impact": { "type": "score", "instructions": "Rate the business impact using only the reported facts.", "criteria": [ "No function impaired", "One user impaired, with a workaround", "Many users blocked from a core function", "Data loss or legal exposure" ] } }};
const response = await fetch("http://127.0.0.1:8000/v1/systemone", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body),});if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);const { answers } = await response.json();
for (const [name, answer] of Object.entries(answers)) { if (answer.type === "noul") { console.log(name, Number(answer.noul.toFixed(3))); } else { const [top, p] = Object.entries(answer.probabilities).sort((a, b) => b[1] - a[1])[0]; console.log(name, top, Number(p.toFixed(3))); }}// urgent 0.159// queue billing 0.962// impact 1 0.648Run against the CPU stand-in at v0.11.1 on 2026-10-14: the answers are the stand-in's, not the measured system's.
The comment lines show what the measured system answered (recorded; the stand-in prints other numbers).
Recorded decision: Gemma 4 31B, decisio 0.9.0, RTX PRO 6000 at 600 W, 2026-10-08; record 1 of 60 of decisio-examples' support-routing run; the printed probabilities are rounded to three places.
| Word | Meaning |
|---|---|
noul | a yes/no question; its answer is the probability of yes |
probabilities | a probability for each option of a choice, or each level of a score; they add up to 1 |
top-level await | await outside a function, which a .mjs file allows |
1. With fetch
Section titled “1. With fetch”The script posts the body as JSON and reads answers, which holds one answer per question under the name you gave it.
Check response.ok before reading: a request the server cannot read is answered with 422, and one the engine cannot answer with 400, each with a detail in the body.
2. In TypeScript
Section titled “2. In TypeScript”Types for the parts of the answer the script reads, and nothing else; Node 22 runs this file by stripping the types (node --experimental-strip-types ask.ts):
const body: { state: string; questions: Record<string, unknown> } = { "state": "I was charged twice for October. Both charges are 49.00 EUR, same day. Please refund one.", "questions": { "urgent": { "type": "noul", "instructions": "Does this ticket need a response within the hour?" }, "queue": { "type": "choice", "instructions": "Which team should handle this ticket?", "criteria": { "billing": "Invoices, payments, refunds, prices, VAT", "access": "Login, passwords, two-factor, SSO, permissions, invitations, account security", "bug": "The product behaves wrongly: errors, crashes, wrong numbers, lost data", "feature": "A request for something the product does not do yet", "cancellation": "Cancelling, pausing or closing an account, deleting data", "other": "Press, partners, jobs, sales pitches, wrong address, thanks, general questions" } }, "impact": { "type": "score", "instructions": "Rate the business impact using only the reported facts.", "criteria": [ "No function impaired", "One user impaired, with a workaround", "Many users blocked from a core function", "Data loss or legal exposure" ] } }};
const response = await fetch("http://127.0.0.1:8000/v1/systemone", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body),});if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);type Answer = { type: string; noul?: number; probabilities?: Record<string, number> };const { answers } = (await response.json()) as { answers: Record<string, Answer> };
for (const [name, answer] of Object.entries(answers)) { if (answer.type === "noul") { console.log(name, Number(answer.noul!.toFixed(3))); } else { const [top, p] = Object.entries(answer.probabilities!).sort((a, b) => b[1] - a[1])[0]; console.log(name, top, Number(p.toFixed(3))); }}// urgent 0.159// queue billing 0.962// impact 1 0.648Run against the CPU stand-in at v0.11.1 on 2026-10-14: the answers are the stand-in's, not the measured system's.
3. Where to run it
Section titled “3. Where to run it”The server has no authentication: the Authorization header and any API key are accepted and ignored.
Call it from code you run, a backend or a script, with the server on 127.0.0.1 or behind a reverse proxy that authenticates.
What next
Section titled “What next”- Python: the same call from Python.
- Frameworks: the JavaScript integrations that were checked.
- The HTTP API: every route, request field and response field.