Guia TypeScript

OpenAI Decisions API em TypeScript

A OpenAI não publicou um SDK para sua Decisions API — não existe client.decisions.create para copiar. Esta página mostra TypeScript funcional e totalmente tipado para o endpoint deste site — uma alternativa chamável à OpenAI Decisions API que serve decisions-1 e segue o mesmo padrão de decisão restrita.

Atualizado

Defina o contrato

Tipe a requisição uma vez e reutilize em todo lugar. model é uma union de literais, então o id fixado nunca vira um typo. questions é um record indexado pelos seus ids, cada um de tipo noul, choice ou score.

Tipe as respostas como uma union discriminada por type — é isso que torna o manuseio da resposta seguro: uma resposta noul tem noul, uma choice tem choice e probabilities — ao restringir por type você obtém os campos certos.

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

Faça a chamada

Um único POST com chave Bearer. satisfies DecisionRequest verifica o corpo em tempo de compilação; AbortSignal.timeout evita que chamadas travadas travem o pipeline. Restrinja answers pelo campo type antes de ler.

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 e tentativas

429 e 502 merecem uma tentativa curta com backoff — chamadas que falham não são cobradas. 402 significa saldo vazio: recarregue, não tente de novo. 422 é erro de validação; a mensagem indica o campo, então corrija o corpo em vez de tentar de novo.

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

Mantenha o provedor atrás de uma função

Quem chama deve ver uma função tipada que recebe texto e devolve um rótulo — não detalhes de HTTP. Quando a OpenAI abrir sua Decisions API você troca o interior de decide() e todos os pontos de chamada ficam iguais. O texto das perguntas, as opções e os limiares são preservados.

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

Perguntas frequentes

Existe um exemplo oficial do SDK da OpenAI para a Decisions API?

Não. A OpenAI não publicou métodos de SDK nem um esquema de requisição para sua Decisions API — qualquer código com client.decisions.create é inventado. Esta página usa HTTP puro, que é o que qualquer SDK de provedor envolveria.

Preciso de um gerador de código para os tipos?

Não — as interfaces desta página cobrem todo o contrato. Copie para seu projeto; são pequenas o suficiente para auditar e estáveis entre provedores.

Como envio contexto estruturado?

state aceita um objeto JSON ou array, não só string — passe dicts diretamente no corpo json e o modelo os lê como contexto.

Execute uma decisão no navegador

Sem configuração — rode uma chamada real no playground com 2 créditos grátis para novos visitantes.