Inspiration
An electric shutoff notice arrives. If English is not your first language, you find the big date — September 18th — and you think you have three weeks.
But the deadline that actually stops the shutoff is not that one. It is a phrase buried in the third paragraph: "within ten business days." That lands on September 11th. Seven days earlier.
We kept meeting this shape of failure, and it is never a vocabulary problem. A translation app gives you a perfect translation of a confusing letter, which is still a confusing letter. The deadline is still buried, and nothing tells you what happens if you do nothing.
About 25 million people in the United States have limited English proficiency. What they lose when one of these letters goes unanswered is not embarrassment. It is health coverage, electricity, housing, or a court judgment entered without a hearing.
What it does
You hand Paperwall an official English letter. It hands back three files.
An action card, in the household's own language AND in English side by side — so a neighbor, a library volunteer, or a caseworker can read it with them. Deadline first, consequence second, action third. Nothing is explained before the reader knows what day they have to act by.
A calendar file (.ics) with an alarm three days before the deadline. A summary that is read once and forgotten is worth very little. A phone alarm is what actually saves the benefit.
A machine-readable record of every fact it found, so the work can be audited.
Along the way it extracts EVERY deadline — printed dates, relative phrases like "within 30 days of the date of this notice," and business-day counts that skip the weekend. It works out what happens if the household does nothing, and ranks urgency by consequence rather than by proximity: forty days to a court date beats five days to a newsletter.
It also checks for scam signals, because the same households are targeted precisely because this official tone is hard to price in an unfamiliar language. When a letter demands gift cards, threatens arrest, or tells you to keep it secret, the scam verdict outranks the deadline section entirely — and the ordinary advice ("call the sender and ask") is replaced with its opposite, because that number reaches the scammer.
Supported languages: English, Korean, Spanish, Chinese, Vietnamese.
How we built it
Paperwall is built with the Strands Agents SDK: one Agent, a system prompt, and six tools.
The decision that shapes everything is this: THE FACTS COME FROM CODE, THE PROSE COMES FROM THE MODEL.
A household is going to act on what this agent says — write a date on a calendar, send $568.57, read a case number aloud on the phone. So dates, dollar amounts, phone numbers, case numbers and the scam verdict are extracted by deterministic Python from the literal characters of the letter. The model chooses WHICH TOOL TO CALL. It never COMPUTES A VALUE. A paraphrase of a date is a wrong date.
Every deadline on the card carries a "basis" string saying exactly where it came from — "'within 10 business days' counted as 10 business days from the letter date 2026-08-28" — so a volunteer at a library desk can check it against the letter in ten seconds.
That constraint paid for something unexpected. Because the facts already come from code, we could implement a fourth model provider that needs no credentials at all: a real strands.models.Model subclass that emits the Bedrock-shaped StreamEvent protocol and drives the genuine Strands agent loop — same agent, same tools, same tool-result plumbing — with a deterministic planner instead of a network call.
It is a planner, not a model. It does not comprehend language and does not claim to. It exists because a judge who cannot run the project cannot score the project. Clone the repo, pip install, and it runs — no AWS account, no API key, no network. Turn the real model back on with one environment variable and the tool layer does not change.
The six tools: read_document, find_deadlines, find_amounts_and_contacts, check_scam_signals, find_local_help, and build_action_card. The free-help directory is curated and dated; Paperwall never invents a phone number, and says it does not know when a topic is not in the list.
Challenges we ran into
Three bugs taught us more than the features did, and all three now have regression tests.
The case-number extractor returned "September" from "Date of Notice: September 1, 2026." Every check passed — it is a string, it is in the right place, it looks like an identifier. It is exactly the kind of plausible-looking value a household would read out on the phone. A wrong identifier is worse than no identifier, so the extractor now requires a digit.
The scam letter rendered as "NO DEADLINE FOUND" — because it genuinely has no deadline. To a frightened person that reads as "nothing to worry about," which is the precise opposite of the truth, and the one output that could get someone robbed. The scam verdict now outranks the deadline section entirely.
And the generic advice for an unclassified letter is "call the sender and ask, in plain words, what they need from you." On a scam letter that is the worst possible advice, because the number printed on it reaches the scammer. The scam path now replaces the instruction list wholesale.
The common thread: every one of these failures looked green.
Accomplishments that we're proud of
It finds the deadline nobody sees. On the utility notice, Paperwall surfaced the assistance filing deadline seven days BEFORE the printed shutoff date, counted the business days across the weekend, and showed its arithmetic.
It runs with nothing. No AWS account, no API key, no network — and not by faking it. The offline provider is a real Strands model implementation driving the real agent loop.
It knows what it does not know. "Deadline not found" and "no deadline exists" are different verdicts. "No scam signal found" is stated as not being proof the letter is real. The help directory refuses to invent a phone number.
22 tests, all offline, four of them full end-to-end agent runs.
What we learned
That the barrier is not the language. It is that official mail encodes its most important information — the deadline and the consequence — in the two forms a non-native reader is least equipped to catch: a relative phrase instead of a date, and an implication instead of a statement.
And that in a system people will act on, the most valuable thing you can specify is what the model must NOT do.
What's next for Paperwall
OCR, so a phone photo of a letter is a valid input. Right now read_document refuses a scanned image rather than guessing, which is the honest answer but not the useful one.
Deployment on Amazon Bedrock AgentCore. The agent is a single stateless invocation over one document, which is the shape AgentCore Runtime expects, so this is a packaging step rather than a redesign.
A drafted reply in both languages — correct formal English to send, and the same text in the household's language so they know what they are sending. Paperwall will still never send it. It drafts; a person sends.
More languages, and a directory that can be scoped to a city so the free-help entries are the ones actually reachable from where the household lives.
Built With
- accessibility
- ai-agents
- amazon-bedrock
- amazon-web-services
- civic-tech
- pypdf
- python
- python-dateutil
- strands-agents
Log in or sign up for Devpost to join the conversation.