Como classificar ticket, e-mail e mensagem com lista fechada de opções na Decisions API da OpenAI
A Decisions API da OpenAI (endpoint POST /v1/decisions, em beta pública desde 06/10/2026 e hoje só com o gpt-6-luna) responde escolhendo entre opções que você define, em vez de gerar texto livre. Pra classificar ticket, e-mail e mensagem, use perguntas do tipo choice com valores distintos e mutuamente exclusivos, cada um com a descrição de quando se aplica, e inclua uma saída other como boa prática. A resposta traz o valor escolhido, a probabilidade de cada opção e a confiança: confiança baixa ou other vai pra fila humana. Cobra só entrada, US$ 0,10 por 1 milhão de tokens
Se tu já colocou um LLM pra triar ticket, tu conhece a dor: um dia ele responde Financeiro, no outro Cobrança, no outro cobranca sem acento, e de vez em quando inventa uma categoria novinha que não existe em lugar nenhum 😅
Aí o roteamento quebra, o ticket cai no limbo e alguém do suporte descobre isso três dias depois
A Decisions API da OpenAI ataca exatamente esse problema: em vez de gerar texto livre, ela responde perguntas escolhendo entre respostas que VOCÊ definiu antes
Tu manda um contexto (texto ou imagem), manda as perguntas com as respostas possíveis, e ela devolve uma resposta por pergunta
A própria OpenAI apresenta o uso pra classificar conteúdo, rotear pedidos e escolher a próxima ação de um agente
Ela foi apresentada no DevDay, em 29/09/2026, em preview limitado, e desde 06/10/2026 está aberta em beta pública pra todos os desenvolvedores
Bora ver como montar uma lista fechada que funciona de verdade? 🙂
Por que uma lista fechada muda o jogo na triagem e no roteamento?
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 45min
Pensa no texto livre como pedir pra alguém "descrever" o assunto do e-mail
Cada pessoa descreve de um jeito, né? E aí tu precisa de uma camada inteira de código só pra normalizar: tirar acento, padronizar caixa, mapear sinônimo, tratar o caso que não bate com nada…
Com lista fechada é como entregar um formulário com caixinhas pra marcar
No tipo choice da Decisions API, o retorno é sempre um dos valores que tu forneceu, então ele vira direto a chave da fila, a tag ou a rota no seu código, sem tradução no meio
E tem um bônus que faz MUITA diferença: além do valor escolhido, a resposta traz a probabilidade de cada opção e um número de confiança separado
Que confiança? É o quanto o modelo "bancou" aquela escolha
Com isso tu deixa de confiar cegamente na resposta e passa a decidir com regra: confiança alta segue automático, confiança baixa vai pra uma pessoa olhar
O ganho real é de engenharia: saída previsível e um sinal claro de quando desconfiar
O que você precisa antes de começar:
A lista é curta, e só com o que está confirmado:
- Acesso à API da OpenAI: a Decisions API está em beta pública pra todos os desenvolvedores desde 06/10/2026, e a disponibilidade geral (GA) ainda não saiu (a OpenAI fala em "próximas semanas")
- Modelo: hoje o único suportado é o
gpt-6-luna, uma versão especializada do GPT-6 Luna - Endpoint:
POST /v1/decisions, separado das outras rotas da API
Se tu lida com dado sensível (saúde, dado pessoal de cliente e etc), se liga nisso: o endpoint suporta Zero Data Retention e uso HIPAA pra clientes elegíveis, além de residência de dados com processamento regional nos EUA e na Europa (EEE + Suíça)
A referência oficial é o guia da Decisions API, deixa ele aberto do lado enquanto monta as coisas
Passo a passo: classificando tickets com o tipo choice
A lógica aqui é explicar o PORQUÊ de cada passo e já mostrar onde o pessoal costuma tropeçar
Passo 1: desenhe a lista fechada
Antes de escrever qualquer requisição, tu precisa decidir as opções
A orientação da documentação pra perguntas choice é usar valores distintos e uma descrição que explique quando cada opção se aplica
O exemplo oficial de triagem de suporte é este:
billing -> pagamentos, faturas e reembolsos
technical -> problemas para usar o produto
shipping -> entrega e rastreio
Repara que a descrição não é enfeite: é ela que diz pro modelo onde está a fronteira entre uma categoria e outra
O erro comum deste passo: criar duas opções que se sobrepõem, tipo pagamento e reembolso
Reembolso É assunto de pagamento, então o mesmo ticket cabe nas duas e a probabilidade se divide entre elas
Resultado: confiança baixa sem motivo e roteamento instável
Se tu precisa separar reembolso, isso é subcategoria (a gente chega lá no passo 6)
Passo 2: adicione a saída "nenhuma das anteriores"
Todo suporte recebe aquele e-mail que não tem nada a ver com nada: proposta comercial, currículo, alguém agradecendo, por aí vai
Se a lista não tem uma saída pra isso, o modelo é obrigado a encaixar o ticket em alguma categoria "menos pior"
Por isso, como boa prática de design (não é exigência da API), vale incluir uma opção tipo other:
billing -> pagamentos, faturas e reembolsos
technical -> problemas para usar o produto
shipping -> entrega e rastreio
other -> nenhuma das categorias acima se aplica ou o assunto não está claro
O erro comum deste passo: forçar todo ticket a caber numa categoria
Aí o currículo vai parar na fila técnica e alguém perde tempo lendo… já vi isso acontecer mais vezes do que gostaria haha
Passo 3: monte a requisição
A requisição tem três campos: model escolhe o modelo, input traz o contexto compartilhado (uma string de texto ou mensagens de usuário com texto e imagens) e questions é um array de perguntas
Cada pergunta tem um nome, um tipo, instruções e as opções permitidas
O esqueleto fica assim:
POST /v1/decisions
{
"model": "gpt-6-luna",
"input": "Oi, fui cobrado duas vezes no cartão este mês e quero o estorno de uma das cobranças",
"questions": [
{
"name": "departamento_suporte"
// tipo: choice
// instruções: "Classifique o departamento que deve atender este ticket"
// opções: billing, technical, shipping, other (cada uma com valor + descrição)
}
]
}
Os comentários ali dentro marcam o que cada pergunta leva: tipo, instruções e opções (cada opção com valor + descrição), no formato que está no guia oficial 😛
O input é onde entra o texto do ticket, do e-mail ou da mensagem do WhatsApp, o que for
O erro comum deste passo: dar um name genérico tipo q1 ou pergunta
O nome volta na resposta, então se ele não diz nada, ler o array de respostas vira um quebra-cabeça, principalmente quando tu tiver várias perguntas na mesma chamada
Passo 4: leia a resposta (e trate a recusa)
A API repete o name de cada pergunta no array answers, e é por ele que tu casa pergunta com resposta
Na resposta de uma pergunta choice tu tem três coisas: o valor escolhido, a probabilidade de cada opção e a confiança
Só que tem um detalhe: qualquer pergunta pode voltar como recusa (refusal) em vez de resposta
Então a lógica de leitura fica mais ou menos assim:
def resposta_por_nome(answers, nome):
for resposta in answers:
if resposta["name"] == nome:
return resposta
return None
resposta = resposta_por_nome(answers, "departamento_suporte")
if resposta is None or veio_recusa(resposta):
mandar_para_fila_humana(ticket)
else:
valor, confianca = extrair_valor_e_confianca(resposta)
veio_recusa e extrair_valor_e_confianca são funções suas: dentro delas tu lê os campos com os nomes que estão no guia oficial
Isolar isso numa função é massa porque, se o schema mudar até a GA, tu mexe num lugar só
O erro comum deste passo: assumir que sempre vem uma resposta
Caso venha uma recusa e teu código vá direto buscar o valor, ele estoura erro no meio da fila e trava tudo atrás dele
Tome cuidado!
Passo 5: roteie com base na confiança
Agora sim o roteamento, usando o valor E a confiança:
FILAS = {
"billing": "fila_financeiro",
"technical": "fila_suporte_tecnico",
"shipping": "fila_logistica",
}
def rotear(ticket, valor, confianca, limite):
if valor == "other" or confianca < limite:
return "fila_humana"
return FILAS.get(valor, "fila_humana")
E qual o limite? Não existe número mágico
Quem define é a tua base: roda com tickets antigos já classificados e vê a partir de qual confiança os acertos ficam aceitáveis pro teu caso
O erro comum deste passo: usar só o valor e ignorar a confiança
O valor sempre vai ser uma opção válida
E é justamente isso que engana: uma escolha "no chute" parece tão certinha quanto uma escolha firme, e só a confiança mostra a diferença entre as duas
Passo 6: subcategoria ou decisão dependente? Segunda chamada
Todas as perguntas de uma mesma requisição usam o mesmo input
Isso quer dizer que, se a próxima decisão depende de uma resposta anterior, ela precisa de uma segunda requisição
Exemplo: primeiro tu descobre que o ticket é billing, e só então pergunta se é cobrança duplicada, fatura ou reembolso
# chamada 1: departamento
departamento = classificar(ticket, pergunta_departamento)
# chamada 2: só faz sentido depois da primeira
if departamento == "billing":
subtipo = classificar(ticket, pergunta_subtipo_billing)
O erro comum deste passo: tentar encadear tudo numa requisição só
As perguntas da mesma chamada não "enxergam" a resposta umas das outras, então a pergunta de subcategoria de billing vai ser respondida até pra ticket de entrega, o que não faz sentido nenhum
Choice, predicate ou score: qual tipo usar em cada triagem?
A Decisions API tem três tipos de pergunta, e escolher o certo evita muita gambiarra:
| Tipo | O que devolve | Quando usar na triagem |
|---|---|---|
| choice | Um dos valores fornecidos, a probabilidade de cada opção e a confiança | Departamento, categoria, fila de destino |
| predicate | Probabilidade de 0 a 1 de uma condição ser verdadeira | "É spam?", "Pede reembolso?" |
| score | Média dos índices dos níveis, ponderada pela probabilidade | Severidade ou urgência em níveis ordenados |
Quando usar choice?
Sempre que tu precisa de um rótulo exato pra rotear: departamento de um ticket, tipo de um e-mail, intenção de uma mensagem
É o tipo deste tutorial todo, e é o que acaba com a categoria inventada
Quando usar predicate?
Pra perguntas de sim ou não, tipo "essa mensagem é spam?" ou "esse e-mail pede reembolso?"
Como volta uma probabilidade de 0 a 1, tu decide o corte no teu código
Quando usar score (e por que ele NÃO serve pra rotear)?
O score pontua contra níveis ordenados, tipo baixa, média e alta severidade
Só que ele devolve a média dos índices ponderada pela probabilidade, e o exemplo oficial mostra o pegadinha: probabilidades 0,1, 0,7 e 0,2 em três níveis dão score 1,1
E 1,1 não corresponde a nenhum nível!
É ótimo pra ordenar a fila (o 1,1 vem antes de um 0,4, por exemplo), mas se tu precisa de um rótulo exato pra mandar pra uma rota específica, o certo é choice
Combinando perguntas no mesmo input
Como todas as perguntas da requisição compartilham o mesmo input, tu pode extrair várias informações independentes de um e-mail numa chamada só:
{
"model": "gpt-6-luna",
"input": "<texto do e-mail>",
"questions": [
{ "name": "categoria" }, // tipo choice: billing, technical, shipping, other
{ "name": "urgencia" }, // tipo score: níveis ordenados de urgência
{ "name": "pede_reembolso" } // tipo predicate
]
}
O que vale é a regra do passo 6: isso funciona porque nenhuma dessas perguntas depende da resposta da outra
Quanto custa e quão rápido é classificar em volume?
Os números divulgados pela OpenAI são estes:
- Preço: só tokens de entrada são cobrados, a US$ 0,10 por 1 milhão de tokens
- Saída e cache: tokens de saída e leitura/escrita de cache não são cobrados
- Latência: cerca de 150 ms por decisão, contra cerca de 1,6 s numa chamada padrão do GPT-6 Luna (a OpenAI fala em cerca de 10x mais rápido)
Na prática, o que pesa no custo é o tamanho do que tu manda no input, então ticket gigante com histórico inteiro custa mais que a mensagem curta
Vale pensar no que realmente precisa entrar no contexto pra decidir a categoria
Já a latência abre espaço pros dois cenários: triagem em lote (aquela fila acumulada do fim de semana) e triagem em tempo real, classificando a mensagem no momento em que ela chega, antes de alguém abrir
Só lembra que ainda é beta pública e a GA é esperada nas próximas semanas, então coisa pode mudar até lá 😉
Próximo passo: monte sua primeira lista fechada
Recapitulando o que faz a triagem com a Decisions API funcionar:
- Opções com valores distintos e mutuamente exclusivos
- Descrição dizendo quando cada opção se aplica
- Uma saída
otherpra o que não cabe em lugar nenhum - Confiança (e recusa) decidindo quando o ticket vai pra uma pessoa
- Segunda chamada pra subcategoria e decisão encadeada
O próximo passo é bem concreto: pega 3 a 5 categorias reais da tua fila de suporte, escreve a descrição de cada uma e roda contra tickets antigos que já têm a categoria certa
Vai ficar claríssimo onde as opções se sobrepõem e qual limite de confiança faz sentido pra você
E aí, vai colocar na tua fila? Bora trocar uma ideia nos comentários 🙂
até o próximo post!
Perguntas frequentes
Qual a diferença entre a Decisions API e mandar um prompt de classificação pro GPT-6 Luna normal?
Na Decisions API a resposta é obrigatoriamente uma das opções que você definiu, com probabilidade por opção e confiança separada. Além disso, segundo a OpenAI, a latência é de cerca de 150 ms contra cerca de 1,6 s numa chamada padrão do GPT-6 Luna, o que ela descreve como cerca de 10x mais rápido.
Quanto custa classificar um ticket com a Decisions API?
Segundo a OpenAI, com o gpt-6-luna a Decisions API cobra US$ 0,10 por 1 milhão de tokens de entrada. Tokens de saída e leitura/escrita de cache não são cobrados, ou seja, custo US$ 0 nesses dois itens.
Posso usar a Decisions API em produção hoje?
Sim, desde 06/10/2026 ela está em beta pública aberta pra todos os desenvolvedores, não é mais o preview limitado anunciado no DevDay. A disponibilidade geral (GA) ainda não saiu, a OpenAI fala em próximas semanas.
Dá pra fazer uma pergunta que depende da resposta de outra na mesma requisição?
Não. Todas as perguntas de uma mesma requisição usam o mesmo input compartilhado, então uma decisão que depende de uma resposta anterior precisa de uma segunda requisição separada.
A Decisions API funciona com imagem, ou só texto de ticket e e-mail?
O campo input aceita tanto uma string de texto quanto mensagens de usuário com texto e imagens. Então classificar um print de erro enviado pelo cliente, por exemplo, está dentro do que o endpoint suporta.
Qual modelo a Decisions API usa pra classificar?
Hoje o único modelo suportado é o gpt-6-luna, uma versão especializada do GPT-6 Luna. Esse é o modelo que aparece no changelog oficial da OpenAI registrando o lançamento em beta.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares

Como escrever uma rubrica que a Decisions API aplique sempre do mesmo jeito
Entenda como montar uma rubrica Decisions API com níveis testáveis, fronteiras claras e sem rótulos vagos para a OpenAI aplicar sempre igual.

Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação A popularidade da automação de processos com o n8n está em alta, principalmente […]
O que significa “ChatGPT network error” e como resolver
O “ChatGPT Network Error” é uma ocorrência frequente na rotina de muitos usuários do ChatGPT. Porém, poucos compreendem seu significado, quando esse erro surge, etc. […]
