The morning summary pattern automates the routine part of daily data quality triage. An automated agent runs dbt test, parses failures, categorizes by severity, cross-references documentation, and annotates with history. The result is a structured Slack report waiting before the workday starts, covering context assembly so human time goes to decisions rather than investigation setup.
The Two-Cycle Design
An effective automated quality reporting system runs on two cycles with different purposes.
The daily cycle handles incident detection. At midnight (or whenever your production pipelines complete), the agent triggers dbt test against the production environment. It parses every failure, looks up documentation context, assesses severity, checks downstream impact, and reviews historical patterns. At 7 AM — or whatever time you want to be briefed before your day starts — it delivers a structured summary to Slack.
The weekly cycle handles pattern detection. Individual daily reports show you what broke today. A weekly digest shows you what keeps breaking, what’s never been tested, and which sources are getting progressively more delayed. The weekly view is where structural decisions get made: which tests to add, which recurring issues need escalation to source owners, which models have accumulated technical debt in their test coverage.
The two cycles are separate cron jobs, not a single job that aggregates. Keeping them separate makes each one simpler and more reliable, and the weekly digest feels qualitatively different from a daily summary — it prompts different types of decisions.
The Daily Summary Structure
A good morning summary follows a consistent structure. Consistency matters because it trains the reader: after a week of seeing the same format, you process the critical section in seconds and skip to the first item requiring action.
Data Quality Report, 2026-03-20 (7:00 AM)
🔴 2 Critical | 🟠 1 High | 🟡 3 Medium | 147/153 tests passed
---
CRITICAL
1. unique_mrt__sales__customers_customer__id — 3 duplicate rows Model: mrt__sales__customers (7 downstream dependents, 2 marts) Impact: Duplicate customers mean double-counted revenue in sales dashboards Context: First occurrence → Investigate deduplication logic in base__shopify__customers
2. Source freshness: raw_shopify.orders — 26 hours behind schedule Impact: All order-related models are stale Context: Last occurred 2 weeks ago (vendor maintenance window) → Check Shopify connector status. If vendor delay, no action needed.
HIGH
3. not_null_int__orders_enriched_order__customer_id — 12 null rows Model: int__orders_enriched (4 downstream dependents) Context: Failing intermittently since March 14 → Likely related to the source freshness issue above
MEDIUM
4-6. [Additional failures with less detail]
---
Previously investigated (skipping):- raw_ga4.events freshness (noted March 18: expected on weekends)A few things about this structure are intentional:
The count summary at the top (🔴 2 Critical | 🟠 1 High) tells you the scope before you read anything. On a good day, you glance at the green count and move on. On a bad day, two red circles tell you this is a firefighting morning before you read a single failure.
Critical failures get full detail, including impact, context, and a suggested action. High failures get moderate detail. Medium and below get truncated entries — enough to know they exist without cluttering the summary. This hierarchy means the report is fast to read when things are mostly fine and detailed where detail is needed.
The “previously investigated” section at the bottom lists failures the agent knows about from prior runs and has contextual notes for. Showing these as skipped rather than silently omitting them preserves trust — you know the agent is aware of them and isn’t confused; it just knows you’ve already made a call.
Suggested actions (the → lines) are the hardest part to get right. They need to be specific enough to save investigation time without being so presumptuous that they send you down the wrong path. The goal is to name the first thing to check, not to diagnose the root cause. “Investigate deduplication logic in base__shopify__customers” is better than “Fix the unique test” (too vague) and better than “The issue is that Shopify is sending duplicate customer records due to a webhook retry bug” (overstepping).
Slack Delivery with Threading
Post the summary as a single message to a dedicated Slack channel. Use a channel specifically for quality alerts — separate from general data team channels — so the signal-to-noise ratio stays high.
For each Critical or High failure, create a threaded reply under the main message with additional detail: sample failing rows, the relevant section of the schema documentation, and the full list of downstream models. Threading keeps the main channel scannable while preserving depth for failures that need investigation.
The practical instruction for an agent:
## Slack delivery
1. Post the main summary as a single message to #data-quality-alerts2. For each Critical failure: - Post a thread reply under the main message - Include: sample failing rows (up to 5), full downstream model list, relevant schema.yml description for the failing column3. For each High failure: - Post a thread reply with downstream model list and column description4. Do not thread Medium or Low failuresThis design means your Slack channel stays readable. The main message is the briefing. The threads are the investigation materials, available without opening a terminal.
Follow-Up in Slack
The most practically useful extension of this pattern is making Slack a two-way interface. After the morning summary posts, you can reply to a specific failure thread and ask questions:
- “Show me the 3 duplicate customer IDs”
- “When did this test last pass?”
- “Is this related to the source freshness issue?”
The agent has the full context from the morning run and the persistent memory from previous runs. Follow-up questions get contextual answers without starting a new investigation from scratch. Instead of opening a terminal, connecting to the warehouse, and running queries manually, you reply in the thread from your phone and get the answer in the same conversation.
This requires configuring the agent to respond to Slack messages in addition to posting on a schedule — a different mode than the outbound cron job. The setup depends on your agent platform, but the pattern is worth the configuration cost: it converts Slack from a notification destination into a conversation interface.
The Weekly Digest
The weekly digest runs on a Friday afternoon cron job, after the final business-day dbt run, and aggregates patterns from the past seven days.
Data Quality Weekly Digest — Week of March 23-27, 2026
RECURRING FAILURES (3+ times this week)- not_null_int__orders_enriched_order__customer_id: 4/5 days → Still unresolved. Recommend escalating to source data owner.
- source_freshness_raw_ga4_events: 2/5 days (Tue, Wed) → Pattern suggests mid-week volume spike delays. Consider adjusting freshness threshold.
COVERAGE GAPS- 14 models have zero tests (list attached) → Priority gaps: int__marketing__attribution (feeds 3 marts, no tests)
RESOLUTION METRICS- Failures resolved same-day: 3/5 this week (60%)- Oldest unresolved failure: not_null_int__orders_enriched (14 days)
TREND- Overall pass rate: 96.2% this week vs 97.8% last week- Source freshness reliability: improving (2 failures vs 5 last week)The weekly view surfaces decisions that daily reports don’t prompt. A failure that happens twice a week looks different in a 7-day aggregate than it does in two individual daily reports. A model that’s been flagged as having zero test coverage every single day looks obviously wrong once you see it listed seven times.
The recurring failures section is particularly valuable for identifying issues that aren’t getting resolved. A daily report creates urgency. A weekly digest creates accountability — if the same failure appears five times in one week, the weekly review is the moment to decide whether to fix it, update the test, or explicitly accept it as known behavior.
Observed Outcomes
Running this pattern across two client projects suggests roughly 20-30 minutes of morning triage time saved per project per day. The weekly digest surfaces patterns that accumulate slowly in daily reports: recurring test failures, test coverage gaps expressed as a list with model names and downstream impact counts, and trend data on overall pass rates.