Inspiration
Disaster response runs on people juggling too much at once. Someone has to notice a shelter's running low on water, decide what to send and where, and adjust the moment a road closes, all while five other things are also on fire. I wanted to see how much of that a Gemini-powered agent could genuinely take off someone's plate, not just describe the problem, but actually act on it.
What it does
ReliefOps reads shelter occupancy, warehouse stock, and road conditions, then does the coordination work itself. It scores each shelter's priority using a fixed formula written in plain Python, not something Gemini gets to eyeball and guess at, so the same inputs always produce the same score, and Gemini's job is to explain that number, not invent one. From there it drafts a supply plan against real warehouse numbers, runs it past an approval policy (allocation size, route risk, whether the warehouse can even cover it), and only lets things through automatically when they're genuinely low-risk. Everything else waits for a human.
The part I actually built this to prove out: it reacts on its own. If a road closes mid-task, a Pub/Sub event reaches the agent, it updates its own picture of the world, and replans, no one has to go back and ask it again.
How we built it
Gemini 3.5 Flash through Vertex AI, wired up with Google ADK as the agent framework. Nine tools handle shelters, inventory, and routes, feeding into a priority engine, an allocation planner, and an approval policy, each one deterministic Python underneath, Gemini reasons over the output rather than computing it itself. Shelter and inventory data are synthetic JSON bundled into the container, since nothing writes to those at runtime. Routes and tasks are the two things that actually change while the system runs, so those live in Firestore instead. The whole thing is deployed on Cloud Run, and a standalone Python script listens on a Pub/Sub subscription, feeding live events straight into the same agent through ADK's Runner.
Challenges we ran into
Cloud Run's filesystem resets on every fresh instance, which I found out the hard way when a task I'd just created vanished on the next deploy. That's what pushed the Firestore migration partway through the build, and the same issue came back once I got to routes for the Pub/Sub piece.
The bigger challenge wasn't technical, it was discipline. More than once, the agent gave me a confident, correct-sounding answer built on a tool call that never actually fired, or a file that was still empty underneath. The only thing that caught it was checking the underlying data directly instead of taking the response at face value, every single milestone today got independently verified before I called it done.
Accomplishments that we're proud of
Getting the Pub/Sub replan working end to end, and proving it, not just running it once and hoping. A road closure event lands, Firestore updates, and a completely separate browser session reflects that change with nobody re-prompting it directly. That's the actual difference between a chatbot and an agent, and it's real in this build, not simulated for the demo.
What we learned
Verify everything independently. An agent's own account of what it did is not proof that it happened. And architecture decisions that seem like overkill on day one, splitting mutable state into Firestore while leaving static reference data as bundled JSON, pay for themselves fast the moment you add anything event-driven.
What's next for ReliefOps Agent
A real per-shelter medical data source instead of the fixed placeholder currently in the priority formula. Incident tracking, which exists as a schema but isn't wired up yet. Turning the Pub/Sub listener into its own persistent Cloud Run service instead of a script someone has to keep running. And more event types beyond road closures, supply convoy delays, new shelter openings, anything that should trigger the same autonomous replanning loop.
Log in or sign up for Devpost to join the conversation.