Talero ATS
AI-native applicant tracking, built to earn trust
A production backend that turns a CV plus a 20-minute psychometric game into an auditable, bias-controlled hiring recommendation, built to satisfy the EU AI Act's high-risk bar while keeping LLM spend close to zero.
Visit taleroai.com
About the project
I designed and built the backend for an AI-native Applicant Tracking System that evaluates candidates across four independent evidence layers (experience, skills, behaviour and personality) and produces an explainable, audit-logged hiring recommendation for every application. The hard part was not calling an LLM; it was building a system a regulator, a recruiter and a rejected candidate could all trust: deterministic where it matters, AI-assisted where it adds value, and traceable end to end.
Stack
Stack by layer
- API
- Node.js 22 · TypeScript · Express · Zod (runtime validation)
- Async / queues
- BullMQ on Redis (resume parsing, EBHE scoring, Vertex evaluation)
- AI pipeline
- Python · FastAPI · PyMuPDF · Tesseract OCR · spaCy NER · rapidfuzz · sentence-transformers
- LLMs
- Claude Haiku → GPT-4o-mini fallback · Gemini Flash-Lite (multi-agent panel)
- Data
- PostgreSQL + pgvector · Supabase (Auth, Storage, RLS)
- Realtime
- Server-Sent Events (SSE) for live recruiter dashboards
- Infra
- Docker Compose · Caddy (reverse proxy) · GCP VM · GitHub Actions
- Observability
- Sentry (releases tied to Git SHA) · Pino structured logging · autoheal watchdog
Noticeable changes
- Designed a 4-layer Evidence-Based Hiring Engine (EBHE v2.0) with an asymmetric gap-penalty model, blending CV claims (30%) with behavioural-game evidence (70%).
- Kept ~90% of CV processing at $0 with a deterministic, LLM-free multilingual parser, cheapest-capable-model routing and local embeddings.
- Built for the EU AI Act high-risk bar: pseudonymised evaluation, excluded protected attributes, full audit trail and regulator-ready PDF exports.
What it does
- Ingests CVs (PDF/DOCX, including scanned CVs via OCR) and extracts structured data (contact, work history, education, skills, certifications) with a deterministic, no-LLM parser in three languages (EN / DE / SV).
- Blends two signal sources, what the CV claims (30%) and what a behavioural game proves (70%), into a merged psychometric profile, surfacing discrepancies and hidden strengths between the two.
- Scores every candidate against every role with EBHE v2.0, a custom 4-layer model with an asymmetric gap-penalty algorithm that punishes under-qualification far more than over-qualification.
- Runs a multi-agent evaluation panel (eligibility, skills-fit, evidence, uncertainty, synthesised by a summariser) on pseudonymised profiles.
- Generates the full compliance trail: every AI decision is logged with its engine version, model, inputs hash and a fairness snapshot, and can be exported as a regulator-ready PDF.

Architecture that earns trust
- Deterministic core, AI at the edges. The CV parser is intentionally LLM-free (regex, spaCy NER and a curated skills lexicon with fuzzy matching), so extraction is reproducible and auditable, and the system never pays per token to read a résumé.
- Privacy by design (GDPR Art. 25). Raw CV text and PII never reach an LLM; the parser emits a minimized-for-LLM payload stripped of identity and protected attributes, and the behavioural evaluators only ever see a pseudonymised profile.
- Resilience built in. Every external AI provider sits behind a circuit breaker (5 failures → 60s open) with an automatic fallback chain (Anthropic → OpenAI → graceful degradation), and a healthcheck plus autoheal watchdog catches hung containers, the fix for a real 31-minute silent outage.
Cost reduction and optimization
This is where backend engineering, not prompt engineering, moved the needle.
- ~90% of CV processing is $0: because parsing is deterministic, the only LLM calls are for genuinely generative work, and the parser stays the source of truth over the model.
- Cheapest-capable-model routing: Claude Haiku and GPT-4o-mini for extraction, Gemini Flash-Lite for the evaluation panel, small models chosen per task instead of defaulting to a frontier model.
- Conditional Docker builds in CI: the ~1.1 GB Python AI image only rebuilds when ai-pipeline/ actually changed, saving ~5 min of build time and ~1 GB of disk pressure on typical pushes.
- Disk-space hygiene as code: the deploy step prunes stopped containers, dangling images and BuildKit cache before each build, after a real incident where a 20 GB VM filled up mid-deploy.
- Embeddings run locally: semantic skill matching uses a local all-MiniLM-L6-v2 model (384-dim vectors) instead of a paid embeddings API.
CI/CD, hardened by incidents
Two gated jobs (test → deploy) where almost every line exists because something broke once.
- lint-and-test on every push and PR: real Postgres (pgvector) and Redis service containers, lint → Vitest → TypeScript build.
- Two pre-deploy guards that caught a production crash-loop: rendering docker compose config with an empty env to flush out missing defaults, and booting the Zod env schema with production-shaped input as the cheapest 'would the container even start?' smoke test.
- Deploy only on main and only if tests pass: documentation-only pushes skip deploy, rsync --delete keeps the VM in sync, and image rebuilds are conditional on the changed-paths diff.
- Polling smoke test against /ready (DB, Redis, Resend, AI pipeline, game Supabase) with a ~3-minute budget that tolerates the transient 503s a freshly-rebuilt container throws.
- Sentry release tagging: GIT_SHA is forwarded so every deploy is a distinct, traceable release.

Compliance and fairness (EU AI Act, Annex III)
An ATS that ranks people is a high-risk AI system, so the backend was built to meet that bar, not bolt it on afterwards.
- Human oversight: the AI produces a recommendation with strengths, risks and a confidence score; a human recruiter makes the actual stage decision.
- Transparency: a /compliance/transparency endpoint and a per-application PDF export documenting engine version, model, processing region and the fairness snapshot.
- Fairness by construction: protected attributes are excluded from the feature set entirely, and a fairness service monitors feature distributions.
- Full audit trail: every decision is written to ai_audit_logs with an inputs hash (not the raw data), making decisions reproducible without storing PII.

Outcomes
- A hiring decision pipeline that is auditable, explainable and regulator-ready.
- LLM cost kept minimal by doing the deterministic work deterministically.
- A CI/CD pipeline that fails loudly before prod, deploys only what changed, and self-documents the incidents that shaped it.