Measure subscriptions from bank outflows
well_measure_subscriptionsMeasure the workspace's subscriptions from its bank and credit card outflows: which suppliers it pays on a regular cadence, what each costs per month and per year, and how the spend moved month by month. It draws no card.
Call it when the user asks what they pay for on a regular basis, what their subscriptions cost, or how that spend moved. Then draw the two cards from its result, trend first:
well_render_category_trendwith onecategory_trendsentry, passed as it is.well_render_monthly_pivotwith thepivotsentry of the same currency, passed as it is. When the result holds more than one currency, draw one pair per currency. Never add two currencies together. Whencategory_trendsandpivotsare empty, no subscription was found: say so and draw nothing.
The server applies every rule, and the result states each one in rules. Quote the figures as returned: never recompute a cost, a total or a cadence, and never loosen a rule to list a supplier the user expects. A supplier in not_recurring missed the rule named in its missed_rule.
Every amount in the result is in the major units of its currency, never in cents: 1860 is 1,860.00 EUR, not 18.60 EUR.
The window is fixed: the last 24 complete calendar months in UTC and the running month are read, and the cards draw the last 12 complete months (the pivot draws the running month apart, marked as in progress). window, current_month and display_months say which months those were.
What the result is:
subscriptions: the suppliers on a cadence (monthly, bimonthly, quarterly, yearly) whose category is software or a service paid on a schedule, largest cost per month first, at most 50;subscription_countis the full count, and a list that shows fewer says how many it shows. Each carries its cadence evidence, its amount pattern (fixed, changed, varying), the amount its cost per month starts from, the cost per month and per year, its latest month,possibly_ended, its category andstate(possibly_ended, rising, falling, varying, stable): the one section it belongs to. Never list one supplier under two states.uncategorised_recurring: suppliers on a cadence whose category says nothing about them (none, residual or suspense), at most 25;uncategorised_recurring_countis the full count anduncategorised_recurring_monthly_totaltheir cost per month, one entry per currency, as decimal strings, over all of them and not only the listed ones. They are not counted as subscriptions and are in no total: give the count and the monthly total as leads (recurring payments Well cannot categorise yet, which may be subscriptions), and point the user to categorizing their counterparties. Never add the monthly total tototals.totals: per currency, the subscription count, the total cost per month and per year, and the part from subscriptions flagged as possibly ended (already inside the total).possible_duplicates: subscription suppliers charged their own price more than once in a month. A lead to check, never a verdict, and never in a total. Taxes, meals, travel and a one-off transfer are never in it.not_recurring: suppliers paid in the window that are not subscriptions, at most 25, with the rule missed (one_month, too_few_months, multiple_debits_in_month, irregular_gaps, not_subscription_category).not_subscription_categoryis a supplier paid on a cadence whose category is work, fees or spend by use, such as an agency or a contractor: never call it a subscription.unattributed: outflows whose payee resolves to no company. Real spend with no supplier to repeat, so never on a cadence.category_trendsandpivots: the render inputs, one per currency. A trend holds at most 6 lines, the smallest categories rolled into the last one.excluded: what fell out, counted apart.internal_transfersare movements between the workspace's own accounts, card repayments among them. A charge on a credit card the workspace connected is measured like a bank debit, on the day of the charge and against its supplier, so its repayment is never counted a second time.no_asset_movementcounts the outflows with no leg on an owned bank account or credit card: rows whose payer resolved to no account, a charge on a card that is not connected among them. Say so whenever the count is not zero: payments on rows linked to no connected account are NOT measured here.payments_to_own_accountsare payments to another owned account, such as a loan,own_companypayments to the workspace's own company,unreadable_rowsrows with no readable amount or currency.category_keyslists the categories never counted as subscriptions (transfers, treasury, loans, taxes, salaries, social charges), andcategory_excludedis how many bank outflows those categories removed.internal_transferscounts a transfer whatever its category. Anullcount was not measured, which is not zero.
Never claim a saving. A possibly ended subscription or a possible duplicate is what the bank shows, and Well cannot see whether a service is in use.
The yearly leads. Each subscription carries rise_per_year: what its price rise costs over a year, null when the amount did not rise. rise_leads lists the rises that count as leads: a possibly ended subscription is none, and a copy already counted in paid_in_several_workspaces is none, because dropping that copy drops its rise too. annual_lead_totals sums, per currency, every rise lead and every extra copy below, with how many it sums. Quote them as returned: a lead to check, never a saving made.
Every workspace of the person. When the person asks where they can save or what they could cut, do not answer from this tool alone: load the subscription-spend skill (with well_get_skill, or with the host's own skill tool when the Well skills are installed in it) and follow it, because it orders the answer (the subscriptions first, then the leads, every amount per year) and names each workspace. A list ask, such as "which subscriptions do I pay?", loads the skill first too, on an AI app host and on WhatsApp; on WhatsApp it takes that same answer across the person's workspaces. On WhatsApp, pass workspaces: "all_my_workspaces" on every call. Elsewhere, pass it when the person asks where they can save, what to cut, or about everything they pay across their workspaces. other_workspaces then holds each other real workspace the person may read: on WhatsApp, every workspace of the login the turn acts as, the starting login or the one picked with /account (at most 24); elsewhere, each other real workspace this same signed-in person is a member of (at most 5). Each comes with its subscriptions, totals and possible duplicates. paid_in_several_workspaces holds the suppliers two or more of them pay for what reads as one subscription: the same payee domain, cadence and category, at a comparable cost. When the person may read more workspaces than that, other_workspaces_skipped counts the ones not read, and every total covers the workspaces read only. Well finds those workspaces from the person; a workspace is never named in the call, and an AI app connection reaches only the workspaces its grant covers. all_workspaces_totals gives, per currency, the subscription count and the cost per year of every workspace read, this one included. other_workspaces_status says why the list is what it is: not_requested, read, no_signed_in_person or unreadable (which is not "no other workspace"). The cards draw this workspace only.
The order and the numbers. workspace_order.workspace_ids is the order to list the workspaces in: the biggest cost per year first, in workspace_order.currency, and on a tie this workspace (the one the call runs in), else the person's own space. leads is every yearly lead annual_lead_totals sums, numbered in the order a reply shows them: the biggest amount_per_year first, and on a tie the lead acting in this workspace, else in the person's own space. Each lead carries its kind (rise, paid_in_several_workspaces), the one action it proposes (renegotiate, cancel_extra_copies) and its targets: the workspace and the supplier row each action runs on (a null workspace_id is this workspace). A cancel_extra_copies lead also names in kept the copy it keeps; show the kept copy and the copies cancelled on its line. Show each lead under its number, never renumber them: the person answers with these numbers, and the same measure numbers the same leads the same way. lead_key joins the action, the supplier, the sorted target workspaces, the sorted target supplier rows and the supplier row of the copy kept: when a person answers a number from an earlier answer, act only when the lead under that number in a fresh measure has the same lead_key as in the answer they read, because the figures can move and give the number another supplier, action or workspace.
Naming a workspace. workspace and each other_workspaces[].workspace carry workspace_name, own_company_name, is_personal and bank_names. Name a workspace from them, by what sets it apart, never by a generic label such as "personal space" alone.
partial: true means nothing was measured: the read was cut short, or the workspace holds no bank account and no credit card. Say so rather than reporting no subscriptions. rows_truncated: true means the smallest counterparties were not read, so every total is a floor.
scope is required: own_and_adopted is the spend population the burn counts, own the workspace's own rows only.
When the token authorizes one workspace, call this directly — no workspace call is needed first. When it authorizes several, this read will not guess which one you mean: pass workspace_id on the call.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| scope | Yes | Which rows are this workspace's: `own_and_adopted` for its spend, `own` for its own rows only. Required; see the description. | |
| workspaces | No | Which workspaces the measure reads. Omit it, or pass "this_workspace", for this workspace alone. Pass "all_my_workspaces" on every call on WhatsApp, and elsewhere when the person asks where they can save, what to cut, or what they pay across all their workspaces: `other_workspaces` then measures each other workspace the same signed-in person is a member of. | |
| workspace_id | No | Target workspace. Omit when the token authorizes one workspace. Required when it authorizes several: this read reports one workspace's own figures and will not choose which. | |
| conversation_id | No | The conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation. | |
| workspace_scope | No | Restrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| error | No | ||
| leads | Yes | ||
| rules | Yes | ||
| scope | Yes | ||
| pivots | Yes | ||
| totals | Yes | ||
| window | Yes | ||
| partial | Yes | ||
| success | Yes | ||
| excluded | Yes | ||
| workspace | Yes | ||
| rise_leads | Yes | ||
| unattributed | Yes | ||
| current_month | Yes | ||
| not_recurring | Yes | ||
| subscriptions | Yes | ||
| display_months | Yes | ||
| rows_truncated | Yes | ||
| category_trends | Yes | ||
| conversation_id | No | The conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation. | |
| newly_connected | No | Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: "<name> is connected.". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later. | |
| workspace_order | Yes | ||
| other_workspaces | Yes | ||
| annual_lead_totals | Yes | ||
| resolved_workspace | No | The workspace that answered, when the caller named none and the token authorizes several. | |
| subscription_count | Yes | ||
| not_recurring_count | Yes | ||
| possible_duplicates | Yes | ||
| conversation_id_note | No | Present only when the server opened a fresh lane, stating that no choice recorded earlier was read. | |
| all_workspaces_totals | Yes | ||
| conversation_id_source | No | Where the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened. | |
| other_workspaces_status | Yes | ||
| subscriptions_truncated | Yes | ||
| uncategorised_recurring | Yes | ||
| other_workspaces_skipped | Yes | ||
| possible_duplicate_count | Yes | ||
| paid_in_several_workspaces | Yes | ||
| uncategorised_recurring_count | Yes | ||
| uncategorised_recurring_monthly_total | Yes |