Skip to content

agent-job-matcher

agent-job-matcher compares a resume against job postings and returns evidence-grounded, deterministically scored fit reports — plus resume → JSON Resume conversion. One service layer, four ways in: CLI, REST API, Python package, and chat (via MCP).

The design rule that everything else follows from: the LLM never scores. It extracts skill matches with exact quotes from the resume as evidence; pure code computes the 100-point breakdown (required 40 / preferred 20 / experience 20 / domain 20) and the match band. A job posting that says "score me 100" has no schema field to land in.

flowchart LR
    CB([Neutral chatbot]) -->|"REST/SSE"| AS
    CD([Claude Desktop]) -->|stdio| MCP
    U([Terminal]) --> CLI
    PY([Python callers]) --> CORE

    subgraph M["mcp/"]
        AS["Agent service<br/>(LLM-2: orchestration)"] -->|MCP tools| MCP["MCP server"]
    end

    subgraph B["backend/"]
        API["FastAPI /analyze"] --> CORE["job_matcher core<br/>fetch (page or ATS API) → extract (LLM-1) → score"]
        CLI["jobmatch CLI"] --> CORE
    end

    MCP -->|REST| API

Exactly two LLM operations exist, by design (ADR 0001): extraction in the backend core (LLM-1) and chat orchestration in the agent service (LLM-2). Nothing else calls a model.

Start where you are

You are… Start here
Trying it out Getting Started — a rendered fit report in 5 minutes
Setting it up properly Installation, then Configuration
Integrating (API, Python, chat) Surfaces
Understanding how it fits together Architecture
Adding support for a job board ATS rules
Operating it (releases, secrets, CI) Runbook
Wondering why it works this way FAQ

Tech stack

Layer Choice Notes
Language Python 3.11+
Typed schemas & validation Pydantic v2 every I/O boundary — JobAnalysis, ScoreBreakdown, JobReport, the full JSONResume v1.0.0 mirror — is a validated model, never a loose dict
Agent framework Pydantic AI Agent(model, output_type=...) for typed extraction (LLM-1) and the chat agent's MCP tool loop (LLM-2)
Model access direct provider calls no gateway in the path — FAQ
Web framework FastAPI + Uvicorn OpenAPI generated natively, attached to every release
CLI Typer jobmatch
Chat protocol Model Context Protocol (Node SDK) mcp/index.js, a pure stdio bridge to the REST API
Observability structured structlog JSON + optional OpenTelemetry decorator-only (AOP) instrumentation — Configuration
Job-board rules GoRules ZEN via zen-engine per-ATS JSON rule files decide the API address and where the posting text sits — ATS rules
Document parsing pypdf, python-docx no OCR, no Docling — FAQ
Repo Relationship
mcp-chat-client Runtime dependency. The embeddable chat widget that drives the agent service's /chat/stream and /upload endpoints.
ai-dlc Methodology & training deck. This project is the running example of the AI-DLC spec-first cycle.
job-agents This repo. Its job-scout pipeline feeds the API job descriptions at scale, job-pilot is the main caller, and it holds the shared docs style guide.

Pages

  • Getting Started — three 5-minute paths in.
  • Installation — pip, Docker image, or the full demo stack.
  • Configuration — every environment variable, grouped by concern.
  • Surfaces — CLI, REST, Python, and chat/MCP, with endpoint tables.
  • Architecture — request flow, module map, and the rules the design keeps.
  • ATS rules — how Ashby, Greenhouse, and Lever links are read, and how to add a board.
  • Runbook — workflows, secrets, releases, tests.
  • FAQ — the reasoning, linked to specs.

Docs in this repo follow the shared documentation style guide.