A morning digest your team actually reads: AI-summarised news, spend and system health

by

in artificial-intelligence,business-operations,

September 7, 2026

Most Australian operations teams I talk to are subscribed to too much. Cloud billing alerts to one inbox, an uptime tool posting to a Slack channel, ad platform notifications to whoever set up the account three years ago, four vendor newsletters, and a deploy bot that fires on every merge. Nobody reads any of it. The item that actually mattered last Tuesday was sitting in a channel someone muted in March.

The approach we keep coming back to is unglamorous: one email, one delivery list, sent at 7am, ordered by what needs a decision today. Industry news summarised by a model, yesterday’s cloud and ad spend, and anything monitoring flagged overnight. This post is part of our Practical AI in Business Operations series, and it is the cheapest useful thing on the list.

Why one digest beats ten streams

Notification channels rot quietly, and nothing tells you when they do. A good example sits in a push notification service where the send call returned a bare boolean, so a permanent APNS 410 (the token is dead, the app was uninstalled or push was disabled) looked identical to a transient network blip. Dead device tokens were never pruned and the failures kept accumulating with nobody watching (TrackRat #1802).

That is the same failure mode as ten alert channels in an organisation. Each one is a small integration nobody owns. One digest with a known distribution list is a single thing to keep honest, and every recipient notices the day it stops arriving.

What the digest contains, in the order it matters

Order sections by what forces action, not by data source. Grouping by category buries the item that needs a response, which is exactly what happened to a changelog generator that grouped commits by their type prefix. Breaking changes were rendered under “Added” and “Changed”, and one commit that deleted eight internal packages shipped in a published changelog under “Changed” where an auditor would never look for it. The fix was to give breaking changes their own section and sort it to the top (go-kure #775).

So the running order in ours is:

  • Overnight alerts. Anything monitoring raised between the last digest and this one, with the alert still open flagged separately from the ones that self-cleared.
  • Spend. Yesterday’s AWS or Azure spend against the trailing seven-day average, plus Google and Meta ad spend from the same window. Percentage moves in the heading, dollars in the row.
  • Industry and vendor news. Summarised, triaged, and always last, because it is the section a reader is allowed to skip.

The architecture

It is a scheduled task, not a platform. Ours runs on a cron trigger before business hours in Sydney and takes a few seconds:

  • One collector per source, each returning (rows, error). Collectors never raise into the pipeline.
  • One summariser call per section that needs prose. The alerts and spend sections are rendered from data with no model involved.
  • One renderer producing HTML and a plain text alternative that says the same thing.
  • One run log recording which sources answered, which failed, and how many items each contributed.

The (rows, error) shape carries more weight than it looks like it should:

def render(section):
    if section.error:
        return f"{section.title}: COULD NOT READ ({section.error})"
    if not section.rows:
        return f"{section.title}: nothing overnight"
    return format_rows(section.rows)

An empty read and a failed read must render differently. A morning brief script learnt this the hard way: its calendar collector called the API with no calendarId, so it read the account default and returned zero events for a week that had nine, including a weekly planning meeting. The brief printed “nothing” on days that had meetings, and the zero read as a pass. The prompt named the calendar in prose, which the author summarised as “prose is not an argument” (kipi-system #299).

That is the archetypal silent digest failure. The email still arrives, still looks complete, and an entire data source is missing. Enforce data scope in code with an explicit parameter, and make source coverage a section of the digest itself so a missing feed is visible to every reader rather than to nobody.

Prompt design that stays faithful to sources

Three rules do most of the work.

First, the model chooses, and code checks the choice. Give the summariser a small set of named admission rules and require it to cite which rule admitted each item it keeps. Then validate the citation in code and drop anything citing something else. A team digest at PostHog did exactly this with four named rules (contract, assumption, decision, customer) and went from keeping 21 of 26 merges to keeping zero to two (PostHog #88286). Their earlier attempt used a count target in the prompt, which squeezed out real news on busy days and admitted routine work on quiet ones.

Second, no untrusted text reaches the prompt in a position where it can address the summariser. The same PostHog change removed contributor-written PR bodies from the prompt entirely, and made sure the remaining values could not close their own tag and continue as instructions. Vendor news is worse than internal commits here: press releases are written to be persuasive, and you are feeding them to a model whose job is to be sceptical about them.

Third, ask for assessment, not paraphrase. A summary that repeats an item’s own marketing copy is worse than the headline alone, because it launders the claim into your team’s morning reading. A live automated feed we looked at as a format reference gets this right: a headline count (“20 new videos across your watchlist”), then per item a title, source, a triage verdict such as Skim or Skip, and one line of critical assessment (youtube-digest #10). The triage label is what ten notification streams can never give you. It tells the reader what not to open.

Freshness rules, and the trap underneath them

Decide deliberately what happens to an item the digest did not carry, because there are two separate loss paths and they need different answers. Something cut by a render cap is different from something the summariser read and rejected.

Get this wrong and the digest quietly decays. PostHog’s was carrying merges that had landed up to six days earlier with nothing marking them as old, because anything the cap cut or the summariser dropped was re-queued into the next morning’s run. The rejected ones then produced the same empty result every day, forever, since the same input to the same prompt returns the same answer. Their fix was to let a run consume everything it claims, including an empty answer. Either age items out or label them explicitly as carried over.

Editorial rules as a binding contract

Write the rules down once, in one referenced document, and treat them as constraints any agent revising the text must obey. Scattering them through ad-hoc prompts guarantees drift. A useful example of the form is an editorial supervision contract written for agent-generated prose: core rules, an explicit list of banned constructions, and a revision standard listing what every pass must actively search for (janeco #3).

For a digest, ours is short. Every claim links to its source. No item is described in the vendor’s own adjectives. An item the model cannot summarise from the source text gets a link and no summary. Every section states its coverage. Nothing in the digest ever asserts something the collector did not read.

Honest limits and costs

The model spend is a rounding error next to the cloud bill the digest reports on. A handful of calls a day against a small model costs less than the coffee consumed while reading the output. The real cost is engineering time on the collectors, because ad platforms and cloud billing APIs change, and a broken collector that fails loudly still needs someone to fix it that week.

The other limit is scope. A digest is a reading aid, not a control system. It should never take an action, close an alert, or approve spend. Every item links back to the console where a person does that. And it needs one owner who reads it every morning and notices the day a section goes quiet for the wrong reason.

Build the smallest version first. One source, one section, one recipient, running for a fortnight before you add the second source. Most of the value shows up in week one.

PicNet builds production AI systems for Australian organisations. Talk to us about what a first project could look like.

Tagged: #llm-summarisation #automation #monitoring #cloud-costs #prompt-design