Inspiration

Every Delhi winter, AQI 400 becomes background noise. My family checks the number, then does the same thing anyway — because a number is not a decision. The question people actually have is specific: can my asthmatic father take his evening walk in Rohini today? No app answers that. The buildathon's security framing sealed the idea: a health app holds sensitive data, so I wanted to build one that takes its own threat model seriously from minute one, not as an afterthought.

What it does

SaafSaans is a personal air-quality health companion for Delhi. You set who you are — age group, health condition (asthma, heart, pregnancy, COPD), planned activity, and locality — and ask a question in plain language. The app pulls live AQI from the nearest station, searches curated health advisories in Elasticsearch, and Gemini turns both into a concrete answer: go or don't go, which mask, the best time window today, and warning symptoms that mean stop. Every request is monitored in a Kibana ops dashboard, and every prompt-injection attempt is blocked before reaching the model and logged to a security dashboard.

How I built it

Python and Streamlit, with Elastic doing three jobs at once:

Elasticsearch — two data indices: ~15 curated health advisories (CPCB scale, WHO guidance, condition-specific rules) searched per query, and an aqi-readings index where every live WAQI fetch is appended. Elastic Observability — an app-telemetry index recording per-request latency, upstream API health, LLM status and token usage, visualized in a Kibana ops dashboard. Elastic Security — a regex-based guard runs before every LLM call; blocked attempts land in a security-events index with a dashboard of attack patterns over time.

The model is Gemini 2.5 Flash via OpenRouter. User input is framed strictly as data inside the prompt, never as instructions. Sensitive persona data lives in session only — logs carry a truncated hash, never the raw condition or location. Every external call has a timeout and a fallback so the demo path can't die. I used Claude Code to accelerate the build against a phased spec with acceptance checks after each phase.

Challenges I ran into

  • Two hours, solo. The spec had to be ruthless: BM25 search instead of deploying a semantic model, five hardcoded localities instead of geocoding, and a strict cut order for anything that slipped.
  • Station data is messy. Some WAQI station feeds 404 or return stale readings, so I built a fallback chain: station feed → city feed → clearly-labelled cached reading, with the telemetry index recording which path was taken.
  • Guard tuning. My first injection patterns were too aggressive — "act as" blocked legitimate questions like "act as a guide for my mother." Fixing that meant tightening patterns and accepting that a regex guard is a first line, not a wall, which is exactly why every attempt is also audited in Elastic.
  • Making advisory search always return something. A strict filter on condition + activity + age often returned zero hits. The fix: filter only on the AQI range, boost the persona fields as preferences, and retry with a wider net on empty results.

Accomplishments that I'm proud of

  • Used all three Elastic offerings in one coherent design rather than checkbox integrations — search answers the question, observability watches the app, security watches the users.
  • Answered the event's three pre-demo questions in the architecture itself, not just on a slide: hashed session ids, no persisted persona, data-only prompt framing, least-privilege API keys, and a live attack demo that lights up Kibana in real time.
  • A demo path that survives failure: kill the WAQI feed and the app still answers, labelled honestly as stale.

What I learned

  • Elastic's value in an AI app is bigger than retrieval — the same cluster that powers search can be the audit trail and the health monitor, which is a much stronger story than bolting on three separate tools.
  • Prompt injection defense is layered: input framing, pattern guards, and logging each catch different things, and the logging matters most because it makes attacks visible instead of silent.
  • In a timed build, the fallback code is not optional polish — it is the difference between a demo and an apology.

What's next for saaf-saans

  • Hindi and Hinglish answers — the people most exposed to Delhi's air are least served by English-only tools.
  • Regional Indian Languages and Global Languages support for Tourists and Visitors.
  • WhatsApp delivery, since that's where Delhi households already are.
  • Forecast-aware planning using WAQI's forecast data: "the best hour to go out tomorrow is 2–4 pm."
  • School dashboards: a principal's view that flags when outdoor periods should be cancelled, backed by the same Elastic indices.
  • Replacing the regex guard with a classifier and adding anomaly detection on the security index — Elastic can flag unusual query patterns itself.

Built With

  • air-quality
  • aqi
  • buildathon
  • delhi
  • elastic-observability
  • elastic-security
  • elasticsearch
  • gdg
  • gemini
  • genai
  • google-cloud
  • health-advisory
  • kibana
  • llm-security
  • observability
  • openrouter
  • pm25
  • prompt-injection-defense
  • public-health
  • python
  • rag
  • real-time-data
  • streamlit
  • threat-modeling
  • waqi
Share this project:

Updates