[{"slug":"ZV-2026-0261","server_name":"api.wellapp.ai","severity":"breaking","title":"api.wellapp.ai: Resource ui://well/widget/640c0aaa was removed, consumers reading it will break.","summary":"[safe] Tool well_list_counterparties was added. [safe] Tool well_list_missing_invoices was added. [safe] Tool well_list_periods was added. [safe] Tool well_preview_invoice_fetch was added. [safe] Tool well_switch_workspace was added. [safe] Tool well_wait_for_selection was added. [safe] Description of well_get_cash_position changed (25% word delta). [risky] Field balance_history was added to well_get_cash_position output. [risky] Field connectors_url was added to well_get_cash_position output. [risky] Field connectors_url was added to well_get_runway output. [risky] Description of well_list_connectors changed (44% word delta). [risky] Optional field kind was added to well_list_connectors; may shift model behaviour. [safe] Description of well_list_workspaces changed (24% word delta). [risky] Field session was added to well_list_workspaces output. [safe] Description of well_query_records changed (6% word delta). [risky] Description of well_update_company changed (38% word delta). [risky] Optional field category_ids was added to well_update_company; may shift model behaviour. [risky] Field category_count was added to well_update_company output. [breaking] Resource ui://well/widget/640c0aaa was removed, consumers reading it will break. [safe] Resource ui://well/widget/856bffe9 was added.","changes":[{"kind":"tool_added","tool":"well_list_counterparties","detail":"Tool `well_list_counterparties` was added.","severity":"safe"},{"kind":"tool_added","tool":"well_list_missing_invoices","detail":"Tool `well_list_missing_invoices` was added.","severity":"safe"},{"kind":"tool_added","tool":"well_list_periods","detail":"Tool `well_list_periods` was added.","severity":"safe"},{"kind":"tool_added","tool":"well_preview_invoice_fetch","detail":"Tool `well_preview_invoice_fetch` was added.","severity":"safe"},{"kind":"tool_added","tool":"well_switch_workspace","detail":"Tool `well_switch_workspace` was added.","severity":"safe"},{"kind":"tool_added","tool":"well_wait_for_selection","detail":"Tool `well_wait_for_selection` was added.","severity":"safe"},{"kind":"description_changed","tool":"well_get_cash_position","after":"Get the workspace's current cash position: total cash on hand right now, converted to the workspace base currency, plus a per-account breakdown — the exact same computation and numbers the Well app's canvas KPI card shows. Use this instead of summing account balances yourself.\n\nReturns `amount`/`currency` (the converted total), `accounts` (per-account contributions: native amount/currency, converted amount, the FX rate applied), `as_of` (the FX-rate anchor date this snapshot is valid for), and `balance_history` when the workspace has one.\n\n`balance_history` is the trailing closed month-ends plus today, oldest first. Month-end is the only historical granularity that exists, so describe movement between months, never within one, and never as a daily series. A `null` amount is a month no connected account covered — not a zero balance. The field is absent when there is no reconstructed history, so make a trend claim only when it is present.\n\n`unavailable: true` means `amount` is a placeholder, not a real measurement (e.g. no accounts connected yet) — say so plainly rather than presenting it as a real €0 balance. `partial: true` means one or more accounts were excluded from an otherwise real total (e.g. missing FX rate) — mention the exclusion count and any `hints` rather than presenting the number as unconditionally complete.\n\nEverything here is backward-looking — no burn rate or runway is implied. Call `well_get_runway` instead for a forward-looking figure.\n\nCall this directly — no other tool call is needed first (workspace is resolved from the caller's authorized token, same as every other well_* tool).","before":"Get the workspace's current cash position: total cash on hand right now, converted to the workspace base currency, plus a per-account breakdown — the exact same computation and numbers the Well app's canvas KPI card shows. Use this instead of summing account balances yourself.\n\nReturns `amount`/`currency` (the converted total), `accounts` (per-account contributions: native amount/currency, converted amount, the FX rate applied), and `as_of` (the FX-rate anchor date this snapshot is valid for).\n\n`unavailable: true` means `amount` is a placeholder, not a real measurement (e.g. no accounts connected yet) — say so plainly rather than presenting it as a real €0 balance. `partial: true` means one or more accounts were excluded from an otherwise real total (e.g. missing FX rate) — mention the exclusion count and any `hints` rather than presenting the number as unconditionally complete.\n\nThis is a snapshot only — no burn rate or runway is implied. Call `well_get_runway` instead for a forward-looking figure.\n\nCall this directly — no other tool call is needed first (workspace is resolved from the caller's authorized token, same as every other well_* tool).","detail":"Description of `well_get_cash_position` changed (25% word delta).","severity":"safe","descriptionDelta":0.2450331125827815},{"kind":"output_property_added","path":"outputSchema.properties.balance_history","tool":"well_get_cash_position","after":{"type":"array","items":{"type":"object","required":["month","amount"],"properties":{"month":{"type":"string"},"amount":{"anyOf":[{"type":"number"},{"type":"null"}]}},"additionalProperties":false}},"detail":"Field `balance_history` was added to `well_get_cash_position` output.","severity":"risky"},{"kind":"output_property_added","path":"outputSchema.properties.connectors_url","tool":"well_get_cash_position","after":{"anyOf":[{"type":"string"},{"type":"null"}]},"detail":"Field `connectors_url` was added to `well_get_cash_position` output.","severity":"risky"},{"kind":"output_property_added","path":"outputSchema.properties.connectors_url","tool":"well_get_runway","after":{"anyOf":[{"type":"string"},{"type":"null"}]},"detail":"Field `connectors_url` was added to `well_get_runway` output.","severity":"risky"},{"kind":"description_changed","tool":"well_list_connectors","after":"List the connectors a workspace can install AND everything it has already connected, each with a one-click install deep link.\n\nONE tool answers both halves of the connect question — \"what can I connect to Well?\" and \"what is connected, still syncing, or broken?\" — because every existing connection is overlaid onto its catalog row. Do NOT read workspace_connectors records to work out connection coverage; this tool is that answer.\n\nEach entry has:\n- service_id: the connector's stable catalog id (e.g. \"stripe\"), used in the install link.\n- name, category_id, direction: what the connector is.\n- data_domains: the financial domains it serves — any of \"bank\", \"accounting\", \"invoicing\" — or null for a non-financial connector. One connector can serve several domains (Qonto serves all three). \"bank\" here means the connector delivers cash movements, which a payroll or billing platform also does; do NOT read it as \"this is a bank\". To list banks, pass kind: \"bank\", which the server scopes on its own bank classification.\n- status: \"available\" connectors are connectable now; \"coming_soon\"/\"unavailable\"/\"maintenance\" are not.\n- is_matched / is_selected: whether this workspace's detected tools matched this connector / already picked it.\n- match_score: 0..1 confidence of that match; null when unmatched. A high score is a tool Well is confident the workspace already uses.\n- is_connected: this workspace has a connection you should REPAIR or MANAGE, not install fresh. True for \"enabled\", \"processing\", \"error\", \"need_reconnect\" and \"suspended\"; false for \"to_configure\" and \"disabled\", where a fresh install IS the right next step.\n- connection_status: the existing connection's state, or null when this workspace has no connection row for the connector at all. One of:\n  - \"enabled\" — connected and syncing.\n  - \"processing\" — the grant is in and the FIRST sync is still running; data may be partial. Connected: do NOT ask the user to connect it again.\n  - \"error\" — authenticated but its last real sync failed. Offer install_url as a reconnect.\n  - \"need_reconnect\" — the grant is dead and only the user can restore it. Offer install_url as a reconnect, NOT a first install.\n  - \"suspended\" — the connection is held back administratively; tell the user it is paused. The user cannot fix it by reconnecting.\n  - \"to_configure\" — a connect attempt that never completed its handshake. Nothing is connected: offer install_url as a first install, and never claim the tool is connected.\n  - \"disabled\" — the connection was torn down. Offer install_url as a first install.\n  A \"degraded\" connector never appears: it is resolved server-side against its own sync history into \"enabled\" or \"error\", so you never surface a state that clears itself. A connection whose state this build cannot read also reports null, and there is_connected stays true — read the two fields together, and treat \"null status, is_connected true\" as an existing connection whose health is unknown.\n- workspace_connector_id: the connection instance's id, or null when there is no connection row. This is the id well_invoke_connector_tool and well_list_connector_tools need — resolve it HERE, never via well_query_records on workspace_connectors.\n- last_successful_sync_at: ISO timestamp of the last SUCCESSFUL sync, or null when none has landed yet. An \"enabled\" connector with null here has a valid grant but has never delivered data.\n- sync_in_progress: a data sync is running right now. Tell the user to wait rather than to act.\n- is_preselected: Well recommends connecting this one now (a high-confidence match with is_connected false). The interactive picker pre-checks exactly these. A \"to_configure\" or \"disabled\" row can still be pre-checked — installing it IS the fix.\n- install_url: a one-click link that STARTS or REPAIRS the connection in Well. It works from any state — it signs the user in if needed, creates their workspace if they have none, then runs the connector's own auth flow — and it covers banks too (a bank opens its bank-login flow pre-selected). Null only when the connector is not \"available\". Hand this to the user to get started in one click.\n\nScoping: pass kind (\"bank\" | \"accounting\" | \"invoicing\") to get only the connectors serving that domain — the whole set, server-ordered, including the long tail of bank institutions. Pass q to name-search the full catalog. Omit both for the curated, matched-first view. Use well_list_connector_tools for a live connection's actions.","before":"List the connectors a workspace can install, each with a one-click install deep link.\n\nUse this to answer \"what can I connect to Well?\" or \"how do I connect <provider>?\". Each entry has:\n- service_id: the connector's stable catalog id (e.g. \"stripe\"), used in the install link.\n- name, category_id, direction: what the connector is.\n- status: \"available\" connectors are connectable now; \"coming_soon\"/\"unavailable\"/\"maintenance\" are not.\n- is_matched / is_selected: whether this workspace's detected tools matched this connector / already picked it.\n- match_score: 0..1 confidence of that match; null when unmatched. A high score is a tool Well is confident the workspace already uses.\n- is_connected: this workspace already holds a live connection for the connector — offer a reconnect, not a first install.\n- connection_status: that live connection's state, or null when not connected. \"enabled\" is connected and syncing; \"processing\" means the grant is in and the FIRST sync is still running (connected — do not ask the user to connect it again); \"error\" is authenticated but its last real sync failed, which warrants a reconnect.\n- workspace_connector_id: the connected instance's id, or null when not connected. This is the id well_invoke_connector_tool and well_list_connector_tools need — resolve it HERE, never via well_query_records on workspace_connectors.\n- is_preselected: Well recommends connecting this one now (a high-confidence match that is not yet connected). The interactive picker pre-checks exactly these.\n- install_url: a one-click link that STARTS the connection in Well. It works from any state — it signs the user in if needed, creates their workspace if they have none, then runs the connector's own auth flow — and it covers banks too (a bank opens its bank-login flow pre-selected). Null only when the connector is not \"available\". Hand this to the user to get started in one click.\n\nThe default view returns the curated, matched-first connectors; pass q to name-search the full catalog (e.g. a specific bank). This is ALSO the tool that answers \"what have I connected?\" — read is_connected / connection_status / workspace_connector_id here rather than querying workspace_connectors records. Use well_list_connector_tools for a live connection's actions.","detail":"Description of `well_list_connectors` changed (44% word delta).","severity":"risky","descriptionDelta":0.44333333333333336},{"kind":"input_property_added","path":"inputSchema.properties.kind","tool":"well_list_connectors","after":{"enum":["bank","accounting","invoicing"],"type":"string","description":"Scope the catalog to one financial domain: \"bank\" (every bank and neobank, including the long tail of open-banking institutions, plus the platforms that hold an account like Qonto and Pennylane — never a payroll or billing tool that merely reports transactions), \"accounting\", or \"invoicing\". Use this for a connect-a-bank or connect-an-accounting-tool step instead of filtering the default view yourself. Omit for every connectable connector."},"detail":"Optional field `kind` was added to `well_list_connectors`; may shift model behaviour.","severity":"risky"},{"kind":"description_changed","tool":"well_list_workspaces","after":"List the workspaces this connection is authorized to access.\n\nUse this FIRST when a single token may cover more than one workspace. Each entry has:\n- workspace_id: pass this as the workspace_id argument on other tools to target one workspace.\n- workspace_name: human-readable name (null if it can't be resolved).\n- is_primary: true for the token's default workspace (used when you omit workspace_id on a write).\n- identity: the company behind the workspace (registered name, trade name, registry number, country, website, currency, fiscal year start), so two similarly-named workspaces can be told apart. Every field is null when the workspace has no accounting settings yet. Tax identifiers are deliberately not included.\n\nThe result also carries `session` — what the user's card clicks have already recorded this session: `pinned_workspace_id` (null when not switched), `workspace_queue` (the workspaces to work through next, empty when none), and `selected_periods` (the months picked on the period card, empty when none). Call this any time you need to resync with clicks you may have missed.\n\nWhen the token authorizes a single workspace you can omit workspace_id everywhere; when it authorizes several, read tools fan out across all of them unless you pass a workspace_id, and write tools require one.","before":"List the workspaces this connection is authorized to access.\n\nUse this FIRST when a single token may cover more than one workspace. Each entry has:\n- workspace_id: pass this as the workspace_id argument on other tools to target one workspace.\n- workspace_name: human-readable name (null if it can't be resolved).\n- is_primary: true for the token's default workspace (used when you omit workspace_id on a write).\n- identity: the company behind the workspace (registered name, trade name, registry number, country, website, currency, fiscal year start), so two similarly-named workspaces can be told apart. Every field is null when the workspace has no accounting settings yet. Tax identifiers are deliberately not included.\n\nWhen the token authorizes a single workspace you can omit workspace_id everywhere; when it authorizes several, read tools fan out across all of them unless you pass a workspace_id, and write tools require one.","detail":"Description of `well_list_workspaces` changed (24% word delta).","severity":"safe","descriptionDelta":0.23809523809523814},{"kind":"output_property_added","path":"outputSchema.properties.session","tool":"well_list_workspaces","after":{"type":"object","required":["pinned_workspace_id","workspace_queue","selected_periods"],"properties":{"workspace_queue":{"type":"array","items":{"type":"string"}},"selected_periods":{"type":"array","items":{"type":"object","required":["calendar_year","calendar_month"],"properties":{"calendar_year":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991},"calendar_month":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991}},"additionalProperties":false}},"pinned_workspace_id":{"anyOf":[{"type":"string"},{"type":"null"}]}},"description":"What this session's card clicks recorded so far; null/empty fields when nothing was clicked yet.","additionalProperties":false},"detail":"Field `session` was added to `well_list_workspaces` output.","severity":"risky"},{"kind":"description_changed","tool":"well_query_records","after":"Query records from Well's database.\n\n⚠️ WORKFLOW:\n1. To SHOW the user a table of a record type, just omit `fields`. You never choose\n   columns for presentation: the table the user sees is ALWAYS the root's display\n   view in the Well web app's column order, trimmed on the widest roots to what fits\n   a chat-width table.\n2. To answer a targeted question, call well_get_schema(root) FIRST to discover\n   available fields, then name in `fields` ONLY the extra values you need (5-15\n   typically). They are ADDED to the display view in the payload you read — they do\n   not replace, reorder, or trim the columns the user sees.\n\nROOTS (read-only — all 33): companies, people, connectors, invoices, documents, transactions, accounts, payment_means, workspace_connectors, memberships, cards, checks, ledger_accounts, journals, journal_entries, tax_rates, exchange_rates, invoice_transactions, categories, account_balances, tasks, workspaces, invoice_payment_means, chat_conversations, blueprint_runs, workspace_connector_sync_logs, media, emails, phones, web_links, locations, invoice_items, billing_events\n(The accounting graph — ledger_accounts, journals, journal_entries — and balances/rates are read-only projections owned by the sync/posting pipelines; query them for financial context, you cannot create/update them here. Sub-resources like emails/phones/locations are usually richer when read via their parent company/person.)\n\nCATEGORY CATALOGS: \"categories\" holds two independent taxonomies, separated by `category_type`. Always filter on it — an unfiltered read mixes them:\n- `whereClause: { category_type: { _eq: \"company\" } }` is the COMPANY-CATEGORY catalog: the industry labels a counterparty carries, and the ids `well_update_company({ category_ids })` accepts. There is no curated allowlist — the labels are minted during enrichment — so read them here rather than inventing a taxonomy.\n- `whereClause: { category_type: { _eq: \"transaction\" } }` is the management/transaction taxonomy.\n\nCONNECTED TOOLS: do NOT use this tool to show the user what they have connected — call well_list_connectors instead. It owns that job: connection status, and an install link for anything not connected yet. Query root \"workspace_connectors\" here only for genuine RECORD-level needs — reading sync timestamps, filtering connections, joining them with other roots. (\"connectors\" is the installable catalog; \"workspace_connector_sync_logs\" is per-sync history.)\n\nWell already syncs the providers' data into the roots above — invoices, transactions, accounts, the accounting graph. ALWAYS read it from here. well_invoke_connector_tool and a provider's own tools are for an ACTION the user explicitly asked to take on that provider (e.g. \"create this record in Attio\"), never a way to fetch data Well already holds.\n\nEXAMPLE - show the user their invoices (no `fields`, ever):\nwell_query_records({ root: \"invoices\", limit: 50 })\n\nEXAMPLE - answer \"how much is still owed on the unpaid invoices?\":\nwell_query_records({\n  root: \"invoices\",\n  fields: [[\"invoices\", \"balance_due\"]],\n  whereClause: { \"payment_status\": { \"_in\": [\"unpaid\", \"partial\"] } }\n})\n// balance_due arrives in the rows for you to total up; the user still sees the\n// standard invoices table, with its identity, counterparty and status columns.\n\n⚠️ RULES:\n- `fields` is ADDITIVE — it widens the data you receive, never the table the user sees\n- Omitting fields (default view) or naming a few extras both beat allFields\n- Field paths from schema: \"invoices.issuer.name\" → [\"invoices\", \"issuer\", \"name\"]\n- Default 50 records per request, max 500.\n\nONE CALL IS THE ANSWER — do not walk the root:\nEvery response already carries `totalCount` (ALL matches, not just this page) and\n`records_url` (the full web-app table, with your filter and sort already applied).\nSo a request to see a record type is ONE call: the user gets a table of the first\npage, the count tells them how many there are, and the link takes them to the rest.\n\"Show me all my invoices\" is answered by one call + the link — NOT by fetching 483\nrows into this conversation.\n- A non-null `nextCursor` is NOT a to-do. It means more rows exist, which\n  `totalCount` already told you and the link already covers.\n- Never paginate to compute a total, count, average or breakdown: aggregate over\n  the filtered set instead. Summing a paginated sample produces a wrong number.\n- Never paginate to \"be thorough\". Large roots will exhaust the output limit\n  mid-walk, and the user ends up with nothing legible.\n- Paginate ONLY for per-row work over every match that no aggregate can express,\n  and tell the user the cost before starting. Then: pass the returned\n  `nextCursor` as `cursor`; `nextCursor: null` is the last page.\n\nFILTERING (whereClause):\n- Uses Hasura-style operators on field names.\n- Safe operators (work on ALL field types): _eq, _neq, _in, _nin, _is_null\n- Numeric/date only: _gt, _gte, _lt, _lte\n- Text only: _like, _ilike\n- When unsure of a field's type, prefer _eq or _in (they always work).\n- Combine with _and, _or, _not\n- For relationship fields, use nested syntax: { \"issuer\": { \"company_id\": { \"_eq\": \"<company_id>\" } } }\n- NEVER select the workspace's OWN records by matching a company name. One legal entity appears under\n  several labels — a registered name, a trade name, a bank-issued label — so a name filter silently\n  drops rows and the total reads as complete. On the invoices root, pass `partyScope` instead: it\n  resolves the workspace's own side on the server, so this query needs no id lookup and no extra call.\n  Call well_get_own_company for the id only when a root has no `partyScope` and you must filter on\n  issuer_pk / receiver_pk or the nested company_id yourself.\n- Match a counterparty by id too whenever you have one. Reach for _ilike on a name only to DISCOVER\n  candidates to show the user, never to compute a figure you will report.\nExamples:\n  { \"status\": { \"_eq\": \"unpaid\" } }\n  { \"grand_total\": { \"_gt\": 1000 } }\n  { \"local_currency\": { \"_eq\": \"EUR\" } }\n  { \"_and\": [{ \"status\": { \"_eq\": \"unpaid\" } }, { \"grand_total\": { \"_gte\": 500 } }] }\n  { \"issuer\": { \"company_id\": { \"_eq\": \"<company_id from well_get_own_company>\" } } }\n\nSORTING (orderBy):\n- Sort by any field: { field: \"grand_total\", direction: \"desc\" }\n- Default sort is by primary key ascending.\n\nReturns { rows, totalCount, nextCursor, success }.","before":"Query records from Well's database.\n\n⚠️ WORKFLOW:\n1. To SHOW the user a table of a record type, just omit `fields`. You never choose\n   columns for presentation: the table the user sees is ALWAYS the root's display\n   view in the Well web app's column order, trimmed on the widest roots to what fits\n   a chat-width table.\n2. To answer a targeted question, call well_get_schema(root) FIRST to discover\n   available fields, then name in `fields` ONLY the extra values you need (5-15\n   typically). They are ADDED to the display view in the payload you read — they do\n   not replace, reorder, or trim the columns the user sees.\n\nROOTS (read-only — all 33): companies, people, connectors, invoices, documents, transactions, accounts, payment_means, workspace_connectors, memberships, cards, checks, ledger_accounts, journals, journal_entries, tax_rates, exchange_rates, invoice_transactions, categories, account_balances, tasks, workspaces, invoice_payment_means, chat_conversations, blueprint_runs, workspace_connector_sync_logs, media, emails, phones, web_links, locations, invoice_items, billing_events\n(The accounting graph — ledger_accounts, journals, journal_entries — and balances/rates are read-only projections owned by the sync/posting pipelines; query them for financial context, you cannot create/update them here. Sub-resources like emails/phones/locations are usually richer when read via their parent company/person.)\n\nCONNECTED TOOLS: do NOT use this tool to show the user what they have connected — call well_list_connectors instead. It owns that job: connection status, and an install link for anything not connected yet. Query root \"workspace_connectors\" here only for genuine RECORD-level needs — reading sync timestamps, filtering connections, joining them with other roots. (\"connectors\" is the installable catalog; \"workspace_connector_sync_logs\" is per-sync history.)\n\nWell already syncs the providers' data into the roots above — invoices, transactions, accounts, the accounting graph. ALWAYS read it from here. well_invoke_connector_tool and a provider's own tools are for an ACTION the user explicitly asked to take on that provider (e.g. \"create this record in Attio\"), never a way to fetch data Well already holds.\n\nEXAMPLE - show the user their invoices (no `fields`, ever):\nwell_query_records({ root: \"invoices\", limit: 50 })\n\nEXAMPLE - answer \"how much is still owed on the unpaid invoices?\":\nwell_query_records({\n  root: \"invoices\",\n  fields: [[\"invoices\", \"balance_due\"]],\n  whereClause: { \"payment_status\": { \"_in\": [\"unpaid\", \"partial\"] } }\n})\n// balance_due arrives in the rows for you to total up; the user still sees the\n// standard invoices table, with its identity, counterparty and status columns.\n\n⚠️ RULES:\n- `fields` is ADDITIVE — it widens the data you receive, never the table the user sees\n- Omitting fields (default view) or naming a few extras both beat allFields\n- Field paths from schema: \"invoices.issuer.name\" → [\"invoices\", \"issuer\", \"name\"]\n- Default 50 records per request, max 500.\n\nONE CALL IS THE ANSWER — do not walk the root:\nEvery response already carries `totalCount` (ALL matches, not just this page) and\n`records_url` (the full web-app table, with your filter and sort already applied).\nSo a request to see a record type is ONE call: the user gets a table of the first\npage, the count tells them how many there are, and the link takes them to the rest.\n\"Show me all my invoices\" is answered by one call + the link — NOT by fetching 483\nrows into this conversation.\n- A non-null `nextCursor` is NOT a to-do. It means more rows exist, which\n  `totalCount` already told you and the link already covers.\n- Never paginate to compute a total, count, average or breakdown: aggregate over\n  the filtered set instead. Summing a paginated sample produces a wrong number.\n- Never paginate to \"be thorough\". Large roots will exhaust the output limit\n  mid-walk, and the user ends up with nothing legible.\n- Paginate ONLY for per-row work over every match that no aggregate can express,\n  and tell the user the cost before starting. Then: pass the returned\n  `nextCursor` as `cursor`; `nextCursor: null` is the last page.\n\nFILTERING (whereClause):\n- Uses Hasura-style operators on field names.\n- Safe operators (work on ALL field types): _eq, _neq, _in, _nin, _is_null\n- Numeric/date only: _gt, _gte, _lt, _lte\n- Text only: _like, _ilike\n- When unsure of a field's type, prefer _eq or _in (they always work).\n- Combine with _and, _or, _not\n- For relationship fields, use nested syntax: { \"issuer\": { \"company_id\": { \"_eq\": \"<company_id>\" } } }\n- NEVER select the workspace's OWN records by matching a company name. One legal entity appears under\n  several labels — a registered name, a trade name, a bank-issued label — so a name filter silently\n  drops rows and the total reads as complete. On the invoices root, pass `partyScope` instead: it\n  resolves the workspace's own side on the server, so this query needs no id lookup and no extra call.\n  Call well_get_own_company for the id only when a root has no `partyScope` and you must filter on\n  issuer_pk / receiver_pk or the nested company_id yourself.\n- Match a counterparty by id too whenever you have one. Reach for _ilike on a name only to DISCOVER\n  candidates to show the user, never to compute a figure you will report.\nExamples:\n  { \"status\": { \"_eq\": \"unpaid\" } }\n  { \"grand_total\": { \"_gt\": 1000 } }\n  { \"local_currency\": { \"_eq\": \"EUR\" } }\n  { \"_and\": [{ \"status\": { \"_eq\": \"unpaid\" } }, { \"grand_total\": { \"_gte\": 500 } }] }\n  { \"issuer\": { \"company_id\": { \"_eq\": \"<company_id from well_get_own_company>\" } } }\n\nSORTING (orderBy):\n- Sort by any field: { field: \"grand_total\", direction: \"desc\" }\n- Default sort is by primary key ascending.\n\nReturns { rows, totalCount, nextCursor, success }.","detail":"Description of `well_query_records` changed (6% word delta).","severity":"safe","descriptionDelta":0.06024096385542166},{"kind":"description_changed","tool":"well_update_company","after":"Update an existing company in the current workspace.\n\nUse this tool when the user asks to change, fix, rename, or edit a company's\nfields.\n\nREQUIRED: company_id\nOPTIONAL (only include fields the user wants changed): name, description,\n  domain, registered_name, trade_name, tax_id_value, tax_id_type,\n  registry_country (ISO 3166-1 alpha-2, e.g. \"FR\"), business_type,\n  registered_value, registry_name, locale (ISO 639-1 two-letter language\n  code, e.g. \"en\", \"fr\" — not \"en_US\").\n\nCATEGORIES (a counterparty's industry): pass `category_ids` — the COMPLETE set\n  of category ids the company should carry. It REPLACES the current set: ids you\n  leave out are unlinked, and `[]` clears every category. Omit the field to\n  leave the categories untouched. Read the catalog first with\n  well_query_records({ root: \"categories\", whereClause: { category_type: { _eq:\n  \"company\" } } }) and pass ids from it — an id that is not a\n  `category_type = \"company\"` row is refused, and this tool never creates a\n  category.\n\nNOT CHANGEABLE via this tool: emails, phones, locations, linked people, media.\nThose require dedicated tools (not yet available).\n\nReturns { success: true, company_id, name } on success — plus category_count,\nthe number of categories the company carries afterwards, when the call passed\n`category_ids`. Returns { success: false, error } on failure.","before":"Update an existing company in the current workspace.\n\nUse this tool when the user asks to change, fix, rename, or edit a company's\nfields.\n\nREQUIRED: company_id\nOPTIONAL (only include fields the user wants changed): name, description,\n  domain, registered_name, trade_name, tax_id_value, tax_id_type,\n  registry_country (ISO 3166-1 alpha-2, e.g. \"FR\"), business_type,\n  registered_value, registry_name, locale (ISO 639-1 two-letter language\n  code, e.g. \"en\", \"fr\" — not \"en_US\").\n\nNOT CHANGEABLE via this tool: emails, phones, locations, linked people, media.\nThose require dedicated tools (not yet available).\n\nReturns { success: true, company_id, name } on success, or\n{ success: false, error } on failure.","detail":"Description of `well_update_company` changed (38% word delta).","severity":"risky","descriptionDelta":0.3828125},{"kind":"input_property_added","path":"inputSchema.properties.category_ids","tool":"well_update_company","after":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"maxItems":20,"description":"The COMPLETE set of company-category ids this company should carry. Replaces the current set; [] clears it; omit to leave categories unchanged."},"detail":"Optional field `category_ids` was added to `well_update_company`; may shift model behaviour.","severity":"risky"},{"kind":"output_property_added","path":"outputSchema.properties.category_count","tool":"well_update_company","after":{"type":"integer","maximum":9007199254740991,"minimum":-9007199254740991},"detail":"Field `category_count` was added to `well_update_company` output.","severity":"risky"},{"kind":"resource_removed","tool":"ui://well/widget/640c0aaa","before":"ui://well/widget/640c0aaa","detail":"Resource `ui://well/widget/640c0aaa` was removed, consumers reading it will break.","severity":"breaking"},{"kind":"resource_added","tool":"ui://well/widget/856bffe9","after":"ui://well/widget/856bffe9","detail":"Resource `ui://well/widget/856bffe9` was added.","severity":"safe"}],"published_at":"2026-08-21T11:16:52.005Z"},{"slug":"ZV-2026-0225","server_name":"api.wellapp.ai","severity":"breaking","title":"api.wellapp.ai: Resource ui://well/widget/f98d62fc was removed, consumers reading it will break.","summary":"[safe] Tool well_get_own_company was added. [safe] Description of well_query_records changed (10% word delta). [risky] Optional field partyScope was added to well_query_records; may shift model behaviour. [breaking] Resource ui://well/widget/f98d62fc was removed, consumers reading it will break. [safe] Resource ui://well/widget/640c0aaa was added.","changes":[{"kind":"tool_added","tool":"well_get_own_company","detail":"Tool `well_get_own_company` was added.","severity":"safe"},{"kind":"description_changed","tool":"well_query_records","after":"Query records from Well's database.\n\n⚠️ WORKFLOW:\n1. To SHOW the user a table of a record type, just omit `fields`. You never choose\n   columns for presentation: the table the user sees is ALWAYS the root's display\n   view in the Well web app's column order, trimmed on the widest roots to what fits\n   a chat-width table.\n2. To answer a targeted question, call well_get_schema(root) FIRST to discover\n   available fields, then name in `fields` ONLY the extra values you need (5-15\n   typically). They are ADDED to the display view in the payload you read — they do\n   not replace, reorder, or trim the columns the user sees.\n\nROOTS (read-only — all 33): companies, people, connectors, invoices, documents, transactions, accounts, payment_means, workspace_connectors, memberships, cards, checks, ledger_accounts, journals, journal_entries, tax_rates, exchange_rates, invoice_transactions, categories, account_balances, tasks, workspaces, invoice_payment_means, chat_conversations, blueprint_runs, workspace_connector_sync_logs, media, emails, phones, web_links, locations, invoice_items, billing_events\n(The accounting graph — ledger_accounts, journals, journal_entries — and balances/rates are read-only projections owned by the sync/posting pipelines; query them for financial context, you cannot create/update them here. Sub-resources like emails/phones/locations are usually richer when read via their parent company/person.)\n\nCONNECTED TOOLS: do NOT use this tool to show the user what they have connected — call well_list_connectors instead. It owns that job: connection status, and an install link for anything not connected yet. Query root \"workspace_connectors\" here only for genuine RECORD-level needs — reading sync timestamps, filtering connections, joining them with other roots. (\"connectors\" is the installable catalog; \"workspace_connector_sync_logs\" is per-sync history.)\n\nWell already syncs the providers' data into the roots above — invoices, transactions, accounts, the accounting graph. ALWAYS read it from here. well_invoke_connector_tool and a provider's own tools are for an ACTION the user explicitly asked to take on that provider (e.g. \"create this record in Attio\"), never a way to fetch data Well already holds.\n\nEXAMPLE - show the user their invoices (no `fields`, ever):\nwell_query_records({ root: \"invoices\", limit: 50 })\n\nEXAMPLE - answer \"how much is still owed on the unpaid invoices?\":\nwell_query_records({\n  root: \"invoices\",\n  fields: [[\"invoices\", \"balance_due\"]],\n  whereClause: { \"payment_status\": { \"_in\": [\"unpaid\", \"partial\"] } }\n})\n// balance_due arrives in the rows for you to total up; the user still sees the\n// standard invoices table, with its identity, counterparty and status columns.\n\n⚠️ RULES:\n- `fields` is ADDITIVE — it widens the data you receive, never the table the user sees\n- Omitting fields (default view) or naming a few extras both beat allFields\n- Field paths from schema: \"invoices.issuer.name\" → [\"invoices\", \"issuer\", \"name\"]\n- Default 50 records per request, max 500.\n\nONE CALL IS THE ANSWER — do not walk the root:\nEvery response already carries `totalCount` (ALL matches, not just this page) and\n`records_url` (the full web-app table, with your filter and sort already applied).\nSo a request to see a record type is ONE call: the user gets a table of the first\npage, the count tells them how many there are, and the link takes them to the rest.\n\"Show me all my invoices\" is answered by one call + the link — NOT by fetching 483\nrows into this conversation.\n- A non-null `nextCursor` is NOT a to-do. It means more rows exist, which\n  `totalCount` already told you and the link already covers.\n- Never paginate to compute a total, count, average or breakdown: aggregate over\n  the filtered set instead. Summing a paginated sample produces a wrong number.\n- Never paginate to \"be thorough\". Large roots will exhaust the output limit\n  mid-walk, and the user ends up with nothing legible.\n- Paginate ONLY for per-row work over every match that no aggregate can express,\n  and tell the user the cost before starting. Then: pass the returned\n  `nextCursor` as `cursor`; `nextCursor: null` is the last page.\n\nFILTERING (whereClause):\n- Uses Hasura-style operators on field names.\n- Safe operators (work on ALL field types): _eq, _neq, _in, _nin, _is_null\n- Numeric/date only: _gt, _gte, _lt, _lte\n- Text only: _like, _ilike\n- When unsure of a field's type, prefer _eq or _in (they always work).\n- Combine with _and, _or, _not\n- For relationship fields, use nested syntax: { \"issuer\": { \"company_id\": { \"_eq\": \"<company_id>\" } } }\n- NEVER select the workspace's OWN records by matching a company name. One legal entity appears under\n  several labels — a registered name, a trade name, a bank-issued label — so a name filter silently\n  drops rows and the total reads as complete. On the invoices root, pass `partyScope` instead: it\n  resolves the workspace's own side on the server, so this query needs no id lookup and no extra call.\n  Call well_get_own_company for the id only when a root has no `partyScope` and you must filter on\n  issuer_pk / receiver_pk or the nested company_id yourself.\n- Match a counterparty by id too whenever you have one. Reach for _ilike on a name only to DISCOVER\n  candidates to show the user, never to compute a figure you will report.\nExamples:\n  { \"status\": { \"_eq\": \"unpaid\" } }\n  { \"grand_total\": { \"_gt\": 1000 } }\n  { \"local_currency\": { \"_eq\": \"EUR\" } }\n  { \"_and\": [{ \"status\": { \"_eq\": \"unpaid\" } }, { \"grand_total\": { \"_gte\": 500 } }] }\n  { \"issuer\": { \"company_id\": { \"_eq\": \"<company_id from well_get_own_company>\" } } }\n\nSORTING (orderBy):\n- Sort by any field: { field: \"grand_total\", direction: \"desc\" }\n- Default sort is by primary key ascending.\n\nReturns { rows, totalCount, nextCursor, success }.","before":"Query records from Well's database.\n\n⚠️ WORKFLOW:\n1. To SHOW the user a table of a record type, just omit `fields`. You never choose\n   columns for presentation: the table the user sees is ALWAYS the root's display\n   view in the Well web app's column order, trimmed on the widest roots to what fits\n   a chat-width table.\n2. To answer a targeted question, call well_get_schema(root) FIRST to discover\n   available fields, then name in `fields` ONLY the extra values you need (5-15\n   typically). They are ADDED to the display view in the payload you read — they do\n   not replace, reorder, or trim the columns the user sees.\n\nROOTS (read-only — all 33): companies, people, connectors, invoices, documents, transactions, accounts, payment_means, workspace_connectors, memberships, cards, checks, ledger_accounts, journals, journal_entries, tax_rates, exchange_rates, invoice_transactions, categories, account_balances, tasks, workspaces, invoice_payment_means, chat_conversations, blueprint_runs, workspace_connector_sync_logs, media, emails, phones, web_links, locations, invoice_items, billing_events\n(The accounting graph — ledger_accounts, journals, journal_entries — and balances/rates are read-only projections owned by the sync/posting pipelines; query them for financial context, you cannot create/update them here. Sub-resources like emails/phones/locations are usually richer when read via their parent company/person.)\n\nCONNECTED TOOLS: do NOT use this tool to show the user what they have connected — call well_list_connectors instead. It owns that job: connection status, and an install link for anything not connected yet. Query root \"workspace_connectors\" here only for genuine RECORD-level needs — reading sync timestamps, filtering connections, joining them with other roots. (\"connectors\" is the installable catalog; \"workspace_connector_sync_logs\" is per-sync history.)\n\nWell already syncs the providers' data into the roots above — invoices, transactions, accounts, the accounting graph. ALWAYS read it from here. well_invoke_connector_tool and a provider's own tools are for an ACTION the user explicitly asked to take on that provider (e.g. \"create this record in Attio\"), never a way to fetch data Well already holds.\n\nEXAMPLE - show the user their invoices (no `fields`, ever):\nwell_query_records({ root: \"invoices\", limit: 50 })\n\nEXAMPLE - answer \"how much is still owed on the unpaid invoices?\":\nwell_query_records({\n  root: \"invoices\",\n  fields: [[\"invoices\", \"balance_due\"]],\n  whereClause: { \"payment_status\": { \"_in\": [\"unpaid\", \"partial\"] } }\n})\n// balance_due arrives in the rows for you to total up; the user still sees the\n// standard invoices table, with its identity, counterparty and status columns.\n\n⚠️ RULES:\n- `fields` is ADDITIVE — it widens the data you receive, never the table the user sees\n- Omitting fields (default view) or naming a few extras both beat allFields\n- Field paths from schema: \"invoices.issuer.name\" → [\"invoices\", \"issuer\", \"name\"]\n- Default 50 records per request, max 500.\n\nONE CALL IS THE ANSWER — do not walk the root:\nEvery response already carries `totalCount` (ALL matches, not just this page) and\n`records_url` (the full web-app table, with your filter and sort already applied).\nSo a request to see a record type is ONE call: the user gets a table of the first\npage, the count tells them how many there are, and the link takes them to the rest.\n\"Show me all my invoices\" is answered by one call + the link — NOT by fetching 483\nrows into this conversation.\n- A non-null `nextCursor` is NOT a to-do. It means more rows exist, which\n  `totalCount` already told you and the link already covers.\n- Never paginate to compute a total, count, average or breakdown: aggregate over\n  the filtered set instead. Summing a paginated sample produces a wrong number.\n- Never paginate to \"be thorough\". Large roots will exhaust the output limit\n  mid-walk, and the user ends up with nothing legible.\n- Paginate ONLY for per-row work over every match that no aggregate can express,\n  and tell the user the cost before starting. Then: pass the returned\n  `nextCursor` as `cursor`; `nextCursor: null` is the last page.\n\nFILTERING (whereClause):\n- Uses Hasura-style operators on field names.\n- Safe operators (work on ALL field types): _eq, _neq, _in, _nin, _is_null\n- Numeric/date only: _gt, _gte, _lt, _lte\n- Text only: _like, _ilike\n- When unsure of a field's type, prefer _eq or _in (they always work).\n- Combine with _and, _or, _not\n- For relationship fields, use nested syntax: { \"issuer\": { \"name\": { \"_ilike\": \"%acme%\" } } }\nExamples:\n  { \"status\": { \"_eq\": \"unpaid\" } }\n  { \"grand_total\": { \"_gt\": 1000 } }\n  { \"local_currency\": { \"_eq\": \"EUR\" } }\n  { \"_and\": [{ \"status\": { \"_eq\": \"unpaid\" } }, { \"grand_total\": { \"_gte\": 500 } }] }\n  { \"issuer\": { \"name\": { \"_ilike\": \"%acme%\" } } }\n\nSORTING (orderBy):\n- Sort by any field: { field: \"grand_total\", direction: \"desc\" }\n- Default sort is by primary key ascending.\n\nReturns { rows, totalCount, nextCursor, success }.","detail":"Description of `well_query_records` changed (10% word delta).","severity":"safe","descriptionDelta":0.09718670076726343},{"kind":"input_property_added","path":"inputSchema.properties.partyScope","tool":"well_query_records","after":{"enum":["purchase","sales","intra_self","unattributed"],"type":"string","description":"Which side of an invoice the workspace itself occupies, resolved from its own company rather than a party name. `invoices` root only. \"purchase\" = the workspace owes it (payables); \"sales\" = the workspace is owed (receivables); \"intra_self\" = both parties are companies the workspace owns; \"unattributed\" = Well cannot place it on either side. The four partition every invoice, so report the \"unattributed\" count beside any payable total rather than dropping it — an unattributed invoice may still be owed. Prefer this over hand-writing an issuer/receiver filter."},"detail":"Optional field `partyScope` was added to `well_query_records`; may shift model behaviour.","severity":"risky"},{"kind":"resource_removed","tool":"ui://well/widget/f98d62fc","before":"ui://well/widget/f98d62fc","detail":"Resource `ui://well/widget/f98d62fc` was removed, consumers reading it will break.","severity":"breaking"},{"kind":"resource_added","tool":"ui://well/widget/640c0aaa","after":"ui://well/widget/640c0aaa","detail":"Resource `ui://well/widget/640c0aaa` was added.","severity":"safe"}],"published_at":"2026-08-20T11:52:40.550Z"},{"slug":"ZV-2026-0160","server_name":"api.wellapp.ai","severity":"breaking","title":"api.wellapp.ai: Resource ui://well/widget/6c49d60e was removed, consumers reading it will break.","summary":"[risky] Field usage_notes was added to well_list_connector_tools output. [breaking] Resource ui://well/widget/6c49d60e was removed, consumers reading it will break. [safe] Resource ui://well/widget/f98d62fc was added.","changes":[{"kind":"output_property_added","path":"outputSchema.properties.usage_notes","tool":"well_list_connector_tools","after":{"type":"string"},"detail":"Field `usage_notes` was added to `well_list_connector_tools` output.","severity":"risky"},{"kind":"resource_removed","tool":"ui://well/widget/6c49d60e","before":"ui://well/widget/6c49d60e","detail":"Resource `ui://well/widget/6c49d60e` was removed, consumers reading it will break.","severity":"breaking"},{"kind":"resource_added","tool":"ui://well/widget/f98d62fc","after":"ui://well/widget/f98d62fc","detail":"Resource `ui://well/widget/f98d62fc` was added.","severity":"safe"}],"published_at":"2026-08-18T13:07:31.126Z"},{"slug":"ZV-2026-0126","server_name":"api.wellapp.ai","severity":"breaking","title":"api.wellapp.ai: Tool well_add_contact_channel was removed.","summary":"[breaking] Tool well_add_contact_channel was removed. [breaking] Tool well_create_company was removed. [breaking] Tool well_create_invoice_document was removed. [breaking] Tool well_create_invoice_from_data was removed. [breaking] Tool well_create_person was removed. [breaking] Tool well_delete_company was removed. [breaking] Tool well_delete_invoice was removed. [breaking] Tool well_delete_person was removed. [breaking] Tool well_get_cash_position was removed. [breaking] Tool well_get_cost_structure was removed. [breaking] Tool well_get_entity was removed. [breaking] Tool well_get_investment_holdings was removed. [breaking] Tool well_get_runway was removed. [breaking] Tool well_get_schema was removed. [breaking] Tool well_invoke_connector_tool was removed. [breaking] Tool well_list_connector_tools was removed. [breaking] Tool well_list_connectors was removed. [breaking] Tool well_list_workspaces was removed. [breaking] Tool well_query_records was removed. [breaking] Tool well_remove_contact_channel was removed. [breaking] Tool well_resolve_reconciliation_task was removed. [breaking] Tool well_resolve_register_diff_gap was removed. [breaking] Tool well_run_register_diff was removed. [breaking] Tool well_update_company was removed. [breaking] Tool well_update_invoice was removed. [breaking] Tool well_update_person was removed.","changes":[{"kind":"tool_removed","tool":"well_add_contact_channel","detail":"Tool `well_add_contact_channel` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_create_company","detail":"Tool `well_create_company` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_create_invoice_document","detail":"Tool `well_create_invoice_document` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_create_invoice_from_data","detail":"Tool `well_create_invoice_from_data` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_create_person","detail":"Tool `well_create_person` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_delete_company","detail":"Tool `well_delete_company` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_delete_invoice","detail":"Tool `well_delete_invoice` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_delete_person","detail":"Tool `well_delete_person` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_get_cash_position","detail":"Tool `well_get_cash_position` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_get_cost_structure","detail":"Tool `well_get_cost_structure` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_get_entity","detail":"Tool `well_get_entity` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_get_investment_holdings","detail":"Tool `well_get_investment_holdings` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_get_runway","detail":"Tool `well_get_runway` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_get_schema","detail":"Tool `well_get_schema` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_invoke_connector_tool","detail":"Tool `well_invoke_connector_tool` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_list_connector_tools","detail":"Tool `well_list_connector_tools` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_list_connectors","detail":"Tool `well_list_connectors` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_list_workspaces","detail":"Tool `well_list_workspaces` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_query_records","detail":"Tool `well_query_records` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_remove_contact_channel","detail":"Tool `well_remove_contact_channel` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_resolve_reconciliation_task","detail":"Tool `well_resolve_reconciliation_task` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_resolve_register_diff_gap","detail":"Tool `well_resolve_register_diff_gap` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_run_register_diff","detail":"Tool `well_run_register_diff` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_update_company","detail":"Tool `well_update_company` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_update_invoice","detail":"Tool `well_update_invoice` was removed.","severity":"breaking"},{"kind":"tool_removed","tool":"well_update_person","detail":"Tool `well_update_person` was removed.","severity":"breaking"}],"published_at":"2026-08-17T22:51:40.742Z"}]