Demo Video
our demo final view this please: https://drive.google.com/file/d/18nnetkUeE0aK_PT3jescEELxsAEVuqg4/view?usp=sharing
Inspiration
Picture a 15,000-person music festival at Birrarung Marr, the terraced park on the Yarra next to Fed Square. About 300 volunteers are on site, and there's one safety coordinator. We called him Mo.
Mo's day is a flood of messages from every direction:
"Gate B queue is past the bridge. Need more hands." "…medic to the River Stage barrier… kshh…" "Lost child at the Lawn Stage. Blue shirt, about 6." "Is anyone covering Water 2?" "Mo??"
They come in over radio, texts, calls and voice notes. Messages get dropped, the same request gets repeated three times, and nobody is sure whether anyone has actually gone. Meanwhile a festival-goer whose friend is fainting doesn't know who to ask. A guest who only wants the nearest toilets ends up taking a volunteer's time.
None of this needs a smarter radio. What's missing is a loop: anyone says something, the right person gets it, and nothing goes silent. That's moloop.
What it does
Anyone can report by voice or text: a festival-goer with no account, a volunteer, or a team lead. The AI works out what the report is and who should handle it. A person still makes the decisions that matter.
- Festival-goers ask or report from their phone. Routine questions ("where are the toilets?") get an instant answer in their own language, and no volunteer is pulled away. Real problems become tasks, and the guest sees who is coming and roughly when.
- Volunteers have one task at a time, read aloud to them. They reply by holding a button and talking: "on my way", "done", "I need help". The AI interprets the reply.
- Team leads approve the AI's pick of volunteer for urgent tasks, answer "need help" calls, and reassign work.
- Mo has a console with a Needs action inbox, a task log, the crew list and a live map. He only approves the things that really need him.
When things escalate, moloop escalates too. If a guest says "she's fainted, she's on the ground now", nobody has to press an "it's worse" button. The AI reads the follow-up, raises the task from P2 to P1 and alerts the lead.
For whole-site incidents we encoded four standard operating procedures (SOPs) as playbooks: storm, crowd crush, heat with a water shortage, and gate breach. In our demo, a wind sensor at the Lawn Stage climbs past 60 km/h while two volunteers report the storm. A planner model reads the storm playbook against who is on duty and where they are, and gives Mo one plan to review: clear the lower terrace, open the two shelters, barricade the bridge landings. Mo approves once, and every volunteer in the plan gets their task on their phone, both pushed and spoken aloud.
How we built it
- App: Expo + React Native with Expo Router. One codebase runs on iOS, Android and the web, and Mo's console is the web build. The venue is a hand-built illustrated map rendered with MapLibre, with zones, routes and crew positions.
- Data: Supabase. Phones read Postgres directly through row-level security (RLS) and Realtime. Every write goes through our command server, so the AI and the rules can never be bypassed.
- Command server: Bun + Hono. All model calls happen here, never on the phone.
- The agents: a set of small specialists instead of one big agent:
- a transcriber for hold-to-talk audio, which echoes back "Heard: …" so the speaker can check it;
- a gate classifier that decides whether a message is routine and needs nobody sent;
- an intake agent that picks the team and the priority (P1, P2 or P3), then calls exactly one tool:
create_task,escalateoranswer_question; - a re-triage matcher that asks whether a report is about an open task nearby, and whether it's getting worse;
- a reply interpreter that turns "on my way" or "I can't, I'm on break" into accept, decline, done, need help or a new report;
- a picker that re-ranks the free crew and chooses one to three people;
- a mobilization planner (
gpt-6-solthrough the Responses API) that turns a playbook plus a live snapshot of the site into a crew plan.
- Typed decisions: narrow yes/no and multiple-choice questions run on OpenAI's Decisions API, which returns probabilities rather than prose. Each decision asks exactly one question, so we can set a threshold on it and audit it.
- Rules, not models, for anything that should be predictable: a 5-second scheduler for nudges and no-shows, a rule-based ranker (team → free → skill → nearest), sensor triggers and push notifications.
- Audit everything: every state change goes into
task_eventsand every model decision intotriage_runs. - A demo simulator (
npm run simulate) acts as the sensors and the people and drives the real server. Only the wind readings and two reports are fake. Everything after that runs on the real pipeline.
Challenges we ran into
Deciding when the AI may answer on its own. Wrongly telling someone "here's the nearest toilet" when their friend is collapsing is the worst error this system can make. We built a 336-case evaluation set and swept the gate's threshold. Our first design had two models voting on priority and needed merge rules to settle disagreements, which forced the gate up to 0.95. We then made the intake agent the only owner of priority, so the gate now answers one question: is this routine? In the evaluation, no message that needed a person scored above 0.49, so we set the threshold at 0.8, and 87% of routine questions still pass. If a model call fails, the system fails closed: the message goes to a person at P2, and the AI never answers.
Local models versus cloud models. We had a DGX Spark running qwen3.5:4b, with typed decisions in 0.1–0.2 s and speech models on the same box. We built a two-tier path: try the Spark first, and fall back to OpenAI after 4 s. It worked, but every decision then had two providers to test and reason about, and the box sat behind a tunnel whose address could change mid-demo. In the final pull we moved all decisions onto OpenAI and kept the Spark as an opt-in for speech.
Making a whole-site plan fast and honest. The planner has to read a full SOP and a live snapshot of who is free, then produce a plan. We tuned it to about 19–21 seconds across our storm, heat and crowd-surge checks, and every plan we checked passed both server-side validation and a human review. Speed mattered less than honesty, though. If a team doesn't have enough free people, the plan says "2 short, will keep trying" instead of pretending. If the planner fails or runs slow, the plan is built straight from the playbook's required actions.
Hold-to-talk on iOS. The gesture handler's long-press never fired on iOS, so the main way to use the app silently did nothing. We rebuilt it on Pressable's onPressIn and onPressOut, and merged three different voice bars into one VoiceDock used everywhere.
Finding someone in a crowd. A map pin isn't enough to spot a person. Phone GPS is 5–15 m off in a crowd, and UWB only works between two iPhones. We wrote a small native Bluetooth module instead: both phones advertise a UUID derived from the task, and the received signal strength drives a "getting closer / very close / here" finder that works between iPhone and Android.
Moving the festival on the last day. We started on University Oval, then moved the whole festival to Birrarung Marr so the demo would tell a better story, with a river, terraces, bridges and a real storm risk. That meant a new map, zones, routes, ~300 crew placed into new positions, and forward migrations so that databases already running the old site could move over without being reset.
Four people, two days, one main branch. About 120 commits and many parallel branches touched the same migrations and screens. When an integration didn't fit, we reverted it rather than ship something half-merged.
What we learned
- The AI's job is routing, not deciding. The models are best at turning messy human language into a typed, auditable decision: which team, how urgent, is this the same incident, did they just say yes. People keep the final say on P1s, on escalations and on mobilizations.
- Narrow questions beat clever prompts. One question per decision, with a probability attached, gave us something we could evaluate, put a threshold on and debug. One big agent wouldn't have.
- Measure safety-critical thresholds. We only trusted the 0.8 threshold after the evaluation showed where the dangerous errors sat.
- Design for silence. In a crisis the most common failure isn't a wrong answer but no answer. Silence never closes a task in moloop: volunteers get nudged, leads hear when someone goes quiet, and no-shows are flagged with who is free to cover.
- Use rules where rules will do. Schedulers, rankers and thresholds are boring, predictable and fast, which is exactly what you want at a festival gate at 11 pm.
What's next
- A proper lost-child playbook that hands over between the Info tent, security and the guardian.
- Real sensor feeds (wind, crowd density, water levels) in place of the simulator.
- Offline-first volunteer mode for when the festival's mobile network is saturated.
- A trial with a real volunteer crew at a community event.
Log in or sign up for Devpost to join the conversation.