Inspiration
During emergencies (eg. COVID 19) government agencies get flooded with resource appeals from affected businesses, all needing review at once. Officers face an impossible bottleneck: review everything manually and fall behind exactly when speed matters most, or make faster decisions without full context on precedent and policy. We wanted to see if an LLM could handle the first-pass reasoning against policy documents, so officers spend their time on judgment calls instead of paperwork triage.
What it does
CaseTriage ingests business appeals and has Claude (via Amazon Bedrock) adjudicate each one against government policy documents using forced tool-use — producing a structured, auditable decision rather than free text. Every AI decision surfaces on a Next.js dashboard where human officers review the reasoning and override if needed, keeping a human firmly in the loop while removing the manual read-every-appeal bottleneck.
How I built it
The backend runs as a containerized Python Lambda triggered by SQS, which processes appeals and decides how much of a shared resource pool to allocate per approved case, with live stock values stored in the database. Claude, via Amazon Bedrock, adjudicates each appeal against government policy documents, weighing urgency directly as part of its policy-based reasoning to prioritize cases. Bedrock's forced tool-use constrains Claude's output into a fixed schema (decision, confidence, cited policy clause) for consistent, structured results. Appeals and decisions persist in DynamoDB, supporting documents live in S3, and the pipeline is provisioned via CloudFormation. The officer-facing dashboard is built in Next.js/TypeScript.
Challenges I ran into
- Planned to split urgent and standard appeals across two SQS queues, but the single Lambda handling both adjudication and resource allocation created concurrency issues; since allocation reads and writes shared stock values in the database, parallel invocations could race on the same values. Worked around this by having the AI handle prioritization directly through policy-based reasoning instead of queue-level separation.
- Getting Bedrock's forced tool-use to reliably cite the correct policy clause rather than a plausible-sounding but wrong one.
- Talking to actual officers who'd use the tool surfaced UX gaps I hadn't anticipated. e.g. they needed to judge appeals from the list view itself rather than clicking into each one, since that click-through cost real time at volume.
What I learned
Hands-on experience with Bedrock's forced tool-use for structured outputs, and a concrete lesson in Lambda concurrency: a single function handling two responsibilities (decision + resource allocation) against shared mutable state doesn't scale cleanly, even when the individual pieces work. Also learned the value of talking to end users early; officer feedback reshaped the UI (surfacing AI assessments directly in the list view) in ways I wouldn't have guessed sitting alone with the code.
Built With
- amazon-web-services
- bedrock
- nextjs
- react
Log in or sign up for Devpost to join the conversation.