Headhunt is an autonomous, agentic recruiting platform for early-stage founders.
Connect Gmail, Cal.com, and Slack via Auth0 for AI Agents Token Vault. A crew of five agents runs the pipeline in the background. You step in only when it’s time to approve something high-stakes.
Demo video (≤ 3 minutes): <ADD_VIDEO_LINK>
Live app: <ADD_PUBLIC_URL>
Devpost: <ADD_DEVPOST_LINK>
Test user (for judges/testing):
Email: test@test.com
Password: Headhunt@123
- Intercepts candidate emails + resume attachments from Gmail.
- Triages inbound threads into the right lane (application vs scheduling reply vs noise).
- Analyzes candidates with multi-pass scoring (objective score + confidence + breakdown).
- Schedules interviews by fetching live availability, proposing 3 options total (1 per day), then booking.
- Drafts offer letters and requires a founder approval gate (CIBA) before sending.
This README follows the execution flow in plan.md (priority 1), then product logic from product/headhunt-spec-v1.md.
- Demo flow
- System architecture
- Hackathon rubric (judge checklist)
- Screenshots
- Local development
- Deployment (Vercel + Supabase)
- MCP server (FastMCP)
- Agent skill doc
- Credits / non-commercial note
- Log in as a founder.
- Finish onboarding (connect Gmail + Slack + Cal.com via Token Vault).
- Enter the dashboard.
- A first intake run triggers automatically post-onboarding.
- Send an application email with a resume PDF attached.
- Headhunt triages + analyzes the candidate and updates the pipeline.
- Schedule an interview from the pipeline: pick a provider (Cal.com or Google Meet fallback) and select slots.
- Candidate replies; Headhunt parses the reply, rechecks overlap, and books.
- Draft an offer from Cmd+K.
- Founder receives a CIBA push and approves in Auth0 Guardian.
- Offer is released only after approval; pipeline state updates everywhere.
- Intercept — ingests inbox signals (thread, body, attachments).
- Triage — classifies inbound messages and decides whether to write pipeline state.
- Analyst — deep candidate evaluation with multi-pass scoring.
- Liaison — scheduling orchestration: slots → outreach → reply parsing → booking.
- Dispatch — offer workflow (draft → CIBA approval → send).
Headhunt has two ways to run agent work:
- Interactive operator runtime (in-app)
- Next.js UI (App Router) under
src/app. - Tool-calling agent runtime under
src/app/api/chat/route.ts(Vercel AI SDK).
- Headless automation runtime (cron/webhook/worker style)
- Vercel Cron triggers
GET/POST /api/cron/intake-polling(configured invercel.json). - That route proxies to Supabase Edge Function:
v2-orchestrator-cron. - Supabase orchestration calls back into the app via
POST /api/automation/executeto execute specific handler types.
This gives you:
- cookie-independent execution when M2M is configured
- deterministic handler execution
- observable run state in the database
The automation runtime is a persistent queue:
- Queue table:
automation_runs(Drizzle schema insrc/lib/db/schema/automation-runs.ts) - Audit table:
audit_logs - Core engine:
src/lib/automation/queue.ts
Key properties:
- Idempotency: inserts use
(handlerType, idempotencyKey)conflict protection. - Retries: runs can retry with backoff and end in
dead_letterwhen terminal. - Separation of concerns: orchestration (cron/webhooks) schedules work; execution runs a single handler deterministically.
Common handler types you’ll see:
intake.scancandidate.scorescheduling.request.sendscheduling.reply.parse_bookoffer.draft.createoffer.submit.*/ approval + send flows
Triage is built to be cheap and decisive:
- one structured
generateObjectclassification pass - outputs a classification + confidence (e.g. application vs scheduling reply)
- only “application” results trigger candidate/application persistence
Analyst is built to be strict:
- multiple evaluator passes (not surface-level filtering)
- produces distinct objective score and confidence score plus a breakdown
- persists structured output to candidate records so the UI can render instantly
Scheduling is designed to feel like a human coordinator:
- fetch live slots
- propose 3 options total (1 per day) across the next few days
- parse the candidate reply (option number or freeform window)
- recheck overlap to avoid stale selections
- book and move the candidate stage forward
Security model
- Token Vault holds OAuth tokens; agents don’t handle raw credentials.
- Headless execution uses an M2M app rather than replaying user cookies.
- High-stakes actions are gated with step-up approval (CIBA).
User control
- Role enforcement is handled via Auth0 FGA checks, not only UI.
- All important transitions are persisted and auditable.
Technical execution
- Next.js 15 + Vercel AI SDK for interactive tool-calling.
- Supabase Edge Functions + Vercel Cron for automation.
- FastMCP server to expose the pipeline to any MCP client.
Design
- Operator-first UI: pipeline board, candidate detail, and command-center actions.
Insight value
- CIBA used as a delegation escalation gate: draft is easy, release is protected.
Create docs/images/* and replace the placeholders below.
![]() Landing page |
![]() Dashboard |
![]() Pipeline (Applied → Interview → Offer) |
![]() Jobs |
![]() Candidate detail (score + intel) |
![]() Scheduling modal (slots + provider) |
- Node.js
>=18 - Docker (for Postgres + pgvector)
npm installdocker compose up -dcp .env.example .env.localMinimum envs for local dev:
NIM_API_KEYAUTH0_DOMAIN,AUTH0_CLIENT_ID,AUTH0_CLIENT_SECRET,AUTH0_SECRET,APP_BASE_URLDATABASE_URLFGA_STORE_ID,FGA_CLIENT_ID,FGA_CLIENT_SECRET,FGA_API_URL,FGA_API_AUDIENCE
npm run db:migrate
npm run fga:initnpm run devOptional:
npm run lint
npm run seed:demo- Set all required env vars from
.env.example. - Configure a cron auth secret:
CRON_SECRET(orAUTOMATION_CRON_SECRET)
Cron endpoint:
GET/POST /api/cron/intake-polling- schedule is configured in
vercel.json
You can also trigger it manually:
curl -X POST "https://<your-app-domain>/api/cron/intake-polling" \
-H "Authorization: Bearer <CRON_SECRET>" \
-H "Content-Type: application/json" \
--data '{}'Edge functions live under supabase/functions/* (legacy and v2-*). The recommended wiring uses:
v2-orchestrator-cronv2-webhook-candidate-createdv2-webhook-offer-statusv2-agent-*facades (intercept/triage/analyst/liaison/dispatch)
Set secrets (names in .env.example) and deploy functions. Then wire DB webhooks for inserts/updates that should enqueue work.
Headhunt is built to run without fragile cookie forwarding. The clean setup is:
- Auth0 Web App for interactive login
- Auth0 Machine-to-Machine (M2M) App for headless execution
- Token Vault connections (Google, Cal.com, Slack)
- CIBA + Guardian Push for step-up approval
- Auth0 FGA for role enforcement
AUTH0_TOKEN_VAULT_M2M_CLIENT_IDAUTH0_TOKEN_VAULT_M2M_CLIENT_SECRETAUTH0_TOKEN_VAULT_M2M_AUDIENCE
- Enable the CIBA grant type.
- Enable Guardian push and enroll the founder user.
- Set:
HEADHUNT_FOUNDER_USER_ID(orHEADHUNT_FOUNDER_USER_IDS)AUTH0_CIBA_AUDIENCEAUTH0_CIBA_SCOPE
If token exchange isn’t available in a given environment, Headhunt can fall back to the Auth0 Management API to retrieve federated connection token material (requires explicit permissions).
AUTH0_MANAGEMENT_CLIENT_IDAUTH0_MANAGEMENT_CLIENT_SECRETAUTH0_MANAGEMENT_AUDIENCE(typicallyhttps://YOUR_DOMAIN/api/v2/)AUTH0_MANAGEMENT_SCOPE(must includeread:federated_connections_tokens)
This repo includes an MCP server so you can query jobs/pipeline/candidate details from any MCP-compatible client.
npm run mcp:httpOr for local dev-only stdio:
npm run mcp:stdioEnv vars:
MCP_AUTH_AUDIENCEMCP_AUTH_ISSUER(optional; defaults toAUTH0_DOMAIN)MCP_PORT,MCP_ENDPOINT(optional)
Tools exposed include:
list_jobslist_pipelineget_candidate_detailsummarize_pipeline_health
- “List my jobs, then show my pipeline for the most recent job. Return the top candidates by score and any stalled stages.”
- “Summarize pipeline health across all jobs and tell me what to do next.”
See skills/SKILL.md for a detailed “operating manual” designed for AI agents and contributors.
- Agentation (by Benji Taylor)
- Auth0 for AI Agents — Token Vault, CIBA, and FGA
- Next.js, Vercel AI SDK, Supabase, Drizzle, FastMCP
This project is MIT licensed, but the current intent is non-commercial, demo/hackathon usage only.





