Deep dive: agent tooling

A job search kit where every number can be rerun for free

Seven skills, seven agents and eleven Python scripts that score a résumé, LinkedIn profile, GitHub profile and portfolio against live public labor data, then rebuild them from one source of truth.

  • $0in API keys or paid data to run the whole chain
  • 7 + 7 + 3skills, agents and commands
  • 62offline tests, passing in under a second
  • 0third-party Python dependencies
Role
Sole author. Version 1.1.0.
Stack
Python 3.10+ standard library, Claude Code skills, subagents and slash commands
Data
O*NET database files, BLS Employment Projections, BLS Public Data API, public Greenhouse, Lever and Ashby job boards, GitHub REST API
Built for
The Job Hunting in the Age of AI workshop on Master.dev (formerly Frontend Masters), 11 November 2026

The problem

Job seekers get résumé advice with no source behind it, and AI tools that will happily invent a metric to make a bullet sound better. A candidate then walks into an interview carrying a claim they cannot defend. The people this hurts most are the ones Vets Who Code serves: career changers with real experience and no network to tell them what the market wants.

What it has to do

The kit is built on three laws, stated in its README:

  1. Measure everything.
  2. Never list what you can’t defend.
  3. Distribution beats talent.

In practice that means every score traces to public data a learner can fetch themselves, and the tooling refuses to write a claim the candidate did not supply.

Approach and architecture

The portfolio is the master record. A portfolio.json file and a curated brag database hold the facts. The résumé, LinkedIn and GitHub profile are scored against the market, then regenerated from that record so they always agree with each other.

Scoring chain: the résumé scorer runs first against live O*NET and BLS data, then LinkedIn, GitHub and portfolio scorers reuse its target, a composite scorer combines them, an improvement plan ranks fixes, and the résumé rebuilder regenerates the résumé from the portfolio record. O*NET + BLS, live 1. Résumé scorer sets the target 2. LinkedIn 3. GitHub 4. Portfolio same JSON shape 5. Composite two reads 6. Improvement plan biggest gain first 7. Résumé rebuilder from portfolio.json
Each step is a skill with a script behind it. Every scorer writes the same JSON shape so step 5 can combine them.

Data model

  • portfolio.json: profile, experience and artifacts. The master record.
  • brag/entries/: curated wins, promoted by hand from an inbox that a Friday script fills from merged pull requests, with redaction.
  • resume-score.json: the market target from step 1, reused by steps 2 to 4.
  • One score file per surface, all in the same shape.

Key tradeoffs

Standard library only, keyless data only

The kit uses no pip packages and no licensed or keyed data, because, in the words of its method document, “every learner has to be able to rerun every number for free.” That rules out richer commercial labor data. Recorded as DR-007.

Live data or stop

If a data source cannot be reached, the script prints STOPPED: and exits. It never falls back to a remembered number. A learner sometimes gets no score, and never gets a stale one presented as current. Recorded as DR-008.

Scripts compute, the model grades evidence

Every number comes from a script. The model’s job is to judge whether a line of the résumé is evidence for a skill, and it has to answer with a quote. Scripts reject a quote that is not in the text. Recorded as DR-009.

Two composite scores, with the weights declared as judgment

A machine read weights the résumé at 40, LinkedIn 35, GitHub 15 and portfolio 10. A human read weights portfolio 35, GitHub 30, résumé 20 and LinkedIn 15. The documentation calls those weights “a VWC design judgment, not research,” and every one can be overridden from the command line. Recorded as DR-010.

Measurable outcome

  • The full chain runs with no account, no API key and nothing to install beyond Python.
  • 62 tests in 19 classes run offline against synthetic fixtures and pass in under a second. They cover parsing, both O*NET file layouts, matcher false positives, every chain step, the live-data stop and redaction.
  • A GitHub scoring run uses about 20 of the 60 unauthenticated requests an hour the API allows.

AI collaboration note

The kit is itself a set of instructions for an AI assistant, so its guardrails are the product:

  • The résumé rebuilder may not invent employers, titles, dates, metrics or skills. A missing fact is written as [ask: …] for the person to fill in.
  • Every sourced number carries a tag for where it came from. Unverified figures are never used as rules.
  • Agent tool access is restricted. The final-round panel agent can only read.
  • The mock interviewer does not score tone, accent or pace.
  • Nothing sends, posts or applies on the user’s behalf.
  • Scripts refuse to read or write a résumé inside a git repository, so personal data is not committed by accident.

Known limits

  • Neither composite is a hiring prediction. The documentation says so.
  • Outside proof is corroboration the user supplies. The kit does not verify it.
  • Interview answers have no second-grader agreement check yet.
  • Portfolio sites rendered entirely in JavaScript cannot be fully audited.
  • The BLS public API has a small daily quota.

What I’d change in v2

  • Add CI. The tests exist and pass locally. They should run on every push.
  • Publish grader agreement numbers. The tooling to measure agreement between two graders is in the kit, with a target of the same letter on 90% of qualifications. The measured results belong in the repo.
  • Add a second-grader check for interview answers.

Walk me through it

  1. The failure this prevents: a candidate defending a number an AI made up.
  2. Why the portfolio is the master record and everything else is generated from it.
  3. The chain, one step at a time, and why step 1 sets the target for the rest.
  4. What the scripts do and what the model is allowed to do.
  5. Why the kit stops when data is unavailable.
  6. Why there are two scores and why the weights are labelled as judgment.