The US government recalls dangerous products. Companies are supposed to pull them from shelves. Many never come off. Deadstock walks the gap in three moves.
The CPSC recall database is public but opaque — thousands of PDFs and structured records describing what was pulled, when, and for what hazard. We ingest the last three years, normalize hazard type, and build a semantic query per record.
The recall list is static. What's on shelves is not. Apify's Amazon actor pulls fresh listings against every recall query — title, price, image, seller, review count. Cached to disk minutes before demo so the venue wifi can't kill it.
Elasticsearch semantic_text joins the two sides. A recall says "clothing storage unit." The listing says "chest of drawers." Zero keyword overlap — but the embeddings put them next to each other. Same data, same index, two queries side by side.
Apify answers a question nobody has an API for: what is for sale right now, on the actual page a shopper sees. The recall database is public and static. Live inventory is not. Actors handle the scraping surface — pagination, anti-bot, structured extraction — so we can pull an Amazon search page as JSON in seconds.
Elastic then does two things a vector store alone can't. First, semantic_text matches meaning across vocabularies that never overlap — dresser, chest of drawers, clothing storage unit — the join a keyword index will never make. Second, ES|QL runs regulator-grade aggregations over the same index: how many recalled products are still listed, grouped by hazard, by retailer, by how long ago the recall was issued. Semantic search + aggregations over one index is the specific thing Elastic does.
The Kibana Agent Builder is the interface layer. Two tools — index_search for semantic lookup, ES|QL for the aggregate questions — and one agent that decides which to call. Judges ask a question out loud, the agent answers it against data scraped minutes ago.
EnHomee 15-Drawer 51-inch Dressers — unstable if not anchored to the wall, posing tip-over and entrapment hazards.
15 Drawer Dresser for Bedroom, Tall Fabric Chest of Drawers with Side Pockets, Sturdy Metal Frame, Wood Top, Closet Organizer for Nursery
Toggle the match mode to see what a plain keyword index would return vs. what semantic_text catches. Filter by retailer or hazard type. Every card links to the original CPSC notice — always verify before drawing conclusions.
A pair of diagrams: the shape at a glance, then every wire, index, and tool call. Cached to disk at every stage so the venue wifi can't kill the demo.
semantic_text joins them into deadstock-matches. The Agent Builder agent answers questions on top.
data/ at every stage, three indices carry the pinned inference id, and three Agent Builder tools sit on top of deadstock-matches — one index_search, two parameterized ES|QL.
Deadstock makes accusations for a living. The guardrails aren't a disclaimer — they're the design.
Deadstock was built live for the Elastic + Apify Hack Night in Austin on July 31, 2026. If it's useful to you — regulators, safety researchers, journalists, or retailers — the code and the method are on GitHub.