Pay Reconciliation Agent
Code location: product/mr-people-agents/recon/
Linear ticket: MRP-109
Status: LIVE — runs weekly, Syra reviews findings
Uses AI: No. Purely rules-based, deterministic.
What it does
This agent audits Paylocity employee data by comparing CSV exports against a set of configurable rules. It catches data integrity issues, pay discrepancies, and compliance gaps before they become problems. Think of it as an automated auditor that runs the same checks a careful HR person would do manually, but every week without missing anything.
What it audits
| Audit | What it checks | Cadence |
|---|---|---|
| Field integrity | Required fields aren't blank, emails match expected domains, values are from allowed lists, conditional fields are correct (e.g., "if role is X, then field Y must be Z") | Weekly (biweekly gate tied to payday) |
| Reporting structure | Manager assignments are valid, org hierarchy is consistent | Weekly |
| Time-off / accrual assignment | Accrual banks match what the employee should have based on state, employment type, and role | Weekly |
| Zero hours worked | Flags employees who weren't paid in a pay period. Classifies each as: new hire (expected), absent from Legion (investigate), or worked-but-unpaid (urgent) | Weekly |
| Benefit class consistency | Full-time vs part-time status matches benefit class assignment | Weekly |
| Wage audit | Compares hourly rates and salaries against federal, state, and local minimum wage floors | Monthly |
| Job change closeout | Validates that job changes processed last week were completed correctly | Every Monday |
Data flow
Paylocity
↓ Scheduled CSV reports (weekly, Sunday 2pm)
↓ via SFTP to MR's own server
GitHub Action (recon-report-bridge, lives in mr-people repo)
↓ Pulls from SFTP, deposits into Google Drive inbox folder
Apps Script (recon agent)
↓ Reads CSVs from Drive, validates headers/schemas
↓ Runs rules against each row
↓ Deduplicates findings against existing Exception Queue
Spreadsheet
├── Exception Queue tab (findings for Syra to review)
├── Audit Log tab (append-only record of everything)
└── Dry Run tabs (snapshot per run date, for review before go-live)
CSV reports consumed
The agent reads 6-7 different Paylocity report exports:
- Biweekly integrity report (employee fields)
- Base employee data
- Accrual/time-off balances
- ENP (Employees Not Paid) report
- Benefit class report
- Current rates (hourly/salary)
- Job change report (Monday closeout)
Ingest validation
Before processing, the agent validates each CSV:
- Schema drift protection — checks that column headers match expected schema. If Paylocity changes a column name, the agent fails loudly instead of silently processing wrong data.
- Row-floor gates — if a report has suspiciously few rows (e.g., 3 employees when there should be 1,200), it flags it as a data quality issue rather than processing garbage.
Rules engine
Rules are defined as spreadsheet rows in the FieldRules tab, not as code. Each rule has:
| Column | What it means |
|---|---|
rule_id | Unique identifier (e.g., FI-001) |
report | Which CSV report this rule applies to |
field | Which column to check |
type | What kind of check: not_blank, email_domain, one_of, equals, matches_map, required_if, blank_if, etc. |
param | The expected value, list, or map name |
severity | How urgent: error, warning, info |
This means the People team can add, modify, or disable rules by editing spreadsheet rows. No code change or deploy needed.
Rule types (8 total)
- not_blank — field must have a value
- email_domain — email must end with expected domain (e.g.,
@madison-reed.com) - one_of — value must be in an allowed list
- equals — value must exactly match a specific value
- matches_map — value must match a lookup table (e.g., department code maps to expected job title family)
- required_if — field is required only when another field has a certain value
- blank_if — field must be blank when another field has a certain value
- Additional conditional types for complex business rules
Exception handling
When the agent finds an issue:
- It creates a finding with a dedup key (so the same issue isn't flagged twice)
- It checks the Exception Queue for existing open findings with that key
- If it's new, it appends to the queue with status
open - It routes the finding to a named reviewer based on the Routing tab (exception type maps to a person's email)
- When the underlying data is fixed in Paylocity, the next run's auto-clear pass marks the finding as
cleared
Syra is the primary reviewer. Findings that involve fields the employee controls (email, address) route to the employee for self-fix.
Webhook (optional)
The agent can also be triggered by Paylocity events via an HTTP webhook:
- URL:
https://script.google.com/macros/s/.../exec?k=<secret>&event=<name> - Events:
payroll_processed,employee_change,new_hire,termination,job_change - Authentication: long secret in the URL query parameter
- Response: 200 + JSON
This lets the agent react to real-time events (e.g., run an integrity check immediately after payroll processes) in addition to the scheduled weekly runs.
Current status and recent history
- Week 1 results: Rules converged from 249 open findings to 19, every reduction attributable to a specific rule refinement
- Rule refinements from Syra's first review (July 15): contractor scoping, LOA suppression, time-bank home-state fallback, benefit-class prior-month rule, CEO-direct exemption, suppression list, persistent reviewer notes
- Hardening complete: rules goldens (baseline snapshots), janitor (cleanup), build stamps, handover docs (operator manual + rules codebook + report contracts) all set in
mr-people - Auto-clear working: when Syra fixes something in Paylocity, the next run picks it up and clears the finding. 17 of her fixes were awaiting verification as of late July.
Open items
| Item | Status | Notes |
|---|---|---|
| Benefit Class Report audit decision | Waiting on Syra | Whether to expand the FT/PT check to a full composite (state x salaried/hourly = exact benefit class) |
| Legion by-day auto-ingest wiring | Open | Automating the daily Legion email pickup |
| Policy-sheet mapper phase 2 | Open | Extending the rule engine to handle more complex policy lookups |
| Time-bank eligibility rules | Needs Syra's input | Which accrual bank for which state/county/FT-PT combo |
| Code migration to mr-people | Decided | Moves after first live cycle + Syra sign-off |