Dashboards and reporting skill 04 of 6
Report automation
A scheduled report is a small production system, not a one-off send. This skill makes an AI agent set one up so it arrives on time with fresh data, reaches the right people, and raises an alert when it fails, instead of quietly sending last week’s numbers to a list half of whom have left.
By Afeez Adebayo, Marketing, SEO & Growth Expert with 10+ years of experience.
Created 3 November 2026. Updated 3 November 2026. Free to use under CC BY 4.0.
When to use this, and when not to
Use this skill when the job is to make a report happen on a schedule without someone rebuilding it by hand each time: a weekly performance email, a monthly board pack, a daily operational summary, a report burst to many recipients with each seeing their own slice. The triggers are a request to automate or schedule a report, email a dashboard on a cadence, set up recurring delivery, or a complaint that a scheduled report is stale, failing, or that people are drowning in report emails.
Do not use it to design the live dashboard people open themselves, which is dashboard-design, to write the narrative and recommendation inside a report, which is data-storytelling, or to choose which metrics the report should carry, which is metric-selection. Building the pipeline that loads the warehouse is data engineering, upstream of this skill. This skill assumes the report content exists and is correct, and makes its delivery dependable and timely.
The core idea: an automated report is a small production system, not a one-off send. It has inputs that can be late, a job that can fail, recipients whose needs change, and a cost in compute and attention. Treat it that way. The two failures that destroy trust are a report that arrives before its data finished refreshing, so the numbers are wrong, and a report that fails silently, so no one notices until a stakeholder does. Most of this skill is about preventing those two.
Inputs the agent must have before starting
- The decision the report drives, and its cadence. What someone does with it and how often that decision is made. A report read to act today is daily; one reviewed against targets is weekly or monthly. The decision sets the cadence, not habit.
- The recipients and how they differ. Who receives it, and whether they all see the same thing or each needs their own filtered slice (a region, a team, an account). This decides a single send versus a burst.
- The data source and its refresh timing. When the underlying data updates, how long a refresh takes, and its time zone. This is the input that most often breaks a report, so pin it down.
- The delivery channel and format. Email, a chat channel, a shared drive, or an embedded link, and the format (PDF, image, spreadsheet, a link to the live view). Each has different size and security limits.
- The tool doing the sending. The BI tool, spreadsheet, script or orchestration tool, because its scheduling model, limits and failure behaviour set what is possible (the mechanics live in the appendix).
- Who owns it, and when it should stop. A named owner and a review or expiry date, so the report does not outlive its usefulness.
If the report sends to other people, that is an action on their behalf. Set it up in a disabled or test state first, send a sample to the owner, and get explicit confirmation before enabling the live schedule.
Raw SKILL.md file
This is the exact file agents read, including the credit header and licence notice. Save it as report-automation/SKILL.md.
--- name: report-automation description: > Set up recurring reports that arrive reliably and get read: choose the cadence from the decision they serve, make the data refresh finish before the report sends, target the right recipients, handle failures with alerts and retries, and retire reports no one opens. Covers scheduled versus data-driven and conditional delivery, decoupling refresh from render from send, staggering jobs, bursting one report per audience, service accounts and row-level security, report fatigue, and refresh cost and rate limits. Use it when someone says "automate this report", "schedule a weekly report", "email this dashboard every Monday", "set up recurring reports", "our scheduled report is stale or failing", or "stop the report spam". Do NOT use it to design a live dashboard (see dashboard-design), write the narrative content of a report (see data-storytelling), choose which metrics to include (see metric-selection), or build the data pipeline that loads the warehouse (that is data engineering). license: Free to use and adapt under CC BY 4.0, with credit to Afeez Adebayo. Link afeezadebayo.com, https://www.linkedin.com/in/afeez-adebayo/ and this skill's page at https://afeezadebayo.com/skills-md/data/dashboards-reporting/report-automation/. --- # Report automation ## When to use this, and when not to Use this skill when the job is to make a report happen on a schedule without someone rebuilding it by hand each time: a weekly performance email, a monthly board pack, a daily operational summary, a report burst to many recipients with each seeing their own slice. The triggers are a request to automate or schedule a report, email a dashboard on a cadence, set up recurring delivery, or a complaint that a scheduled report is stale, failing, or that people are drowning in report emails. Do not use it to design the live dashboard people open themselves, which is `dashboard-design`, to write the narrative and recommendation inside a report, which is `data-storytelling`, or to choose which metrics the report should carry, which is `metric-selection`. Building the pipeline that loads the warehouse is data engineering, upstream of this skill. This skill assumes the report content exists and is correct, and makes its delivery dependable and timely. The core idea: an automated report is a small production system, not a one-off send. It has inputs that can be late, a job that can fail, recipients whose needs change, and a cost in compute and attention. Treat it that way. The two failures that destroy trust are a report that arrives before its data finished refreshing, so the numbers are wrong, and a report that fails silently, so no one notices until a stakeholder does. Most of this skill is about preventing those two. ## Inputs the agent must have before starting 1. **The decision the report drives, and its cadence.** What someone does with it and how often that decision is made. A report read to act today is daily; one reviewed against targets is weekly or monthly. The decision sets the cadence, not habit. 2. **The recipients and how they differ.** Who receives it, and whether they all see the same thing or each needs their own filtered slice (a region, a team, an account). This decides a single send versus a burst. 3. **The data source and its refresh timing.** When the underlying data updates, how long a refresh takes, and its time zone. This is the input that most often breaks a report, so pin it down. 4. **The delivery channel and format.** Email, a chat channel, a shared drive, or an embedded link, and the format (PDF, image, spreadsheet, a link to the live view). Each has different size and security limits. 5. **The tool doing the sending.** The BI tool, spreadsheet, script or orchestration tool, because its scheduling model, limits and failure behaviour set what is possible (the mechanics live in the appendix). 6. **Who owns it, and when it should stop.** A named owner and a review or expiry date, so the report does not outlive its usefulness. If the report sends to other people, that is an action on their behalf. Set it up in a disabled or test state first, send a sample to the owner, and get explicit confirmation before enabling the live schedule. ## The workflow, step by step ### 1. Confirm a report is the right tool A scheduled report suits information reviewed on a rhythm. If the audience needs to dig into and filter, build a live dashboard instead (`dashboard-design`). If they only need to know when a threshold is crossed, build an alert, not a recurring report, because a daily email that says "nothing changed" trains people to ignore it. Decision rule: if the usual content of the report is "no action needed", switch it to an exception-only alert. ### 2. Set the cadence from the decision, not from habit Match the schedule to how often the decision is actually made: daily for operational monitoring, weekly or monthly for performance tracking, quarterly for strategic review (coupler.io, "Report scheduling"). Decision rule: do not send more often than the audience acts; a daily report for a weekly decision is six wasted emails that erode attention. Pick a send time tied to when the decision is made (a Monday 8 am report for a Monday planning meeting), not an arbitrary midnight. ### 3. Make the refresh finish before the report sends This is the rule that prevents wrong numbers. Schedule the data refresh to complete before any dependent send, with a buffer: a 7:00 am send after a 6:30 am refresh, not both at 7:00 (ChristianSteven, "Tableau scheduled-reporting best practices"). Better still, make delivery data-driven where the tool supports it, so the report sends only after the refresh succeeds rather than at a fixed clock time. In Tableau this is the "When Data Refreshes" subscription rather than "On Selected Schedule" (Tableau Server Help, "Create a Subscription"). Decision rule: never schedule a send at the same time as its refresh; either leave a buffer or trigger the send on refresh completion. ### 4. Decouple refresh, render and delivery Keep the three stages separate: the data refresh, the rendering of the report, and the send. If they are welded together, one slow extract stalls every queued report (ChristianSteven). Separating them lets a failed refresh stop the send (so stale data is never delivered) without taking down unrelated reports, and lets you retry one stage without redoing all three. ### 5. Stagger jobs so they do not collide Do not run every refresh and send at the top of the hour. Stagger them, for example at 6:45, 7:00 and 7:15, so a burst of jobs does not exhaust the tool's capacity or the refresh window (ChristianSteven). Run heavy monthly jobs overnight to keep business-hour capacity free. Respect the tool's refresh limits: shared or entry tiers cap scheduled refreshes per day, higher tiers allow many more, so check the limit before promising an hourly report on a tier that cannot do it (see appendix, and verify the current limits for your tool). ### 6. Target recipients, and burst rather than copy If different people need different slices, use one report filtered per audience segment (bursting) rather than hand-built copies, so a region's lead gets only their region (ChristianSteven). Tie the distribution list to a directory group rather than a list of static email addresses, so the report follows role changes instead of mailing people who have left (ChristianSteven). Decision rule: if you are maintaining more than one near-identical copy of a report by hand, replace them with one bursted report. ### 7. Send only what is worth sending (conditional delivery) Where the tool allows it, send conditionally: skip the email when the view is empty or nothing crossed a threshold, so recipients get a report only when there is something to see. Tableau offers "Don't send if view is empty" for exactly this (Tableau Server Help). Decision rule: for any report whose point is exceptions, make delivery conditional so a quiet period is silent, not a stream of empty reports. ### 8. Handle failure loudly, not silently Treat a scheduled report as a production job (ChristianSteven). A failed refresh or send must raise an alert to the owner immediately, not wait for a stakeholder to notice stale numbers. Route the alert to where the owner will see it (a chat channel, a pager, an email that is itself monitored). Set a retry on transient failures, and know the tool's own failure behaviour: Tableau suspends a subscription after more than five consecutive failures, so a long-broken report stops sending entirely and must be resumed (Tableau Server Help). Decision rule: every automated report has an owner who is alerted on failure; a report no one is alerted about is a report that will silently rot. ### 9. Secure the delivery Run production schedules under a service account, not a named person's login, so the report does not break when that person changes role or leaves (ChristianSteven). Apply row-level security at the source so each recipient sees only the data they are entitled to, especially in a burst. Send a link to a permissioned live view rather than a fully loaded attachment when the data is sensitive, and never put credentials or secrets in the report body or the schedule configuration. Decision rule: if a report contains personal or restricted data, prefer a permissioned link over an open attachment, and confirm the recipient list is entitled to every row. ### 10. Name an owner and a retirement trigger Every automated report gets a named owner, a review cadence, and a condition under which it stops. Audit schedules regularly and retire any report with no engagement, for example one not opened by any recipient in 90 days (ChristianSteven). Unused scheduled reports cost compute, clutter inboxes, and erode trust in the ones that matter. Decision rule: a report that no recipient has opened in a quarter is paused and its owner asked whether to keep it. ### 11. Verify, then enable from a safe state Build the schedule disabled or pointing at a test recipient, run one cycle, and confirm the data is current, the right people are targeted, the format renders, and a forced failure actually raises an alert. Only then enable the live schedule, and only after the owner has confirmed. Run the result against the quality bar below. ## Worked example, end to end A revenue team asks to "automate the weekly sales report and send it to the regional managers every Monday." The quick version schedules the workbook to email at 7:00 am Monday to a static list, with its data extract also refreshing at 7:00 am. Two weeks in, managers get Monday numbers that are actually the previous Tuesday's, because the extract had not finished, and one manager who left still receives a region's full figures. Done as a production job instead. Cadence: weekly, sent 8:00 am Monday to land before the 9:00 am regional call. Refresh: the extract is scheduled for 6:30 am, and the subscription is set to "When Data Refreshes" so it only sends once the refresh succeeds, with a fixed-time fallback disabled until the refresh is proven reliable. Decoupling: refresh, render and send are separate jobs, staggered so this report's refresh at 6:30 does not collide with the finance refresh at 6:30. Recipients: a single bursted report filtered by region, tied to the "Regional managers" directory group, with row-level security so each manager sees only their region. Failure handling: a failed refresh posts to the revenue team's ops channel immediately, with a retry, and the owner is named in the schedule. Security: it runs under a reporting service account, and sends a link to the permissioned view rather than a full attachment. Retirement: reviewed quarterly, paused if a region's manager has not opened it in 90 days. It is enabled only after a test send to the owner confirmed current data and correct targeting. ## Templates you can use verbatim **Report automation spec (fill in before enabling any schedule):** ``` Decision + cadence: what it drives, how often the decision is made, send time Recipients: one list or bursted per segment; directory group or static Data source: where from, refresh duration, time zone Refresh-before-send: buffer time, or data-driven trigger (send on refresh success) Delivery: channel, format, link vs attachment Failure plan: who is alerted, where, retry policy, tool suspend behaviour Security: service account, row-level security, link vs attachment Owner + retirement: owner, review cadence, stop condition (e.g. 90 days unopened) ``` **Pre-enable checklist:** refresh completes before send (buffer or data-driven); recipients correct and entitled; format renders; a forced failure raises an alert; schedule starts disabled or test-only; owner has confirmed; conditional send set if the report is exception-based. **Failure-alert line (adapt per tool):** "Report [name] failed at [stage: refresh/render/send] at [time]. Owner [name] notified via [channel]. Last successful run [time]. Recipients were not sent stale data." ## Failure modes and anti-patterns 1. **Report sends before refresh finishes.** Send and refresh scheduled at the same time, so recipients get stale numbers. Spot it when the report's figures lag a cycle. Fix: leave a refresh buffer or switch to data-driven "send on refresh success" (ChristianSteven; Tableau). 2. **Silent failure.** A broken refresh or send that no one is alerted to, noticed only when a stakeholder flags wrong or missing numbers. Spot it from gaps in delivery history. Fix: alert the owner on every failure, add retries, and know the tool's suspend-after-N-failures behaviour (ChristianSteven; Tableau). 3. **Report fatigue.** A daily report that usually says "nothing changed", so recipients filter it to a folder and miss the day it matters. Spot it from low open rates. Fix: make it exception-based with conditional delivery, or switch to an alert (coupler.io; Tableau "Don't send if view is empty"). 4. **Static recipient lists and hand-built copies.** People who left still receive sensitive reports, and one report is maintained as five near-identical copies. Spot it from bounced or ex-employee recipients. Fix: burst one report by segment, tied to directory groups (ChristianSteven). 5. **Owned by a person's login, no owner on the schedule.** The report breaks when that person changes role, and no one is responsible for it. Spot it when a schedule fails after someone leaves. Fix: run under a service account and name an owner and review cadence (ChristianSteven). ## Quality bar - The cadence matches how often the decision is made, and the send time is tied to when it is used. - The data refresh completes before the report sends, by a buffer or a data-driven trigger; send and refresh are never scheduled at the same instant. - Refresh, render and delivery are decoupled, and jobs are staggered rather than all at the top of the hour. - Recipients are correct and entitled; differing slices are handled by a bursted report tied to a directory group, not hand-built copies. - A failure at any stage alerts a named owner immediately, with a retry policy, and the tool's suspend-after-failures behaviour is known. - Production schedules run under a service account, with row-level security, and sensitive data goes as a permissioned link rather than an open attachment. - Exception-based reports use conditional delivery so quiet periods are silent. - The report has an owner, a review cadence and a retirement trigger, and was enabled from a disabled or test state only after a confirmed test send. ## Data handling and safety Automated reports move data to people on a schedule, which makes a mis-targeted report a repeating leak rather than a one-off mistake. Confirm every recipient is entitled to every row before enabling a schedule, apply row-level security at the source, and prefer a permissioned link to the live view over a fully loaded attachment for anything personal or restricted. Never put credentials, tokens or secrets in a report body, a subject line, or a schedule's configuration. Enabling a recurring send to other people is an irreversible action on their behalf that then repeats, so set it up disabled, send a test to the owner, and get explicit confirmation before it goes live; the same applies to changing the recipient list of a live report. Never fabricate the contents of a report to fill a scheduled slot: if the data did not refresh, the honest outcome is a held send and an alert, not a report of last cycle's numbers presented as current. When a report informs decisions about money, health, legal standing or employment, make sure its stated data freshness and any caveats travel with it, so a late or partial refresh is visible rather than hidden. ## Appendix: tool-specific notes (verify before relying on these) - **Tableau:** subscriptions email a PNG or PDF snapshot; use "When Data Refreshes" for data-driven delivery and "On Selected Schedule" for fixed times, "Don't send if view is empty" for conditional sends, and note that a subscription is suspended after more than five consecutive failures and must be resumed. Data Management adds data-quality warnings in the email. Verify current behaviour in your version. - **Power BI:** use subscriptions for scheduled snapshots and data alerts for thresholds; scheduled refreshes are capped per day on shared and Pro capacity and allow many more on Premium, Premium Per User or Fabric capacity, so check the current limit for your licence before promising a frequent report, and set the dataset refresh to complete before the subscription time. - **Looker / Looker Studio:** use scheduled deliveries with filters for bursting, and conditional delivery where available; define the metric once in the model so the scheduled report and the live dashboard agree. - **Spreadsheets and scripts (Google Sheets, Apps Script, cron, Airflow, dbt):** when you own the schedule, make the send depend on the refresh job succeeding rather than a fixed clock time, log every run, alert on failure, and keep credentials in a secret store, not in the script. ## Sources - ChristianSteven Software, "Tableau scheduled-reporting best practices": schedule the refresh to complete before any dependent send with a buffer, decouple refresh, rendering and distribution, stagger jobs rather than running them all at once, treat scheduled reports as production applications with runbooks and failure alerting, burst one filtered report per segment, tie distribution to directory groups, use service accounts, run quarterly audits and retire reports with no engagement in 90 days. (Vendor of a reporting-orchestration tool, so its case for external tooling reflects that; the practices are general.) Verified 3 November 2026. - Tableau Server Help, "Create a Subscription to a View or Workbook": the "On Selected Schedule" and "When Data Refreshes" delivery options, the "Don't send if view is empty" conditional option, subscribing groups, and suspension after more than five consecutive failures with a Resume Subscription action. Verified 3 November 2026. - coupler.io, "Report scheduling": choose the interval from business need (daily for real-time monitoring, weekly or monthly for performance tracking), set the refresh window and time zone so data is current before delivery, enable a notification on an unsuccessful run, and check scheduled solutions regularly rather than assuming a built-in schedule fits. Verified 3 November 2026. - Amplitude, "Leading vs lagging indicators", and general reporting-cadence practice: match reporting frequency to how often the underlying decision is made, which informs the cadence rule here. Verified 3 November 2026.
The workflow, step by step
1. Confirm a report is the right tool
A scheduled report suits information reviewed on a rhythm. If the audience needs to dig into and filter, build a live dashboard instead (dashboard-design). If they only need to know when a threshold is crossed, build an alert, not a recurring report, because a daily email that says "nothing changed" trains people to ignore it. Decision rule: if the usual content of the report is "no action needed", switch it to an exception-only alert.
2. Set the cadence from the decision, not from habit
Match the schedule to how often the decision is actually made: daily for operational monitoring, weekly or monthly for performance tracking, quarterly for strategic review (coupler.io, "Report scheduling"). Decision rule: do not send more often than the audience acts; a daily report for a weekly decision is six wasted emails that erode attention. Pick a send time tied to when the decision is made (a Monday 8 am report for a Monday planning meeting), not an arbitrary midnight.
3. Make the refresh finish before the report sends
This is the rule that prevents wrong numbers. Schedule the data refresh to complete before any dependent send, with a buffer: a 7:00 am send after a 6:30 am refresh, not both at 7:00 (ChristianSteven, "Tableau scheduled-reporting best practices"). Better still, make delivery data-driven where the tool supports it, so the report sends only after the refresh succeeds rather than at a fixed clock time. In Tableau this is the "When Data Refreshes" subscription rather than "On Selected Schedule" (Tableau Server Help, "Create a Subscription"). Decision rule: never schedule a send at the same time as its refresh; either leave a buffer or trigger the send on refresh completion.
4. Decouple refresh, render and delivery
Keep the three stages separate: the data refresh, the rendering of the report, and the send. If they are welded together, one slow extract stalls every queued report (ChristianSteven). Separating them lets a failed refresh stop the send (so stale data is never delivered) without taking down unrelated reports, and lets you retry one stage without redoing all three.
5. Stagger jobs so they do not collide
Do not run every refresh and send at the top of the hour. Stagger them, for example at 6:45, 7:00 and 7:15, so a burst of jobs does not exhaust the tool's capacity or the refresh window (ChristianSteven). Run heavy monthly jobs overnight to keep business-hour capacity free. Respect the tool's refresh limits: shared or entry tiers cap scheduled refreshes per day, higher tiers allow many more, so check the limit before promising an hourly report on a tier that cannot do it (see appendix, and verify the current limits for your tool).
6. Target recipients, and burst rather than copy
If different people need different slices, use one report filtered per audience segment (bursting) rather than hand-built copies, so a region's lead gets only their region (ChristianSteven). Tie the distribution list to a directory group rather than a list of static email addresses, so the report follows role changes instead of mailing people who have left (ChristianSteven). Decision rule: if you are maintaining more than one near-identical copy of a report by hand, replace them with one bursted report.
7. Send only what is worth sending (conditional delivery)
Where the tool allows it, send conditionally: skip the email when the view is empty or nothing crossed a threshold, so recipients get a report only when there is something to see. Tableau offers "Don't send if view is empty" for exactly this (Tableau Server Help). Decision rule: for any report whose point is exceptions, make delivery conditional so a quiet period is silent, not a stream of empty reports.
8. Handle failure loudly, not silently
Treat a scheduled report as a production job (ChristianSteven). A failed refresh or send must raise an alert to the owner immediately, not wait for a stakeholder to notice stale numbers. Route the alert to where the owner will see it (a chat channel, a pager, an email that is itself monitored). Set a retry on transient failures, and know the tool's own failure behaviour: Tableau suspends a subscription after more than five consecutive failures, so a long-broken report stops sending entirely and must be resumed (Tableau Server Help). Decision rule: every automated report has an owner who is alerted on failure; a report no one is alerted about is a report that will silently rot.
9. Secure the delivery
Run production schedules under a service account, not a named person's login, so the report does not break when that person changes role or leaves (ChristianSteven). Apply row-level security at the source so each recipient sees only the data they are entitled to, especially in a burst. Send a link to a permissioned live view rather than a fully loaded attachment when the data is sensitive, and never put credentials or secrets in the report body or the schedule configuration. Decision rule: if a report contains personal or restricted data, prefer a permissioned link over an open attachment, and confirm the recipient list is entitled to every row.
10. Name an owner and a retirement trigger
Every automated report gets a named owner, a review cadence, and a condition under which it stops. Audit schedules regularly and retire any report with no engagement, for example one not opened by any recipient in 90 days (ChristianSteven). Unused scheduled reports cost compute, clutter inboxes, and erode trust in the ones that matter. Decision rule: a report that no recipient has opened in a quarter is paused and its owner asked whether to keep it.
11. Verify, then enable from a safe state
Build the schedule disabled or pointing at a test recipient, run one cycle, and confirm the data is current, the right people are targeted, the format renders, and a forced failure actually raises an alert. Only then enable the live schedule, and only after the owner has confirmed. Run the result against the quality bar below.
Worked example, end to end
A revenue team asks to "automate the weekly sales report and send it to the regional managers every Monday." The quick version schedules the workbook to email at 7:00 am Monday to a static list, with its data extract also refreshing at 7:00 am. Two weeks in, managers get Monday numbers that are actually the previous Tuesday's, because the extract had not finished, and one manager who left still receives a region's full figures.
Done as a production job instead. Cadence: weekly, sent 8:00 am Monday to land before the 9:00 am regional call. Refresh: the extract is scheduled for 6:30 am, and the subscription is set to "When Data Refreshes" so it only sends once the refresh succeeds, with a fixed-time fallback disabled until the refresh is proven reliable. Decoupling: refresh, render and send are separate jobs, staggered so this report's refresh at 6:30 does not collide with the finance refresh at 6:30. Recipients: a single bursted report filtered by region, tied to the "Regional managers" directory group, with row-level security so each manager sees only their region. Failure handling: a failed refresh posts to the revenue team's ops channel immediately, with a retry, and the owner is named in the schedule. Security: it runs under a reporting service account, and sends a link to the permissioned view rather than a full attachment. Retirement: reviewed quarterly, paused if a region's manager has not opened it in 90 days. It is enabled only after a test send to the owner confirmed current data and correct targeting.
Templates you can use verbatim
Report automation spec (fill in before enabling any schedule):
Decision + cadence: what it drives, how often the decision is made, send time
Recipients: one list or bursted per segment; directory group or static
Data source: where from, refresh duration, time zone
Refresh-before-send: buffer time, or data-driven trigger (send on refresh success)
Delivery: channel, format, link vs attachment
Failure plan: who is alerted, where, retry policy, tool suspend behaviour
Security: service account, row-level security, link vs attachment
Owner + retirement: owner, review cadence, stop condition (e.g. 90 days unopened)Pre-enable checklist: refresh completes before send (buffer or data-driven); recipients correct and entitled; format renders; a forced failure raises an alert; schedule starts disabled or test-only; owner has confirmed; conditional send set if the report is exception-based.
Failure-alert line (adapt per tool): "Report [name] failed at [stage: refresh/render/send] at [time]. Owner [name] notified via [channel]. Last successful run [time]. Recipients were not sent stale data."
Failure modes and anti-patterns
- Report sends before refresh finishes. Send and refresh scheduled at the same time, so recipients get stale numbers. Spot it when the report's figures lag a cycle. Fix: leave a refresh buffer or switch to data-driven "send on refresh success" (ChristianSteven; Tableau).
- Silent failure. A broken refresh or send that no one is alerted to, noticed only when a stakeholder flags wrong or missing numbers. Spot it from gaps in delivery history. Fix: alert the owner on every failure, add retries, and know the tool's suspend-after-N-failures behaviour (ChristianSteven; Tableau).
- Report fatigue. A daily report that usually says "nothing changed", so recipients filter it to a folder and miss the day it matters. Spot it from low open rates. Fix: make it exception-based with conditional delivery, or switch to an alert (coupler.io; Tableau "Don't send if view is empty").
- Static recipient lists and hand-built copies. People who left still receive sensitive reports, and one report is maintained as five near-identical copies. Spot it from bounced or ex-employee recipients. Fix: burst one report by segment, tied to directory groups (ChristianSteven).
- Owned by a person's login, no owner on the schedule. The report breaks when that person changes role, and no one is responsible for it. Spot it when a schedule fails after someone leaves. Fix: run under a service account and name an owner and review cadence (ChristianSteven).
Quality bar
- The cadence matches how often the decision is made, and the send time is tied to when it is used.
- The data refresh completes before the report sends, by a buffer or a data-driven trigger; send and refresh are never scheduled at the same instant.
- Refresh, render and delivery are decoupled, and jobs are staggered rather than all at the top of the hour.
- Recipients are correct and entitled; differing slices are handled by a bursted report tied to a directory group, not hand-built copies.
- A failure at any stage alerts a named owner immediately, with a retry policy, and the tool's suspend-after-failures behaviour is known.
- Production schedules run under a service account, with row-level security, and sensitive data goes as a permissioned link rather than an open attachment.
- Exception-based reports use conditional delivery so quiet periods are silent.
- The report has an owner, a review cadence and a retirement trigger, and was enabled from a disabled or test state only after a confirmed test send.
Data handling and safety
Automated reports move data to people on a schedule, which makes a mis-targeted report a repeating leak rather than a one-off mistake. Confirm every recipient is entitled to every row before enabling a schedule, apply row-level security at the source, and prefer a permissioned link to the live view over a fully loaded attachment for anything personal or restricted. Never put credentials, tokens or secrets in a report body, a subject line, or a schedule's configuration. Enabling a recurring send to other people is an irreversible action on their behalf that then repeats, so set it up disabled, send a test to the owner, and get explicit confirmation before it goes live; the same applies to changing the recipient list of a live report. Never fabricate the contents of a report to fill a scheduled slot: if the data did not refresh, the honest outcome is a held send and an alert, not a report of last cycle's numbers presented as current. When a report informs decisions about money, health, legal standing or employment, make sure its stated data freshness and any caveats travel with it, so a late or partial refresh is visible rather than hidden.
Appendix: tool-specific notes (verify before relying on these)
- Tableau: subscriptions email a PNG or PDF snapshot; use "When Data Refreshes" for data-driven delivery and "On Selected Schedule" for fixed times, "Don't send if view is empty" for conditional sends, and note that a subscription is suspended after more than five consecutive failures and must be resumed. Data Management adds data-quality warnings in the email. Verify current behaviour in your version.
- Power BI: use subscriptions for scheduled snapshots and data alerts for thresholds; scheduled refreshes are capped per day on shared and Pro capacity and allow many more on Premium, Premium Per User or Fabric capacity, so check the current limit for your licence before promising a frequent report, and set the dataset refresh to complete before the subscription time.
- Looker / Looker Studio: use scheduled deliveries with filters for bursting, and conditional delivery where available; define the metric once in the model so the scheduled report and the live dashboard agree.
- Spreadsheets and scripts (Google Sheets, Apps Script, cron, Airflow, dbt): when you own the schedule, make the send depend on the refresh job succeeding rather than a fixed clock time, log every run, alert on failure, and keep credentials in a secret store, not in the script.
Sources
- ChristianSteven Software, "Tableau scheduled-reporting best practices": schedule the refresh to complete before any dependent send with a buffer, decouple refresh, rendering and distribution, stagger jobs rather than running them all at once, treat scheduled reports as production applications with runbooks and failure alerting, burst one filtered report per segment, tie distribution to directory groups, use service accounts, run quarterly audits and retire reports with no engagement in 90 days. (Vendor of a reporting-orchestration tool, so its case for external tooling reflects that; the practices are general.) Verified 3 November 2026.
- Tableau Server Help, "Create a Subscription to a View or Workbook": the "On Selected Schedule" and "When Data Refreshes" delivery options, the "Don't send if view is empty" conditional option, subscribing groups, and suspension after more than five consecutive failures with a Resume Subscription action. Verified 3 November 2026.
- coupler.io, "Report scheduling": choose the interval from business need (daily for real-time monitoring, weekly or monthly for performance tracking), set the refresh window and time zone so data is current before delivery, enable a notification on an unsuccessful run, and check scheduled solutions regularly rather than assuming a built-in schedule fits. Verified 3 November 2026.
- Amplitude, "Leading vs lagging indicators", and general reporting-cadence practice: match reporting frequency to how often the underlying decision is made, which informs the cadence rule here. Verified 3 November 2026.
On this page
- When to use this skill, and when not to
- Who it is for
- What is inside
- Example prompts
- Example output
- What the agent needs from you
- How to install in Claude, Cursor and agents
- How to automate a report step by step
- Worked example
- Situations this skill handles
- What makes this skill different
- Common mistakes
- Related skills
When to use this skill, and when not to
Use this skill when the job is to make a report happen on a schedule without rebuilding it by hand each time: a weekly performance email, a monthly board pack, a daily operational summary, or a report burst to many people with each seeing their own slice. It also fits the complaint that a scheduled report is stale, failing, or that people are drowning in report emails.
It is not for designing the live dashboard people open themselves, which is dashboard-design, writing the narrative inside a report, which is data-storytelling, or choosing which metrics to include, which is metric-selection. Building the pipeline that loads the warehouse is data engineering. This skill assumes the content is correct and makes its delivery dependable and timely.
Who it is for
Analysts, BI developers, operations and revenue teams, and anyone responsible for a report that has to land in inboxes or channels on a rhythm. It is written for people using an AI agent to turn a working report into a reliable recurring delivery, and for anyone trying to fix one that sends stale data or fails without warning.
What is inside
An eleven-step workflow with decision rules. It covers confirming a report is the right tool rather than a dashboard or an alert, setting the cadence from the decision, making the refresh finish before the send, decoupling refresh from render from delivery, staggering jobs, bursting one report per audience, conditional delivery, loud failure handling with alerts and retries, securing delivery with service accounts and row-level security, and naming an owner and a retirement trigger.
Example prompts
“Automate this weekly sales report to the regional managers.” “Email this dashboard every Monday at 8am.” “Set up a monthly board pack that sends itself.” “Our scheduled report keeps sending stale numbers, fix it.” “People say they get too many report emails, help.”
Example output
The skill returns a delivery plan and setup: a cadence tied to the decision, a refresh scheduled to finish before the send or a data-driven trigger, decoupled and staggered jobs, a recipient plan (single send or bursted by segment via a directory group), a failure-alert route with retries, a security setup (service account, row-level security, link versus attachment), and an owner with a retirement trigger. It is enabled only from a disabled or test state after a confirmed test send.
What the agent needs from you
The decision the report drives and its cadence, the recipients and whether they each need a different slice, the data source and how long its refresh takes, the delivery channel and format, the tool doing the sending, and who owns it. Because enabling a recurring send to other people is an action on their behalf that repeats, the skill sets it up disabled, sends a test to the owner, and waits for explicit confirmation before going live.
How to install in Claude, Cursor and agents
In the Claude apps, download the SKILL.md from this page, put it in a folder named report-automation, and upload that folder as a skill. In Claude Code, Codex, Cursor and other Agent Skills tools, copy the report-automation folder into your skills directory (for example ~/.claude/skills/ or .agents/skills/). The single-skill download on this page is already in the folder-per-skill shape those tools expect.
How to automate a report step by step
Install the skill as report-automation/SKILL.md. Tell the agent the decision the report serves, its recipients, and when the data refreshes. It first checks a scheduled report is the right tool rather than a dashboard or an alert, then sets the cadence from the decision, schedules the refresh to finish before the send (or triggers the send on refresh success), decouples and staggers the jobs, bursts by segment where needed, adds conditional delivery, wires a failure alert with retries, secures it with a service account and row-level security, and names an owner and a retirement trigger. It enables the live schedule only after a confirmed test send.
Worked example
Asked to “automate the weekly sales report to the regional managers every Monday”, the quick version emails at 7am Monday from a static list while the extract also refreshes at 7am, so managers get last week’s numbers and a manager who left still receives a region’s figures. Done as a production job instead: the extract refreshes at 6:30am, the send is set to fire only when the refresh succeeds and lands at 8am before the 9am call, the report is bursted by region through a directory group with row-level security, failures post to an ops channel with a retry, it runs under a service account, and it is reviewed quarterly. It goes live only after a test send to the owner.
Situations this skill handles
| Situation | What the skill does |
|---|---|
| Report arrives before the data refreshes | Adds a buffer or sends only on refresh success |
| A scheduled report fails silently | Alerts the owner on every failure, with retries |
| People ignore a daily “nothing changed” email | Switches it to conditional, exception-only delivery |
| Five hand-built copies per region | Replaces them with one bursted report |
| Report breaks when its owner leaves | Moves it to a service account and names an owner |
What makes this skill different
Most guidance here is a single tool’s how-to-schedule page. This skill is tool-agnostic and treats a report as a production system: a refresh-completes-before-send rule, decoupling and staggering, conditional delivery, a failure-alert requirement with the tool’s suspend-after-failures behaviour, service accounts and row-level security, a retirement trigger, and a note on refresh cost and rate limits. It hands the report’s content to data-storytelling and its metrics to metric-selection instead of repeating them.
Common mistakes
Scheduling the send at the same time as the refresh, so recipients get stale numbers; a report that fails silently and is only noticed when a stakeholder flags it; a daily report that usually says nothing, so people tune it out; static recipient lists and hand-built per-region copies; and a report owned by one person’s login that breaks when they leave. The skill catches each with a specific test and a fix.
Related skills
Pair it with data-storytelling to write what the report actually says, dashboard-design when a live monitored view fits better than a scheduled send, and metric-selection to choose which numbers belong in it. Chart choices come from chart-selection, and the tracking that feeds the report is the analytics-and-tracking skills.
Frequently asked questions
How do I automate a report?
Treat it as a production job: set the cadence from the decision it serves, make the data refresh finish before the send (or trigger the send on refresh success), target the right recipients, add a failure alert with retries, run it under a service account, and enable it only after a test send. Build it disabled first and confirm before going live.
When should I use a scheduled report instead of a dashboard?
Use a scheduled report when information is reviewed on a rhythm and pushed to people. Use a live dashboard when people need to filter and dig into the data themselves, and use an alert when they only need to know the moment a threshold is crossed. A daily report that usually says nothing should be an alert.
How do I stop a report sending stale data?
Never schedule the send at the same time as the refresh. Leave a buffer so the refresh finishes first, or better, make delivery data-driven so the report sends only after the refresh succeeds. In Tableau that is the “When Data Refreshes” subscription rather than a fixed schedule.
How often should an automated report be sent?
As often as the decision it supports is made, and no more. Daily for operational monitoring, weekly or monthly for performance tracking, quarterly for strategic review. Sending more often than the audience acts just erodes attention until the report is ignored.
How do I stop report fatigue or report spam?
Make exception-based reports conditional so a quiet period is silent rather than a stream of empty emails, cut any report no one opens, and match the cadence to the decision. Several tools support a “do not send if empty” option for exactly this.
What happens when a scheduled report fails?
It should alert the owner immediately and retry transient failures, not fail silently. Know your tool’s behaviour too: Tableau suspends a subscription after more than five consecutive failures, so a long-broken report stops entirely and has to be resumed by hand.
Changelog
1.0.0, 3 November 2026: first release. Use, adapt and share this skill under CC BY 4.0: credit Afeez Adebayo and link to the source page.
