Inspiration

When a heater model can catch fire, the company has to tell every buyer. Recall and safety teams today report one number: sent. Sent says nothing about who knows. A message can sit unread, land in a spam folder, or go to a number that no longer exists, and the report still says 100 %. When a regulator or a lawyer asks "how many people actually know, and can you prove it?", the honest answer is usually "we don't know". We wanted that answer to be a number with evidence behind every person in it.

What it does

Proof of Reach takes a mandatory notice (a product recall, a data-breach notice, a fee change) and a recipient list, and pursues each person until they acknowledge it:

  1. The agent writes the notice. On Amazon Bedrock AgentCore Runtime, the agent writes a short notice per audience (consumers and dealers) and per channel. Code checks every text for product, hazard, action and contact; a text that fails is replaced by the stored default and labelled as such.
  2. It climbs a ladder: RCS, then WhatsApp, then email. Rung 1 is an RCS rich card with an acknowledge button. Anyone without an acknowledgment when the window ends gets a WhatsApp message with a reply button, then an email with an acknowledgment link. An acknowledged person never receives another message.
  3. It keeps proof, not counts. Every delivery, read and tap event from the AWS services lands in a ledger next to its raw payload and message id. There are three tiers, never merged: delivered, read, and acknowledged. Read receipts can be switched off and email opens are pixel based, so only a tap or a click counts as acknowledged.
  4. It names the gap. The dashboard shows one bar that fills only on acknowledgment, the per-channel breakdown, the raw AWS event beside each live device, and a report that ends with the next action, for example "47 people: unreachable, letter needed".

In the demo take (2,000 recipients, 3 real devices, 1,997 simulated), the run closed after 7 min 32 s at 1,643 of 2,000 acknowledged (82 %): read only 212, delivered only 98, unreachable 47. The demo windows are 90 seconds so the whole ladder fits on camera.

How we built it

  • Three AWS Communication Developer Services, all called at runtime: SendRcsMessage (AWS End User Messaging, boto3 pinpoint-sms-voice-v2), SendWhatsAppMessage (AWS End User Messaging Social, boto3 socialmessaging), and SendEmail (Amazon SES v2). The README lists the file and line of each call, and a test fails if they drift.
  • Proof events: RCS delivery, read and two-way suggestion taps, WhatsApp status and reply webhooks, and SES delivery, open and click events each arrive on their own Amazon SNS topic. They are buffered in Amazon SQS (with dead-letter queues) and processed by AWS Lambda consumers into one Amazon DynamoDB ledger: one row per recipient, tiers that never regress, raw event kept verbatim.
  • The ladder is a rule, not a model: Amazon EventBridge Scheduler creates a one-time schedule per window; a Lambda rule engine sends the next rung to everyone not yet acknowledged. The model writes text and summarizes replies; it never decides who gets what.
  • Agent: Amazon Bedrock AgentCore Runtime hosts the notice writer and reply summarizer (Claude Haiku 4.5 on Amazon Bedrock).
  • Surface: a static dashboard on Amazon S3 and Amazon CloudFront, reading a Lambda function URL. The API never returns phone numbers or mailboxes; raw events pass through an allowlist.
  • Reproducible: one AWS SAM template, scripts/deploy.sh, a seed script for 2,000 recipients, and 168 tests.

How we used WhatsApp (AWS End User Messaging Social)

WhatsApp is the second rung of the ladder. When the RCS window ends without an acknowledgment, the rule engine calls SendWhatsAppMessage with an interactive reply-button message (or an approved template outside the 24-hour window). We put the recipient's postback id in biz_opaque_callback_data, which Meta echoes on every status webhook, so each sent, delivered, read and failed status finds its ledger row without guessing. The tap arrives as an inbound interactive.button_reply carrying the same postback id and is recorded as acknowledged. In the demo, phone B never opened the RCS card; WhatsApp reached it after the 90-second window and its button tap turned the row green, with the raw WhatsApp payload shown beside it.

Challenges we ran into

  • Correlating WhatsApp statuses. Meta's status webhooks carry their own message id (wamid), not the AWS send id. We added three ways back to the recipient: the echoed callback data, the AWS message id, and a phone-number map, so a status is never dropped as unmatched.
  • Honest demo data. Two thousand real phones were not possible, so 1,997 recipients are simulated events published to the same SNS topics and processed by the same consumers. The dashboard footer states the split on every frame, and nothing writes to the ledger directly.
  • A link tap is not an acknowledgment. On RCS, tapping "Read the notice" opens the notice but proves only a read. We separated the two buttons so only the explicit acknowledgment counts.
  • Feedback to AWS. PutMessageFeedback returned ResourceNotFoundException for real RCS message ids in our tests. We record the outcome on the recipient row and never let the acknowledgment depend on it.

Accomplishments that we're proud of

  • A real end-to-end take on three real devices: an iPhone (RCS), an Android (RCS, then WhatsApp) and a laptop mailbox (email), with every state on screen backed by an AWS event id.
  • The report ends with a next action, not a vanity number: who still does not know, and why.

What we learned

The services already emit the evidence. RCS, WhatsApp and SES each report delivery, read and reply events per message. The missing piece was a ledger that keeps them apart, refuses to count a read receipt as proof, and keeps escalating until a person answers.

What's next

  • Customer windows of hours or days instead of 90 seconds, and SMS and voice as further rungs.
  • Exports of the ledger (CSV and PDF) for an audit file.
  • Approved WhatsApp templates and launched RCS agents per country, so the ladder works outside the 24-hour window and beyond test devices.
  • Packaging as a repeatable offering for recall, breach-notification and compliance teams.

AI disclosure

This project was built with AI coding assistants. The repository was created for this hackathon and contains no earlier code beyond open source libraries. The demo voiceover was generated with ElevenLabs from the presenter's own voice.

Built With

Share this project:

Updates

Submission history