6ixPulse: piloting agentic neighbourhood research, starting with Toronto

Community Article
Published June 15, 2026

Field notes from the Hugging Face "Build Small" hackathon.

Why I built this

I'm exploring moving somewhere new, and every time I sit down to do it, I'm reminded how much work it is to choose a neighbourhood. It's never one number. It's a pile of trade-offs: how much leisure am I willing to give up for safety? How much rent for a shorter commute? How much quiet for cafés and life on the street? The "right" place is different for every person because everyone weighs those things differently — and the only way to find yours today is hours of manual research across a dozen tabs.

That time cost is the thing that frustrated me most. Rent lives on one site, crime stats on another, commute times on a third, "what's it actually like to live there" buried in a forum. You end up stitching it together by hand, and you still don't trust the result.

So I wanted to pilot something different: agentic neighbourhood research — point an agent at your priorities and let it do the legwork, with its sources shown so you can trust it. I started with Toronto (the 6ix) to help people here first, with the plan to grow it to more people and more cities once the workflow proves itself.

What it does

You describe your ideal place in plain language —

"I make $80k, work near Union, want safe streets, cafes, under 40 min commute, max rent $2,200."

— and 6ixPulse runs a real, traceable agent workflow on a live Mapbox 3D map:

  1. Plans a task for each "City Agent" (affordability, commute, safety, lifestyle, growth) and a final recommendation.
  2. Discovers the Toronto neighbourhoods that fit your prompt and their coordinates — Nothing about the candidate list is hardcoded; the map draws what the model found.
  3. Scores all eight signals — Affordability, Safety, Commute, Transit, Amenities, Lifestyle, Growth, and an overall Match — each from a real, named source.
  4. Fans out a researcher per agent, then a Recommendation agent runs last with every agent's findings and* all of their sources, and makes the call.
  5. Reads it back to you with a one-tap spoken summary, in case you'd rather listen.

The whole thing is a custom React + Mapbox/deck.gl frontend served through gradio.Server, with a Node agent backend behind it.

The principle I cared about most: no source, no claim

Housing decisions are high-stakes, so I made the app fail closed. Internal heuristics are only ranking scaffolding — they never reach the screen. The UI refuses to show a rent, commute, crime, or growth number unless the backend can tie it to evidence, and it labels each one with the actual source name (Toronto Police Service, OpenStreetMap, CMHC…), never a "[S1]". When the research is thin, it honestly says "needs source" instead of inventing a confident answer. A pretty map that lies is worse than one that admits what it doesn't know.

Every signal comes from a no-key public source:

Signal Source
Safety Toronto Police Service neighbourhood crime rates (matched by point-in-polygon)
Commute distance to Union Station over the TTC + GO network
Transit / Amenities / Lifestyle / Growth OpenStreetMap (Overpass) — stations, cafés, parks, construction
Affordability CMHC market context + a density model
Coordinates Wikipedia

Models — all under 32B

This was a Build Small hackathon, so staying small was the point:

  • Main brain: NVIDIA Nemotron Nano Omni Reasoning (enable_thinking, reasoning_budget) — it plans, discovers neighbourhoods, and writes the final recommendation.
  • Assistant: a small OpenBMB MiniCPM running through llama.cpp — OpenBMB is the model, llama.cpp is the runtime, so one move satisfies both. It helps summarise evidence.
  • Voice: Kokoro-82M neural TTS running entirely in the browser (transformers.js) — no key, no backend, just a Play button.
  • Fallback: an HF-hosted model so the agent always lands on a working brain.

What bit me (the honest part)

Nemotron wasn't callable the obvious way. I pointed the HF router at nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16 and got "not a chat model." That repo is a weights-only multimodal release with an empty inferenceProviderMapping — you can download it, but nothing hosts it as a chat endpoint. The callable version lives on NVIDIA's own API as nvidia/nemotron-3-nano-omni-30b-a3b-reasoning with an nvapi- key. Worse, my config said provider=nvidia with no key, so every request silently fell back to heuristics and the LLM never ran. Lesson: check the mode a run actually used, not the model you configured.

My web search got the Space flagged. To research listing/review sites that block bots, I wired in a Cloudflare-bypass tool. Hugging Face auto-flagged the Space as abusive. The fix wasn't a workaround — it was to remove the bypass entirely and lean on official public APIs (Toronto Open Data, OpenStreetMap), which are higher-signal anyway. Lesson: if reaching the data requires fighting a bot wall, that's a signal to find a cleaner source.

In-browser TTS froze the UI. Eagerly pre-generating audio ran the Kokoro WASM model on the main thread and locked scrolling. Fix: generate only on demand, and serialize so two clips never run at once. Lesson: small local models are great, but "in the browser" means "on the main thread" — treat it like one.

What's next

Toronto is the pilot. The workflow is intentionally city-agnostic — discovery, scoring, and the evidence policy don't assume Toronto — so the next step is widening it to more cities and more people, and deepening each agent's research as I add sources. The goal stays the same: take the days of trade-off research out of choosing where to live, and show the receipts.

Reproduce

npm install
cp .env.example .env   # add NVIDIA_API_KEY for Nemotron (or HF_TOKEN; or run llama.cpp locally)
npm run dev:full       # UI + agent backend
npm run trace:share    # capture a shareable agent trace

Live Space: https://huggingface.co/spaces/build-small-hackathon/6ixPulse

Community

Sign up or log in to comment