5

Pitch: achei que o difícil de automatizar candidatura era o CAPTCHA. Era um select

Fala, pessoal.

Tô construindo o G3 Apply, um copilot que acha vaga em página oficial de carreira e preenche a candidatura pra você. Quando comecei, eu jurava que a briga ia ser com CAPTCHA. Errei feio. O que me derruba é pergunta de formulário.

Vou abrir os números do piloto. Ele ainda é pequeno: 291 candidaturas preparadas desde 12/10, em 10 contas.

13 perguntas por vaga

Greenhouse, Lever, Ashby e Gupy deixam cada empresa inventar as perguntas que quiser. Peguei 177 candidaturas e contei: 2.363 perguntas. A mediana dá 13 por candidatura. A campeã tinha 33.

De onde saiu cada resposta:

  • 45% veio direto do perfil que a pessoa preencheu
  • 25% o modelo de linguagem respondeu
  • 26% ficou em branco

O resto (uns 4%) veio de resposta antiga guardada ou da própria pessoa na revisão.

Uma em branco e já era

De 1.794 perguntas obrigatórias, 340 ficaram sem resposta. Dá 19%, parece pouco, né? Só que basta uma pra candidatura não sair. Resultado: 123 das 177 tinham pelo menos uma obrigatória em branco. 7 em cada 10.

E eu não deixo o robô chutar. Se não tem resposta confiável, a candidatura para e espera a pessoa. Marcar "sim" errado em "você precisa de visto?" é bem pior que não mandar.

O culpado: select

Campo de texto curto ficou em branco 11% das vezes (100 de 926). Select, 30% (219 de 741). De cada três perguntas em branco, duas são select.

O motivo é meio besta: as opções são texto que cada empresa escreve do jeito dela. Eu sei quanto a pessoa quer ganhar, mas o campo vem com umas faixas que a empresa inventou. Eu sei o país, mas a pergunta é "você mora na América Latina?" com Sim e Não.

O que mais ficou em branco (separei por palavra-chave, então é aproximado):

TemaPerguntas
Salário41
"Como soube da vaga?" e quem indicou33
Onde você mora29
Diversidade e pronomes27
Anos de experiência com tal tecnologia22
Visto21
Autorização de trabalho18

O pior é que em boa parte disso o dado já tava no perfil. Só não tava no formato do campo.

O que eu arrumei

Dia 13/11 subi uma correção que converte o perfil pro formato do campo: disponibilidade vira data, país vira Sim ou Não, pretensão vira faixa. Rodei de novo em 30 candidaturas travadas:

  • data de início: 7 de 7
  • "mora na América Latina?": 6 de 6
  • visto: 9 de 11
  • faixa salarial em select: 3 de 6

Três candidaturas saíram no mesmo dia. As outras 26 continuam paradas. Parte é salário em texto livre, que ainda vou atacar. Parte eu nem quero automatizar: aceitar checagem de antecedentes, pronome, quem te indicou. Isso é a pessoa que responde.

E o tal do CAPTCHA?

Travou 1 candidatura. Uma.

O que travou de verdade foi login: 37, todas na Gupy, que exige conta do candidato. No Greenhouse o que apareceu pra mim nem foi CAPTCHA, foi um código que chega no e-mail na hora de enviar. As 7 que mandei por lá desde 31/10 passaram por isso. E teve 4 em que o formulário foi, mas não consegui confirmar. Essas não conto como enviadas.

Onde eu tô

Sendo bem honesto: das 291, saíram 17, e todas são da minha conta ou de conta de teste. Ninguém de fora chegou no envio ainda. É isso que quero ver agora.

Stack, pra quem curte: TypeScript, Postgres e Next.js.

Quer testar?

Tem plano grátis, sem cartão: https://apply.g3infotech.app/?utm_source=tabnews&utm_medium=post

E tem um checador de currículo pra ATS que roda sem cadastro: https://apply.g3infotech.app/ats-check/pt-br?utm_source=tabnews&utm_medium=post

Agora a pergunta pra quem já sofreu com isso: como vocês lidam com select que cada empresa escreve de um jeito? Hoje, na dúvida, eu deixo em branco e pergunto pra pessoa. Se alguém tiver ideia melhor, tô aceitando.

Carregando publicação patrocinada...
4

Parabéns pela transparência e pela dissecação dos números, Rodrigo! Pouca gente que tenta automatizar candidatura chega nesse nível de maturidade analítica pra perceber que o gargalo de verdade nunca foi o CAPTCHA, e sim a heterogeneidade bizarra do schema de formulários dos ATSs.

Sobre o desafio dos selects, lidamos com problemas parecidos e algumas abordagens ajudam bastante a reduzir essas travas sem alucinação:

  1. Camada de normalização semântica (Embedding Cosine Sim + Threshold): Em vez de chamar LLM pura para todo select, indexar as opções do select no momento do parse da página e calcular a similaridade de cosseno contra os atributos canônicos do perfil do candidato. Com um threshold conservador (ex: > 0.85), você resolve boa parte das variações triviais de escrita (ex: "América Latina", "LATAM", "South America / Brazil") com custo e latência mínimos.

  2. Parsing de Intervalos Numéricos / Faixas Salariais: Para pretensão salarial e anos de experiência, regex com extração de bounds (min, max) mapeado contra o valor numérico exato do usuário resolve a maior parte. Ex: se o usuário pede R$ 8.000 e as opções são "5k - 8k" ou "8k - 12k", uma regra determinística de borda (ex: priorizar faixa superior quando igual ao teto) evita adivinhação aleatória.

  3. Fallback Estruturado com JSON Schema (Function Calling): Quando cai abaixo do threshold do embedding, passar para um modelo leve apenas: o valor do perfil + o array exato de opções do select, forçando a resposta a ser um enum restrito à lista do HTML ou null. Se o modelo retornar null ou confiança baixa, você joga pro fallback manual (sua estratégia de perguntar pro usuário está 100% certa — errar pergunta eliminatória de visto ou modelo de contratação destrói a candidatura).

Outro ponto que você mencionou e que é brutal: o ecossistema da Gupy com autenticação proprietária e SPAs pesadas (onde o "select" muitas vezes nem é uma tag nativa, mas uma árvore de divs com listeners de click) é ordens de grandeza mais hostil que o Greenhouse/Lever. Acompanhando o projeto, baita iniciativa!

4

Valeu demais, jobiabr! Comentário de ouro.

Vou analisar com calma o que você trouxe, principalmente a ideia de travar a resposta do modelo nas opções exatas do select (ou null) e a regra fixa pra faixa salarial. Quando testar, volto aqui e conto o que funcionou.

E sim, a Gupy é outro nível de hostilidade kkk