# Twenty Questions > A real game of twenty questions against a model, built as a genuine multi-turn app: one > server-side conversation per game, one billed turn per question, and a fact ledger that is > restated on every turn so a long game cannot drift. Live at https://twenty-questions.skillsafe.ai/ · API tutorial at /api.html ## What it does Two modes, and the mode is fixed when the game starts. **guess** — you think of something. The app asks yes/no questions, one at a time, and commits to a guess when it is confident. A guess spends one of the twenty whether it lands or not, so guessing early is a real decision rather than a free shot. **hold** — the app picks the secret and you do the asking. You get twenty questions and one final guess. ## The fairness mechanics, which are the point A model asked to "think of something" and then quizzed about it has nothing to be consistent with. Left alone it drifts, and at the reveal it names whatever fits the answers it happened to give. Two mechanisms stop that, and both live outside the model. **A commitment code, for when the app holds the secret.** The secret is chosen once, in a setup turn, and hashed with a random 64-bit salt into a short code that is displayed before the player asks anything. From then on the literal secret string is re-sent in every turn envelope, so the model reports a property of a fixed thing rather than inventing one that fits. At the reveal the code is recomputed from the revealed answer and compared; a mismatch is shown as a mismatch. It is tamper evidence, not cryptography: it proves the reveal matches what was locked in at question one, and it is not meant to withstand a player working backwards from a short word. **A restated fact ledger and a contradiction detector, for when the player holds the secret.** The platform truncates a long conversation oldest-pair-first, and in this game the earliest answers are the load-bearing ones — "is it alive? no" constrains everything after it. So every outbound turn restates the complete established-fact ledger, and correctness never depends on the conversation surviving. On top of that the browser checks each new question against the ledger and flags it in the transcript when the model re-asks an answered question, asks the same question with the negation flipped, or asks something an earlier yes/no already settles. ## The turn protocol Every message the model receives is a labelled block restating the whole state: mode, category, difficulty, questions used and left, the secret when the app is holding it, the full fact ledger, any guesses already rejected, the player's move, and a one-line instruction naming what this turn must return. Replies are plain labelled lines, not JSON — they stream a line at a time, so a half-arrived reply still renders, and one stray comma cannot destroy a turn. The labels are `THINKING`, `RULED_OUT`, `CONFIDENCE`, `ASK`, `GUESS`, `ANSWER`, `NOTE`, `SECRET`, `CATEGORY`, `HINT`, `VERDICT`, `REVEAL`, `RESULT` and `SAY`. Each turn shape declares which are required: `setup` needs `SECRET`, `ask` needs `ASK` or `GUESS`, `answer` needs `ANSWER`, `verdict` needs `VERDICT`, `finish` needs `RESULT`. A reply missing its required label gets exactly one reformat turn, and the interface says out loud that the retry cost an extra one. ## What runs free, in the browser, with no account - The fact ledger and the repeat / inversion / implication detector. - The information meter. Twenty yes/no answers is twenty bits — about a million things — and the remaining candidate space is shown falling. A hedged answer is scored at part of a bit, because it genuinely narrows less. - A question-quality score and an axis coach that names the properties nobody has asked about yet. - A two-player mode: you ask, whoever is holding the secret taps the answer, nothing is sent anywhere. - Two complete recorded games that replay through the real parser and the real renderers. ## Money and state Metered on `gpt-terra`, `markup_bps` 1000, `price_credits` 0. One `ss.sessions.send` per question, each one a billed job; the per-turn charge is shown on the turn and totalled for the game. The balance is checked against a free `estimate` before a game can start, and the interface says how many questions the balance covers rather than quoting one turn as if it were the price. Games are rows in a declared `games` collection (`acl_read: owner`, `acl_write: user`), with `localStorage` as a mirror for instant paint. The in-progress game is a row rather than an `ss.data` key, deliberately: the key-value read caches per subject and key for roughly ninety seconds, so a pointer-shaped resume hands back a stale game to anyone who reloads twice in a minute. The row carries the whole game — transcript, ledger, secret, commitment — and the session id is treated as a cache, so a game survives its session being deleted, evicted or expired. Because a session turn cannot carry an idempotency key, a turn interrupted by a reload is settled by asking the session how many messages it actually holds: if the move landed, its reply is adopted rather than sent again. ## Not what it is Not a knowledge base, not an oracle, not a search engine. It plays one game. It will not chat as a real person, will not accept a real private individual as a secret, and ends the game politely rather than following a player somewhere hateful or sexual.