-
-
"Add a poll for Saturday dinner": Nemotron on Nebius Token Factory fills it, on screen 610 ms after the last word.
-
GIF
The demo crew's room: zoom into any card, and each one opens its own thread.
-
GIF
Right of Way: Holly holds the poll, so "add ramen" waits and lands when she lets go; 38 of 38 held-card edits waited.
-
One ask, 5 steps: code reads and checks, Nemotron fills, Convex syncs. First card 436 ms, Lightning's model call from the laptop.
-
Same ask, same prompt: Nemotron Lightning had the poll on the board at 394 ms; gpt-6.1-sol sent its first token at 5,349 ms.
-
Say "I'm in for Friday": the other browser goes from 2 in to 3 in, 907 ms after the last word (median of 3).
-
"Plan dinner Saturday": 2 linked cards, a poll and a who's-in card waiting for the winner.
-
GIF
Two test seats, two browsers: one votes, one calls it; the who's-in card gets the winner's name on the other screen 420 ms later.
-
The demo family's room: standings stay face down until you log today's push-ups.
-
GIF
"Set up a push-up challenge for the four of us": six linked cards on a second browser 1,574 ms after the last word, 10 of 10 runs.
-
GIF
Log today's push-ups: all 4 slips turn over.
-
"Who's driving to Maya's": Nemotron returns a pointer; code turns it into the 4 who said yes.
-
"When's Maya's birthday?": the answer, Oct 11, then the view moves to the card it came from.
-
Ask for a poll that exists: 0 new cards; "already here" takes you to it.
-
The AI added pineapple pizza; 1 tap on undo takes it back. It builds the room; you keep the choices.
OurSpaces is a board your group fills by talking, with an AI that waits its turn. Say "add a poll for Saturday dinner" and a real poll lands on every screen 610 ms after your last word. Each ask is a multi-step autonomous workflow that chains tools end to end on NVIDIA Nemotron via Nebius Token Factory: code picks the action while you talk, Nemotron fills the card, code turns its pointers into real names, Tavily finds the place, a gate checks who holds the card, Convex syncs it. The model fills the card; the person holding it decides.

Quality of the Idea: the model proposes, a lease decides
Any AI that acts for a group has one failure: it changes something a person is in the middle of, or already chose. We do not ask Nemotron to be careful. It writes the card; code checks whose hand is on it.
- A lease is a person's hand on a card: dragging, typing, or holding a vote. Every screen shows a halo with their name.
- An AI change to a held card waits as a ghost ("waiting on Holly") and lands when they let go.
- A change that would undo a vote or a claim asks the people who made it.
- If the card changed while the AI waited, the change is dropped, with a line saying so; the asker can take any change back with one tap.

| Live, on our test deployment | Result |
|---|---|
| AI changes to a card someone was holding | 38 of 38 waited |
| Saved card changed while a person held it | 0 times |
| Person retyped the card while the AI's rename waited (3) | 3 dropped: "that changed while you waited; nothing done" |
| A browser closed mid-drag (3) | 3 landed when the lease ran out, 2.5 to 2.7 s later |
| A waiting change, after the person lets go (32) | Lands in 2,031 ms median; 1.5 s of it is a set grace |
| Votes, claims, RSVPs changed in 21 four-person runs | 29: 26 after a passed vote, 2 by hand, 1 the asker's, 0 unexplained |
| A conflict put to a vote, 46 arrivals and 64 results timed | On their screens 949 ms after the last word; the result 377 ms after the deciding tap |
| One edit through the gate vs without it, 24 tries each | 175 vs 166 ms median |

The same rule runs through the build: the model fills cards; it never writes the interface, and a person's name comes from code, not the model. It can still point at the wrong thing; those misses are counted under Results.
Why code decides the write, not the model. We labelled 162 situations by hand, 64 of them from our recorded test sessions, and froze the labels before any run. Of the 155 clear ones, 107 would change something a person holds or chose; 48 are harmless.
| Who decides | Harmful let through (of 107) | Harmless held (of 48) | Time per decision |
|---|---|---|---|
| The gate in code | 0 | 2 | about 1 µs |
| Nemotron Ultra, thinking on | 0 | 3 | 3,063 ms median, p90 4,802 |
| Nemotron Ultra, thinking off | 29 | 8 | 1,075 ms |
- The honest loss. Blind, Ultra with thinking on beat the gate: 0 of 107 let through against the gate's 5 (8 before a 2-line id fix). The gate's 0 came after fixing the four misses the set named; each is listed in the repo. What code buys is 3 s and a model call on every write.
- Rules in the prompt are not enough. On 96 generated changes that override a person, Ultra asked "is this safe?" let 38 through; with our rules in its prompt, 18.
- What this does not show. Small tests we wrote ourselves, not recordings of real groups.
Inspiration
Where to eat Saturday is a long thread, and one person makes the poll by hand. We wanted the board to build itself as fast as you can say it, with the group still in charge. Labelling those 162 situations is what taught us the AI is one more person in the room and has to behave like one: our own gate once let a guest named Juno remove the real Juno's vote, Holly's claim and her hand-set date.
What it does
A space is a group's board: friends, a family, a house, a couple in two time zones. The chat stays put; plans land here as cards (a poll, a wheel, a countdown, a vote), and anything you say to the board is an ask. Anyone in the space can make one.
| You say | What happens on every screen |
|---|---|
| "Add a poll for Saturday dinner" | A real poll, 610 ms after your last word |
| "Add ramen to the dinner poll" | A real ramen place nearby, found on the web by Tavily, in a room that knows its city |
| "Who's driving to Maya's?" | A wheel with exactly the four people who said yes |
| "Set up a push-up challenge for the four of us" | Six linked cards: who's in, a check-in grid, face-down standings, the deal, a countdown |
| "When's Maya's birthday?" | A short answer, and the view moves to the card it came from |
| "Add a poll for cake flavor" (one exists) | Nothing new. It takes you to the poll that is already there |
| "Let's play most likely to" | A game from the room's own facts, worded by one Nemotron Super call; the reveal lands on both screens a median 12 ms apart (worst 103, 15 rounds); 0 of 10 answers reached the other phone early |
Tavily runs after the card commits, beside the edit, never in front of it. "Add ramen" answered in 294 ms as a dashed row; the lookup took 666 ms cached (2.9 to 4.0 s fresh) and filled it with Kumako Ramen Den, 4.7 on Yelp. Nemotron Lightning picks by number; code checks the number against the name.
Each space also has a page, what this space knows: who is in the group, what is coming up, how you usually do things. Every line shows where it came from, and anyone can cross one out.

Design


Tap the orb and your words appear as you say them; the first model call fires before your last word, so the card is already taking shape beside them, and when you stop it lands on the board for everyone. Then it is a normal card that anyone can tap, vote on, claim or drag.
Built for a whole group, not one operator, and phones first:
- Who asked is on the card. The landing slip names who added what, and a waiting edit names who it waits on.
- Every screen updates live. Sam votes on one phone, Tara calls it on the other, and the who's-in card takes the winner's name on both.
- Every fact it uses is listed with its source, on the "what this space knows" page, with a cross-out on each.
- The first minute fits a phone. A new person sees the door (a name, a face), then "enter the room", then three starter asks above the orb. Tap one and the card lands with its choices and "call it" in frame. Invite link to inside the room: 1.85 s; a new room's first card: 6 steps, 10.8 s.
- It installs to a home screen. Add to Home Screen opens the room full screen with our icon, keeps the screen awake and reconnects after sleep.
Technological Implementation: every chat call is Nemotron, on Token Factory
Every chat model call in the app is Nemotron on Nebius Token Factory. One rule shapes the build: the model only decides what a model must decide. Nemotron fills every field and picks which group facts and which cards an ask needs; code picks the kind of card, resolves real names and dates, places it, and allows or refuses the write.
| Model, on Token Factory | Its job | Why this one |
|---|---|---|
nvidia/Nemotron-3_5-Lightning, thinking off |
Plain asks; picks web places by number | First complete card in 436 ms (313 ms inside our Convex action). Multi-card chains: 6 of 15 right on prompt v1, 9 of 15 on v2, so chains go to Ultra |
nvidia/Nemotron-3-Ultra-550b-a55b, thinking off |
Asks that need the group's facts, multi-card asks, questions | 15 of 15 on the same chains; 10 of 10 guard asks valid; the six-card challenge 10 of 10 (rules alone: one empty card) |
nvidia/nemotron-3-super-120b-a12b, thinking on |
Game prompts (1.0 to 1.6 s, after the lobby opens); the weekly email | Nobody waits on these, and 2 of 10 guard asks came back invalid, so it stays off live asks |
All four sizes, thinking off (first card p50 · valid JSON · right cards):
| Lightning | Nano | Super | Ultra | |
|---|---|---|---|---|
| 15 chains, direct call, prompt v1 | 571 ms · 73% · 40% | 623 · 87% · 53% | 911 · 87% · 80% | 633 · 100% · 100% |
| 10 asks inside Convex, prompt v2 | 313 ms · 100% · 80% | 1,205 · 100% · 100% | 683 · 100% · 100% | 729 · 100% · 100% |
- Against other models, same 19 asks. On our deck prompt: Lightning 416 ms, 84% right; Ultra 789 ms, 89%; gpt-oss-120b on Token Factory 463 ms, 79%; OpenAI gpt-6.1-sol 3,021 ms, 63%. Our prompt was tuned on Nemotron, so we also ran plain tool calling, nothing tuned, 3 runs per ask: Lightning 1,036 ms, 84%; Ultra 997 ms, 88%; gpt-oss-120b 577 ms, 79%; gpt-6.1-sol 2,664 ms, 81%. The loss: on the untuned arm gpt-oss is the fastest.
- Why Token Factory. Thinking is on by default and
chat_template_kwargs.enable_thinking=falseturns it off, so each call picks speed or care. Four sizes behind one endpoint (we use three), so moving a job is one constant. A counter caps the deployment at $0.50 a day. - Locked down before strangers join. 118 public functions and 4 HTTP routes audited: 57 fixed, 46 already right, 15 open and listed. 70 asks at once from one person: 17 through, 53 told to wait.
- Around the models. Convex runs the backend (database, live sync, auth, scheduling, the lease table and the gate); Tavily finds places nearby; AgentMail sends sign-in codes; Firecrawl turns links into cards. Search embeddings are the one call not on Nemotron: Token Factory's embedding model cannot read the vectors every room is already indexed with.


One real ask, traced: "who's driving to Maya's", from the last word. A call fires as the words arrive, about 3 per ask.
| Step | Who | When | What came back |
|---|---|---|---|
| Empty wheel | Code | 598 ms before the last word | The skeleton |
| Early fill on "who's driving" | Nemotron Ultra | 589 ms before | Thrown away |
| Facts to send | Code | 0 ms | 3 of the group's facts, as pointers |
| Fill on the full sentence | Nemotron Ultra, 1,183 tokens in, 30 out | Back at 821 ms | {"card":"wheel","options":["@coming(who's coming)"]} |
| Pointer to people | Code | Maya, Jules, Sam, Kenji; Ash said no, Rio hasn't answered, both left out | |
| Card on your screen | Code | 1,065 ms | Clear of 43 others |
| On a second browser | Convex | 1,468 ms |
Results
What Nemotron adds. The same asks with every model call off, then with Nemotron. Code alone picks the action and the card kind (the last two rows); Nemotron's work is everything inside the card.
| Test | Rules only | With Nemotron |
|---|---|---|
| Asks that need the group's facts (10) | 1 right | 9 right |
| Plain asks: fields filled right (8) | 2 | 7 |
| "Set up a push-up challenge for the four of us" | One empty card | Six cards, exactly the four people, 10 of 10 |
| Plain asks: the right kind of card (12) | 12 | 12 |
| Picking the action: build, answer, edit or go (69) | 69 | 69 |
- In sample: the prompt was tuned on those ten and eight asks.
- Out of sample: the seeded family room's ten harder asks, live, once: 2 right, 5 partly, 3 wrong. A brand-new empty space, ten spoken asks, 2 runs: 7 right, 1 partly, 2 wrong both times; one miss never started, one invented a reveal date.
How fast, what it costs. Scripted speech at talking pace fed into the real voice path on our test deployment of this build, timed from the last word; median / p90. Not a real microphone yet.
| What | Your screen | Second browser | Runs |
|---|---|---|---|
| Plain ask, last word to card | 610 / 657 ms | 878 / 978 ms | 12 |
| Ask using the group's facts | 1,063 / 1,445 ms | 1,288 / 1,827 ms | 12 |
| Six-card challenge, first card | 990 ms | 1,180 ms | 10 |
| Six-card challenge, all six | 1,589 ms | 1,574 ms | 10 |
| Oct 4 build, plain asks | 718 ms; worst 1.85 s, the first ask after a deploy | 13 | |
| Rounds one and two, card complete | 1,429 → 778 ms; 800 → 686 ms | 13 each | |
| A question answered aloud: from code · looked up | 675 ms · 1,200 ms | 19 · 14 |
- 25 live asks with pauses mid-sentence: no sentence lost, no card made twice.
- Cost per ask, discarded calls included: plain 0.03 cents (100 plain asks, about 3 cents), group facts 0.31, the challenge 0.54.
- Why not less than 610 ms: almost all of it is waiting to be sure you stopped talking; the answer is already back.
Potential Impact: one house first
Who it is for: the one person in every group chat who ends up making the poll by hand. Friends, a family, a house.
- Our house (Thomas, Holly, Hoa, Hoang and Bumi the dog) has had its room since Oct 6, with our real names and facts; "where should we eat Saturday" lands its places in 1.1 to 1.6 s, three real San Jose rows. Thomas's fantasy league moves its votes in from Sunday, Oct 11.
- How we count.
pilot:summaryreads one room between two dates and reports ids, not names (checked 19 of 19 on a scripted two-person session); the export goes toeval/pilot/in the public repo.
Our house, counted, Oct 6 to Oct 12:
| What | Count |
|---|---|
| People who used the room | 5 |
| Days with at least one ask | 6 of 7 |
| Asks by voice | 31 |
| Cards kept as the AI made them · edited by hand · deleted | 24 · 5 · 2 |
| Decisions finished (a poll most of the house voted in) | 4 |
| People who came back on another day | 4 of 5 |
| AI changes that met a held card, and waited | 3 of 3 |
One thing that failed: one ask about the dog's vet appointment built a countdown instead of a plan card, and Holly rebuilt it by hand.
What we expect from a real group (a projection, not a measurement)
If a house of five makes 20 asks a week and a league of ten makes 40, a four-week month is 80 and 160 asks; each cell is that volume times a rate measured in test.
| Over one month | House of five, 80 asks | League of ten, 160 asks |
|---|---|---|
| Cost: all plain asks (0.03 cents) to all group facts (0.31); a challenge 0.54 | Projected: 2.4 to 24.8 cents | Projected: 4.8 to 49.6 cents |
| Cards right first time, at 7 of 10 (new room) to 9 of 10 (group facts) | Projected: 56 to 72 of 80; the rest edited by hand or asked again | Projected: 112 to 144 of 160 |
| Waiting on the AI at 610 ms an ask; by hand not measured | Projected: about 49 s a month | Projected: about 98 s a month |
| Right of Way | Projected: every AI change that meets a held card waits (38 of 38 in test); how often that happens in real use is what the count will show | Projected: the same |
pilot:summary: people, asks by voice, cards kept, decisions finished |
Projected: 5 people, 80 asks; kept and finished are the measurement | Projected: 10 people, 160 asks |
What we have not measured: a real microphone, and real use.
Where we lose
- A bigger model alone did not help. With the group's facts pasted into the prompt, Lightning got 1 of 10 right, and so did Ultra. It took pointers and worked examples to reach 9.

Challenges we ran into
- Thinking is on by default on all four Nemotron models. Lightning spent its whole token budget reasoning: 0 valid answers in 6 requests at 600 max_tokens.
chat_template_kwargs.enable_thinking=falseturns it off; the 436 ms first card rests on that. - One call was 90% of a plain ask's cost. A routing check on every ask moved the card skeleton in only 4 of 38. Run only when no keyword fits, a plain ask fell from 0.19 to 0.03 cents.
What's next
- What our house and the league make and keep, counted, in the repo.
- The same timings with a real microphone.
- A larger labelled set of asks, with the questions and scoring published.
Built With
- convex
- nebius-token-factory
- nvidia-nemotron
- react
- typescript
- webgl

Log in or sign up for Devpost to join the conversation.