-
-
"Your search box is leaking revenue" + ~15% / $8,400 / <2min stats, Elastic + Google Cloud badges
-
Gemini step pills (Discover→Revenue) + live log: "Found 20 zero-result queries across 608 log events", "Classifying with Gemini 2.5 Flash"
-
$581/mo recovered, $6,976/yr, 20 analysed / 18 fixed / $32 per fix, "Estimated by Gemini 2.5 Flash"
-
trainers→running shoes (SYNONYM), sneeks→sneakers (SPELLING), NIKE AIR (CASE), adibas→adidas… with $/mo + HIGH/MED/LOW
-
Read-only demo explainer, "Safe to apply / No data deleted", step 3 name.search, Proposed fixes header
Inspiration
Every e-commerce site silently loses money to failed searches. A shopper types "trainers," the catalogue says "running shoes," and they get zero results — so they leave. These misses are invisible: they don't show up in a sales report, nobody files a bug, and most stores never measure them. We wanted an agent that surfaces this hidden leak and closes it — not with a dashboard a human has to act on, but by generating and applying the actual Elasticsearch fix.
What it does
SearchSaver connects to any Elasticsearch cluster and:
- Finds every search from the last 30 days that returned zero results, ranked by frequency.
- Classifies each one with Gemini 2.5 Flash:
SYNONYM(trainers → running shoes),SPELLING(adibas → adidas),CASE(NIKE AIR), orMISSING(genuinely not in the catalogue — unfixable). - Generates real Elasticsearch analyzer settings — a
synonym_graphfilter pluspattern_replacefilters — and on your own cluster applies and verifies them (re-indexes a.searchsub-field and confirms the query now returns results). - Quantifies the impact: it estimates and animates the monthly revenue recovered per fix (query frequency × conversion rate × average order value).
The hosted demo runs live against a real Elastic Cloud cluster seeded with 48 products and 608 search events.
How we built it
- Google ADK 2.1.0 orchestrates the agent; the model is Gemini 2.5 Flash via Vertex AI.
- Elastic is the partner integration: Elasticsearch 8.13 holds the catalogue + search logs, and the Elastic MCP server runs as a second Cloud Run service for cluster inspection.
- A FastAPI backend streams progress to a vanilla-JS frontend over Server-Sent Events.
- Deployed on Google Cloud Run (two services: the app + the Elastic MCP server).
- Key decision: the agent is tool-free. A Python pre-fetch layer runs the server-side aggregations, hands the model a compact brief, and lets it only reason and emit JSON. Writes go through a dedicated apply step over httpx.
Challenges we ran into
- Malformed tool calls. Giving the agent the Elastic MCP toolset directly made Gemini attempt — and ~1/3 of the time malform — tool calls it didn't need, the main cause of failed analyses. Switching to the pre-fetch pattern took reliability from ~2/3 to 5/5 and cut end-to-end time from ~90s to ~25s.
- Elasticsearch won't let you change a live field's analyzer, and
synonym_graphcan't run at index time. The fix builds a separate search analyzer and an analyzed.searchsub-field, then runs_update_by_queryto populate it — so multi-word synonyms actually match. - Free-tier model limits capped the AI Studio key at ~20 requests/day and broke the live demo, so we moved to Vertex AI with a service account.
- A safe public demo: visitors can analyse the shared cluster freely, but writes are locked and the API key is injected server-side, never exposed.
What we learned
For agentic reliability, don't give the model a tool it doesn't need. Pre-computing the data deterministically in code and reserving the LLM for the reasoning step it's uniquely good at was faster, cheaper, and far more reliable than a fully tool-driven loop.
What's next
- Scheduled re-scans with email alerts on new zero-result spikes.
- Auto-tuning conversion-rate assumptions from each store's real CTR.
- One-click rollback of applied analyzer settings.
Built With
- elastic-mcp
- elasticsearch
- fastapi
- gemini
- google-adk
- google-cloud-run
- javascript
- model-context-protocol
- python
- server-sent-events
- vertex-ai
Log in or sign up for Devpost to join the conversation.