Caso de estudio

Clasificador de correo entrante

Robles Sphère · 2026

Robles Sphère recibía cientos de correos a la semana repartidos entre las cuentas personales de cada comercial, y nadie los clasificaba. Este es el sistema que los recoge y los ordena: qué hace, qué decidí y en qué punto está de verdad.

Estado

Ingesta IMAP
corriendo sobre las cuentas reales
Clasificación
implementada, sin activar
Sale
con el ERP

01 El problema

Cientos de correos a la semana. Unos 40 al día de correo externo nuevo, ya descontados los internos y los duplicados.

  • No había nadie encargado del correo entrante: cada comercial recibía el suyo en su cuenta personal y nada se centralizaba.
  • Nadie clasificaba. No hay un tiempo antes que comparar, porque la tarea no se hacía: el problema no era lo que costaba, era que las peticiones se enterraban en hilos reenviados.
  • Lo que costaba era respuestas tardías y, en ocasiones puntuales, algún pedido perdido.
  • Antes no se había intentado nada. Ni reglas de Outlook, ni filtros.

02 Cómo funciona

Un proceso propio de larga duración, fuera de la API HTTP, que se despierta cada cinco minutos y no espera a ningún evento.

Buzón IMAPCron · 5 minPostgreSQLClaude · SonnetBuzón IMAPCron · 5 minPostgreSQLClaude · Sonnet
Fig. 06 — El cron lee en modo lectura, filtra contra la base de datos y solo entonces llama al modelo. La clasificación cuelga del proceso, nunca del buzón: el correo se lee, no se toca.
  • Abre el buzón de cada cuenta por IMAP en modo lectura: leer no marca el correo como leído. Pide primero solo los identificadores, los cruza contra la base de datos y descarga únicamente los que no estén guardados.
  • Tres filtros ahorran la llamada antes de gastarla: identificador ya conocido, mensaje duplicado entre cuentas, y correo solo interno. Los internos se guardan con su motivo en vez de clasificarse, para poder auditar si el filtro descarta algo real.
  • De cada correo salen asunto, remitente y cuerpo recortado a 6.000 caracteres. Los adjuntos se guardan, pero nunca llegan al modelo.
  • El modelo responde con una llamada a herramienta forzada contra un esquema: categoría, urgencia, resumen y tres campos opcionales. No hay puntuación de confianza, porque no se pidió.
  • El resultado se guarda y ahí acaba. No mueve el correo, no lo etiqueta, no crea tareas y no avisa a nadie.

03 Decisiones

Un modelo por tarea, no un modelo para todo

Sonnet lee un hilo reenviado y entiende qué pide el último mensaje por encima de las citas antiguas. En otra parte del mismo proyecto, Haiku casa el nombre de un fichero contra una lista de carpetas.

La segunda es una decisión mecánica y cuesta céntimos; la primera no. Elegir un solo modelo para las dos habría pagado de más en una o acertado de menos en la otra.

Modelo en vez de reglas

Las cuatro categorías dependen de la intención, no del vocabulario: una petición de presupuesto y una consulta comparten palabras, y un cliente puede pedir precio sin escribir "presupuesto".

Un sistema de reglas habría necesitado mantenimiento constante y habría fallado justo en los casos ambiguos, que son los que importan. Al volumen real, clasificar con Sonnet cuesta del orden de doce dólares al mes: el argumento clásico contra usar un modelo para una tarea simple es el coste, y a este tamaño no aplica.

Lee y no escribe

El sistema no marca como leído, no mueve, no etiqueta, no procesa adjuntos y no crea tareas.

Un solo argumento lo sostiene: mientras la clasificación no esté medida, cualquier efecto secundario convierte un fallo del modelo en trabajo perdido del equipo. Un correo mal clasificado que además desaparece de la bandeja es peor que un correo sin clasificar.

La que salió mal: los veinte de siempre

La primera versión descargaba los veinte no leídos más recientes en cada pasada. Como el sistema nunca marca el correo como leído —que era la decisión deliberada de arriba— esos mismos veinte ocupaban la ventana en cada vuelta, indefinidamente: todo lo que llegara por encima del límite no se procesaba nunca.

No fallaba nada de forma visible. No había excepción, ni aviso, ni cola creciendo: simplemente había correo que no se clasificaba. Dos decisiones correctas por separado se multiplicaron mal.

El arreglo invierte el orden: pedir solo los identificadores, cruzarlos contra la base de datos y descargar únicamente los que no estén guardados. De regalo, los correos ya conocidos ni se descargan, y con ellos se ahorra el ancho de banda de cuerpos de cientos de kilobytes.

04 Estado y lo que no está medido

La ingesta lleva tiempo corriendo sobre las cuentas reales y ha dejado un corpus con el que calibrar. La clasificación con modelo está implementada y en espera.

Lo único medido hasta hoy es la línea base. Un clasificador por palabras clave, escrito para tener contra qué comparar, acierta 7 de 13 correos revisados a mano. Ese 54 % no es un resultado del modelo: es la razón por la que hace falta uno, y el patrón del fallo está documentado — la regla solo mira si la palabra aparece, sin entender si el correo abre una petición, la sigue o la cierra.

Precisión con modelo
no ha corrido sobre correo real
Tiempo antes y después
no hay antes: la tarea no se hacía
Tiempo en producción
cero para la clasificación
Volumen clasificado
cero por modelo; la ingesta recoge ~40 al día
Qué dice quien lo usa
nadie lo usa todavía

El enum de cuatro categorías se queda corto. Al revisar los correos a mano aparecieron "seguimiento de un proyecto ya presupuestado" y "gestión interna", que hoy caen en consulta por descarte. Está detectado, escrito y sin corregir: es lo que hay que decidir antes de activar.

Y una carencia que se nota: un correo que falle se reintenta cada cinco minutos indefinidamente, sin contador de intentos. Un fallo permanente gasta una llamada cada vez.

← Volver a la portada