JobScout is an agentic AI job-search assistant that automates searching, scoring, and tailoring resumes/CVs for job postings with human-in-the-loop approval. It orchestrates multiple LLM-powered modules β resume parsing, tailored content generation, cover-letter writing, semantic matching, and persistent storage β in a repeatable scouting cycle.
Layer
Role
CLI / Harness
Entry point (run_scouting_cycle) that orchestrates the end-to-end pipeline: parse β search β score β tailor β write β store
Matching Engine
Scoring module (semantic + keyword overlap) against a local Chroma vector database
Tools
Modular LLM callables β resume_parser, resume_tailor, cover_letter_writer
Storage
ChromaDB for persistent job embeddings + seen-URL deduplication; CSV / Excel exports; SQLite metadata cache (via Langfuse telemetry)
External Services
OpenAI-compatible LLM API, Ollama (local nomic-embed-text), Langfuse (telemetry), custom Parse API (PARSE_API_KEY)
View High-Level Design
Category
Package
Purpose
Async HTTP
aiohttp
Async job-search HTTP requests, API calls
LLM SDK
claude-agent-sdk
Claude / Anthropic model client
Vector Store
chromadb
Local persistent embeddings & deduplication
PDF Handling
pypdf
Parse .pdf resumes
Docx Handling
python-docx
Parse .docx resumes & generated documents
Spreadsheet Output
openpyxl
Export results to .xlsx / .csv
Data Validation
pydantic
Typed schemas for CycleResult, TailoredResume, CoverLetter, etc.
Environment Config
python-dotenv
.env variable injection
Config / YAML
pyyaml
YAML configuration loading
Telemetry & Tracing
langfuse
Embedding traces, latency tracking, LLM call monitoring
Package
Purpose
pytest β₯ 7.0
Test runner
pytest-asyncio β₯ 0.21
Async test support
pytest-timeout β₯ 2.3
Guard against hanging tests
ruff
Fast Python linter / formatter
Service
Role
Config Key(s)
OpenAI-compatible LLM API
Claude, GPT-4-style model calls for parsing, tailoring, cover-letter generation
PARSE_API_KEY, OPENAI_API_KEY (or equivalent env vars)
Ollama
Local embedding model (nomic-embed-text) for vector similarity scoring
Installed locally; no remote API key
Langfuse Cloud / Self-hosted
Traces, metrics & cost monitoring for every LLM call
LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY (optional)
Custom Parse API
Proprietary resume parsing endpoint (fallback to local OCR when offline)
PARSE_API_KEY
Tool
Coverage
Mode
pytest + pytest-asyncio
Unit, integration, and harness-level tests (~165+ tests)
Auto mode for async fixtures
Timeout guard
Prevents hung tests (> 60 s each)
pytest-timeout enforced globally
Markers
Categorisation: integration, ollama, harness
Granular test selection via -m flag
βββ src/ # Core source code (Python package)
β βββ matching/ # Scorer, cosine-similarity, semantic match logic
β βββ tools/ # resume_parser, resume_tailor, cover_letter_writer
β βββ harness/ # run_cycle.py β pipeline orchestration
β βββ local_models/ # OllamaClient wrapper (nomic-embed-text)
β βββ data/ # vector_store.py β ChromaDB persistence layer
β βββ config/ # YAML / env-driven configuration loaders
βββ applications/ # CLI entry points, dashboard consumers
βββ tests/ # Full test suite (unit + integration)
βββ data/ # Sample resumes, generated job sheets (XLSX/CSV)
βββ help/ # Onboarding docs and helper scripts
βββ pyproject.toml # Build config, deps, ruff & pytest settings
βββ .env.example # Template for required environment variables
βββ run_jobscout.sh # Bash bootstrap entry point
βββ cleanup.sh # Sanitization & temporary-file removal
Local-first vector storage β ChromaDB data lives on-disk; no cloud vector endpoint required.
Embeddings stored locally via Ollama (nomic-embed-text) β sensitive resume content never leaves the machine for retrieval.
LLM calls may transmit text to third-party APIs; PARSE_API_KEY / OPENAI_API_KEY are managed through .env.
Exported spreadsheets (data/*.xlsx, data/*.csv) should be reviewed before sharing externally.
Source
Format
Usage
.env / .env.example
Key-value pairs
API keys, model names, ChromaDB path
config/*.yaml (if present)
YAML
Thresholds, scoring weights, job-search parameters
# 1. Install dependencies
# 2. Set up environment variables
# Edit .env with your API keys
# 3. Run the scouting cycle (CLI or harness)
./run_jobscout.sh # Bash bootstrap entry point
python -m src.harness.run_cycle # Direct Python entry
pytest -m " integration " # Tests requiring real API keys
pytest -m " ollama " # Tests requiring local Ollama
Metric
Instrumented Via
Notes
LLM token usage & cost
Langfuse spans
Per-parse, per-tailor, per-cover-letter
Embedding latency
Langfuse + custom logging
Vector-store fetch time tracked separately
Match scores (semantic vs overlap)
CycleResult payload
Exported to Excel for review
Last updated: August 2026 Β· Project Version 0.1.0