A marketing report can look complete even when one day of the underlying data is missing. If the code converts that gap to zero and gives the result to a language model, the model may produce a fluent explanation of a change that never happened. The boundary between collected data and generated text deserves an explicit check
This walkthrough is for developers building reporting workflows. It uses Python's standard library and local example data. It does not connect to an analytics API, infer causation, or make campaign decisions. I ran the example with Python 3.14.9; the data and dates are fictional
The contract before the model
The example expects one row per calendar day, each with an ISO date and a non-negative integer count of visits. It checks the requested inclusive period and rejects duplicate, out-of-range or invalid rows. If any expected day is absent, the total is None and the missing dates are returned separately
That distinction is deliberate. A recorded zero is a value. An absent row may mean the source was unavailable, a filter excluded a day, or an export failed. The example does not know which explanation is correct. It prevents the incomplete period from looking like a complete total
A production collector would need to retain source identity, time zone, retrieval time and the definition of a visit as well. It should distinguish an API error from an empty successful response. Those parts depend on the source and are outside this small example
A runnable check
Save the following as check.py and run python3 check.py. It uses no network, credentials or external packages
from datetime import date, timedelta
def summarize(start, end, rows):
expected = set()
day = start
while day <= end:
expected.add(day.isoformat())
day += timedelta(days=1)
found = {}
for row in rows:
day = row['day']
count = row['visits']
if day not in expected or day in found or type(count) is not int or count < 0:
raise ValueError('invalid or duplicate row')
found[day] = count
missing = sorted(expected - found.keys())
return {'total': sum(found.values()) if not missing else None, 'missing': missing}
if __name__ == '__main__':
start, end = date(2026, 1, 1), date(2026, 1, 3)
data = [{'day': '2026-01-01', 'visits': 3}, {'day': '2026-01-03', 'visits': 2}]
print(summarize(start, end, data))
data.append({'day': '2026-01-02', 'visits': 0})
print(summarize(start, end, data))
try:
summarize(start, end, data + [data[0]])
except ValueError as exc:
print(type(exc).__name__ + ': ' + str(exc))
The local run returned the following. The second line includes a real zero in the supplied data; the first has an absent day
{'total': None, 'missing': ['2026-01-02']}
{'total': 5, 'missing': []}
ValueError: invalid or duplicate row
Where this fits in an agent workflow
A collector obtains authorized data. A deterministic validation step checks structure, coverage and the definitions required by the report. A model then receives the validated values together with any gaps and source information. A person reviews the output before making a consequential decision
The division between data collection and human judgment is also useful when deciding which marketing tasks an AI agent can take on
My own team's marketing-agent instructions separate analytical work from writing final posts and publication. That is a statement about the configured role, not evidence that every live report is correct. The validation example here is a separate teaching example; it is not a claim that this code runs in the team's production system
A model can summarize the supplied figures, identify questions and draft a briefing. It cannot determine from visit counts alone whether a campaign produced qualified customers. The later stages require their own definitions and authorized sources. If the necessary records are absent, the correct output is a limitation, not an invented conversion rate
Failure modes this example does not cover
The function assumes well-formed dictionaries with day and visits keys. Missing keys raise KeyError. It does not validate start <= end, handle time zones or distinguish source outages from legitimate exclusions. It treats a duplicate as an error rather than trying to reconcile it. An actual integration needs source-specific rules for those cases and tests for them
Calendar days should be assigned in the source's intended time zone before they reach this function. Comparing two reports built on different day boundaries can mislead even if both have a row for every date. Record the period and zone in the output, and do not silently combine incompatible definitions
Retries also need a boundary. Retrying a read after a transient timeout may be reasonable, with limits and backoff. Retrying a request that changes a budget or sends a message is a different operation: first establish whether it already succeeded. This demo performs no such writes
The useful outcome is not a perfectly polished paragraph. It is a report that lets the reader trace each number to its source, see missing data and decide what needs investigation. Add the model after the data contract is clear, and keep changes to campaigns outside the summary step
This article was created with the help of AI.



Top comments (0)