AI agents

Bias-aware CV screener with audit log

LangGraph agent that scores CVs against must-have criteria, writes two-line reasons, drafts replies, redacts protected traits and logs scores for audit.

pythonlanggraphpydanticpytestuvruff

Built 1 time, downloaded 0 times.

Install from your terminal

Run this in your project folder. It signs you in, shows what changes and asks before it overwrites a file.

npx claude-lab add bias-aware-cv-screener-with-audit-log-6c080f
CLAUDE.md
# CV screener

## Purpose

One run scores a folder of CVs against the hiring manager's must-have list from a job file. Each candidate gets a per-criterion result, a two-line reason, and a draft rejection or interview invite. A human reviews and sends every message. The tool never sends email.

## Stack

- Python 3.12, managed with uv
- LangGraph for the agent graph, Pydantic v2 for all state and models
- pytest, ruff, mypy
- Package layout: `src/screener/` with `nodes/`, `graph.py`, `models.py`, `redact.py`, `audit.py`, `cli.py`

## Commands

- Tests: `uv run pytest -q`
- Lint: `uv run ruff check .`
- Types: `uv run mypy src`
- Dry run: `uv run python -m screener.cli run --job jobs/example.yaml --cvs data/sample_cvs --dry-run`

## Hard rules

- Protected traits never reach a scoring prompt or a reason. This covers age, date of birth, gender, name-implied gender, nationality, photo, marital status and graduation year. `redact.py` runs before any LLM call.
- Scoring uses only the must-have criteria in the job file. Do not infer or add criteria.
- Each criterion gets `met`, `partial` or `not_met`, plus a quoted CV snippet as evidence.
- Every score writes one append-only JSON line to `audit/scores.jsonl`: run_id, job_id, candidate_id hash, criteria results, total, model, prompt_version, timestamp. If the write fails, the node fails.
- Reasons are exactly two lines and refer to criteria only.
- Drafts are polite, give no reasons beyond the criteria, and are saved as drafts. They are never sent.
- No real CVs or personal data in the repo, tests or commits. Use synthetic fixtures in `tests/fixtures/`.
- Secrets come from environment variables such as `YOUR_API_KEY`. Never commit them.
- Do not hand-edit `audit/`. Do not change the audit schema without asking.

## Gotchas

- LangGraph state must be Pydantic models. Identify candidates by a hash of the ID, never by name.
- Keep temperature 0 for scoring.
- Bump `prompt_version` whenever a prompt changes. The fairness check and REVIEW.md both look for this.
- Changing effort keeps the prompt cache on current Claude models. Switching models breaks it, so avoid switching mid-task.

## Workflow

- Explore, then plan, then code, then run the `verify` skill before saying done.
- Use `/clear` between unrelated tasks and `/compact` at natural breaks.
- Phases and their `/goal` prompts are in PLAN.md. Run `/clear` between phases.
- Changes that touch prompts, `redact.py` or scoring nodes also need the `fairness-check` skill.

## Review

@REVIEW.md
Use for my project