Bonus Blog Post
The promise
I didn't set out to "add auth." I set out to make a promise in the UI: when you click Schedule or Send follow‑up, it either works or it fails in a way that makes sense. No limbo states. No invisible token drama.
The reality check
Token Vault ended up as the backbone, and honestly, it was more humbling than I expected. The goal was connect once, then forget. What I actually got was a crash course in OAuth edge cases:
- Missing
offline_access(where supported) - Flaky
userinfopayloads when the right scopes aren’t there - “Refresh tokens” that exist in theory but not in practice unless you push
prompt=consentat the right moment
The technical wins
My assistant routinely fires multiple tool calls (calendar checks, email drafts, CRM updates). That surfaced a nasty pattern: simultaneous token reads triggering refresh races, which cascaded into repeated “please reconnect” loops.
What I shipped (and what I’m most proud of):
- In‑flight token dedupe + a short retry/cooldown guard to stop refresh storms
- Auth-as-state, not exceptions: Token Vault “authorization required” becomes a first‑class UI path
- Token‑Vault‑aware automation: when a tool returns the specific “authorization required to access the Token Vault” signature, the run pauses in an explicit awaiting reauth state, preserves
tokenVaultLoginHint, and resumes after reconnect without the user replaying steps
Security UX (the underrated part)
Token Vault kept token handling behind a narrow boundary, so long-running actions degrade safely: draft instead of send, propose times instead of book, and resume only when the Vault is healthy.
That combination—intent‑preserving UX plus strict token boundaries—is when the project stopped feeling like “a chatbot with integrations” and started feeling like a dependable recruiting copilot.
Headhunt — Hiring, on autopilot.
Inspiration
Most early-stage founders are also the hiring manager, the interviewer, and the person who has to keep shipping product at the same time. And somehow, in between all of that, they're also sorting inboxes. Moving names through a spreadsheet. Sending the same "thanks for applying" email for the fourteenth time.
Congratulations, you've built a full-time job out of copy-pasting names into a spreadsheet.
Every tool that exists was built for recruiting teams - the ones most of us can't afford yet. We wanted something built for the founder doing it alone.
What it does
You describe the role. Headhunt handles everything after that.
Post the job, connect your Gmail, and a fully agent-driven pipeline takes over. An Intercept agent pulls incoming emails. A Triage agent reads each one and classifies it - application, scheduling reply, or noise. The Analyst agent runs a fit review against your actual job description, not a generic rubric. Dispatch drafts the offer letter the moment you're ready.
You don't sort. You don't forward. You don't chase. You show up at the end to make the call.
How we built it
Five agents, each with a single job, talking to each other through a webhook-driven pipeline. No polling. No manual triggers. When an email lands, the system moves.
The JD and offer letter generation runs on Kimi K2. The agent orchestration layer sits on top of a user-specific database that isolates each org's pipeline cleanly. Auth runs off the logged-in user's token - intentionally lightweight for the demo, with an M2M route documented for production use.
The model throughout: if an agent can do it autonomously, it should. The human only shows up where judgment is actually required.
Challenges we ran into
Getting the agents to hand off cleanly without a human in the loop was harder than expected. The webhook chain - email in, triage fires, analyst triggers, status updates... had to be airtight or the whole "autonomous" story falls apart.
M2M authentication via the Management API hit a configuration wall during the build. We pivoted to a headed approach using the logged-in user's token, which works for the demo and is honest about its constraints rather than hiding them.
Accomplishments that we're proud of
The Analyst agent doesn't just route - it reads. When a strong candidate applies for a founding PM role with only scaled-company experience, it flags the gap. That's not keyword matching. That's the kind of signal a good recruiter catches, and the system is doing it without being asked.
End to end, from job posted to candidate triaged and offer letter drafted, with zero inbox time from the founder.
What we learned
Agents are only as good as their handoffs. The UX of an autonomous system is almost entirely about what happens when something goes wrong mid-pipeline — and building the failure states is where most of the real work lived.
Also: founders don't want more dashboards. They want fewer decisions. That reframe changed how we thought about every screen.
What's next for Headhunt
Scheduling automation - the agent books the call, not just classifies the reply. Structured scorecards generated from the JD before the interview, not after. Deploying the platform's tool bundled in a MCP that anyone can use with Claude or ChatGPT, anytime anywhere.
The goal is a hiring process that runs in the background like infrastructure. You think about it when you're ready to make a hire. Not before.
Built With
- auth0
- cal.com
- gmail
- google-gmail-oauth
- next.js
- oauth
- slack
- supabase
- vercel


Log in or sign up for Devpost to join the conversation.