Inspiration

I've spent nearly 20 years at Radio Milwaukee, and the whole job comes down to one moment: a listener hears something on our air that sticks. A band they'd never heard. A restaurant worth the drive. A story about their own block. They come looking for us, they go deeper, and one day they become a member. That relationship is how public radio survives.

In 2025 Congress pulled about $1.1 billion from public broadcasting. Up north, WXPR in Rhinelander lost a quarter of its budget and is down to one reporter covering nine counties. Stations like that can't build their way onto new platforms, and that's exactly where listeners went: 40% of our own streaming hours now run through smart speakers.

On a smart speaker, we're just a stream. You hear a song on the drive home, and it's gone. You can't ask about the story you half-heard in the kitchen, save the song, or give. And when people ask an assistant instead of tuning in, the answers come from somewhere else: Amazon's new AI-hosted Alexa Podcasts draw on more than 200 licensed newsrooms, and no public radio partner is named.

Alexa+ changes that: it holds a real conversation, and a station can plug in its own tools. So I built Radio Commons from inside the station, with every answer checked against our own reporting and approved by our own editors, and made it open source, so the stations that can least afford to build this don't have to.

What it does

Radio Commons is an MCP server (the way Alexa+ add-ons plug in) with 24 tools, so Alexa+ answers from Radio Milwaukee's own reporters, DJs and editors. Asked in the demo, all against live data:

  • "What was that This Bites episode about frugal dining?" finds the episode by what you half-remember. Alexa chains two tools on its own (find_station_story, then get_station_story) and shows an MCP Apps card; "Where are those places?" maps the 10 places it mentions.
  • "What's the tomato martini at Birch?" answers with the exact moment: "At 26:32, the episode says…", and plays the hosts' own voices from that point.
  • "Any live music near El Tsunami?" takes a place from the story and finds tonight's shows nearby, with Add to calendar.
  • "When did you last play Ellie Jackson?" → "Tell me about it." → "Save it." finds the song in the station's playlist, tells you Radio Milwaukee premiered it, and one sentence saves it to your 88Nine Finds, adds it to Apple Music and follows the artist.
  • "What's new for me?", days later, is a digest of what changed since your last visit: your artists' spins, shows and the station's stories. Memory across sessions, which Amazon's add-on docs leave to each add-on.
  • "I want to support Radio Milwaukee." offers a membership by voice, paid with Amazon Pay (sandbox: no real money moves, and Alexa says so).

Every answer is grounded. The stories come from Backstory, a story engine we built for the station: it transcribes every episode, pulls out the people, places and moments, checks each one word for word against what was actually said, and holds everything until an editor at the station approves it. Nothing reaches Alexa until a person says yes.

How we built it

  • radio-commons (Next.js on Vercel): the MCP server (spec 2025-11-25, Streamable HTTP), MCP Apps cards for Echo Show, OAuth account linking (Clerk), the Alexa+ add-on manifest (alexa/addon-package/addon.json), and an Alexa+ simulator: Deepgram hears you, Claude Haiku 4.5 on Amazon Bedrock plays Alexa+ and calls our MCP tools through the official MCP client, Amazon Polly speaks the answer, and "What Alexa did" shows every tool call.
  • Backstory (Convex): reads NPR's content system, which every member station already publishes to; transcribes with Deepgram; extracts people, places and moments with Claude Haiku 4.5 on Amazon Bedrock; keeps only facts whose quote is found in the transcript; and waits for an editor.
  • rm-playlist-v2 (Convex + Trigger.dev): the station's playlist database, enriched with Apple Music and MusicBrainz; we added listener Finds, follows and the cross-session memory.
  • MKE Field Guide (Next.js + Neon): the station's event guide; we added the public events API, the Concert Picks import and the editor's review screens. Venues are geocoded with Amazon Location Service.
  • Amazon Pay (sandbox) for memberships: checkout session, charge permission, charge and cancel are real sandbox API calls; no money moves.

Challenges we ran into

  • No Alexa+ developer tools for entrants. Amazon confirmed the tools are in preview with select partners only, so we took the simulated path: our simulator calls the same MCP server Alexa+ would, and shows every call.
  • Making AI answers trustworthy. Early extraction models paraphrased quotes. Backstory now rejects any fact whose quote isn't in the transcript, and nothing ships without an editor.
  • Memory across sessions. Alexa+ keeps the current conversation; "what's new since my last visit" had to be built server-side.
  • Cold starts. The first story question after a quiet spell could time out; we measured it (0.4–0.5 s cold vs 40–90 ms warm) and moved the limit from 0.35 s to 1.5 s, inside Amazon's 3-second guidance.

Accomplishments that we're proud of

  • A public radio station building its own Alexa+ add-on, open source, from inside the station.
  • Every fact Alexa says is quote-checked and editor-approved, and the demo shows the real review screen.
  • One sentence that runs across services: playlist → station story → Finds → Apple Music → follow.

What we learned

  • Trust is a product feature: the editor step is what makes station content safe to hand to an assistant.
  • Agentic chaining works best when each tool returns small, confirmable facts Alexa can say back.

What's next for Radio Commons

  • A second station on Backstory (adding a show is a short profile, not new code).
  • Real memberships once Amazon Pay approves nonprofit fundraising.
  • The Alexa+ developer tools, when Amazon opens them, to ship the same server as a live add-on.

Built With

Share this project:

Updates

Submission history