Skip to main content
Glama

Costory: Your Finops MCP

preview_report_widget

Read-only

Dry-run preview of ONE report widget. Read-only and in-memory: does not persist a report, does not mutate any Costory object, and does not send Slack/Teams/email. Pass the same reportContext + widget object you will later hand to create_report. Returns a token-bounded, per-type result. By type: DIGEST → resolvedPeriod, comparison totals, largest changes, root nodes, summary markdown (when display is "summary"), recommendations; TOP_FLOP → bounded top/flop rows; GRAPH_SNAPSHOT → bounded series sample (no image) + explorerUrl; DASHBOARD_PDF/TEXT → validity pointer. Put shared period / groupBy / metric / currency / conditionsCel in reportContext; widgets omit matching fields to inherit. The legacy context alias is temporarily accepted but deprecated; never send both. DIGEST hierarchy: reportContext.groupBy (root, preferred) + additionalGroupBy (deeper levels). Per-widget override: set useDashboardGroupBy: false to ignore reportContext.groupBy for this widget — the first additionalGroupBy item (or queries[0].groupBy) becomes the root; false requires at least one dimension. DIGEST threshold defaults: 100 absolute / 5% relative / 20 changes (topLargestAbsoluteChange integer 1–100, applied at every tree level). DIGEST AI (opt-in, still preview-only — nothing is saved or delivered): display ("tree" default | "table" | "summary" for LLM executive narrative) and enableAiInvestigation (boolean, default false — per-node deep analysis, independent of display). DIGEST aggBy is Month or Week — never Period (Period is TOP_FLOP). EXAMPLES: • Monthly DIGEST by env → project → service (AI summary) → { reportContext: { datePreset: "LAST_MONTH", groupBy: "cos_environment", metricId: "cost", currency: "USD" }, widget: { type: "DIGEST", queries: [{ type: "cost", name: "a" }], aggBy: "Month", additionalGroupBy: ["cos_sub_account_id", "cos_service_name"], minAbsoluteDiff: 100, minRelativeDiff: 5, topLargestAbsoluteChange: 20, display: "summary", enableAiInvestigation: false } } • Kubernetes-only weekly DIGEST (per-widget filterCel) → { reportContext: { datePreset: "LAST_WEEK", groupBy: "cos_namespace_reallocated", metricId: "cost", currency: "USD" }, widget: { type: "DIGEST", title: "Kubernetes", queries: [{ type: "cost", name: "a", filterCel: "cos_cluster_name != null" }], aggBy: "Week", additionalGroupBy: ["cos_workload_name"] } } • Namespace-rooted DIGEST overriding the report group-by → { reportContext: { datePreset: "LAST_MONTH", groupBy: "cos_environment", metricId: "cost", currency: "USD" }, widget: { type: "DIGEST", title: "Kubernetes", useDashboardGroupBy: false, queries: [{ type: "cost", name: "a" }], aggBy: "Month", additionalGroupBy: ["cos_namespace_reallocated", "cos_workload_name"] } } • Weekly TOP_FLOP → { reportContext: { datePreset: "LAST_WEEK", groupBy: "cos_service_name", metricId: "cost", currency: "USD" }, widget: { type: "TOP_FLOP", queries: [{ type: "cost", name: "a" }], aggBy: "Period", topN: 5, flopN: 5 } }

Input Schema

NameRequiredDescriptionDefault
slugNoOrganization slug. Omit to auto-detect from your account (fails if you belong to multiple orgs).
widgetYesSingle widget to preview (same shape as create/update `widgets[]` items).
contextNoDeprecated alias for `reportContext`; supported temporarily for backward compatibility. Do not send both fields.
reportContextNoOptional shared context the widget inherits (same shape as `create_report` `reportContext`).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / widget / oneOf
      Previous 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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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": {
      -        "$ref": "#/definitions/ReportMcpQueries"
      -      },
      -      "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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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": 100,
      -        "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": {
      -        "$ref": "#/definitions/ReportMcpQueries"
      -      },
      -      "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": 100,
      -        "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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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": {
      -        "$ref": "#/definitions/ReportMcpQueries"
      -      },
      -      "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 (integer 1–100). Applied at every tree level.",
      -        "maximum": 100,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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": {
      +        "$ref": "#/definitions/ReportMcpQueries"
      +      },
      +      "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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": 100,
      +        "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": {
      +        "$ref": "#/definitions/ReportMcpQueries"
      +      },
      +      "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": 100,
      +        "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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": {
      +        "$ref": "#/definitions/ReportMcpQueries"
      +      },
      +      "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 (integer 1–100). Applied at every tree level.",
      +        "maximum": 100,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "DIGEST",
      +        "type": "string"
      +      },
      +      "useDashboardGroupBy": {
      +        "default": true,
      +        "description": "Use `reportContext.groupBy` as this DIGEST's root group-by (default true). Set false to override: the report context group-by is ignored for this widget and the first `additionalGroupBy` item (or `queries[0].groupBy`) becomes the root. `false` requires at least one dimension (a non-empty `additionalGroupBy` or a `queries[0].groupBy`). Example: useDashboardGroupBy: false + additionalGroupBy: [\"cos_namespace_reallocated\",\"cos_workload_name\"] → root cos_namespace_reallocated, report context key ignored for this widget only.",
      +        "type": "boolean"
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed1 schema field changed
    • changedInput schema / definitions / ReportMcpQueries / description
      Previous value: -"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`. Cost inherits metricId/currency/groupBy from reportContext; usage requires metricId (omit groupBy = ungrouped). Cost/usage inherit conditionsCel. `visible: false` hides a series. DIGEST: one cost query. See skill reports."New value: +"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`. Cost inherits metricId/currency/groupBy from reportContext; usage requires metricId (omit groupBy = ungrouped). Budget groupBy is explicit (budget VD bqName); it does not inherit reportContext.groupBy. Cost/usage inherit conditionsCel. `visible: false` hides a series. DIGEST: one cost query. See skill reports."
  3. Changed8 schema fields changed
    • addedInput schema / definitions
      Added value: +{
      +  "ReportMcpContext": {
      +    "properties": {
      +      "conditionsCel": {
      +        "description": "Report-wide CEL filter merged into cost and usage widgets. Omit or empty string for no report-level filter.",
      +        "type": "string"
      +      },
      +      "currency": {
      +        "anyOf": [
      +          {
      +            "enum": [
      +              "USD",
      +              "EUR",
      +              "GBP",
      +              "CNY",
      +              "KRW"
      +            ],
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "datePreset": {
      +        "anyOf": [
      +          {
      +            "enum": [
      +              "TRAILING_90_DAYS",
      +              "TRAILING_30_DAYS",
      +              "TRAILING_45_DAYS",
      +              "TRAILING_7_DAYS",
      +              "TRAILING_3_DAYS",
      +              "TRAILING_1_DAYS",
      +              "TRAILING_14_WEEKS",
      +              "MTD",
      +              "QTD",
      +              "YTD",
      +              "CURRENT_MONTH",
      +              "CURRENT_QUARTER",
      +              "CURRENT_YEAR",
      +              "LAST_WEEK",
      +              "LAST_MONTH",
      +              "LAST_6_MONTHS",
      +              "LAST_12_MONTHS",
      +              "LAST_4_YEARS",
      +              "LAST_3_MONTHS",
      +              "LAST_INVOICE_MONTH"
      +            ],
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Default date preset inherited when a widget omits date fields. Forecast: CURRENT_MONTH / CURRENT_QUARTER / CURRENT_YEAR. Prefer this over startDate/endDate."
      +      },
      +      "endDate": {
      +        "anyOf": [
      +          {
      +            "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": "null"
      +          }
      +        ]
      +      },
      +      "groupBy": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Default group-by axis inherited by widgets that omit `groupBy`. For DIGEST, this is the root hierarchy axis — put deeper levels in `additionalGroupBy`."
      +      },
      +      "metricId": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Default metric inherited by widget cost queries that omit `metricId`."
      +      },
      +      "scopeId": {
      +        "anyOf": [
      +          {
      +            "anyOf": [
      +              {
      +                "type": "string"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ]
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Optional saved team scope id (from list_teams). Applied report-wide unless a widget overrides."
      +      },
      +      "startDate": {
      +        "anyOf": [
      +          {
      +            "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": "null"
      +          }
      +        ],
      +        "description": "Used only when `datePreset` is null; ISO date (YYYY-MM-DD)."
      +      }
      +    },
      +    "type": "object"
      +  },
      +  "ReportMcpQueries": {
      +    "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`. Cost inherits metricId/currency/groupBy from reportContext; usage requires metricId (omit groupBy = ungrouped). Cost/usage inherit conditionsCel. `visible: false` hides a series. DIGEST: one cost query. See skill reports.",
      +    "items": {
      +      "additionalProperties": {},
      +      "propertyNames": {
      +        "type": "string"
      +      },
      +      "type": "object"
      +    },
      +    "type": "array"
      +  }
      +}
    • addedInput schema / properties / context / allOf
      Added value: +[
      +  {
      +    "$ref": "#/definitions/ReportMcpContext"
      +  }
      +]
    • removedInput schema / properties / context / properties
      Removed value: -{
      -  "conditionsCel": {
      -    "description": "Report-wide CEL filter merged into cost widgets. Omit or empty string for no report-level filter.",
      -    "type": "string"
      -  },
      -  "currency": {
      -    "anyOf": [
      -      {
      -        "enum": [
      -          "USD",
      -          "EUR",
      -          "GBP",
      -          "CNY",
      -          "KRW"
      -        ],
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ]
      -  },
      -  "datePreset": {
      -    "anyOf": [
      -      {
      -        "enum": [
      -          "TRAILING_90_DAYS",
      -          "TRAILING_30_DAYS",
      -          "TRAILING_45_DAYS",
      -          "TRAILING_7_DAYS",
      -          "TRAILING_3_DAYS",
      -          "TRAILING_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "LAST_WEEK",
      -          "LAST_MONTH",
      -          "LAST_6_MONTHS",
      -          "LAST_12_MONTHS",
      -          "LAST_4_YEARS",
      -          "LAST_3_MONTHS",
      -          "LAST_INVOICE_MONTH"
      -        ],
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Default date preset inherited when a widget omits date fields. Forecast: CURRENT_MONTH / CURRENT_QUARTER / CURRENT_YEAR. Prefer this over startDate/endDate."
      -  },
      -  "endDate": {
      -    "anyOf": [
      -      {
      -        "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": "null"
      -      }
      -    ]
      -  },
      -  "groupBy": {
      -    "anyOf": [
      -      {
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Default group-by axis inherited by widgets that omit `groupBy`. For DIGEST, this is the root hierarchy axis — put deeper levels in `additionalGroupBy`."
      -  },
      -  "metricId": {
      -    "anyOf": [
      -      {
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Default metric inherited by widget cost queries that omit `metricId`."
      -  },
      -  "scopeId": {
      -    "anyOf": [
      -      {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Optional saved team scope id (from list_teams). Applied report-wide unless a widget overrides."
      -  },
      -  "startDate": {
      -    "anyOf": [
      -      {
      -        "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": "null"
      -      }
      -    ],
      -    "description": "Used only when `datePreset` is null; ISO date (YYYY-MM-DD)."
      -  }
      -}
    • removedInput schema / properties / context / type
      Removed value: -"object"
    • addedInput schema / properties / reportContext / allOf
      Added value: +[
      +  {
      +    "$ref": "#/definitions/ReportMcpContext"
      +  }
      +]
    • removedInput schema / properties / reportContext / properties
      Removed value: -{
      -  "conditionsCel": {
      -    "description": "Report-wide CEL filter merged into cost widgets. Omit or empty string for no report-level filter.",
      -    "type": "string"
      -  },
      -  "currency": {
      -    "anyOf": [
      -      {
      -        "enum": [
      -          "USD",
      -          "EUR",
      -          "GBP",
      -          "CNY",
      -          "KRW"
      -        ],
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ]
      -  },
      -  "datePreset": {
      -    "anyOf": [
      -      {
      -        "enum": [
      -          "TRAILING_90_DAYS",
      -          "TRAILING_30_DAYS",
      -          "TRAILING_45_DAYS",
      -          "TRAILING_7_DAYS",
      -          "TRAILING_3_DAYS",
      -          "TRAILING_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "LAST_WEEK",
      -          "LAST_MONTH",
      -          "LAST_6_MONTHS",
      -          "LAST_12_MONTHS",
      -          "LAST_4_YEARS",
      -          "LAST_3_MONTHS",
      -          "LAST_INVOICE_MONTH"
      -        ],
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Default date preset inherited when a widget omits date fields. Forecast: CURRENT_MONTH / CURRENT_QUARTER / CURRENT_YEAR. Prefer this over startDate/endDate."
      -  },
      -  "endDate": {
      -    "anyOf": [
      -      {
      -        "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": "null"
      -      }
      -    ]
      -  },
      -  "groupBy": {
      -    "anyOf": [
      -      {
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Default group-by axis inherited by widgets that omit `groupBy`. For DIGEST, this is the root hierarchy axis — put deeper levels in `additionalGroupBy`."
      -  },
      -  "metricId": {
      -    "anyOf": [
      -      {
      -        "type": "string"
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Default metric inherited by widget cost queries that omit `metricId`."
      -  },
      -  "scopeId": {
      -    "anyOf": [
      -      {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      {
      -        "type": "null"
      -      }
      -    ],
      -    "description": "Optional saved team scope id (from list_teams). Applied report-wide unless a widget overrides."
      -  },
      -  "startDate": {
      -    "anyOf": [
      -      {
      -        "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": "null"
      -      }
      -    ],
      -    "description": "Used only when `datePreset` is null; ISO date (YYYY-MM-DD)."
      -  }
      -}
    • removedInput schema / properties / reportContext / type
      Removed value: -"object"
    • changedInput schema / properties / widget / oneOf
      Previous 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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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": 100,
      -        "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": 100,
      -        "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_1_DAYS",
      -          "TRAILING_14_WEEKS",
      -          "MTD",
      -          "QTD",
      -          "YTD",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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 (integer 1–100). Applied at every tree level.",
      -        "maximum": 100,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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": {
      +        "$ref": "#/definitions/ReportMcpQueries"
      +      },
      +      "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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": 100,
      +        "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": {
      +        "$ref": "#/definitions/ReportMcpQueries"
      +      },
      +      "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": 100,
      +        "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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": {
      +        "$ref": "#/definitions/ReportMcpQueries"
      +      },
      +      "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 (integer 1–100). Applied at every tree level.",
      +        "maximum": 100,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "DIGEST",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  }
      +]
  4. Changed2 schema fields changed
    • changedInput schema / properties / context / properties / datePreset / description
      Previous value: -"Default date preset inherited when a widget omits date fields. Prefer this over startDate/endDate whenever an available preset matches."New value: +"Default date preset inherited when a widget omits date fields. Forecast: CURRENT_MONTH / CURRENT_QUARTER / CURRENT_YEAR. Prefer this over startDate/endDate."
    • changedInput schema / properties / reportContext / properties / datePreset / description
      Previous value: -"Default date preset inherited when a widget omits date fields. Prefer this over startDate/endDate whenever an available preset matches."New value: +"Default date preset inherited when a widget omits date fields. Forecast: CURRENT_MONTH / CURRENT_QUARTER / CURRENT_YEAR. Prefer this over startDate/endDate."
  5. Changed2 schema fields changed
    • changedInput schema / properties / context / properties / currency / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "USD",
      -      "EUR",
      -      "GBP",
      -      "CNY"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "USD",
      +      "EUR",
      +      "GBP",
      +      "CNY",
      +      "KRW"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / reportContext / properties / currency / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "USD",
      -      "EUR",
      -      "GBP",
      -      "CNY"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "USD",
      +      "EUR",
      +      "GBP",
      +      "CNY",
      +      "KRW"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  6. Changed3 schema fields changed
    • changedInput schema / properties / context / properties / datePreset / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "TRAILING_90_DAYS",
      -      "TRAILING_30_DAYS",
      -      "TRAILING_45_DAYS",
      -      "TRAILING_7_DAYS",
      -      "TRAILING_3_DAYS",
      -      "TRAILING_14_WEEKS",
      -      "MTD",
      -      "QTD",
      -      "YTD",
      -      "CURRENT_MONTH",
      -      "CURRENT_QUARTER",
      -      "CURRENT_YEAR",
      -      "LAST_WEEK",
      -      "LAST_MONTH",
      -      "LAST_6_MONTHS",
      -      "LAST_12_MONTHS",
      -      "LAST_4_YEARS",
      -      "LAST_3_MONTHS",
      -      "LAST_INVOICE_MONTH"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "TRAILING_90_DAYS",
      +      "TRAILING_30_DAYS",
      +      "TRAILING_45_DAYS",
      +      "TRAILING_7_DAYS",
      +      "TRAILING_3_DAYS",
      +      "TRAILING_1_DAYS",
      +      "TRAILING_14_WEEKS",
      +      "MTD",
      +      "QTD",
      +      "YTD",
      +      "CURRENT_MONTH",
      +      "CURRENT_QUARTER",
      +      "CURRENT_YEAR",
      +      "LAST_WEEK",
      +      "LAST_MONTH",
      +      "LAST_6_MONTHS",
      +      "LAST_12_MONTHS",
      +      "LAST_4_YEARS",
      +      "LAST_3_MONTHS",
      +      "LAST_INVOICE_MONTH"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / reportContext / properties / datePreset / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "TRAILING_90_DAYS",
      -      "TRAILING_30_DAYS",
      -      "TRAILING_45_DAYS",
      -      "TRAILING_7_DAYS",
      -      "TRAILING_3_DAYS",
      -      "TRAILING_14_WEEKS",
      -      "MTD",
      -      "QTD",
      -      "YTD",
      -      "CURRENT_MONTH",
      -      "CURRENT_QUARTER",
      -      "CURRENT_YEAR",
      -      "LAST_WEEK",
      -      "LAST_MONTH",
      -      "LAST_6_MONTHS",
      -      "LAST_12_MONTHS",
      -      "LAST_4_YEARS",
      -      "LAST_3_MONTHS",
      -      "LAST_INVOICE_MONTH"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "TRAILING_90_DAYS",
      +      "TRAILING_30_DAYS",
      +      "TRAILING_45_DAYS",
      +      "TRAILING_7_DAYS",
      +      "TRAILING_3_DAYS",
      +      "TRAILING_1_DAYS",
      +      "TRAILING_14_WEEKS",
      +      "MTD",
      +      "QTD",
      +      "YTD",
      +      "CURRENT_MONTH",
      +      "CURRENT_QUARTER",
      +      "CURRENT_YEAR",
      +      "LAST_WEEK",
      +      "LAST_MONTH",
      +      "LAST_6_MONTHS",
      +      "LAST_12_MONTHS",
      +      "LAST_4_YEARS",
      +      "LAST_3_MONTHS",
      +      "LAST_INVOICE_MONTH"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / widget / oneOf
      Previous 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",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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",
      -          "CURRENT_MONTH",
      -          "CURRENT_QUARTER",
      -          "CURRENT_YEAR",
      -          "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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": 100,
      +        "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": 100,
      +        "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_1_DAYS",
      +          "TRAILING_14_WEEKS",
      +          "MTD",
      +          "QTD",
      +          "YTD",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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 (integer 1–100). Applied at every tree level.",
      +        "maximum": 100,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "DIGEST",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  }
      +]
  7. Changed3 schema fields changed
    • changedInput schema / properties / context / properties / datePreset / anyOf
      Previous value: -[
      -  {
      -    "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"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "TRAILING_90_DAYS",
      +      "TRAILING_30_DAYS",
      +      "TRAILING_45_DAYS",
      +      "TRAILING_7_DAYS",
      +      "TRAILING_3_DAYS",
      +      "TRAILING_14_WEEKS",
      +      "MTD",
      +      "QTD",
      +      "YTD",
      +      "CURRENT_MONTH",
      +      "CURRENT_QUARTER",
      +      "CURRENT_YEAR",
      +      "LAST_WEEK",
      +      "LAST_MONTH",
      +      "LAST_6_MONTHS",
      +      "LAST_12_MONTHS",
      +      "LAST_4_YEARS",
      +      "LAST_3_MONTHS",
      +      "LAST_INVOICE_MONTH"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / reportContext / properties / datePreset / anyOf
      Previous value: -[
      -  {
      -    "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"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "TRAILING_90_DAYS",
      +      "TRAILING_30_DAYS",
      +      "TRAILING_45_DAYS",
      +      "TRAILING_7_DAYS",
      +      "TRAILING_3_DAYS",
      +      "TRAILING_14_WEEKS",
      +      "MTD",
      +      "QTD",
      +      "YTD",
      +      "CURRENT_MONTH",
      +      "CURRENT_QUARTER",
      +      "CURRENT_YEAR",
      +      "LAST_WEEK",
      +      "LAST_MONTH",
      +      "LAST_6_MONTHS",
      +      "LAST_12_MONTHS",
      +      "LAST_4_YEARS",
      +      "LAST_3_MONTHS",
      +      "LAST_INVOICE_MONTH"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / widget / oneOf
      Previous 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"
      -  }
      -]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",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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",
      +          "CURRENT_MONTH",
      +          "CURRENT_QUARTER",
      +          "CURRENT_YEAR",
      +          "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"
      +  }
      +]
  8. Changed1 schema field changed
    • changedInput schema / properties / widget / 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"
      +  }
      +]
  9. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: 'read-only and in-memory', no persisted report, no Costory object mutation, no Slack/Teams/email delivery, and 'Returns a token-bounded, per-type result'. It also flags slower opt-in paths (display: "summary", enableAiInvestigation via async analysis_agent_run) and the deprecation of the `context` alias — disclosure an agent cannot get from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core claim and safety profile, then organized by concern (inheritance, hierarchy, thresholds, AI options) and closed with worked examples. It is long and some clauses restate schema descriptions, but for a five-variant discriminated-union payload the density is largely earned.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the return-shape burden — and it does, listing per-type results (DIGEST resolvedPeriod/comparison totals/root nodes; TOP_FLOP bounded rows; GRAPH_SNAPSHOT series sample + explorerUrl; DASHBOARD_PDF/TEXT validity pointer). Combined with the inheritance and override rules, an agent can call this correctly without further context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline would be 3, but the description adds cross-field semantics the schema cannot express cleanly: widgets omit matching fields to inherit from reportContext, never send both `context` and `reportContext`, and the DIGEST hierarchy rules plus threshold defaults (100/5%/20). Slight redundancy with the per-parameter schema text keeps it off a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: 'Dry-run preview of ONE report widget', which immediately separates it from create_report (persist), preview_alert and query. The per-type return breakdown further pins down exactly what the tool produces for each widget type.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the lifecycle relationship explicitly: 'Pass the same reportContext + widget object you will later hand to create_report', which tells the agent this is the validation step before persistence. It also gives when-to-use guidance per widget type (DIGEST vs TOP_FLOP vs GRAPH_SNAPSHOT). It stops short of naming exclusion conditions such as when to skip preview and call create_report directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources