Group and total records
odoo_read_groupAggregate records on an Odoo model (sum, avg, count, etc.) with optional grouping. Prefer this over odoo_search_read for totals or top-N. A workspace skill may already encode the right query: load it with tuqui_skill(action='get') when something names one, else look for one with tuqui_skill(action='list'). Always pass a tight limit and order so only the relevant slice comes back. Aggregates use 'field:agg' specs (e.g. 'amount_total:sum', '__count') and work on every Odoo version. Group by date with 'field:granularity' (e.g. 'date_order:month'). On Odoo 19+, use having to filter groups by aggregate values. Grouping by a currency only labels the amounts correctly if the measure is denominated in that same currency — check currency_field in odoo_fields_get ('amount_total' is in 'currency_id', 'amount_total_signed' in 'company_currency_id'); a mismatch is rejected. When a page comes back full the envelope reports the real total of groups — trust it: never consolidate a partial page of groups as if it were the full set; when has_more is true, call again with next_offset to read the rest.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"model": "<model>",
"domain": "<domain>",
"groupby": "<groupby>"
},
"name": "odoo_read_group"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| lazy | No | Deprecated and ignored: the tool always returns the full cross-grouping of every groupby level, with the count named '__count', on every Odoo version. Accepted only so older saved calls don't break. | |
| limit | No | Max groups per page (default 20, max 500). | |
| model | Yes | Odoo model technical name (e.g., 'sale.order', 'res.partner') | |
| order | No | ||
| domain | Yes | Odoo domain filter as logical operators ('&', '|', '!') and/or 3-item condition tuples like ['field', '=', 'value'] or ['field', 'in', ['a', 'b']]. For relational filters use 'any' / 'not any' with a sub-domain on a to-one/to-many field (Odoo 17+), which does a whole anti-join in one query: [['sale_order_ids', 'any', [['date_order', '>=', '2025-01-01']]], ['sale_order_ids', 'not any', [['date_order', '>=', '2026-01-01']]]]. | |
| fields | No | Legacy alias of 'aggregates' (classic read_group spelling, same 'field:agg' specs). Prefer 'aggregates'; kept for backwards compatibility. DO NOT pass groupby granularities (e.g. 'date_order:year') here — those go in 'groupby' only. | |
| having | No | Odoo 19+ ONLY: post-aggregation filter on aggregate values, e.g. [['__count', '>', 5]]. On Odoo 16/17/18 it is rejected with an error (the classic API cannot express it) — fetch the groups and filter on the aggregate values yourself instead. | |
| offset | No | ||
| context | No | Optional Odoo execute_kw context. The user's ``lang`` is injected from their profile — pass it here only to override it. See each field below for what it does. | |
| groupby | Yes | Fields to group by. Use 'field:granularity' for dates (month, year, etc.). | |
| aggregates | No | Aggregate specs 'field:agg'. Supported aggs: sum, avg, min, max, count_distinct. Use '__count' for record count. Works on every Odoo version — the tool routes to the right grouping API internally. DO NOT include groupby granularities like 'date_order:year' — those belong in 'groupby' only. |