sanqian notes just shipped voice. It looks like almost nothing: a mic button in the chat composer, next to where you'd type. Press it (or hit ⌘⇧D) and talk. Say "make the second paragraph shorter" and red lines appear in the note. Ask "does the third paragraph follow?" and an answer appears in chat. Say both in one breath and both things happen, in order, in the same timeline.
That last sentence is the feature. This post is about why it was hard.

The screenshots in this post are of this post being written.
Talking doesn't come in modes
Every voice interface I've used makes you choose before you speak. Dictation mode: your words become text, verbatim. Assistant mode: your words become a conversation. Pick one, then talk.
But nobody talks over a document that way. Working through a draft out loud sounds like: "make this paragraph shorter — actually, is the logic here even right?" That's an edit and a question in one breath. There's no mode boundary in the sentence, because there was none in your head.
Our first design had the boundary anyway. Voice and chat were two panels with a tab switch between them — say edits in one, type questions in the other. On paper this was clean separation of concerns. In use it meant that the moment a question occurred to you mid-edit, you stopped talking, moved your hand, and switched panels. The interface was interrupting the exact flow it was supposed to protect.
Where each sentence goes
The fix is a router. Every utterance passes through one LLM call that splits it into commands and labels what it found: an edit, a question, or both.
"make the second paragraph shorter — and does the logic here hold?"
│
▼
split (LLM)
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
edit question mixed
│ │ │
▼ ▼ ▼
voice pipeline auto-sent edit lands first,
red lines in chat message then the question
the note answered in dispatches
the thread- An edit goes down the specialized voice pipeline and lands in the note.
- A question becomes a chat message, sent on your behalf, and the assistant answers in the thread.
- A mixed utterance does both: the edit lands in the document first, then the question is dispatched — so the assistant answers about the document you have now, not the one you had when you started the sentence.
We considered the two obvious alternatives. The conservative one — voice only edits, questions you type yourself — is the two-panel problem again. The radical one — hand the whole voice stream to the general assistant and let it decide everything with tool calls — sounds elegant and quietly deletes the specialized edit pipeline, with its fast paths, its tracked changes, its review gates. We kept the routing at the split layer instead. Merging the UI didn't mean merging the execution paths. An edit still costs exactly two model calls — one to split the utterance, one to generate the rewrite; everything between them is ordinary code.
There's also a context handoff hiding in the mixed case. When your question reaches the assistant, "the paragraph I just changed" has to mean something. So a chat message sent from voice carries the recent voice actions on that note along with it — the assistant can see what your voice just did before it answers.
One mode did survive, deliberately. Dictation — talk and have the words land verbatim — is still an explicit switch, not a guess. Telling an edit from a question is a two-option guess with cheap failures. Telling either from dictation is a famously unsolved problem, and the failure isn't cheap: read a draft aloud that happens to contain the words "delete this section," and you'd rather the system not take initiative. We shrank the guessing to the one boundary where being wrong is affordable.
What speech knows that typing doesn't
Routing decides what kind of sentence you said. There's a second question under it: which part of the document you meant. And here speaking and typing genuinely differ. When you type "shorten this" into chat, you've usually pasted the text or made a selection — the referent travels with the request. When you say "shorten this," the pointing stays in your body: your selection, your caret, whatever your mouse is resting on.
So while you speak, sanqian notes scores those signals, and the scores decay in seconds, the way a pointing gesture does:
"shorten this" — evidence for where "this" is:
selection ─ strongest
caret ─
hover ─
merely on screen ─ weakestThere's one human detail in the timing. People's hands run a beat behind their mouths — they say "this" and then point. So evidence that arrives just after the word gets a short grace window instead of a penalty. The original design assumed pointing comes first; real users taught it otherwise.
The model still picks the target; it's the only party that can read the document. But it picks while looking at evidence typing never generates. When the evidence is strong, the edit applies directly and stays undoable. When it's weak, the edit arrives as red lines for review. When there's none, the system does nothing at all — which is the correct edit for a sentence that was probably filler.
Wrong guesses are cheap on purpose
A router that classifies natural speech will misclassify some of it. What made this shippable isn't router accuracy — it's that the two failure directions cost almost nothing.
A question misread as an edit produces red lines, not silent changes. You reject them, one click. An edit misread as a question produces a paragraph of chat and an untouched document. You say it again. Neither failure loses work; neither failure requires undoing anything you didn't see happen.
We leaned on that asymmetry explicitly: the first version ships with no "convert this answer into an edit" remediation button. If the routing data comes back bad, we'll build one. So far the cheap recovery — reject, or repeat — has been enough.
The same caution sets the outer boundary of what voice is allowed to do. Spoken edits are confined to focused rewrites of existing passages. Replacing a whole document, changing its title — those you type, through the normal approval flow. The mic never gets to do anything you couldn't cheaply take back.
The merge was smaller than it looked
The part I expected to be expensive wasn't. Chat's assistant could already edit notes — it has had an update_note tool all along, going through the same tracked-change machinery voice uses. Same runtime, same apply layer, same red lines. The two features were already sharing an execution kernel; they had just never shared a surface.
So the merge touched UI and routing, and left execution alone. Even the unified timeline is shallower than it looks: voice keeps its own ledger of turns and commands, chat keeps its conversations, and the interleaved view is assembled at read time. One source of truth per side, no synchronization to get wrong.
voice ledger chat store
turns · commands · status conversations · messages
│ │
└────────► merged at ◄───────────┘
read time
│
▼
one interleaved
timeline
Elsewhere
The industry has mostly converged on a different shape: canvas plus thread. ChatGPT Canvas, Claude Artifacts, and Gemini in Google Docs all keep the document on one surface and the conversation on another, coordinated but separate — edits never appear as conversation, and none of them listen for an edit and a question in the same utterance. Dictation tools like superwhisper and Wispr Flow solve a different problem entirely: voice as a faster keyboard. sanqian notes keeps the canvas — edits land in the note, as red lines — but lets the record of everything you said, did, and asked interleave in one thread.
What it was really about
The mic button is the smallest part of the feature. Almost everything else was deciding, for each kind of sentence a person says over a document, where it should land — and making sure that when the system decides wrong, the price is one click or one repeated sentence.
Speech recognition turns sound into words. That part is solved. The part that isn't is that talking, unlike software, doesn't come in modes.