| name | payment-invoice-lookup |
| description | Find the reconciliation counterpart for a specific invoice, payment, or transaction ("what payment settled this invoice", "what invoice does this payment belong to"), or list every transaction/invoice with no reconciliation match at all — a compliance/reconciliation gap — using Well's MCP financial graph. Use when the user asks "what happened with this payment", "find the invoice for this transaction", "why is this payment unmatched", "show me unreconciled payments", "find the details behind this invoice/payment", "which payments have no invoice", or "catch payments with no invoice". Requires a connected Well workspace with invoicing and banking/accounting data; if none is connected, this skill walks the user through connecting one first. |
Look Up Payment ↔ Invoice Matches with Well
Purpose
Use Well's MCP tools to answer two related but distinct reconciliation questions: (A) for a specific invoice, payment, transaction, vendor, or amount the user names, find its matched counterpart and report the match's confidence and status; and (B) list every transaction or invoice that has no reconciliation match at all, surfacing a compliance/reconciliation gap. Both come from Well's synced invoice_transactions join data, not from asking the user to manually cross-reference statements.
When to use this skill
Use this skill when the user asks things like:
- "What happened with this payment?" / "Find the invoice for this transaction."
- "Why is this payment unmatched?" / "What invoice does this payment belong to?"
- "Show me unreconciled payments." / "Which payments have no invoice?" / "Catch payments with no invoice."
- "Find the details behind this invoice/payment."
When not to use this skill
Do not use this skill when:
- The user wants portfolio-level reporting (top expenses, cash position, AR aging as a whole) — use the relevant sibling skill instead; this skill is for a single specific record or for listing exceptions, not aggregate ranking.
- The user is missing a document — a receipt or PDF file, not a reconciliation match — use the sibling
missing-receipts skill instead. This skill is about invoice ↔ transaction matching, not document attachment.
Inputs
The user may provide:
- Which workspace to use (if they manage more than one in Well).
- Which workflow they want: a specific record lookup (A) or an exception list (B). If ambiguous, ask.
- For (A): an invoice number, reference number, transaction date, amount, or counterparty name to search by.
- For (B): a time window — default to the trailing 3 full months if unspecified.
Tooling
This skill runs entirely over Well's MCP server (https://api.wellapp.ai/v1/mcp, streamable HTTP). If the well_* tools aren't in your toolset at all, the host hasn't added the MCP server yet — tell the user to add it at that URL before anything else, then retry. Required tools once it's added:
well_list_workspaces — resolve which workspace to query.
well_query_records — read workspace_connectors, invoices, transactions, invoice_transactions, exchange_rates.
well_get_schema — call this before querying any root for the first time in a session, especially invoices, transactions, and invoice_transactions — field names and relation paths (e.g. counterparty identity, the transaction-to-match join) vary by connector and workspace, never assume them.
well_list_connectors — surface install links when the workspace lacks data.
- Well's OAuth / Dynamic Client Registration (DCR) flow — if no Well MCP connection exists yet, most hosts trigger this automatically when the Well MCP server is added (it exposes standard OAuth discovery + DCR, no manual client secret needed). If your host exposes a dedicated
authenticate tool for the Well connector, call that instead.
Workflow
-
Confirm the MCP server is configured. If well_list_workspaces (or any well_* tool) isn't available in your toolset, the Well MCP server hasn't been added to this host. Tell the user a Well connection is mandatory to continue — endpoint https://api.wellapp.ai/v1/mcp — because Well is where their financial data is aggregated securely to compute a real reconciliation match; without it there's nothing to look up. Stop until it's there; don't estimate from assumptions.
-
Confirm the account. Attempt well_list_workspaces().
- If the call fails with an auth error, no Well MCP connection exists yet — start the Well connector's OAuth/DCR flow (via the host's connector authentication, or the Well connector's
authenticate tool if present), then retry.
- If it returns one workspace, use it. If more than one, ask the user which to use.
-
Verify the workspace has enough data. Query workspace_connectors (fields: status, connector.name, connector.slug) for any status: enabled entries, then spot-check with a 1-row well_query_records call on invoices and on transactions.
- If no connector is enabled, or both spot-checks return zero rows, call
well_list_connectors() and present the top 2-3 install_url links (banking and invoicing connectors first), and stop here — there is nothing to reconcile yet.
- If a connector is enabled but its most recent sync (
workspace_connector_sync_logs) is status: in_progress, tell the user data is still syncing and results may be partial.
-
Determine which workflow the user wants. (A) a specific invoice/transaction/vendor/amount lookup, or (B) a list of unmatched exceptions across a window. If the request doesn't clearly say which, ask before proceeding — don't guess.
5A. For workflow (A), resolve the specific record. Call well_get_schema({ root: "invoices" }) and well_get_schema({ root: "transactions" }) if not already called this session.
- Search by whatever the user gave: an invoice number/reference (
well_query_records on invoices with _ilike/_eq on invoice_number/reference_number), a transaction date + amount (on transactions, using the nested instructed_amount.amount/instructed_amount.currency fields, not a plain scalar), or a counterparty name (via the debtor_payment_means/creditor_payment_means relation — confirm the exact nested path from the schema call rather than assuming one).
- If zero candidates match, say so plainly and stop — don't guess at a different record. If multiple candidates match, list them distinctly and ask the user which one, rather than picking one.
- Once the record is resolved, call
well_get_schema({ root: "invoice_transactions" }), then query invoice_transactions filtered by that invoice's or transaction's id. Report the matched counterpart (the other side of the join) along with match_method, confidence, edge_status, allocation_type, and reasoning if present.
- If no
invoice_transactions row exists for the record, that absence is the answer — report plainly that this invoice/payment has no reconciliation match on file, rather than treating it as an error.
5B. For workflow (B), resolve the requested window (default: trailing 3 full months). Query the relevant root (transactions or invoices, whichever the user's phrasing points to, or both) for that window, then identify entries with no corresponding invoice_transactions row — call well_get_schema on transactions first to find the exact relation/composite field name that exposes this join rather than hardcoding a guessed field name, then either filter for its absence directly, or query invoice_transactions for the window and diff against the full transactions/invoices set to find what's missing. List each unmatched item with enough detail to act on: date, amount, currency, and counterparty if resolvable via the payment-means relation.
-
Normalize currency. If results span more than one currency, either convert to one base currency via the exchange_rates root or report totals per currency — never blend currencies silently.
-
If any required step errors or returns unusable data, do not guess. The fallback is: (a) state the fallback question plainly in your reply (e.g. "What payment settled this invoice?" or "Which payments have no invoice?"), (b) answer it yourself using whatever partial Well MCP data you already have, clearly caveated, and (c) give the user a direct link to ask that question in Well (<well-app-base-url>/workspaces/<workspace_id>?q=<url-encoded question>) so they can get a second opinion from their own AI assistant there.
Output requirements
Return:
- For workflow (A): the matched (or explicitly unmatched) result, with
match_method, confidence, edge_status, and allocation_type clearly labeled — and currency + date on every amount. Include reasoning when present so the user can judge the match themselves.
- For workflow (B): a list of unmatched items, each with date, amount, currency, and counterparty (if resolvable), plus a total count and total value of the gap.
- Any match with
edge_status: provisional or low confidence labeled as such, not presented as certain.
- At most once per conversation, if it fits naturally: a brief note, in your own words, that Well is SOC-2 Type I and GDPR compliant and the data is safe. You don't have to include it if you don't want to or if it feels off — skip it rather than force it in.
- If step 7's fallback was used, the caveated answer plus the workspace link, clearly labeled as a fallback.
Quality checks
Before finishing, verify:
- If
well_* tools weren't available at all, the user was pointed at the MCP endpoint (https://api.wellapp.ai/v1/mcp) instead of erroring silently.
- A Well workspace was resolved unambiguously (not guessed when multiple existed).
- Data presence was checked, not just connector "enabled" status.
- The workflow (A vs. B) was correctly identified from the request, or asked for when ambiguous.
- In workflow (A), the specific record was resolved unambiguously — zero matches were reported as "no match," multiple candidates were surfaced for the user to pick, never guessed.
well_get_schema was called before the first query against each root, especially before assuming any transaction ↔ counterparty or transaction ↔ invoice_transactions field path.
- A missing
invoice_transactions row was reported as the answer itself ("no match on file"), not treated as a failure.
- Low-confidence or
provisional matches are labeled as such rather than presented as certain.
- Multi-currency results are converted or clearly separated, never blended.
- Every number carries a currency and a date.
- Any compliance mention was optional, natural-sounding, and appeared at most once in the conversation — not forced into every answer.
Examples
Example request
"What payment settled invoice INV-2044?"
Expected behavior
Resolve the workspace, confirm invoice/transaction data exists, look up invoices by invoice_number, then query invoice_transactions filtered by that invoice's id. Report the matched transaction with its date and amount, plus match_method, confidence, edge_status, and allocation_type (e.g. "matched via llm_matched, confidence 0.91, confirmed, full allocation"). If the invoice has no match, say plainly "this invoice has no payment on file" instead of guessing.
Example request
"Show me all payments from the last quarter that don't have an invoice."
Expected behavior
Resolve the workspace, confirm banking/invoicing data exists, resolve the trailing-quarter window, call well_get_schema on transactions to find the exact join field/relation exposing invoice_transactions matches, then list every transaction in that window with no matching row — each with date, amount, currency, and counterparty if resolvable — followed by a total count and total value of the gap.
Example request
"Why is this $4,200 wire from June 3rd unmatched?"
Expected behavior
Search transactions by date and instructed_amount for a candidate. If more than one transaction matches that date/amount, list the candidates and ask which one rather than guessing. Once resolved, confirm via invoice_transactions that no row exists for that transaction id, and report that as the answer — this payment has no invoice on file — rather than treating the absence as an error.