TypeScript-Guide
OpenAI Decisions API in TypeScript
OpenAI hat kein SDK für seine Decisions API veröffentlicht — es gibt kein client.decisions.create zum Kopieren. Diese Seite zeigt funktionierendes, vollständig typisiertes TypeScript für den Endpoint dieser Seite — eine aufrufbare OpenAI-Decisions-API-Alternative, die decisions-1 liefert und demselben eingeschränkten Entscheidungsmuster folgt.
Aktualisiert
Den Vertrag definieren
Tipisiere den Request einmal und verwende ihn überall. model ist eine Literal-Union, die gepinnte ID wird nie zum Tippfehler. questions ist ein Record, der über deine IDs indiziert ist, jeweils vom Typ noul, choice oder score.
Tipisiere die Antworten als discriminated union über type — genau das macht die Antwortverarbeitung sicher: eine noul-Antwort hat noul, eine choice-Antwort hat choice und probabilities — das Eingrenzen auf type liefert die richtigen Felder.
TypeScript
interface DecisionQuestion {
type: 'noul' | 'choice' | 'score'
instructions: string
criteria?: Record<string, string> | string[]
}
interface DecisionRequest {
model: 'decisions-1' | 'decisions-latest'
state: string | Record<string, unknown> | unknown[]
questions: Record<string, DecisionQuestion>
}
interface DecisionAnswers {
[questionId: string]:
| { type: 'noul'; noul: number }
| { type: 'choice'; choice: string; probabilities: Record<string, number>; confidence: number }
| { type: 'score'; score: number; legend: string[]; probabilities: Record<string, number>; confidence: number }
}Den Call ausführen
Ein einzelner POST mit Bearer-Schlüssel. satisfies DecisionRequest prüft den Body zur Compile-Zeit; AbortSignal.timeout verhindert, dass hängende Calls die Pipeline blockieren. Grenze answers vor dem Lesen über das type-Feld ein.
TypeScript
const res = await fetch('https://decisions-api.net/api/v1/decisions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(request satisfies DecisionRequest),
signal: AbortSignal.timeout(30000),
})
const { answers } = (await res.json()) as { answers: DecisionAnswers }
const team = answers.team
if (team.type === 'choice' && team.confidence >= 0.7) {
routeTo(team.choice)
}Timeouts und Retries
429 und 502 lohnen einen kurzen Backoff-Retry — fehlgeschlagene Calls werden nicht berechnet. 402 heißt Guthaben leer: aufladen, nicht erneut versuchen. 422 ist ein Validierungsfehler; die Meldung nennt das Feld, also korrigiere den Body statt zu wiederholen.
TypeScript
async function decide(body: DecisionRequest, attempts = 3): Promise<DecisionAnswers> {
for (let i = 0; i < attempts; i++) {
const res = await fetch('https://decisions-api.net/api/v1/decisions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000),
})
if (res.status === 429 || res.status === 502) {
await new Promise(r => setTimeout(r, 2 ** i * 1000))
continue
}
if (res.status === 402) throw new Error('out of credits')
if (!res.ok) throw new Error(`decision call failed: ${res.status}`)
return (await res.json() as { answers: DecisionAnswers }).answers
}
throw new Error('decision call failed')
}Den Call in einen Helper kapseln
Aufrufer sollten eine Funktion sehen, die Text nimmt und ein Label zurückgibt — keine HTTP-Details. Timeout, 402-Check und Retry-Schleife einmal in decide() legen, und jede Aufrufstelle bleibt sauber.
TypeScript
// Keep the call behind one typed function — timeouts, 402s,
// and retries live inside it, not at every call site.
export async function routeTicket(text: string): Promise<string> {
const answers = await decide({
model: 'decisions-1',
state: text,
questions: {
team: {
type: 'choice',
instructions: 'Which team should own this ticket?',
criteria: {
payments: 'Checkout or billing.',
frontend: 'Rendering or browser behavior.',
account: 'Login or permissions.',
},
},
},
})
const team = answers.team
return team.type === 'choice' && team.confidence >= 0.7 ? team.choice : 'triage'
}FAQ
Gibt es ein offizielles OpenAI-SDK-Beispiel für die Decisions API?
Nein. OpenAI hat weder SDK-Methoden noch ein Request-Schema für seine Decisions API veröffentlicht — alles mit client.decisions.create ist erfunden. Diese Seite nutzt schlichtes HTTP.
Brauche ich einen Code-Generator für die Typen?
Nein — die Interfaces auf dieser Seite decken den gesamten Vertrag ab. Kopiere sie in dein Projekt; sie sind klein genug zum Prüfen und mit deinem Code versionierbar.
Wie sende ich strukturierten Kontext?
state akzeptiert ein JSON-Objekt oder -Array, nicht nur einen String — übergib dicts direkt im json-Body; das Modell liest sie als Kontext.
Eine Entscheidung im Browser ausführen
Ganz ohne Setup — führe einen echten Call im Playground mit 1 kostenlosem Credit für neue Besucher aus.