🎯 El problema
Buscar trabajo en LinkedIn es un trabajo en sí mismo. Abrir la búsqueda, leer veinte ofertas donde quince no aplican, adaptar el CV para las que sí, escribir un mensaje distinto para cada reclutador y repetir todo al día siguiente. Es exactamente el tipo de proceso manual y repetitivo que me dedico a automatizar para empresas, así que decidí automatizarlo para mí.
Así nació jobhunter, una CLI open source en Python que hoy tiene estrellas, forks y usuarios reales reportando issues en GitHub. Este post es el case study de cómo funciona por dentro.
🤖 La arquitectura, un pipeline de 4 agentes
El corazón del sistema no es un solo prompt gigante sino cuatro agentes especializados que se pasan el trabajo en cadena, cada uno con una responsabilidad clara.
- Filtrador. Analiza cada publicación scrapeada y decide si es relevante para tu perfil, extrayendo datos estructurados (rol, stack, modalidad, empresa). Es el que más impacto tiene en la calidad de todo lo demás.
- CV Writer. Genera un CV personalizado para cada oferta relevante con ReportLab, resaltando la experiencia que esa vacante específica pide.
- Email Writer. Escribe el mensaje para el reclutador en unas 100 palabras. Corto, específico y sin plantillas genéricas.
- Optimizer. Aprende de cada corrida y ajusta la query de búsqueda según tu perfil y el historial de resultados.
El scraping usa Playwright con sesiones persistentes para no re-autenticar en cada corrida, y el envío va por Gmail SMTP con TLS.
⚖️ Las decisiones que más importaron
El humano aprueba, el agente prepara. La decisión de diseño más importante no fue técnica sino de producto. jobhunter tiene modo dry-run y todo termina en una revisión humana antes de enviar nada. Un agente que aplica a ciegas por ti es spam con extra pasos. Un agente que te deja seis aplicaciones listas para revisar convierte una hora de trabajo repetitivo en cinco minutos de criterio.
Filtros deterministas antes que IA. Blacklist de empresas, deduplicación de ofertas ya vistas y filtros de tiempo corren antes de gastar un solo token. El LLM solo ve lo que vale la pena analizar, y eso mantiene el costo por corrida en centavos.
Elegir el modelo por tarea. El usuario elige qué modelo de Gemini usar (flash, lite o pro). Filtrar cientos de ofertas no necesita el modelo más caro; escribir el CV sí se beneficia de uno mejor. Es la misma lección de optimización de costos que aplico en producción.
📬 Lo que pasó al publicarlo
Publicarlo como open source con licencia MIT cambió el proyecto. Llegaron usuarios que lo corren en sistemas operativos que yo no había probado, issues con casos que no había imaginado y forks adaptándolo a otros países. Mantenerlo me obligó a lo que ningún proyecto privado te exige, CI con GitHub Actions, pre-commit hooks, documentación de instalación para tres plataformas y decir que no a features que no encajan.
La lección más valiosa no fue técnica. Fue descubrir que mantener una herramienta que otros usan es una habilidad distinta a construirla.
🔭 Lo que sigue
El próximo paso es publicar el harness de evaluación del Filtrador, un golden set de ofertas etiquetadas a mano para medir con números qué tan bien clasifica la relevancia, integrado al CI. Si el agente más crítico del pipeline no se puede medir, no se puede mejorar.
El código está en github.com/dev-gaspar/jobhunter y la documentación completa en la landing del proyecto. Si lo pruebas, un issue con tu experiencia vale oro.