Skip to main content

Minimum Wage Monitor

Code location: product/mr-people-agents/minwage/ Linear ticket: MRP-110 Status: Built, awaiting decisions on cadence and jurisdiction scope Uses AI: Yes. One Claude call per statute page (data extraction, not conversation).

What it does

MR has employees in multiple states and cities, each with different minimum wage laws. Before this agent, no system at MR watched wage law changes. If a state raised its minimum wage, someone would have to notice, manually check which employees were affected, and route pay adjustments. This agent automates that surveillance.

It does two things:

  1. Watches public government wage-law pages and extracts the current minimums
  2. Compares employee pay rates against those minimums and flags anyone who's below or will be soon

How it works

Step 1: Statute parsing

The agent fetches public web pages from government labor departments:

  • California DIR (Department of Industrial Relations)
  • Washington L&I (Labor & Industries)
  • Colorado CDLE (Colorado Department of Labor and Employment)
  • San Francisco OLSE (Office of Labor Standards Enforcement)
  • US DOL (Department of Labor, for federal minimums)

For each page, it makes one Claude API call that extracts structured data:

{
"jurisdiction": "California",
"dimension": "hourly",
"new_floor": 16.50,
"effective_date": "2025-01-01",
"source_url": "https://dir.ca.gov/..."
}

The prompt is narrow and strict: extract these four fields as JSON. If the model can't parse the page or returns malformed data, the agent fails loudly (no silent degradation).

Step 2: Threshold state machine

Extracted wage floors don't go live immediately. They enter a staging pipeline:

parse → pending-confirm → (human reviews) → live
→ rejected
needs-human → (human investigates) → live
→ rejected
StateWhat it means
pending-confirmAgent extracted a value; a human needs to verify it's correct
needs-humanAgent couldn't confidently extract the data; human must look at the source
liveHuman confirmed; this threshold is now used for comparisons
rejectedHuman reviewed and said it's wrong; ignored in comparisons
supersededA newer threshold for the same jurisdiction replaced this one

Nothing the agent writes goes directly into the comparison. A human always ratifies first.

Step 3: Wage comparison

Using only live thresholds, the agent compares employee pay against legal minimums:

  • Hourly employees: Is hourly rate >= the floor for their work location?
  • Salaried employees: Does salary meet the FLSA (Fair Labor Standards Act) salary threshold for their exemption classification?
  • Lookahead: Flags employees who will fall below a new minimum within a configurable window (default: 60 days)

Violations and upcoming changes route to the Job Change workflow. The agent flags; a human enters the pay adjustment in Paylocity.

Four dimensions of comparison

The wage comparison handles four dimensions simultaneously:

  1. Federal — FLSA federal minimum wage and salary thresholds
  2. State — State-specific minimums (CA, WA, CO, etc.)
  3. Local — City/county minimums (San Francisco, potentially LA, West Hollywood, Santa Monica)
  4. Employment type — Different thresholds for full-time vs part-time, hourly vs salaried

The highest applicable floor wins (an employee in San Francisco must meet the SF minimum, not just the California or federal one).

Data flow

Government wage-law websites (public)
↓ Agent fetches page text
Claude API (one call per page)
↓ Extracts jurisdiction, dimension, floor, effective_date
Thresholds tab in spreadsheet (pending-confirm state)
↓ Human reviews, flips to live or rejected
Live thresholds
+ Employee current rates (Paylocity CSV export from Drive)
↓ Wage comparison
Exception Queue (violations + upcoming changes)
↓ Routes to named reviewer
Job Change workflow in Paylocity (human enters the fix)

Open decisions

These need to be resolved before the agent goes live:

DecisionWhat it meansWho decides
Cadence (Q8)How often does the agent run? Monthly (mid-month) or quarterly? The code accepts either; installTriggers(cadence) takes it as an argument.Shlanda / Syra
Jurisdiction list (Q9)Which locations to watch. Confirmed: CA, WA, CO, SF. Candidates: LA City, LA County, West Hollywood, Santa Monica.Shlanda
FLSA salary dimension scopeWhich salary thresholds MR needs to track (some FLSA exemption levels may not apply to MR's workforce)Grecia
Confirm-gate owner (Q13)Who ratifies pending-confirm rows before they become live?Shlanda

Key files

FileWhat it does
minwage_lib.jsPure logic: threshold merging, deduplication, state machine transitions, wage comparison, exception fragment construction
Code.gsI/O: fetches web pages, calls Claude, validates JSON output, writes thresholds and exceptions to the spreadsheet
statute_prompt.jsThe prompt and JSON schema for the bounded Claude call

Spreadsheet tabs

TabPurpose
ConfigKey/value settings (lookahead_days, etc.)
SourcesURLs and jurisdictions to watch
ThresholdsState machine: each row is a wage floor with status (live/pending-confirm/needs-human/rejected/superseded)
JurisdictionsMaps employee work locations to jurisdictions (e.g., "San Francisco HCB" maps to SF local + CA state + federal)
RoutingException type to reviewer email
Exception QueueFlagged violations and upcoming changes
Audit LogAppend-only record of every parse, comparison, and routing