Inspiration

A great job application takes real effort: read the posting closely, honestly weigh your fit, and write materials that speak to this role, not a template. Do it right and it takes an hour. Do it at scale and the quality collapses — which is exactly why most applications get filtered out before a human ever reads them.

That's not a chatbot problem. It's a plan-and-execute problem: parse, assess, draft, log, follow up — six steps, zero shortcuts, every time. So we built the agent that runs the whole pipeline itself.

What it does

Give JobPilot one thing: a job posting and your profile. That's the whole interaction. No back-and-forth, no "what should I do next?" — it plans the job and finishes it:

  1. Parses the posting into structured requirements — company, title, seniority, must-have and nice-to-have skills.
  2. Scores your fit, 0–100, and names the specific gaps holding you back.
  3. Writes materials that aren't generic — tailored resume bullets and a cover letter grounded in the actual posting, not filler.
  4. Saves the application as a real, persisted record via a save_application tool call.
  5. Schedules the follow-up it just decided you need, via create_followup.
  6. Reports back — one clean summary: score, gaps, materials, next date.

Every application it's ever run stays visible on the same page, backed by the same Firestore store it wrote to. That's the point: you can watch what it did, not just read what it says it did.

How we built it

  • Google ADK is the backbone — Agent, Runner, InMemorySessionService — orchestrating the full run. The model reasons (parsing, scoring, drafting); it does not get to narrate side effects. Persistence and scheduling are real function tools it must call, not sentences it gets to write.
  • Gemini 3.7 Flash drives every reasoning and generation step.
  • FastAPI serves a single demo page and two endpoints (POST /api/run invokes the ADK Runner; GET /api/applications reads persisted state back) — the only thing deployed to Cloud Run.
  • Firestore (native mode) is the system of record.
  • We verified the installed ADK package's actual Runner / Agent / session-service signatures against the running code before writing the orchestration layer — not just against docs — which caught mismatches while they were still cheap to fix.

Challenges we ran into

The hard part isn't getting an LLM to talk about a six-step plan — it's making it finish one, unattended, with real consequences at each step. That meant drawing a hard line: reasoning stays with the model, every side effect goes through an explicit, auditable tool. Getting the instruction tight enough that it executes end-to-end in a single pass — no stalling for confirmation between steps — took real iteration.

What we learned

An agent framework is only as trustworthy as the boundary between "the model reasoned about this" and "the model actually did this." Free-form text generation for judgment calls, narrow tool calls for anything that touches real state — that boundary is what turns a chat transcript into an agent you can actually rely on.

What's next

Batch runs across multiple postings in one pass, a gap-driven learning resource recommender, and calendar integration for the follow-ups it already schedules.

Built With

Share this project:

Updates

Submission history