Inspiration
A lot of questions can't be answered by Google. While looking for a seat in the Duderstadt Center, we had no way of knowing whether any tables with monitors were free, so we had to walk and check them one by one. The same thing happens all over campus: which study rooms are open? How long is the line at the dining hall? Is the printer on the third floor working, or is there still a sign taped to it saying it's "out of order"? These questions depend on proximity to the place right now, and the answers just aren't online. The people who know the answer are the ones already there. The problem isn't limited to campus either; we often face the same problem at stores, transit, parking lots, and many other places.
What it does
ProxiPrompt lets you ask nearby people what a place is actually like right now. You type a natural question about a place, like "Is Shapiro worth going to right now if I need somewhere quiet to study?", and an AI agent works out what you actually need to know (noise level, seating availability). If fresh reports already exist, it answers instantly and nobody is bothered. If not, it sends a 10-second micro-survey to a few people standing near that place, and their taps become the answer. Either way, you get an answer with confidence and provenance: high / medium / low, plus something like "2 nearby reports · updated 12 s ago." You can also ask from ASI:One chat, no app needed, and it triggers the same real workflow.
The community is the API. If you can't read the room, ask it.
How we built it
- We used SpacetimeDB as our database. Reducers enforce every safety rule (only selected recipients can answer, one answer each, rate limits, cooldowns, anonymity), and live subscriptions push updates to every screen with no refresh. Scheduled reducers run job deadlines, prompt expiry, and cleanup, so the database enforces time even if every worker is down.
- A Fetch.ai uAgent (Python) handles planning and synthesis. It uses ASI:One to plan questions, synthesize answers, and summarize posts. It implements the Chat Protocol on Agentverse, so ASI:One users can ask it directly and trigger the same real workflow.
- Our orchestrator (Node/TypeScript) subscribes to the database, calls the agent, scores evidence, picks responders, and sends Web Push.
- A React PWA, installable to the home screen.
Challenges we ran into
GPS can't tell neighboring buildings apart. Our routing first mapped each responder's raw GPS fix to the nearest place in our campus catalog. In testing we set a responder at the Duderstadt Center, and the map showed them at Pierpont Commons. Phone GPS has an error radius of tens of meters, especially when the user is indoors. Once that radius is bigger than about half the distance between two buildings, the coordinates alone can't say which building someone is in. To address this, we added an explicit claimed building to each responder's presence. Prompts open with "Are you at {place}?", and an "I'm not there" control takes the responder out of the pool for that place. GPS still narrows down who is nearby, and the person's confirmation settles which building they're in.
Time-based rules lived in the wrong place. Every question has deadlines: how long to wait for responders, and when the question expires. At first the Node orchestrator enforced these by polling for overdue questions. If the worker crashed or restarted, nothing moved those questions forward, and they stayed open forever with the asker watching a spinner. We moved deadlines into SpacetimeDB scheduled reducers. When a question is created, its timeouts are scheduled in the same transaction, and the database fires them itself, whether or not the worker is alive. The state machine now advances on its own, and the orchestrator only reacts to state changes through its subscription.
Our responder selection prefers people who are close to the place and were seen recently, and each question only prompts a small first wave. Throwaway test accounts, created with fresh locations right at the target building, looked like the best candidates. They took the prompt slots, and real teammates standing in the building never got asked. We split live and test SpacetimeDB databases and run a separate test orchestrator against the test database. Test traffic can't reach real users' prompts anymore, and the test suite can create and delete users freely.
Accomplishments that we're proud of
A live full loop that runs end to end. One user asks a question and the Fetch.ai agent plans what needs checking, the orchestrator scores the cached evidence, and when that evidence is thin it picks nearby responders and prompts them. Their taps come back as reports, and the agent synthesizes an answer with a high/medium/low confidence label. Every step is a row change in SpacetimeDB, and the asker's screen is subscribed to those rows. The activity timeline and the final answer appear the moment they're written, with no polling and no refresh.
Each person is asked once, then serves everyone after them. If someone asks about a place that was just answered, or a similar question another user already asked, the orchestrator finds the existing reports still fresh enough to trust and answers from them right away. Nobody gets prompted, and the answer still shows how old its evidence is and where it came from. That's the whole point of treating people as sensors.
Responders only answer about places they can see. Eligibility is checked against the place being asked about. Someone at the Michigan Union will never see a question about Shapiro, no matter how few responders are available. We'd rather tell the asker that evidence is thin than ask someone who can't see the place.
Safety is built in. The agent refuses questions about named people, dorm rooms, and anything that amounts to surveillance, and askers stay anonymous to the people answering. ProxiPrompt asks about places, never about people.
What we learned
A real-time database can be more than just storage. We started with the usual split: the database stores rows, and a backend service decides what's allowed. With SpacetimeDB, the rules live in server-side reducers instead. Asking a question, accepting a prompt, submitting a report, and closing a question are each a single transactional reducer that checks its own preconditions, and scheduled reducers handle anything that depends on time. Every client and service subscribes to the same tables, so the phone, the orchestrator, and the agent always see the same state. There are no extra APIs to keep in sync, and a crashed worker can't leave things half-updated.
If we let the ASI:One model judge its own certainty, it would sound confident with one stale report or with none. So the model never sets confidence. Our shared TypeScript core weighs each report by freshness, source, and reliability, and caps the result by how many independent people contributed. The agent only gets that number back, and it can't invent evidence or raise it. The result is answers that read naturally and confidence you can audit.
What's next for ProxiPrompt
Expanding beyond campus. Our place catalog is currently a curated set of University of Michigan – Ann Arbor buildings. The same pipeline works for any place where the answer depends on being there: how crowded the train is, whether a store still has something in stock, whether there's parking, how long the line is at an event. Getting there means importing places from a real place data source instead of a hand-curated list, and adjusting freshness rules per place type.
Bringing in existing data as evidence. Some places already publish data. We want to pull these in as another kind of evidence, scored like everything else by freshness and source weight. When a sensor already answers the question, nobody needs to be asked. Dining menus are already online, so we'd only ask people what machines can't see, like whether the food is actually good.
Built With
- agentverse
- asi:one
- fetch.ai
- node.js
- playwright
- pwa
- pydantic
- pytest
- python
- react
- spacetimeauth
- spacetimedb
- typescript
- uagents
- vite
- vitest
- web-push
- zod
Log in or sign up for Devpost to join the conversation.