Inspiration
I kept meeting the same letter in different clothes. Financial aid: you completed 58% of attempted credits; appeals are rarely approved. Insurance: not medically necessary, after an ER visit. A landlord keeping a deposit for "tired carpet." A school treating an AI-detector percentage as proof.
The letter is designed to end the conversation. Most people never appeal — not because they have no case, but because they cannot see the exception that already lives in the other side's handbook. I wanted a second chair for people who were never supposed to file.
Not a chatbot with a gavel emoji. A war room.
What it does
You drop a denial on the table (paste, PDF, or a built-in matter). Four agents sit:
- Forensics treats their sentences as admissions — deadlines, dollars, "rarely approved," evidence they refuse to show you.
- Precedent retrieves a curated policy corpus (Title IV SAP, ERISA full-and-fair-review, the prudent-layperson ER standard, deposit itemization, FERPA, detector unreliability, ADA/504) and names the hole.
- Strategy picks one theory of the case and one remedy.
- Advocate writes the letter you send, plus a phone script and an enclosure list, in the language you actually speak.
The agents object to each other when the theory is thin. You leave with a packet you can print.
This is not a lawyer and not legal advice. It is a brief so a human can fight.
How I built it
A FastAPI host streams Server-Sent Events into a single cinematic page — no React, no dashboard template. The chambers are a protocol, not a prompt soup: markers for Forensics, annotations, Precedent, Strategy, objections, Advocate, and a structured packet.
Retrieval is local and boring on purpose. Query (q) and policy chunk (d) are bags of tokens. Rank is overlap, length-penalized so a long handbook dump cannot drown a short rule:
$$ \mathrm{score}(q,d)=\frac{|q\cap d|}{|d|^{0.4}} $$
The top chunks are handed to the chambers as a brief. The model does not "remember the law." It is shown the passages it is allowed to cite.
If there is no API key, a local brief still runs the full demo so a judge is never staring at a spinner. Sit Groq or OpenAI at the table and the opinion is live. scripts/build_seed.py emits a multilingual advocate JSONL — the dataset I would import into Adaption Labs (242 languages) and train so Advocate is not a generic model in a costume.
Four agents also sit on a SharedOS kernel (npm run sharedos:prove): Forensics may read the letter; Advocate reading the medical addendum comes back denied / no_matching_grant. Denied is an answer, not a crash.
What I learned
- Discovery is not permission. An agent can see
files.readand still be refused on the exact path. That is the whole product, in miniature: the tool is visible; the Addendum is not. - One theory beats five. Early drafts let Strategy ramble. Judges — and real offices — need a single remedy in one sentence.
- Streaming is a UX problem, not a model problem. A beautiful denial that arrives in 200ms still has to be watched or the war room never happened.
- Institutions already wrote the winning argument. They just wrote it in the handbook, not in the letter.
Challenges
Latency vs. theatre. Five sequential LLM calls look "agentic" and die in a live demo. One streamed completion with named seats looks like chambers and finishes before anyone checks their phone.
Faithfulness. A model that invents a CFR section is malpractice. The policy corpus is small, cited, and retrieved — and the prompt treats missing evidence as a checklist item, not a hallucination opportunity.
The catalog lie. If Advocate's tools include "read everything," the UI is a costume. Grants had to be path-scoped, and denials had to show up in the UI as objections, not stack traces.
Demo without a key. Hackathon Wi-Fi and missing .env files are real. The local brief had to be good enough that "Watch a case" is the entire pitch.
What's next
A live Cloud tenant for the four seats. Adaptive Data on the seed set so Advocate writes like counsel in the student's language, not like a translated template. And a camera intake that treats a photographed letter the same as a paste — still deny-by-default on anything that isn't the page in front of you.
Log in or sign up for Devpost to join the conversation.