CivicSight-Agent — Project Story

Inspiration

Every day, people notice civic problems — a broken streetlight, a pothole, an overflowing bin — and most of the time, nothing happens. Not because no one cares, but because reporting it is friction: find the right department, explain it clearly, wait, hope it doesn't get lost in a queue. I wanted to see if I could remove that friction entirely — turn a plain, messy sentence someone types on their phone into an officially tracked government ticket, instantly, with no manual triage in between.

What it does

CivicSight-Agent takes a natural-language complaint — something like "there's a broken streetlight near the park, it's dangerous at night" — and resolves it end-to-end in a single API call:

  1. IssueAnalyzerAgent reads the raw text and classifies it: severity, category, and geolocation.
  2. ReportRegistrarAgent takes that structured output and auto-issues an official government-style tracking ID.

No human has to manually read, categorize, or route the complaint. What used to be a multi-step process — read, classify, assign, file — collapses into one automated pipeline.

How I built it

The core architecture is a SequentialAgent chain built with Google ADK, which handles orchestration between the two agents — ensuring IssueAnalyzerAgent fully completes and hands off clean, structured data before ReportRegistrarAgent begins, avoiding any race condition where a ticket could get issued for an incompletely classified complaint.

Gemini 2.0 Flash powers the classification step specifically because latency mattered here — a civic reporting tool that takes ten seconds to understand a two-sentence complaint feels broken before it's even useful. Flash's speed makes the whole interaction feel closer to instant.

For deployment, I containerized the pipeline with Docker so it behaves identically across environments, and deployed it on Google Cloud Run — chosen deliberately because civic complaint traffic is unpredictable. Cloud Run scales to zero when nobody's reporting anything and scales up automatically when it's needed, so I'm not paying for idle infrastructure at 3am. Vertex AI handles reliable model serving underneath that scaling.

Challenges I ran into

  • Getting the agent handoff right. Early on, I underestimated how easy it is for a multi-agent chain to silently pass malformed data between steps. Getting IssueAnalyzerAgent's output schema strict and predictable enough for ReportRegistrarAgent to trust it, every time, took more iteration than I expected — a classification agent that's usually right isn't good enough when the next agent in the chain has no way to double-check it.
  • Balancing speed and accuracy. Since I specifically wanted Gemini 2.0 Flash for its latency, I had to be careful with prompt design to get classification accuracy that still held up at that speed — it's easy to get a fast answer that's a little bit wrong, and in a civic reporting context, a misclassified "severity" isn't a cosmetic bug.
  • Making the deployment actually resilient, not just functional on my machine. Getting Docker + Cloud Run + Vertex AI to work together smoothly, especially around cold-start behavior when scaling from zero, took real debugging — a fast agent doesn't help if the container itself takes seconds to spin up.

What I learned

Building this taught me that multi-agent systems are less about the individual AI model and more about the contract between agents — how reliably one agent's output can be trusted as another agent's input. I also came away with a much more concrete sense of why infrastructure choices (like scale-to-zero deployment) aren't just DevOps details — they're product decisions that directly shape whether a tool like this could actually be affordable to run at real civic scale, not just in a demo.

Built With

Share this project:

Updates