Skip to content
Elastic - 2nd Place

BLUEPRINT: AI Property Due Diligence

Seven AI agents read public records on any US address, permits, flood zones, EPA data, then run an adversarial AI debate before delivering a buyer risk score. Powered by Elastic Agent Builder MCP.

Core trick

Pulls permit, flood and EPA records per address, then has two Gemini agents debate a risk score before synthesis.

Tags

Built with

elastic-agent-builderelasticsearchelserepa-ejscreenfastapifema-nfhlgeminigoogle-cloud-adkgoogle-cloud-runjavascriptleaflet.jsmcpnyc-open-datapythonvertex-ai

Description

Inspiration Buying a home is the largest financial decision most people ever make - and they do it with almost no information. A 30-minute walkthrough. A seller's disclosure that's legally optional in half the states. A county permit system that takes a human hours to navigate. I wanted to build something that could do what a real estate attorney, a permit researcher, and an environmental consultant do - in 60 seconds, for any address in the US. What it does BLUEPRINT runs seven AI agents against any US address. It checks building permits across 65 city databases, flood zone status from FEMA, earthquake and climate risk from USGS, environmental hazard proximity from EPA EJSCREEN, and neighborhood data from OpenStreetMap - then synthesizes everything into a buyer risk score. The twist: before the final score is delivered, two Gemini agents run an adversarial debate. An OptimistAgent and a PessimistAgent argue the score in opposite directions. The system resolves the tension and delivers a confidence-adjusted verdict with an exact action plan: what to negotiate, what to fix, ranked by risk-point impact. How we built it Google Cloud ADK 2.0 for the multi-agent pipeline - SequentialAgent orchestrates seven LlmAgents, each with FunctionTools for their data source Elastic Agent Builder MCP as the intelligence layer - SynthesisAgent connects over Streamable HTTP MCP and runs ELSER sparse-vector hybrid search (BM25 + RRF-fused) over everything in memory Elasticsearch stores six live indices: property events, synthesis reports, cases, shared data, watchlist, and percolator alerts ES|QL for five cross-reference queries per analysis, surfaced as actual query text in the report Percolator for reverse-search: saved risk profiles match automatically the moment an analysis completes Gemini 3 Flash Preview for all agent reasoning, with Vertex AI fallback FastAPI + SSE for real-time streaming of pipeline progress to the browser Google Cloud Run for deployment Challenges we ran into Getting the adversarial debate to produce stable, non-degenerate scores was harder than expected. Early versions had the Optimist and Pessimist always anchoring at the extremes. We solved it by adding corpus-level percentile anchoring - agents are told where the preliminary score sits relative to all properties ever analysed, which pulls the debate toward a realistic range. The MCP transport layer also had a subtle bug where the connection would silently drop after the first tool call. Took a full debugging session to trace it to a keep-alive issue in the Streamable HTTP transport. Accomplishments that we're proud of The percolator felt like magic the first time it worked. You run an analysis, and before you've scrolled to the bottom, a saved risk profile has already matched and surfaced an alert - without being asked. That's Elasticsearch doing work the user didn't know to ask for. The adversarial debate architecture is something we haven't seen in property research tools. The fact that the UI shows the tug-of-war - Optimist at 48, Pessimist at 88, settled at 70 - makes the AI's reasoning visible instead of opaque. What we learned ELSER sparse-vector search is genuinely better than keyword search for this use case. Property reports contain domain jargon, permit codes, and environmental terminology that exact-match search misses. ELSER surfaces semantically related findings across the corpus without needing manual synonym lists. Building with MCP changed how we thought about AI tool design. Tools as a protocol - not hardcoded function calls - meant we could swap, extend, and debug the intelligence layer without touching the agent code. What's next for BLUEPRINT: AI Property Due Diligence Watchlist alerts : properties already in the watchlist index get re-analysed automatically when new permit filings or FEMA remapping events come in National permit coverage : 65 cities today, working toward all 50 states via Socrata and county API partnerships Lender integration : export the risk report as a structured PDF for mortgage underwriters Portfolio mode : run 10 properties in parallel for investors comparing acquisition targets
usv240/blueprint★ 11 forksPythonApache-2.0Created May 26, 2026 · last push Jun 5, 2026

README excerpt

# BLUEPRINT: AI Property Due Diligence

Type any US address. BLUEPRINT reads the public record (deeds, building permits, flood maps, earthquake history, EPA environmental data) and has two AI agents argue the findings before giving you a single sourced verdict.

[![Apache 2.0 License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
[![Google ADK 2.0](https://img.shields.io/badge/Google%20ADK-2.0-blue)](https://github.com/google/adk-python)
[![Gemini 3 Flash](https://img.shields.io/badge/Gemini-3%20Flash%20Preview-blue)](https://ai.google.dev)
[![Elastic Agent Builder](https://img.shields.io/badge/Elastic-Agent%20Builder%20MCP-pink)](https://www.elastic.co)
[![FastAPI](https://img.shields.io/badge/FastAPI-async-green)](https://fastapi.tiangolo.com)
[![Live Demo](https://img.shields.io/badge/Live%20Demo-blueprint-brightgreen)](https://blueprint-4foxtttuoa-uc.a.run.app)

Most buyers close on a $500K–$1M home with a 30-minute walkthrough and a seller's disclosure. That disclosure won't mention the 12 open DOB permits, the Superfund site half a mile away, or the fact that the flood zone designation hasn't been updated since 2009. BLUEPRINT surfaces all of it in about 60 seconds.

---

## Architecture

```mermaid
flowchart TD
    U(["👤 User"])

    subgraph CLOUD["Google Cloud Run"]
        direction LR
        FE["Frontend\nVanilla JS"]
        BE["Backend\nFastAPI · SSE stream"]
        FE --> BE
    end

    subgraph ADK["Google Cloud ADK · SequentialAgent · Ge

Team