Inspiration
Official letters from tax offices, landlords and insurers are written in dense English, and missing one deadline can cost real money. Letterbox is for newcomers who read Farsi better than English.
What it does
You give Letterbox a letter as plain English text. It returns:
- a plain-language explanation, in English and then in Farsi
- your options, based only on what the letter asks you to do
- a neutral draft reply in English, with a Farsi explanation of what it says
How I built it
The model never writes a deadline, amount or date. A LangGraph pipeline (extract, verify, explain, options, reply) works like this:
- The model extracts facts, each with the exact sentence from the letter that supports it, in a Pydantic schema. A bad answer gets one retry, then "I'm not sure".
- A verify step checks that every sentence appears in the letter. Amounts, deadlines, dates and conditions must also appear inside their own sentence. If one fails, the reader sees "not sure, check with the sender".
- The model writes explanations with placeholders, and the code fills in the values copied from the letter. Relative deadlines such as "within 90 days" stay exactly as written, so the tool never calculates a date.
Tech stack: Python, Pydantic, LangGraph, Claude via the Anthropic API, pytest, GitHub Actions. I planned the project with Claude and built it with Claude Code, test first, in small pull requests with my own review comments.
Security and ethics
- All letters in the repository are synthetic. The README warns against using real letters, because they contain personal details and are sent to the model API.
- Logs contain only the step name, the error type, a reference code and counts. A test checks that no letter text reaches the log.
- The API key is read only from an environment variable, never from a file.
- The reply draft is checked against a list of phrases that admit fault or promise payment, and the explanation may not sound stronger than the letter.
- I did not deploy a public version, on purpose. A public demo would invite real letters and spend API credit. Letterbox runs locally.
Challenges and what I learned
- Tests that prove nothing. Several of Claude Code's first-draft tests passed without testing anything, so I made sure each new test failed before the feature existed, and I broke code on purpose to check the tests caught it.
- The first real run found four problems the tests couldn't: the model turned "please pay" into "you must pay", the reply took a position the reader never chose, "within" appeared twice in a deadline, and a Farsi version of the sender's name was added. I fixed each with checks and tests.
- Right-to-left Farsi draws wrongly in a terminal, so the tool also writes an HTML page.
Status and limits
This is a prototype. The automated tests use answers I wrote in advance, not Claude, so they check my safety rules and not the model's quality. I ran the real model by hand on one synthetic letter. An evaluation script exists but has not been run on the full set, so I claim no accuracy figures. The Farsi was read by hand on one letter only. Known issues are listed in the README.
What's next
Run the evaluation on a larger set of letters, have a native Farsi reader review the translations, get a privacy review before handling real letters, and build a local-only interface.
Built With
- anthropic
- claude
- claude-code
- github-actions
- langgraph
- pydantic
- pytest
- python
Log in or sign up for Devpost to join the conversation.