Broadsheet

Most news apps give me too much, or they hide how they pick things. So I built a paper that learns what I actually want to read, and shows its working.

Twice a day, Broadsheet pulls stories from 23 news feeds around the world. It has Qwen write a real front page. Then it watches what I react to. Over time it works out my taste and quietly changes what it shows me. Every so often, when it spots something real, it asks me one clear question to check it has read me right.

The idea

Most recommendation systems try to keep you hooked, and they do it in the dark. You never see what they think of you, and you cannot argue back. I wanted the opposite. I wanted an agent whose view of my taste is easy to see and gets sharper each day, and that tells me what it has worked out instead of nudging me in secret. That is also what the MemoryAgent track is about: an agent that builds up experience and gets better over time. So it was a good fit.

What it actually does

You read the paper and react to stories with ❤️, 💤, or ❌. That is the whole thing you do. Behind that:

  • Qwen reads the day's stories and writes a proper front page: a short lead brief and a dozen or more summaries. It files each story by what it is really about. An Nvidia story from a general news outlet gets filed under tech, not world news.
  • Every reaction is saved.
  • When it builds the next edition, the agent reads back everything you reacted to and rewrites its notes on what you like. This includes the hunches it wants to test next time.
  • And when it spots a clear pattern, it asks. Here is one question it actually wrote:

"You've passed on every story involving courts, police, or political negotiations, so I'm shifting toward human resilience and concrete tech/science breakthroughs, is that the right direction?"

The fun part is watching the questions get smarter as it gathers more reactions. Early ones are broad. Later ones are sharp, and a little uncanny.

How it's built

Broadsheet architecture

It keeps three kinds of memory. All of them live in object storage, so they survive between runs:

  • a reaction log, the raw record of everything you reacted to;
  • a reader model, its own written notes on your taste, rebuilt from that log;
  • a world state, a running sense of what is still going on, so the front page can say "this moved" instead of repeating yesterday.

The whole thing runs on Alibaba Cloud. A Function Compute web function hosts the app and the agent. Qwen (qwen3.6-flash) does all the writing and thinking. OSS holds the memory. A twice-daily timer sets it off on its own, so the editions, and the memory, build up without me touching it.

One choice I am happy with: it does not think on every click. A reaction is just a quick save that flags "there is new stuff to think about." The real thinking happens once, at the next build, over everything at once. Clicks feel instant, and Qwen gets called far less often.

Where I got stuck

Most of the time went into fighting the platform, and learning to stop guessing and read the logs.

  • The runtime installs nothing for you. Function Compute's custom runtime ignores requirements.txt, and the packages I built on my own machine did not match its setup. The fix was to install the packages straight into the function, so they are built for its machine, and to drop gunicorn for Python's built-in server.
  • The OSS SDK would not even load. oss2 pulls in a pyOpenSSL that clashes with the base image and crashed on load. So I dropped it and wrote the storage layer to sign OSS requests by hand and talk to it over plain HTTPS. Less magic, but it works.
  • The timer hit the wrong door. I set up the twice-daily trigger, and nothing happened. The logs showed why: it was not calling the route I expected. It was POSTing to /invoke and getting a 404. I added that route, and watched a 40-second run (real fetching and thinking) replace the instant blank page-loads. That was the moment it all came together.

What I took away

"Agent memory" turned out to be mostly a storage and retrieval design problem, not a prompting one. The interesting choices were what to remember (tags, not walls of text), when to think (in batches, not on every event), and how to make the agent's read on you something you can see and correct rather than something hidden. And the lesson that kept coming back: when a cloud platform misbehaves, the answer is almost always in the logs, not in another guess.

Built With

  • alibaba-cloud
  • feedparser
  • flask
  • function-compute
  • oss
  • python
  • qwen
Share this project:

Updates