Create a report with shared `reportContext` and one or more `widgets` plus destinations. New reports are creator-only (you get Admin). To share, call set_object_permissions after create — do not send PRIVATE/PUBLIC or teamId. Call get_skill with skillId: "reports" first — see skill for context-first workflow and DIGEST preview iteration. Put shared settings in `reportContext` (period required when query widgets are present: prefer datePreset; plus metricId, common groupBy, currency, optional conditionsCel / scopeId). Query widgets inherit by default and should only specify overrides — do not repeat from/to, datePreset, groupBy, metricId, or currency when they match reportContext. The legacy `context` alias is temporarily accepted but deprecated; never send both. Schedule modes:
• NOW — create an on-demand report and immediately deliver it to every destination. DANGER ZONE: this sends real messages now. Summarize scope, schedule, and every destination, then ask the user to confirm before calling.
• UNSCHEDULED — save an on-demand draft without delivery.
• SCHEDULED — create a recurring report (DAILY / WEEKDAYS / WEEKLY / MONTHLY). DANGER ZONE: this authorizes future channel delivery. Summarize the recurring schedule and every destination, then ask the user to confirm before calling.
Optional `tagIds`: existing IDs from list_tags and/or `{ name, color? }` for new tags; color defaults to #6366F1; missing tags are created. Omit and `[]` both leave the report untagged. Widget types: DASHBOARD_PDF, GRAPH_SNAPSHOT, TOP_FLOP, TEXT, and DIGEST. A DASHBOARD_PDF widget renders an existing dashboard as a PDF — pass `{ type: "DASHBOARD_PDF", dashboardId: "<id from search>" }` (dashboardId required). TEXT widgets use `{ type: "TEXT", contentMarkdown }` (not dashboard `textContent`). DIGEST hierarchy: `reportContext.groupBy` (root, preferred) + ordered `additionalGroupBy` (deeper levels); also supports thresholds. Per-widget override: set DIGEST `useDashboardGroupBy: false` to ignore `reportContext.groupBy` for that widget — the first `additionalGroupBy` item (or `queries[0].groupBy`) becomes the root; `false` requires at least one dimension. DIGEST accepts a per-widget `queries[0].filterCel` (CEL) — AND-combined with `reportContext.conditionsCel` by default (`extendDashboardConditions` defaults true), applied to both the comparison periods, and named by the AI summary. Use it for focused digests (e.g. Kubernetes only: `cos_cluster_name != null`) next to an unfiltered org-wide digest in the same report. DIGEST AI (opt-in, slower): `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). Preview and create use the same `reportContext` + widget shape. For WEEKLY schedules, `schedule.weekday` is required (0 = Sunday … 6 = Saturday). Destinations: SLACK/TEAMS take `channelId`; EMAIL takes `email` (a single address, the literal ALL_ACTIVE_USERS to reach every active user, or destinations.email.self from list_available_destinations for "email me"). Returns report URL and nextRunAt; NOW also returns execution URLs and per-destination status.
EXAMPLE monthly DIGEST: { schedule: { mode: "UNSCHEDULED" }, reportContext: { datePreset: "LAST_MONTH", groupBy: "cos_environment", metricId: "cost", currency: "USD" }, widgets: [{ 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 }, { type: "DIGEST", title: "Kubernetes", queries: [{ type: "cost", name: "a", filterCel: "cos_cluster_name != null" }], aggBy: "Week" }], destinations: [{ destinationType: "SLACK", channelId: "C…" }] }
EXAMPLE namespace-rooted DIGEST (overrides reportContext.groupBy for this widget only): { schedule: { mode: "UNSCHEDULED" }, reportContext: { datePreset: "LAST_MONTH", groupBy: "cos_environment", metricId: "cost", currency: "USD" }, widgets: [{ type: "DIGEST", title: "Kubernetes", useDashboardGroupBy: false, queries: [{ type: "cost", name: "a" }], aggBy: "Month", additionalGroupBy: ["cos_namespace_reallocated", "cos_workload_name"] }], destinations: [{ destinationType: "SLACK", channelId: "C…" }] }
EXAMPLE GRAPH_SNAPSHOT + TOP_FLOP: { schedule: { mode: "SCHEDULED", period: "WEEKLY", weekday: 1, firstRunAt: "2026-08-04T10:00:00.000Z" }, reportContext: { metricId: "cost", currency: "USD", groupBy: "cos_service_name", datePreset: "LAST_WEEK" }, widgets: [{ type: "GRAPH_SNAPSHOT", title: "Cost by service — trailing weeks", queries: [{ type: "cost", name: "a", chartType: "LINE" }], datePreset: "TRAILING_14_WEEKS", aggBy: "Week" }, { type: "TOP_FLOP", title: "Last week movers by service", queries: [{ type: "cost", name: "a" }], aggBy: "Period", topN: 5, flopN: 5 }], destinations: [{ destinationType: "SLACK", channelId: "C…" }] }