search_expenses
Search and filter the user's expenses; returns matching rows from their spreadsheet. Filter by category, merchant, date range, amount or tags. Results are paginated: when hasMore is true, call again with nextCursor and the same filters; do not split a date range into overlapping searches.
The optional query parameter does deterministic natural-language recall over merchant, city/location, Notes (receipt items, delivery source, payer, Business purpose), Tag and category. Results include matchedFields and a short matchReason to explain the match; when several rows plausibly match, a disambiguation list is returned and each option carries the exact expenseId. Structured filters (categories, merchants, dateRange, tags, minAmount, maxAmount) combine with the query using AND. Each result includes expenseId, the exact durable Receipt ID required by update_expense. For country-based grouping or client-assignment review use groupBy:country with explicit YYYY-MM-DD start/end; this read-only mode reviews at most 100 matching expenses, so narrow the range if too large. Use exact configured categories for travel; a foreign expense is not necessarily travel. Recorded locations can resolve to derived countries, which is not proof of travel. Unknowns stay separate even with a country filter; ask about ambiguous places, never infer from currency. Country review supports categories, merchants, tags, countries and tagAssignment, not free query or pagination. Show counts and currency-separated totals, then copy the returned selectionItems (with tag/date/location expectations) into group_expenses after the user chooses destinations.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Filter by tags | |
| limit | No | Results per page (default 20, maximum 50) | |
| query | No | Optional natural-language recall over merchant, city/location, Notes (receipt items, delivery source, payer, Business purpose), Tag and category. Deterministic case-insensitive matching, no embeddings. Combined with structured filters using AND. Examples: 'Tribeca restaurant', 'client dinner note'. | |
| cursor | No | Opaque nextCursor returned by the previous search_expenses page. Reuse the same filters; never construct or edit this value. | |
| groupBy | No | Read-only country review; requires explicit dateRange.start/end and at most 100 matches. | |
| countries | No | Country-review filter: supported country names/codes, or unknown. Never infer a country from currency or an ambiguous city. | |
| dateRange | No | Time period filter; use exactly one variant matching the user's phrasing. | |
| maxAmount | No | Maximum expense amount | |
| merchants | No | Filter by merchant names (e.g., ['Uber', 'Starbucks']) | |
| minAmount | No | Minimum expense amount | |
| categories | No | Filter by expense categories (e.g., ['Travel', 'Meals']) | |
| hasReceipt | No | When true, return only expenses with a receipt link. When false, return only expenses without one. | |
| clientEmail | No | Accepted client's account email (accountants only). | |
| tagAssignment | No | Country review: unassigned means blank/Business; no_client means no canonical client tag, including project/trip-tagged rows. Neither implies business use. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| count | Yes | Rows matched by the filters. | |
| total | Yes | Home-currency sum in normal search; null in country review. Use countryGroups totalsByCurrency, never sum currencies. | |
| hasMore | No | ||
| message | No | ||
| expenses | Yes | Matching expense rows, newest first, paginated. | |
| pageInfo | No | ||
| nextCursor | No | Opaque signed continuation; reuse with identical filters. | |
| queryApplied | No | ||
| totalMatched | No | Present for free-text searches. | |
| countryGroups | No | Complete bounded country review; unknown locations remain separate. |