changedInput schema / properties / widgets / items / oneOf
Previous value: -[
- {
- "additionalProperties": false,
- "properties": {
- "dashboardId": {
- "description": "Id of the dashboard to render as a PDF (from `search`/`get`).",
- "minLength": 1,
- "type": "string"
- },
- "description": {
- "default": "",
- "type": "string"
- },
- "title": {
- "default": "",
- "type": "string"
- },
- "type": {
- "const": "DASHBOARD_PDF",
- "type": "string"
- }
- },
- "required": [
- "type",
- "dashboardId"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "aggBy": {
- "default": "Month",
- "description": "Time grain for the series: Hour, Day, Week, Month, or Period (default Month).",
- "enum": [
- "Hour",
- "Day",
- "Week",
- "Month",
- "Period"
- ],
- "type": "string"
- },
- "compare": {
- "additionalProperties": false,
- "description": "Add a comparison period to show cost evolution side-by-side. Omit `from`/`to` to compare against the preceding period automatically; set `chartType` to choose how it renders.",
- "properties": {
- "chartType": {
- "default": "WATERFALL",
- "description": "How the comparison renders: WATERFALL (default, contribution to change), TABLE (before/after rows), or KPI_BREAKDOWN (per-group KPI cards). Note KPI_BREAKDOWN and TABLE widgets cannot be exported as PNG via get_widget_png.",
- "enum": [
- "WATERFALL",
- "TABLE",
- "KPI_BREAKDOWN"
- ],
- "type": "string"
- },
- "enabled": {
- "default": true,
- "description": "Defaults to true — supplying `compare` at all turns the comparison on. Pass false to keep the block while disabling it (useful when echoing back a payload from `get`).",
- "type": "boolean"
- },
- "from": {
- "description": "Comparison period start date. Omit (together with `to`) to compare against the preceding period, derived from the main period.",
- "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
- "type": "string"
- },
- "to": {
- "description": "Comparison period end date. Required together with `from`; omit both to auto-derive.",
- "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
- "type": "string"
- }
- },
- "type": "object"
- },
- "datePreset": {
- "description": "Widget-level period override (same DatePreset as dashboards, e.g. LAST_WEEK). Omit to inherit `reportContext.datePreset` / startDate/endDate. Use either datePreset OR explicit from/to, not both.",
- "enum": [
- "TRAILING_90_DAYS",
- "TRAILING_30_DAYS",
- "TRAILING_45_DAYS",
- "TRAILING_7_DAYS",
- "TRAILING_3_DAYS",
- "TRAILING_14_WEEKS",
- "MTD",
- "QTD",
- "YTD",
- "LAST_WEEK",
- "LAST_MONTH",
- "LAST_6_MONTHS",
- "LAST_12_MONTHS",
- "LAST_4_YEARS",
- "LAST_3_MONTHS",
- "LAST_INVOICE_MONTH"
- ],
- "type": "string"
- },
- "description": {
- "default": "",
- "type": "string"
- },
- "from": {
- "description": "Widget-level start date override. Omit to inherit report context period.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- },
- "limit": {
- "description": "Max groups/rows per series. Omit to use the default (100). Increase up to 1000 when you need more than 100 breakdown groups.",
- "maximum": 1000,
- "minimum": 1,
- "type": "integer"
- },
- "queries": {
- "description": "Same series objects as the `query` tool `queries` array (cost / metric / usage / externalMetric / formula / budget). Each requires `type` (never omit) and a `name` (prefer short ids like a/b/c); put human labels in `alias`. On report widgets prefer sparse `{ type: \"cost\", name: \"a\", alias?, filterCel? }` and inherit metricId / currency / groupBy / period from `reportContext`. DIGEST: exactly one `{ type: \"cost\", ... }`. Call get_skill skillId: \"reports\" for examples.",
- "items": {
- "additionalProperties": {},
- "propertyNames": {
- "type": "string"
- },
- "type": "object"
- },
- "type": "array"
- },
- "scopeId": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Optional saved team scope id (from list_teams). Merges the scope whereClause into cost/usage queries."
- },
- "title": {
- "default": "",
- "type": "string"
- },
- "to": {
- "description": "Widget-level end date override (inclusive). Omit to inherit report context period.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- },
- "type": {
- "const": "GRAPH_SNAPSHOT",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "aggBy": {
- "default": "Month",
- "description": "Time grain for the series: Hour, Day, Week, Month, or Period (default Month).",
- "enum": [
- "Hour",
- "Day",
- "Week",
- "Month",
- "Period"
- ],
- "type": "string"
- },
- "datePreset": {
- "description": "Widget-level period override (same DatePreset as dashboards, e.g. LAST_WEEK). Omit to inherit `reportContext.datePreset` / startDate/endDate. Use either datePreset OR explicit from/to, not both.",
- "enum": [
- "TRAILING_90_DAYS",
- "TRAILING_30_DAYS",
- "TRAILING_45_DAYS",
- "TRAILING_7_DAYS",
- "TRAILING_3_DAYS",
- "TRAILING_14_WEEKS",
- "MTD",
- "QTD",
- "YTD",
- "LAST_WEEK",
- "LAST_MONTH",
- "LAST_6_MONTHS",
- "LAST_12_MONTHS",
- "LAST_4_YEARS",
- "LAST_3_MONTHS",
- "LAST_INVOICE_MONTH"
- ],
- "type": "string"
- },
- "description": {
- "default": "",
- "type": "string"
- },
- "flopN": {
- "default": 5,
- "maximum": 50,
- "minimum": 0,
- "type": "integer"
- },
- "from": {
- "description": "Widget-level start date override. Omit to inherit report context period.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- },
- "limit": {
- "description": "Max groups/rows per series. Omit to use the default (100). Increase up to 1000 when you need more than 100 breakdown groups.",
- "maximum": 1000,
- "minimum": 1,
- "type": "integer"
- },
- "queries": {
- "description": "Same series objects as the `query` tool `queries` array (cost / metric / usage / externalMetric / formula / budget). Each requires `type` (never omit) and a `name` (prefer short ids like a/b/c); put human labels in `alias`. On report widgets prefer sparse `{ type: \"cost\", name: \"a\", alias?, filterCel? }` and inherit metricId / currency / groupBy / period from `reportContext`. DIGEST: exactly one `{ type: \"cost\", ... }`. Call get_skill skillId: \"reports\" for examples.",
- "items": {
- "additionalProperties": {},
- "propertyNames": {
- "type": "string"
- },
- "type": "object"
- },
- "type": "array"
- },
- "scopeId": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Optional saved team scope id (from list_teams). Merges the scope whereClause into cost/usage queries."
- },
- "title": {
- "default": "",
- "type": "string"
- },
- "to": {
- "description": "Widget-level end date override (inclusive). Omit to inherit report context period.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- },
- "topN": {
- "default": 5,
- "maximum": 50,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "TOP_FLOP",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "contentMarkdown": {
- "maxLength": 10000,
- "minLength": 1,
- "type": "string"
- },
- "description": {
- "default": "",
- "type": "string"
- },
- "title": {
- "default": "",
- "type": "string"
- },
- "type": {
- "const": "TEXT",
- "type": "string"
- }
- },
- "required": [
- "type",
- "contentMarkdown"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "additionalGroupBy": {
- "default": [],
- "description": "Deeper DIGEST hierarchy levels AFTER the root groupBy, in order. Root axis is `reportContext.groupBy` (preferred) or `queries[0].groupBy` when overriding. Example: reportContext.groupBy=\"cos_environment\" + additionalGroupBy=[\"cos_sub_account_id\",\"cos_service_name\"] → tree path environment → project → service.",
- "items": {
- "minLength": 1,
- "type": "string"
- },
- "type": "array"
- },
- "aggBy": {
- "default": "Month",
- "description": "DIGEST time grain: Week or Month (default Month). Never Period (use TOP_FLOP for whole-period movers).",
- "enum": [
- "Week",
- "Month"
- ],
- "type": "string"
- },
- "compare": {
- "description": "Required only with explicit from/to when not using datePreset or reportContext. Prefer datePreset / reportContext.",
- "properties": {
- "from": {
- "description": "Comparison period start date.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- },
- "to": {
- "description": "Comparison period end date.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- }
- },
- "required": [
- "from",
- "to"
- ],
- "type": "object"
- },
- "datePreset": {
- "description": "Widget-level period override for scheduled DIGESTs (same DatePreset as dashboards, e.g. LAST_WEEK). Omit to inherit `reportContext.datePreset` / startDate/endDate. Mutually exclusive with explicit from/to/compare — do not set both.",
- "enum": [
- "TRAILING_90_DAYS",
- "TRAILING_30_DAYS",
- "TRAILING_45_DAYS",
- "TRAILING_7_DAYS",
- "TRAILING_3_DAYS",
- "TRAILING_14_WEEKS",
- "MTD",
- "QTD",
- "YTD",
- "LAST_WEEK",
- "LAST_MONTH",
- "LAST_6_MONTHS",
- "LAST_12_MONTHS",
- "LAST_4_YEARS",
- "LAST_3_MONTHS",
- "LAST_INVOICE_MONTH"
- ],
- "type": "string"
- },
- "description": {
- "default": "",
- "type": "string"
- },
- "display": {
- "default": "tree",
- "description": "DIGEST presentation: \"tree\" (default, change tree only — faster), \"summary\" (LLM executive narrative — slower; opt-in AI summary), or \"table\" (flat table). Set \"summary\" when the user wants the AI write-up.",
- "enum": [
- "tree",
- "table",
- "summary"
- ],
- "type": "string"
- },
- "enableAiInvestigation": {
- "default": false,
- "description": "When true, deepest-leaf cost movers get per-node AI investigation before delivery (async analysis_agent_run — noticeably slower). Default false. Independent of display: \"summary\" (executive narrative). Prefer display: \"summary\" alone for a written overview; enable this only when the user wants deep node analysis.",
- "type": "boolean"
- },
- "from": {
- "description": "Only for one-off custom ranges (YYYY-MM-DD). Omit to inherit report context. Do not set when datePreset is set.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- },
- "limit": {
- "description": "Max groups/rows per series. Omit to use the default (100). Increase up to 1000 when you need more than 100 breakdown groups.",
- "maximum": 1000,
- "minimum": 1,
- "type": "integer"
- },
- "minAbsoluteDiff": {
- "default": 100,
- "minimum": 0,
- "type": "number"
- },
- "minRelativeDiff": {
- "default": 5,
- "minimum": 0,
- "type": "number"
- },
- "queries": {
- "description": "Same series objects as the `query` tool `queries` array (cost / metric / usage / externalMetric / formula / budget). Each requires `type` (never omit) and a `name` (prefer short ids like a/b/c); put human labels in `alias`. On report widgets prefer sparse `{ type: \"cost\", name: \"a\", alias?, filterCel? }` and inherit metricId / currency / groupBy / period from `reportContext`. DIGEST: exactly one `{ type: \"cost\", ... }`. Call get_skill skillId: \"reports\" for examples.",
- "items": {
- "additionalProperties": {},
- "propertyNames": {
- "type": "string"
- },
- "type": "object"
- },
- "type": "array"
- },
- "scopeId": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Optional saved team scope id (from list_teams). Merges the scope whereClause into cost/usage queries."
- },
- "title": {
- "default": "Cost changes",
- "type": "string"
- },
- "to": {
- "description": "Only for one-off custom ranges (YYYY-MM-DD). Omit to inherit report context. Do not set when datePreset is set.",
- "format": "date",
- "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
- "type": "string"
- },
- "topLargestAbsoluteChange": {
- "default": 20,
- "description": "How many largest-absolute-change nodes to surface. Allowed values: 5, 10, 15, or 20.",
- "type": "number"
- },
- "type": {
- "const": "DIGEST",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- }
-]New value: +[
+ {
+ "additionalProperties": false,
+ "properties": {
+ "dashboardId": {
+ "description": "Id of the dashboard to render as a PDF (from `search`/`get`).",
+ "minLength": 1,
+ "type": "string"
+ },
+ "datePreset": {
+ "description": "Optional period override for the PDF. Omit to inherit the report (and destination) period.",
+ "enum": [
+ "TRAILING_90_DAYS",
+ "TRAILING_30_DAYS",
+ "TRAILING_45_DAYS",
+ "TRAILING_7_DAYS",
+ "TRAILING_3_DAYS",
+ "TRAILING_14_WEEKS",
+ "MTD",
+ "QTD",
+ "YTD",
+ "LAST_WEEK",
+ "LAST_MONTH",
+ "LAST_6_MONTHS",
+ "LAST_12_MONTHS",
+ "LAST_4_YEARS",
+ "LAST_3_MONTHS",
+ "LAST_INVOICE_MONTH"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "default": "",
+ "type": "string"
+ },
+ "from": {
+ "description": "Optional custom range start (YYYY-MM-DD). Use with to instead of datePreset.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "title": {
+ "default": "",
+ "type": "string"
+ },
+ "to": {
+ "description": "Optional custom range end (inclusive, YYYY-MM-DD). Use with from instead of datePreset.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "type": {
+ "const": "DASHBOARD_PDF",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "dashboardId"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "aggBy": {
+ "default": "Month",
+ "description": "Time grain for the series: Hour, Day, Week, Month, or Period (default Month).",
+ "enum": [
+ "Hour",
+ "Day",
+ "Week",
+ "Month",
+ "Period"
+ ],
+ "type": "string"
+ },
+ "compare": {
+ "additionalProperties": false,
+ "description": "Add a comparison period to show cost evolution side-by-side. Omit `from`/`to` to compare against the preceding period automatically; set `chartType` to choose how it renders.",
+ "properties": {
+ "chartType": {
+ "default": "WATERFALL",
+ "description": "How the comparison renders: WATERFALL (default, contribution to change), TABLE (before/after rows), or KPI_BREAKDOWN (per-group KPI cards). Note KPI_BREAKDOWN and TABLE widgets cannot be exported as PNG via get_widget_png.",
+ "enum": [
+ "WATERFALL",
+ "TABLE",
+ "KPI_BREAKDOWN"
+ ],
+ "type": "string"
+ },
+ "enabled": {
+ "default": true,
+ "description": "Defaults to true — supplying `compare` at all turns the comparison on. Pass false to keep the block while disabling it (useful when echoing back a payload from `get`).",
+ "type": "boolean"
+ },
+ "from": {
+ "description": "Comparison period start date. Omit (together with `to`) to compare against the preceding period, derived from the main period.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
+ "type": "string"
+ },
+ "to": {
+ "description": "Comparison period end date. Required together with `from`; omit both to auto-derive.",
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "datePreset": {
+ "description": "Widget-level period override (same DatePreset as dashboards, e.g. LAST_WEEK). Omit to inherit `reportContext.datePreset` / startDate/endDate. Use either datePreset OR explicit from/to, not both.",
+ "enum": [
+ "TRAILING_90_DAYS",
+ "TRAILING_30_DAYS",
+ "TRAILING_45_DAYS",
+ "TRAILING_7_DAYS",
+ "TRAILING_3_DAYS",
+ "TRAILING_14_WEEKS",
+ "MTD",
+ "QTD",
+ "YTD",
+ "LAST_WEEK",
+ "LAST_MONTH",
+ "LAST_6_MONTHS",
+ "LAST_12_MONTHS",
+ "LAST_4_YEARS",
+ "LAST_3_MONTHS",
+ "LAST_INVOICE_MONTH"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "default": "",
+ "type": "string"
+ },
+ "from": {
+ "description": "Widget-level start date override. Omit to inherit report context period.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "limit": {
+ "description": "Max groups/rows per series. Omit to use the default (100). Increase up to 1000 when you need more than 100 breakdown groups.",
+ "maximum": 1000,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "queries": {
+ "description": "Same series objects as the `query` tool `queries` array (cost / metric / usage / externalMetric / formula / budget). Each requires `type` (never omit) and a `name` (prefer short ids like a/b/c); put human labels in `alias`. On report widgets prefer sparse `{ type: \"cost\", name: \"a\", alias?, filterCel? }` and inherit metricId / currency / groupBy / period from `reportContext`. DIGEST: exactly one `{ type: \"cost\", ... }`. Call get_skill skillId: \"reports\" for examples.",
+ "items": {
+ "additionalProperties": {},
+ "propertyNames": {
+ "type": "string"
+ },
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "scopeId": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Optional saved team scope id (from list_teams). Merges the scope whereClause into cost/usage queries."
+ },
+ "title": {
+ "default": "",
+ "type": "string"
+ },
+ "to": {
+ "description": "Widget-level end date override (inclusive). Omit to inherit report context period.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "type": {
+ "const": "GRAPH_SNAPSHOT",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "aggBy": {
+ "default": "Month",
+ "description": "Time grain for the series: Hour, Day, Week, Month, or Period (default Month).",
+ "enum": [
+ "Hour",
+ "Day",
+ "Week",
+ "Month",
+ "Period"
+ ],
+ "type": "string"
+ },
+ "datePreset": {
+ "description": "Widget-level period override (same DatePreset as dashboards, e.g. LAST_WEEK). Omit to inherit `reportContext.datePreset` / startDate/endDate. Use either datePreset OR explicit from/to, not both.",
+ "enum": [
+ "TRAILING_90_DAYS",
+ "TRAILING_30_DAYS",
+ "TRAILING_45_DAYS",
+ "TRAILING_7_DAYS",
+ "TRAILING_3_DAYS",
+ "TRAILING_14_WEEKS",
+ "MTD",
+ "QTD",
+ "YTD",
+ "LAST_WEEK",
+ "LAST_MONTH",
+ "LAST_6_MONTHS",
+ "LAST_12_MONTHS",
+ "LAST_4_YEARS",
+ "LAST_3_MONTHS",
+ "LAST_INVOICE_MONTH"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "default": "",
+ "type": "string"
+ },
+ "flopN": {
+ "default": 5,
+ "maximum": 50,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "from": {
+ "description": "Widget-level start date override. Omit to inherit report context period.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "limit": {
+ "description": "Max groups/rows per series. Omit to use the default (100). Increase up to 1000 when you need more than 100 breakdown groups.",
+ "maximum": 1000,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "queries": {
+ "description": "Same series objects as the `query` tool `queries` array (cost / metric / usage / externalMetric / formula / budget). Each requires `type` (never omit) and a `name` (prefer short ids like a/b/c); put human labels in `alias`. On report widgets prefer sparse `{ type: \"cost\", name: \"a\", alias?, filterCel? }` and inherit metricId / currency / groupBy / period from `reportContext`. DIGEST: exactly one `{ type: \"cost\", ... }`. Call get_skill skillId: \"reports\" for examples.",
+ "items": {
+ "additionalProperties": {},
+ "propertyNames": {
+ "type": "string"
+ },
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "scopeId": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Optional saved team scope id (from list_teams). Merges the scope whereClause into cost/usage queries."
+ },
+ "title": {
+ "default": "",
+ "type": "string"
+ },
+ "to": {
+ "description": "Widget-level end date override (inclusive). Omit to inherit report context period.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "topN": {
+ "default": 5,
+ "maximum": 50,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "TOP_FLOP",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "contentMarkdown": {
+ "maxLength": 10000,
+ "minLength": 1,
+ "type": "string"
+ },
+ "description": {
+ "default": "",
+ "type": "string"
+ },
+ "title": {
+ "default": "",
+ "type": "string"
+ },
+ "type": {
+ "const": "TEXT",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "contentMarkdown"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "additionalGroupBy": {
+ "default": [],
+ "description": "Deeper DIGEST hierarchy levels AFTER the root groupBy, in order. Root axis is `reportContext.groupBy` (preferred) or `queries[0].groupBy` when overriding. Example: reportContext.groupBy=\"cos_environment\" + additionalGroupBy=[\"cos_sub_account_id\",\"cos_service_name\"] → tree path environment → project → service.",
+ "items": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "aggBy": {
+ "default": "Month",
+ "description": "DIGEST time grain: Week or Month (default Month). Never Period (use TOP_FLOP for whole-period movers).",
+ "enum": [
+ "Week",
+ "Month"
+ ],
+ "type": "string"
+ },
+ "compare": {
+ "description": "Required only with explicit from/to when not using datePreset or reportContext. Prefer datePreset / reportContext.",
+ "properties": {
+ "from": {
+ "description": "Comparison period start date.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "to": {
+ "description": "Comparison period end date.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ }
+ },
+ "required": [
+ "from",
+ "to"
+ ],
+ "type": "object"
+ },
+ "datePreset": {
+ "description": "Widget-level period override for scheduled DIGESTs (same DatePreset as dashboards, e.g. LAST_WEEK). Omit to inherit `reportContext.datePreset` / startDate/endDate. Mutually exclusive with explicit from/to/compare — do not set both.",
+ "enum": [
+ "TRAILING_90_DAYS",
+ "TRAILING_30_DAYS",
+ "TRAILING_45_DAYS",
+ "TRAILING_7_DAYS",
+ "TRAILING_3_DAYS",
+ "TRAILING_14_WEEKS",
+ "MTD",
+ "QTD",
+ "YTD",
+ "LAST_WEEK",
+ "LAST_MONTH",
+ "LAST_6_MONTHS",
+ "LAST_12_MONTHS",
+ "LAST_4_YEARS",
+ "LAST_3_MONTHS",
+ "LAST_INVOICE_MONTH"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "default": "",
+ "type": "string"
+ },
+ "display": {
+ "default": "tree",
+ "description": "DIGEST presentation: \"tree\" (default, change tree only — faster), \"summary\" (LLM executive narrative — slower; opt-in AI summary), or \"table\" (flat table). Set \"summary\" when the user wants the AI write-up.",
+ "enum": [
+ "tree",
+ "table",
+ "summary"
+ ],
+ "type": "string"
+ },
+ "enableAiInvestigation": {
+ "default": false,
+ "description": "When true, deepest-leaf cost movers get per-node AI investigation before delivery (async analysis_agent_run — noticeably slower). Default false. Independent of display: \"summary\" (executive narrative). Prefer display: \"summary\" alone for a written overview; enable this only when the user wants deep node analysis.",
+ "type": "boolean"
+ },
+ "from": {
+ "description": "Only for one-off custom ranges (YYYY-MM-DD). Omit to inherit report context. Do not set when datePreset is set.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "limit": {
+ "description": "Max groups/rows per series. Omit to use the default (100). Increase up to 1000 when you need more than 100 breakdown groups.",
+ "maximum": 1000,
+ "minimum": 1,
+ "type": "integer"
+ },
+ "minAbsoluteDiff": {
+ "default": 100,
+ "minimum": 0,
+ "type": "number"
+ },
+ "minRelativeDiff": {
+ "default": 5,
+ "minimum": 0,
+ "type": "number"
+ },
+ "queries": {
+ "description": "Same series objects as the `query` tool `queries` array (cost / metric / usage / externalMetric / formula / budget). Each requires `type` (never omit) and a `name` (prefer short ids like a/b/c); put human labels in `alias`. On report widgets prefer sparse `{ type: \"cost\", name: \"a\", alias?, filterCel? }` and inherit metricId / currency / groupBy / period from `reportContext`. DIGEST: exactly one `{ type: \"cost\", ... }`. Call get_skill skillId: \"reports\" for examples.",
+ "items": {
+ "additionalProperties": {},
+ "propertyNames": {
+ "type": "string"
+ },
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "scopeId": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Optional saved team scope id (from list_teams). Merges the scope whereClause into cost/usage queries."
+ },
+ "title": {
+ "default": "Cost changes",
+ "type": "string"
+ },
+ "to": {
+ "description": "Only for one-off custom ranges (YYYY-MM-DD). Omit to inherit report context. Do not set when datePreset is set.",
+ "format": "date",
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
+ "type": "string"
+ },
+ "topLargestAbsoluteChange": {
+ "default": 20,
+ "description": "How many largest-absolute-change nodes to surface. Allowed values: 5, 10, 15, or 20.",
+ "type": "number"
+ },
+ "type": {
+ "const": "DIGEST",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ }
+]