Inspiration
Legal aid lawyers (lawyers that do pro-bono work for the poor) in Uganda carry an enormous caseload, and they do it for people who have nowhere else to turn. But alongside the actual legal work, client meetings, prison visits, mediations, court appearances, there's a second, quieter job eating their time: preparations and reports.
Before any court appearance, there are must have that every advocate must submit before the case can be heard. This of course is important, but if you have a huge case load, with multiple court appearances every week, this suddenly becomes a huge burden.
In addition, funders require regular monthly and activity reports before they'll keep the money flowing, and rightly so; but writing them is unbelievably time consuming. A lawyer who just spent a week doing fieldwork then has to sit down, pull together statistics by hand, and write a formal narrative report from scratch — while more clients are waiting. It's necessary, but it's not the work they trained for, and it's not the work their clients need them doing. We built Sophia to take that burden off their plate so they can spend their limited hours on the people in front of them, not the paperwork behind them.
The Ask
While discussing with my brother who also happens to be a lawyer with the legal aid clinic under the Law Development Center, these challenges came up and as it so happened I had taken an interest in AI agents and I had an understanding of what they can do. As such I offered to help create an agent that should lighten the burden. It was during my research that I happened on this hackathon and I thought I may as well hit 2 birds with one git commit; which is rare for me, because usually I hit 1 bird and introduce 3 new bugs.
What it does
Sophia is a paralegal assistant built around three things a legal aid lawyer actually needs day to day:
- Chat / research — a conversational agent for researching Ugandan case law, searching a lawyer's own private document corpus, and looking up existing client cases, so preparing for a court appearance takes minutes instead of hours.
- Agent (document drafting) — generates a first draft of a formal court submission in proper Ugandan court format. Instead of starting from a blank page, the lawyer edits a document that's already 90% there and has it ready to file.
- Reports — generates the monthly/quarterly narrative reports and field activity reports that funders require, pulling directly from the lawyer's own case log and producing a polished Word document in minutes rather than hours.
Underneath all three, the case database also doubles as a simple system of record — a place to store case details and generated documents, rather than relying on scattered paper files or personal drives.
How we built it
The chat and drafting experience is powered by an orchestrator agent built with the Strands Agents SDK, running on Amazon Bedrock. The orchestrator delegates to sub-agents for research (Laws.Africa case law + a private vector-searched document corpus), case lookups (Supabase + Tavily web search), and drafting (generates the .docx court submission). This runs behind a small FastAPI backend that the React frontend talks to.
Report generation is handled separately, through Supabase Edge Functions that call an LLM via OpenRouter to write the narrative, then assemble the .docx directly in the function. I wanted to have as few moving parts as possible hence this pipeline.
The frontend is a React app (TanStack Router, Tailwind, shadcn/ui) with three main surfaces: a chat tab, an agent/reports tab, and case log management, all backed by Supabase for auth, the case database, document storage, and row-level security so every lawyer's data stays their own.
Challenges we ran into
AWS is powerful, but it's a lot more complex than the deploy targets we'd gotten used to - places like Vercel and Cloudflare where you push and it's live. Getting the agent backend properly deployed and talking to Bedrock took real trial and error, and we spent a lot of time debugging things that only showed up once we were actually on infrastructure, not in local dev. Spent a lot of time on this; maybe it will get better as I learn the platform better.
What we learned
Strands is a remarkably easy way to build an agent. We plan to keep developing with it, it's genuinely enjoyable to work in, and the fact that it's open source matters a lot to us. We should be able to switch the whole hosting ecosystem with ease. The Bedrock models we're using are fast, and it helped that we had 200 dollars worth of free tokens to experiment with.
But we also learned that for something as high-stakes as a funding report, "fast and conversational" isn't enough, we need the system to be more deterministic. That's exactly why report generation isn't a free-form agent conversation: it's a fixed pipeline (pull the case data, generate the narrative, assemble the document) so the output is consistent and predictable every time. There's still a lot to do there in tightening that pipeline further, this is one of our next priorities.
What's next for Paralegal Sophia
This is version 1, built with a lot of trial and error but looking ahead, we want to connect Sophia more directly into Uganda's legal system itself, reducing cases of lost or misfiled documents, and making the case record something that persists reliably beyond one lawyer's laptop; aiming at an ecosystem like prison's has access to the same information like judiciary, police and legal representation. Which would be a game changer for our legal system. Not to mention an agent that can deterministically work in there. For now, our focus is on giving overstretched legal aid lawyers back the hours they lose to research, drafting, and reporting, so they can spend them on the clients who need them as we f
Built With
- amazon-bedrock
- docker
- fastapi
- legal-aid
- legal-tech
- paralegal
- python
- query
- react
- router
- start
- strands-agents
- supabase
- tailwind
- tanstack
- tavily
- typescript
- uganda-ai
- vite
Log in or sign up for Devpost to join the conversation.