Skip to content

b-enedict/job-application-agent

Repository files navigation

Job Agent (Agent-First)

Single-model, tool-using job application agent for:

  • reading persistent applicant memory (experience_skills.md)
  • reading a persistent master CV Typst source (master_cv.typ)
  • asking for explicit applicant approval with evidence review
  • asking for a specific motivation-letter addition before generation
  • enforcing one output language based on the job posting
  • generating Motivation Letter PDF from text + template
  • generating CV PDF from full Typst source
  • targeting one-page CV output with overflow warnings and retries
  • writing simplified agent execution trace JSON

Quick start

  1. Install dependencies:
uv sync
  1. Set environment variables:
export OPENAI_API_KEY=your_key
# optional overrides
# export OPENAI_MODEL_AGENT=gpt-4.1-mini
# export OPENAI_AGENT_MAX_STEPS=30
  1. Ensure PocketBase collections exist:
uv run python -c "from app.main import ensure_pocketbase_collections; ensure_pocketbase_collections()"
  1. Start the backend API:
uv run uvicorn app.web.api:app --host 127.0.0.1 --port 8000

Docker Compose (Frontend + Backend + PocketBase)

  1. Copy environment template:
cp .env.example .env
  1. Fill in at least:
  • OPENAI_API_KEY
  • POCKETBASE_ADMIN_EMAIL
  • POCKETBASE_ADMIN_PASSWORD
  • WEB_AUTH_COOKIE_SECRET
  • NEXT_PUBLIC_API_BASE_URL (frontend -> backend URL)
  • POCKETBASE_PUBLIC_URL (frontend -> PocketBase URL/domain)
  1. Start everything:
docker compose up --build -d
  1. Access:

Notes:

  • Host ports are configurable via:
    • FRONTEND_HOST_PORT (default 3000)
    • BACKEND_HOST_PORT (default 8000)
    • POCKETBASE_HOST_PORT (default 8090)
  • For an external PocketBase domain, set:
    • POCKETBASE_PUBLIC_URL=https://pb.your-domain.tld (used by frontend)
    • POCKETBASE_URL=https://pb.your-domain.tld (used by backend)

Persistence:

  • PocketBase data is stored in Docker volume pocketbase_data.
  • docker compose down keeps data.
  • docker compose down -v deletes data volumes.

Web UI (Chat + Interactive Tools)

The repository now includes:

  • FastAPI backend with SSE streaming in app/web/api.py
  • Next.js chat UI in web/ (light mode, shadcn-style components)

Start backend API:

uv run uvicorn app.web.api:app --host 127.0.0.1 --port 8000

Start frontend (new terminal):

cd web
npm install
NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8000 \
NEXT_PUBLIC_POCKETBASE_URL=http://127.0.0.1:8090 \
npm run dev

Open http://127.0.0.1:3000.

Web flow:

  1. Paste job description into the large initial textbox.
  2. Click Generate documents.
  3. Watch tool calls stream as grey hint cards in the chat timeline.
  4. Review/modify evidence in the approval card and choose Accept proposal or Suggest changes.
  5. Respond to follow-up prompts in the bottom chat composer.
  6. Download generated files and preview PDFs inline from the final artifacts card.

Bootstrap Utilities

Initialize required PocketBase collections:

uv run python -c "from app.main import ensure_pocketbase_collections; ensure_pocketbase_collections()"

Runtime behavior

The agent uses a strict tool flow:

  1. retrieve experience/skills memory document
  2. retrieve master CV content
  3. select evidence and ask applicant approval
  4. collect optional custom motivation-letter point from applicant
  5. if applicant appends evidence, update memory document
  6. generate motivation letter PDF
  7. generate CV PDF

Language and wording behavior:

  • The agent detects the dominant language in the job text and uses it for both documents.
  • The agent reuses key terminology from the job listing naturally (not copy-paste style).

CV one-page behavior:

  • The agent targets exactly one page for CV output.
  • The CV should not be over-shortened; it should still use page space effectively.
  • Work experience and education are expected in reverse chronological order.
  • Full education curriculum is always preserved.
  • Rule of thumb: around 8 meaningful entries across major categories, plus skills/hobbies sections.
  • If the CV exceeds one page, it attempts compaction (trim less relevant entries, reduce/shorten bullets) and retries.
  • If still over one page, generation still completes with explicit warnings in logs and trace metadata.

Motivation letter behavior:

  • Written in a natural, human, professional tone.
  • Structured into 4 paragraphs (intro, relevant background, why this opportunity, goals/closing).
  • 400-600 words, full paragraphs, no bullet points.
  • Includes any applicant-specific motivation point collected during approval.

Generation tools are hard-gated until approval is granted.

Outputs

Default outputs:

  • trace: data/applications/agent_trace.json
  • generated files: data/applications/generated/<role-company-slug>/
    • MotivationLetter.typ
    • MotivationLetter.pdf
    • CV.typ
    • CV.pdf
  • persistent memory files:
    • data/profile/experience_skills.md
    • data/profile/master_cv.typ

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors