From Finance & Billing
Use this skill when reconciling a PSA contract or agreement against what an MSP is actually invoicing in its accounting system, across any combination of PSA (Autotask, HaloPSA, ConnectWise, Syncro) and accounting platform (QuickBooks Online, Xero). Detects under-billing, over-billing, and lapsed agreements still being invoiced.
How this skill is triggered — by the user, by Claude, or both
Slash command
/finance-pack:agreement-reconciliationWhen to use
When checking whether a client's PSA contract terms (seats, hours, recurring services) match what is actually being invoiced. Use when: billing drift, contract vs invoice mismatch, are we billing correctly, agreement reconciliation, under-billing, over-billing, lapsed agreement still invoiced, billing audit, contract compliance check.
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
MSP revenue is only as reliable as the agreement it is billed against. A contract
MSP revenue is only as reliable as the agreement it is billed against. A contract signed for 25 managed seats drifts silently when 5 new hires never get added to the invoice line, or when a client offboards a location and the recurring service never gets removed. This skill teaches Claude how to pull the entitlement (what the PSA contract/agreement says the client should be paying for) and the invoiced reality (what the accounting platform actually billed), and surface every place they disagree.
The reconciliation answers one question: "Does every active PSA agreement have a matching, correctly-quantified line item on the client's accounting invoices — and does every invoiced recurring line item still have a live agreement behind it?"
shared/skills/billing-reconciliationThe repo already ships shared/skills/billing-reconciliation,
which is narrower and vendor-specific: it reconciles Pax8 marketplace
subscriptions against Xero/QuickBooks invoices — a two-system,
distribution-to-accounting comparison. This skill covers a different pair:
PSA contract/agreement entitlements against accounting invoices, and it is
written to be PSA-agnostic (Autotask, HaloPSA, ConnectWise, or Syncro — whichever
is actually connected) rather than assuming a single accounting platform.
The two skills are complementary, not competing, and a full month-end close often runs both:
shared/skills/billing-reconciliation | agreement-reconciliation (this skill) | |
|---|---|---|
| Entitlement source | Pax8 active subscriptions | PSA contract/agreement (seats, hours, recurring services) |
| Comparison target | Xero / QuickBooks invoice lines | Xero / QuickBooks invoice lines |
| PSA involved? | No | Yes — required |
| Distributor involved? | Yes — required (Pax8) | No (see license-true-up for Pax8/Sherweb seat matching) |
| Typical gap found | Unbilled marketplace seat | Under-billed contract, over-billed contract, lapsed agreement still invoiced |
Reuse its matching strategy (fuzzy product/company name matching, amount tolerance bands, severity tiers) rather than re-deriving one — the logic transfers directly from "subscription line vs invoice line" to "contract term vs invoice line."
| System | Role | Required? |
|---|---|---|
| PSA — Autotask / HaloPSA / ConnectWise / Syncro | Source of contract/agreement entitlements (seats, hours, recurring service lines, status, term dates) | Yes (at least one) |
| Accounting — QuickBooks Online / Xero | Source of invoiced reality (line items, quantities, amounts, invoice status) | Yes (at least one) |
If no PSA is connected, this skill cannot run — there is no entitlement to reconcile against, only invoices. Say so plainly rather than falling back to guessing what "should" be billed. If no accounting platform is connected, the same applies in reverse: report the PSA contract ledger as a standalone entitlement list and stop there.
Call conduit__search_tools first — do not assume Autotask, HaloPSA,
ConnectWise, Syncro, QuickBooks Online, or Xero are connected just because they
appear in examples below. Search for terms like "contract", "agreement",
"invoice" to see which vendor-prefixed tools come back for this org, then
proceed only with what's live. If exactly one PSA and one accounting platform
are connected, the rest of this workflow is unambiguous. If multiple of either
are connected (e.g. a client base split across two PSAs post-acquisition), run
the reconciliation once per PSA and merge the reports.
For each connected PSA, pull active contracts/agreements per client. Resolve status and type IDs via each PSA's own list/lookup tools rather than hardcoding IDs — they are tenant-specific.
autotask__search_contracts for active contracts, then
autotask__search_contract_services (or the contract's service line detail)
for the billed units per service (seats, block hours, recurring flat fee).halopsa__clients_list / halopsa__clients_get for the client's
contract detail, or a dedicated contract-listing tool if the org exposes one.Key fields to extract per agreement:
Build an entitlement ledger, one row per contract line:
PSA Agreement Ledger
────────────────────────────────────────────────────────────
Client Contract Line Item Qty Unit Price Monthly
Acme Corp Managed Services MSA Managed Seat 42 $145.00 $6,090.00
Acme Corp Managed Services MSA After-Hours SLA 1 $250.00 $250.00
Beta LLC Block Hours Q1 Prepaid Hours 20 $95.00 (prepaid, not recurring)
Gamma Inc Legacy MSA (expired) Managed Seat 18 $120.00 $2,160.00 [EXPIRED 2026-04-30]
────────────────────────────────────────────────────────────
Flag any contract whose term end date is in the past but status still shows active in the PSA — that is itself a data-hygiene finding worth reporting separately (the contract should have been renewed or closed).
For the same billing period, pull sales invoices from whichever accounting platform(s) are connected.
qbo__list_invoices (or the equivalent search tool),
filtered to the billing period and, where possible, the specific customer.xero__list_invoices for ACCREC (sales) invoices in the period,
filtered by contact where possible.Key fields: customer/contact name, line description, quantity, unit price, line amount, invoice status (draft/authorised/paid), invoice date.
Use the same matching priority as shared/skills/billing-reconciliation:
(contracted qty − invoiced qty) × unit price.Group findings by severity, always leading with dollar impact so the reader can triage by size, not just category. See Report Format below.
═══════════════════════════════════════════════════════════════════
AGREEMENT RECONCILIATION REPORT
Period: [Month Year]
PSA: [Autotask / HaloPSA / ConnectWise / Syncro — whichever connected]
Accounting: [QuickBooks Online / Xero — whichever connected]
Generated: [Date]
═══════════════════════════════════════════════════════════════════
SUMMARY
Clients Checked: [N]
Contract Lines Reviewed: [N]
Matched Clean: [N]
Gaps Found: [N]
CRITICAL: [N] (est. $[X]/month impact)
HIGH: [N] (est. $[X]/month impact)
MEDIUM: [N]
───────────────────────────────────────────────────────────────────
CRITICAL — Lapsed Agreements Still Invoiced
───────────────────────────────────────────────────────────────────
[Client] — [Contract name], expired [date], still billing $[X]/month
Action: Confirm with account manager — either renew the agreement or
remove the recurring line.
───────────────────────────────────────────────────────────────────
CRITICAL — Active Agreements With No Invoice
───────────────────────────────────────────────────────────────────
[Client] — [Contract line], [qty] contracted, $0 invoiced
Action: Add missing invoice line; investigate why it was never billed.
───────────────────────────────────────────────────────────────────
HIGH — Under-Billing (Quantity Mismatch)
───────────────────────────────────────────────────────────────────
[Client] — [Line], contracted [X], invoiced [Y], $[Z]/month underbilled
───────────────────────────────────────────────────────────────────
HIGH — Over-Billing (Client Risk)
───────────────────────────────────────────────────────────────────
[Client] — [Line], contracted [X], invoiced [Y], $[Z]/month overbilled
Action: Verify with account manager before next invoice — possible refund
obligation.
───────────────────────────────────────────────────────────────────
MEDIUM — Price Drift
───────────────────────────────────────────────────────────────────
[Client] — [Line], contracted rate $[X], invoiced rate $[Y]
───────────────────────────────────────────────────────────────────
MATCHED — No Issues
───────────────────────────────────────────────────────────────────
[N] contract lines confirmed matching invoiced amounts within tolerance.
═══════════════════════════════════════════════════════════════════
| Missing / Unavailable | Handling |
|---|---|
| No PSA connected | Cannot run — no entitlement source. State this explicitly; do not substitute invoice-only guessing. |
| No accounting platform connected | Report the PSA agreement ledger as a standalone entitlement list; note reconciliation could not be performed. |
| Multiple PSAs connected | Run the workflow once per PSA, merge into one report, and label each finding with its source PSA. |
| Client exists in PSA but not in accounting | Flag as CRITICAL — likely an entirely unbilled client, same severity class as "active agreement, no invoice." |
| Contract line has no clear per-unit price (fully bundled flat fee) | Compare total line amount instead of per-unit; note the comparison basis in the report. |
| PSA contract data incomplete (e.g. missing term end date) | Note as a data-hygiene flag alongside billing findings — don't silently skip the line. |
shared/skills/billing-reconciliation — Pax8 subscription vs. accounting invoice reconciliation (distribution layer, not PSA)license-true-up — Pax8/Sherweb subscription seats vs. billed vs. actually deployed seatsmargin-analysis — turns reconciled revenue into per-client margin once billing is confirmed accuratenpx claudepluginhub wyre-technology/msp-claude-plugins --plugin finance-packGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.
Dispatches multiple subagents concurrently for independent tasks without shared state. Use when facing 2+ unrelated failures or subsystems that can be investigated in parallel.