Guide TypeScript

OpenAI Decisions API en TypeScript

OpenAI n'a pas publié de SDK pour sa Decisions API — il n'y a pas de client.decisions.create à copier. Cette page montre du TypeScript fonctionnel et entièrement typé pour l'endpoint de ce site — une alternative appelable à l'OpenAI Decisions API qui sert decisions-1 et suit le même motif de décision contrainte.

Mis à jour

Définir le contrat

Typez la requête une fois et réutilisez-la partout. model est une union de littéraux, l'id épinglé ne peut pas dériver en coquille. questions est un record indexé par vos ids, chacun de type noul, choice ou score.

Typez les réponses comme une union discriminée par type — c'est ce qui rend le traitement sûr : une réponse noul a un champ noul, une choice a choice et probabilities — le filtrage par type vous donne les bons champs.

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 }
}

Faire l'appel

Un seul POST avec une clé Bearer. satisfies DecisionRequest vérifie le corps à la compilation ; AbortSignal.timeout empêche les appels bloqués de figer le pipeline. Filtrez answers par le champ type avant de les lire.

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 et retries

429 et 502 méritent un retry court avec backoff — les appels échoués ne sont pas facturés. 402 signifie solde vide : rechargez, ne réessayez pas. 422 est une erreur de validation ; le message nomme le champ, corrigez donc le corps plutôt que de réessayer.

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')
}

Garder le fournisseur derrière une fonction

L'appelant doit voir une fonction typée qui prend du texte et renvoie une étiquette — pas des détails HTTP. Quand OpenAI ouvrira sa Decisions API, vous remplacerez l'intérieur de decide() et chaque site d'appel restera inchangé. Le texte des questions, les options et les seuils se conservent.

TypeScript

// Keep the decision behind one typed function. Swap the HTTP
// layer when OpenAI publishes its schema — callers never change.
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

Existe-t-il un exemple officiel du SDK OpenAI pour la Decisions API ?

Non. OpenAI n'a publié ni méthodes SDK ni schéma de requête pour sa Decisions API — tout code montrant client.decisions.create est inventé. Cette page utilise du HTTP simple, ce que tout SDK de fournisseur encapsulerait de toute façon.

Ai-je besoin d'un générateur de code pour les types ?

Non — les interfaces de cette page couvrent tout le contrat. Copiez-les dans votre projet ; elles sont assez petites pour être auditées et stables entre fournisseurs.

Comment envoyer un contexte structuré ?

state accepte un objet JSON ou un tableau, pas seulement une chaîne — passez des dicts directement dans le corps json et le modèle les lit comme contexte.

Lancez une décision depuis le navigateur

Aucune configuration — exécutez un vrai appel dans le bac à sable avec 2 crédits offerts aux nouveaux visiteurs.