Key Takeaways
- 1Usa el SDK de Node para OpenAI con el helper zodResponseFormat y olvídate de parsear JSON a mano.
- 2Garantiza respuestas JSON 100% precisas de gpt-4o sin matarte haciendo prompt engineering complejo.
- 3Extrae la intención real y la urgencia a partir de correos desordenados de clientes.
- 4Conecta los resultados de la IA directo a tus etiquetas de Zendesk usando enums de Zod.
- 5Activa reglas de enrutamiento automáticas para escalar los casos de alta prioridad.
Pagarle a un humano para que lea un correo furioso solo para ponerle la etiqueta de 'facturación' y pasarlo a Finanzas es botar plata a la basura.
Usando gpt-4o de OpenAI y Zod, puedes armar un script en Node.js que intercepte los tickets, obligue a la IA a escupir un JSON perfecto y enrute los casos urgentes en milisegundos.
Antes, usar IA para categorizar significaba escribir prompts rogándole al sistema ("Devuelve SOLO un JSON válido") y cruzar los dedos para que el modelo no metiera texto extra. Esa época se acabó.
La función de 'structured outputs' de OpenAI garantiza que la IA te devuelva exactamente la estructura de datos que le pides. Al combinarla con Zod (una librería de validación de esquemas para TypeScript), cualquier JSON malformado es rechazado a nivel de API antes de que rompa tu aplicación.
1. Prepara el entorno en Node.js
Empieza creando un proyecto en blanco de Node.js. Vas a necesitar el SDK oficial de OpenAI y la librería Zod para definir cómo se debe enrutar exactamente todo.
- Inicializa el proyecto: Abre tu terminal y ejecuta `npm init -y` para generar el archivo package.json.
- Instala las dependencias: Ejecuta `npm install openai zod` para traerte el SDK y las herramientas de validación.
- Configura la API key: Ejecuta `export OPENAI_API_KEY="sk-proj-tu-clave-aqui"` en tu sesión de terminal.
2. Imponle la estructura de salida con Zod
Ponle límites estrictos a la IA. Define un esquema de Zod que mapee directamente a los campos personalizados que ya usas hoy en tu Zendesk o Intercom.
import { z } from 'zod';
const TicketTriageSchema = z.object({
category: z.enum(['facturacion', 'problema_tecnico', 'nueva_funcionalidad', 'acceso_cuenta']),
urgency: z.enum(['baja', 'media', 'alta', 'critica']),
summary: z.string(),
suggested_department: z.enum(['finanzas', 'ingenieria', 'producto', 'soporte_nivel_1'])
});Cierra bien las categorías
Al usar `z.enum()`, limitas a la IA a una lista cerrada de strings. La IA físicamente no puede inventarse una categoría nueva como 'reseteo_password' si no la pusiste explícitamente en ese array.
3. Arma la llamada a la API de gpt-4o
Deja de usar el endpoint normal de completions. El helper `client.chat.completions.parse()` agarra tu esquema de Zod, lo convierte en un JSON schema estricto, se lo pasa al modelo y parsea la respuesta automáticamente.
import { zodResponseFormat } from 'openai/helpers/zod';
import OpenAI from 'openai';
const client = new OpenAI();
async function triageTicket(customerEmail: string) {
const completion = await client.chat.completions.parse({
model: 'gpt-4o-2024-08-06',
messages: [
{
role: 'system',
content: 'Eres un agente experto en clasificación de Zendesk. Lee el correo del cliente, categoriza el problema principal y evalúa la urgencia. Una caída del servidor es critica; una sugerencia de interfaz es baja.'
},
{
role: 'user',
content: customerEmail
}
],
response_format: zodResponseFormat(TicketTriageSchema, 'ticket_triage'),
});
return completion.choices[0]?.message?.parsed;
}Elegir bien el modelo importa
Ni se te ocurra usar `gpt-4` o `gpt-3.5-turbo` para esto. Solo `gpt-4o-2024-08-06` y los modelos más recientes soportan structured outputs nativos cumpliendo el esquema al 100%. Los modelos viejos te van a rechazar el payload `response_format` de una.
4. Ejecuta y enruta la carga de datos
Métele a la función un correo caótico y quejumbroso de un cliente. La IA te va a devolver un objeto tipado y limpiecito, listo para enrutarse inmediatamente por Zapier, Make o un webhook personalizado.
const rawEmail = `
Hola equipo,
Estoy intentando descargar mis facturas del Q3 y el botón se queda pensando.
Necesito esto para mi contador en Ciudad de México mañana a primera hora.
¡Arreglen esto urgente!
- Juan`;
async function run() {
const result = await triageTicket(rawEmail);
console.log(result);
if (result?.urgency === 'alta' || result?.urgency === 'critica') {
console.log(`[ALERTA] Notificando por Slack: ¡Enrutando a ${result.suggested_department} de inmediato!`);
}
}
run();Corre el script. La terminal te escupe el JSON exacto, saltándose por completo la pesadilla de parsear a mano:
{
"category": "facturacion",
"urgency": "alta",
"summary": "El cliente no puede descargar las facturas del Q3, las necesita para su contador mañana a primera hora.",
"suggested_department": "finanzas"
}¿Manejas más de 5,000 tickets al mes?
Este script es solo la punta del iceberg. Deja de pelear con la documentación de las APIs. En Kyto construimos motores de enrutamiento con IA personalizados que de verdad le ahorran cientos de horas a tu equipo de soporte.
Agenda una llamadaPreguntas Frecuentes
¿Necesito una base de datos vectorial o armar un RAG para esto?
Para nada. Esta clasificación funciona con 'zero-shot' usando el prompt del sistema y la inteligencia base de gpt-4o. Solo necesitas el texto crudo del correo.
¿Qué pasa si el modelo alucina e inventa una categoría?
Aquí está la magia: Structured Outputs garantiza matemáticamente que el resultado coincida con tu esquema de Zod. Es imposible que devuelva una categoría que no esté en el array z.enum() que tú definiste.
Kyto
AI & Automation Firm
We design and build AI automations and business operating systems. Agency results + Academy sovereignty.

