Elevator pitch

Your closet as governed data in DataHub. An AI roasts your wear habits using only verified stats. No cap.

Slaydar is a wardrobe agent that treats your clothes as governed data assets in DataHub — tracking real wear history, ownership, and staleness — so an AI can roast your habits using only verified numbers, and a buyer can trust a garment's condition on resale.

It's a fashion app on the surface, but under the hood it's a demonstration of a reusable pattern: modeling real-world assets as DataHub entities, continuously contributing usage and provenance back to the graph, and grounding an LLM agent so it can only speak from metadata that actually exists.


Inspiration

Two problems collide in your closet:

  1. You don't know your own wardrobe. People wear ~20% of their clothes 80% of the time, buy duplicates of things they already own, and forget items exist. There's no honest, quantified record of what you actually wear.
  2. Resale runs on blind trust. On Depop/Vinted/Poshmark, "worn twice, like new" is an unverifiable claim. Buyers can't see a garment's real usage or ownership history, so condition is a guess.

Both are fundamentally metadata and provenance problems — exactly what DataHub was built for. A garment has an owner, usage statistics, a freshness/staleness signal, tags, and a history that survives changing hands. That's not a loose analogy to a data asset — it's the same shape. So we modeled garments as first-class DataHub entities and built an agent on top of the graph.

We named the agent Slaydar: a sarcastic wardrobe critic that can only roast you with receipts.


What it does

Slaydar is an end-to-end app with three AI agents and a live DataHub backend.

  1. Catalog from photos or links. Upload closet photos (or paste a product URL) → a vision-extraction agent returns structured fields (category, color, material, brand, style tags) → each garment is created as a DataHub Dataset entity with Ownership + GlossaryTerms + properties.
  2. Daily check-in. Photograph today's outfit → a check-in match agent identifies which catalogued garment it is → you confirm → the backend increments wear_count, updates last_worn_date, recomputes cost_per_wear and a condition_score, and writes it all back to DataHub.
  3. Get roasted — with receipts. A roast agent (locked system prompt) reads the garment's actual DataHub stats and delivers one stat-backed line. It is architecturally forbidden from inventing a number or commenting on your body — only your wear behavior. "Fourth time this week, bestie. This shirt is unionizing."
  4. Automatic staleness flags. Wear something 4+ times in 7 days → it gets a Deprecation flag as overworn. Never touch a catalogued item for 30 days → a staleness sweep flags it never-worn. Both are DataHub's native deprecation aspect, not a bolted-on column.
  5. Resell with verifiable provenance. List a flagged item → its Condition Score is computed from tamper-resistant wear logs on DataHub, not a seller's word. On transfer, we mint a new dataset URN for the new ownership period and link it to the previous owner's URN with UpstreamLineage — so the garment's full cross-owner history renders as a live lineage graph in the DataHub UI.

How we built it

Two services, one shared DataHub instance, a small REST contract between them.

Next.js app (frontend + runtime agents)      FastAPI service (DataHub writer)
 - upload / check-in / roast / listing UI --> - POST /garments          (create entity)
 - Gemini agents run in-app at runtime:       - POST /garments/{id}/checkin
     · vision extraction                      - POST /garments/evaluate-staleness
     · check-in matching                      - POST /garments/{id}/transfer-owner
     · roast generation                       - GET  /garments/{id}/lineage
                                              - GET  /closet/{owner_id}
                                                        |
                                              acryl-datahub Python SDK
                                                        |
                                              DataHub GMS (docker quickstart, v1.7.0)
                                              :9002 UI · :8080 GMS
  • Frontend: Next.js 16 (App Router, React 19), TypeScript, Tailwind v4.
  • Runtime agents: Google Gemini 2.5 Flash (@google/genai) — chosen for its free tier — called from Next.js route handlers. (Claude Code was our dev tool; Gemini is what the shipped app calls.)
  • Backend: FastAPI wrapping the acryl-datahub Python SDK. This is the only thing that talks to DataHub. Every mutation is emitted as a MetadataChangeProposal through one auditable emitter module (datahub_client.py).
  • DataHub: a single shared instance (datahub docker quickstart, v1.7.0), exposed to the frontend over a stable ngrok reserved domain so both builders point at the same graph.

How a garment becomes a real DataHub entity

We deliberately did not fork DataHub to add a custom entity type (out of scope for a 6-day build). Instead every garment is a DataHub Dataseturn:li:dataset:(urn:li:dataPlatform:slaydar,<garment_id>,PROD) — and each garment concept maps onto a built-in DataHub aspect that it genuinely fits:

Garment concept DataHub aspect How we use it
Owner, reassigned on resale Ownership set on create; a new URN is minted per ownership period
Style tags (casual/formal/streetwear…) GlossaryTerms seeded a glossary node once, then tag on create
category / color / material / brand / wear_count / last_worn_date / cost_per_wear / condition_score / cataloged_date / status DatasetProperties.customProperties updated on every check-in; also lets the API fully rehydrate from DataHub on restart
Overworn / never-worn Deprecation DataHub's native staleness aspect — flagged by our rules, not a custom field
Full history across owners new dataset URN per period + UpstreamLineage resale chains URNs → renders as a live lineage graph in the DataHub UI

We don't just read the graph — we continuously contribute to it. Every catalog, check-in, staleness sweep, and ownership transfer emits real metadata. The DataHub graph is the source of truth; the agent is downstream of it.

Verified end-to-end: create → check-in → transfer-owner emit real MetadataChangeProposals, and Ownership, DatasetProperties, GlossaryTerms, Deprecation, and UpstreamLineage are all confirmed present in GMS, with the lineage graph rendering in the UI.


The design decision we're proudest of: an agent that can't hallucinate a stat

Slaydar's roast persona has a non-negotiable, locked system prompt: every line must cite a real number pulled from the garment's DataHub record (wear_count, last_worn_date, cost_per_wear, category counts), and it may never invent a stat or comment on the user's body — only on wear behavior. The route handler passes only the fetched DataHub stats into the model and instructs it to use nothing else.

This is a small, concrete instance of the bigger idea data teams care about: grounding an LLM in governed metadata so it is provably speaking from the graph, not from vibes. Slaydar's jokes are just a fun, legible way to prove the grounding works — if the number's wrong, the joke's wrong, and you'd see it instantly.


Real-world usefulness

For a consumer, Slaydar is immediately useful: it quantifies a wardrobe you can't see clearly and turns "trust me, barely worn" into a verifiable condition score for resale.

But the reason it belongs at a DataHub hackathon is the transferable pattern, which maps directly onto problems data, ML, and AI platform teams face every day:

  • Usage-backed staleness / deprecation. "This garment hasn't been worn in 30 days" is the same governance move as "this dataset hasn't been queried in 30 days — deprecate it." Slaydar automates it via the Deprecation aspect.
  • Provenance across ownership changes. Minting a new URN per ownership period and chaining with UpstreamLineage is exactly how you'd track an asset that changes teams, gets forked, or is handed off — with the full history intact and demoable in the lineage UI.
  • Cost/usage economics as first-class metadata. cost_per_wear is cost_per_query / cost_per_inference in a data platform. Slaydar computes and stores it on every event.
  • An agent grounded in the catalog. The anti-hallucination roast is a toy version of the real prize: analytics/assistant agents that answer only from governed metadata.

Slaydar is a proof that DataHub's built-in aspects are rich enough to model, govern, and reason about any real-world asset with a usage history — not just tables.


Challenges we ran into

  • Modeling without forking DataHub. Custom entity types mean modifying DataHub's source — too slow for 6 days. The win was realizing garments fit the Dataset entity and its aspects cleanly, so we got lineage, ownership, glossary, and deprecation for free.
  • Making lineage demoable. We specifically chose "new URN per ownership period + UpstreamLineage" (over mutating one entity) because it renders as a real graph in the DataHub UI — the strongest proof we didn't fake the integration.
  • Two people, one graph, no drift. We ran a single shared DataHub instance behind a stable ngrok reserved domain and made the API rehydrate its state from DataHub on startup, so restarts and reboots never lost the demo closet.
  • Keeping the agent honest. Early roast drafts drifted into inventing numbers. Locking the system prompt and passing only fetched stats fixed it — the number has to earn the joke.
  • Eventual consistency. DataHub search is eventually consistent, so we keep a lightweight in-process index for an instant /closet, while DataHub remains the durable source of truth.

Accomplishments we're proud of

  • A genuinely end-to-end system: photo → structured entity → DataHub → agent → resale, all working and verified in GMS.
  • Every garment concept maps to a built-in DataHub aspect it actually fits — no misuse, no theming a database.
  • We contribute back to the graph on every interaction, not just read it.
  • A live lineage graph of a garment's cross-owner history.
  • An agent architecturally constrained to never hallucinate a stat.

What we learned

  • DataHub's built-in aspects are far more expressive than "tables and columns" — they model ownership, usage, staleness, and provenance for arbitrary assets.
  • Lineage-as-provenance is a powerful, visual way to prove an integration is real.
  • Grounding an LLM in a metadata graph is both a governance feature and a trust feature — and it's easy to verify when the output cites the numbers.

What's next

  • Real DataHub Assertions for the condition score (currently a computed property) so it's a verifiable assertion, not just metadata.
  • A DataHub MCP Server integration so Slaydar can be queried through DataHub's agent tooling directly.
  • Multi-user resale marketplace with real cross-owner search backed by DataHub's graph queries.

How to try it

Full setup is in the README. Quickstart:

# Backend + DataHub (Person A machine)
cd api && ./scripts/demo_up.sh --seed     # DataHub -> glossary -> API -> tunnel -> seed closet

# Frontend
cd web && npm install && npm run dev       # needs GEMINI_API_KEY + API_BASE_URL in .env.local

The DataHub instance runs locally (datahub docker quickstart); the app and its agents are fully runnable against it. See the demo video for the full walkthrough, ending on the live DataHub lineage graph.


Built with

next.js 16 · react 19 · typescript · tailwindcss · google-gemini (gemini-2.5-flash) · fastapi · python · acryl-datahub · datahub (v1.7.0) · pydantic · pytest · ngrok · docker


How Slaydar maps to the judging criteria

(Stage One — fit & required SDKs: Slaydar fits the agent theme with three runtime agents and uses the required DataHub stack — the acryl-datahub Python SDK emitting MetadataChangeProposals to a live DataHub v1.7.0 instance.)

Use of DataHub. Garments are real DataHub Dataset entities using five built-in aspects — Ownership, GlossaryTerms, DatasetProperties, Deprecation, and UpstreamLineage. We go beyond reading metadata and contribute back to the graph on every interaction (catalog, check-in, staleness sweep, ownership transfer), each emitted as a MetadataChangeProposal. Cross-owner resale renders as a live lineage graph in the DataHub UI.

Technical Execution. Works end-to-end and is verified in GMS: photo → extraction agent → DataHub entity → check-in updates → roast → resale with a lineage edge. Two clean services over a locked REST contract, a hermetic pytest suite (forced dry-run, never pollutes the shared instance), and state that rehydrates from DataHub on restart. The code does exactly what this submission claims.

Originality. We model physical, real-world assets as DataHub entities and put a grounded, persona-driven agent on top — a use of DataHub well outside its out-of-the-box data-catalog framing. We compose shipped aspects (deprecation, lineage, ownership) into a new domain rather than rebuilding them.

Real-World Usefulness. The pattern is directly transferable to data/ML/AI platform teams: usage-backed deprecation, provenance across ownership handoffs, cost-per-use as first-class metadata, and an agent that answers only from the governed catalog. It's a working proof that DataHub can govern and reason about any usage-bearing asset.

Submission Quality. A recorded demo video, this written description, and a full README with copy-paste setup instructions a judge can run themselves.

Built With

Share this project:

Updates