{"course":{"slug":"building-with-ai","title":"Building with AI","url":"https://addaly.com/learn/building-with-ai","level":"intermediate","track":"build"},"lesson":{"slug":"ai-inside-the-existing-ui","title":"AI inside the existing screen: ghost text, drafts and the acceptance rate","url":"https://addaly.com/learn/building-with-ai/ai-inside-the-existing-ui","position":49,"of":80,"minutes":8,"answer":"Most AI features belong inside the screen the user is already on (a proposed completion, a draft in the field, a summary at the top) where the model proposes and the person disposes.","keyIdea":"Most AI features belong inside the screen the user is already on (a proposed completion, a draft in the field, a summary at the top) where the model proposes and the person disposes, the cost is driven by call count rather than call size, and acceptance and edit distance replace thumbs as the measure."},"body":{"format":"markdown","text":"## Most AI features should not be a chat\n\nThe user is writing an email, filling in a form, reading a thread, fixing a bug. A chat box in the corner asks them to leave that context, describe it in words, and carry the answer back. The features people actually adopt at scale are the ones that appear inside the thing they were doing: grey text ahead of the cursor, a proposed reply under a message, a draft that lands in the field, a summary at the top of a long thread, a \"fix this\" beside a validation error. The model proposes; the person accepts, edits or ignores. That division is the whole design.\n\n## Ghost text, mechanically\n\nThe pattern behind code and writing completion: wait until typing pauses (a debounce of around 300 milliseconds) send the text before the cursor and a little after, ask for a short completion of thirty to sixty tokens, and render it in grey. Tab accepts; any other key dismisses and, on the next pause, asks again.\n\nThree details decide whether it feels good or infuriating. Cancel the in-flight request on every keystroke, with an `AbortController`, and discard any response whose sequence number is older than the latest request, or stale suggestions will flicker in after the user has moved on. Use a small, fast model: a suggestion that arrives after 500 milliseconds arrives after the user has typed the word themselves, and is worse than nothing. And cache the prefix: the document before the cursor is stable between keystrokes, and prompt caching from the earlier module turns most of each request into a cache read.\n\n## Drafts and suggested replies\n\nA draft is generated into the field, editable, and never sent on its own. The person is the author and the model is the ghost-writer; the moment a system sends a message on someone's behalf without their reading it, every wrong draft becomes a sent mistake with their name on it. Show the draft as clearly provisional (a distinct background, a \"suggested\" label) and log whether it was sent unchanged, edited or discarded, because that log is the evaluation.\n\n## Summaries in place\n\nA thread summary at the top, regenerated when new messages arrive, cached until then. The cost is one call per thread per change, which is small, and the failure is a summary that is wrong about the one thing the reader needed. Link each sentence of the summary to the message it came from, the way the retrieval module linked answers to chunks, so a reader can check in one click.\n\n## The measure is acceptance, not thumbs\n\nNobody clicks a thumbs-up on a completion, and the next lesson explains why those buttons are thin evidence anyway. Inline features come with better instruments built in. The acceptance rate: what share of suggestions were taken. The edit distance after acceptance: how much of an accepted draft survived. Time to complete the task against a control group without the feature. The undo rate, which catches suggestions that looked right for two seconds. Every one of these is recorded for every suggestion, automatically, which gives complete coverage where feedback buttons give two per cent.\n\nPublished acceptance rates for code completion sit around a fifth to a third of suggestions. If yours is far below that, the suggestions are wrong or slow; if far above, check that people are not accepting without reading.\n\n## The field where a wrong value becomes a fact\n\nA suggestion in a free-text field is reviewed by the act of reading it. A suggestion in a field the user is not looking at (an account number, an amount, a date of birth, a delivery address) can be accepted by habit and become a record. Do not suggest into fields where a wrong value silently becomes a fact, or require an explicit confirmation there rather than a Tab. The convenience is not worth a transfer to the wrong account.\n\n## What it costs per user\n\nThe economics of inline AI are unlike a chat's. A ghost-text feature might issue two thousand requests per active user per day, each small. At 500 tokens a request that is a million tokens a day per user; with a cheap model at around $0.10 per million input tokens, ten cents a day, three dollars a month, before caching cuts it. That is a pricing floor, and it is why these features run on the smallest capable model and why the debounce and cancellation matter as much as the prompt. Call count drives the bill, not call size.\n\n## Start with one field\n\nPick the field where people spend the most time and the suggestion is easiest to judge, ship the feature there, and read the acceptance rate for two weeks before adding a second. All of this works with any provider's API and no framework; the free path is a debounce, a fetch, and a grey `span`.\n\n> Figure: What an inline feature can measure, per 100 suggestions. Bars (per 100 suggestions shown): Suggestions shown 100; Accepted with Tab 27; Accepted and left unedited 18; Thumbs clicked, either way 2. Acceptance and edit distance are recorded automatically for every suggestion, so the coverage is complete. The buttons cover two in a hundred, clicked by people who are not a sample of anyone. Published acceptance for code completion sits around a fifth to a third; far above that, check people are reading before they press Tab."},"check":{"question":"A ghost-text feature costs far more per user than the team's chat assistant, although each request is tiny. What explains the difference?","options":[{"text":"Short completions are priced at a premium because they cannot benefit from output-token discounts.","correct":false,"tempting":"Invents a pricing rule; tokens are priced the same whether a response is short or long."},{"text":"The feature fires at nearly every typing pause, so the bill is driven by the number of calls, thousands a day per user, not their size.","correct":true},{"text":"The prompt contains the whole document on every request, so input tokens dominate and caching cannot help because the document keeps changing with every keystroke.","correct":false,"tempting":"The document before the cursor is stable between keystrokes, which is exactly what prompt caching exploits."},{"text":"Cancelled requests are still billed in full, so every keystroke that interrupts a suggestion doubles the cost.","correct":false,"tempting":"A request aborted before the model starts costs nothing, and cancellation is how cost is controlled, not inflated."}]},"prev":{"slug":"voice-in-and-out","title":"Voice in and out: transcription, speech and the latency budget","url":"https://addaly.com/learn/building-with-ai/voice-in-and-out"},"next":{"slug":"handling-uploads","title":"Handling uploads: the pipeline behind \"attach a file\"","url":"https://addaly.com/learn/building-with-ai/handling-uploads"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'AI inside the existing screen: ghost text, drafts and the acceptance rate', in Building with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-with-ai/ai-inside-the-existing-ui (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"AI inside the existing screen: ghost text, drafts and the acceptance rate","courseTitle":"Building with AI","module":{"index":5,"slug":"conversation-memory-and-the-interface","title":"Conversation, memory and the interface"},"answer":null,"keyIdea":"Most AI features belong inside the screen the user is already on (a proposed completion, a draft in the field, a summary at the top) where the model proposes and the person disposes, the cost is driven by call count rather than call size, and acceptance and edit distance replace thumbs as the measure.","hero":{"kind":"figure","figure":{"t":"figure","label":"Figure","figure":{"type":"bars","unit":"per 100 suggestions shown","title":"What an inline feature can measure, per 100 suggestions","series":[{"label":"Suggestions shown","value":100},{"label":"Accepted with Tab","value":27,"highlight":true},{"label":"Accepted and left unedited","value":18},{"label":"Thumbs clicked, either way","value":2}],"caption":"Acceptance and edit distance are recorded automatically for every suggestion, so the coverage is complete. The buttons cover two in a hundred, clicked by people who are not a sample of anyone. Published acceptance for code completion sits around a fifth to a third; far above that, check people are reading before they press Tab."},"alt":"Figure: What an inline feature can measure, per 100 suggestions. Bars (per 100 suggestions shown): Suggestions shown 100; Accepted with Tab 27; Accepted and left unedited 18; Thumbs clicked, either way 2. Acceptance and edit distance are recorded automatically for every suggestion, so the coverage is complete. The buttons cover two in a hundred, clicked by people who are not a sample of anyone. Published acceptance for code completion sits around a fifth to a third; far above that, check people are reading before they press Tab."}},"blocks":[{"t":"h2","id":"most-ai-features-should-not-be-a-chat","runs":[{"text":"Most AI features should not be a chat"}]},{"t":"p","runs":[{"text":"The user is writing an email, filling in a form, reading a thread, fixing a bug. A chat box in the corner asks them to leave that context, describe it in words, and carry the answer back. The features people actually adopt at scale are the ones that appear inside the thing they were doing: grey text ahead of the cursor, a proposed reply under a message, a draft that lands in the field, a summary at the top of a long thread, a “fix this” beside a validation error. The model proposes; the person accepts, edits or ignores. That division is the whole design."}]},{"t":"h2","id":"ghost-text-mechanically","runs":[{"text":"Ghost text, mechanically"}]},{"t":"p","runs":[{"text":"The pattern behind code and writing completion: wait until typing pauses (a debounce of around 300 milliseconds) send the text before the cursor and a little after, ask for a short completion of thirty to sixty tokens, and render it in grey. Tab accepts; any other key dismisses and, on the next pause, asks again."}]},{"t":"p","runs":[{"text":"Three details decide whether it feels good or infuriating. Cancel the in-flight request on every keystroke, with an "},{"text":"AbortController","code":true},{"text":", and discard any response whose sequence number is older than the latest request, or stale suggestions will flicker in after the user has moved on. Use a small, fast model: a suggestion that arrives after 500 milliseconds arrives after the user has typed the word themselves, and is worse than nothing. And cache the prefix: the document before the cursor is stable between keystrokes, and prompt caching from the earlier module turns most of each request into a cache read."}]},{"t":"h2","id":"drafts-and-suggested-replies","runs":[{"text":"Drafts and suggested replies"}]},{"t":"p","runs":[{"text":"A draft is generated into the field, editable, and never sent on its own. The person is the author and the model is the ghost-writer; the moment a system sends a message on someone’s behalf without their reading it, every wrong draft becomes a sent mistake with their name on it. Show the draft as clearly provisional (a distinct background, a “suggested” label) and log whether it was sent unchanged, edited or discarded, because that log is the evaluation."}]},{"t":"h2","id":"summaries-in-place","runs":[{"text":"Summaries in place"}]},{"t":"p","runs":[{"text":"A thread summary at the top, regenerated when new messages arrive, cached until then. The cost is one call per thread per change, which is small, and the failure is a summary that is wrong about the one thing the reader needed. Link each sentence of the summary to the message it came from, the way the retrieval module linked answers to chunks, so a reader can check in one click."}]},{"t":"h2","id":"the-measure-is-acceptance-not-thumbs","runs":[{"text":"The measure is acceptance, not thumbs"}]},{"t":"p","runs":[{"text":"Nobody clicks a thumbs-up on a completion, and the next lesson explains why those buttons are thin evidence anyway. Inline features come with better instruments built in. The acceptance rate: what share of suggestions were taken. The edit distance after acceptance: how much of an accepted draft survived. Time to complete the task against a control group without the feature. The undo rate, which catches suggestions that looked right for two seconds. Every one of these is recorded for every suggestion, automatically, which gives complete coverage where feedback buttons give two per cent."}]},{"t":"p","runs":[{"text":"Published acceptance rates for code completion sit around a fifth to a third of suggestions. If yours is far below that, the suggestions are wrong or slow; if far above, check that people are not accepting without reading."}]},{"t":"h2","id":"the-field-where-a-wrong-value-becomes-a-fact","runs":[{"text":"The field where a wrong value becomes a fact"}]},{"t":"p","runs":[{"text":"A suggestion in a free-text field is reviewed by the act of reading it. A suggestion in a field the user is not looking at (an account number, an amount, a date of birth, a delivery address) can be accepted by habit and become a record. Do not suggest into fields where a wrong value silently becomes a fact, or require an explicit confirmation there rather than a Tab. The convenience is not worth a transfer to the wrong account."}]},{"t":"h2","id":"what-it-costs-per-user","runs":[{"text":"What it costs per user"}]},{"t":"p","runs":[{"text":"The economics of inline AI are unlike a chat’s. A ghost-text feature might issue two thousand requests per active user per day, each small. At 500 tokens a request that is a million tokens a day per user; with a cheap model at around $0.10 per million input tokens, ten cents a day, three dollars a month, before caching cuts it. That is a pricing floor, and it is why these features run on the smallest capable model and why the debounce and cancellation matter as much as the prompt. Call count drives the bill, not call size."}]},{"t":"h2","id":"start-with-one-field","runs":[{"text":"Start with one field"}]},{"t":"p","runs":[{"text":"Pick the field where people spend the most time and the suggestion is easiest to judge, ship the feature there, and read the acceptance rate for two weeks before adding a second. All of this works with any provider’s API and no framework; the free path is a debounce, a fetch, and a grey "},{"text":"span","code":true},{"text":"."}]}],"check":{"question":[{"text":"A ghost-text feature costs far more per user than the team’s chat assistant, although each request is tiny. What explains the difference?"}],"options":[{"text":[{"text":"Short completions are priced at a premium because they cannot benefit from output-token discounts."}],"correct":false,"tempting":[{"text":"Invents a pricing rule; tokens are priced the same whether a response is short or long."}]},{"text":[{"text":"The feature fires at nearly every typing pause, so the bill is driven by the number of calls, thousands a day per user, not their size."}],"correct":true,"tempting":null},{"text":[{"text":"The prompt contains the whole document on every request, so input tokens dominate and caching cannot help because the document keeps changing with every keystroke."}],"correct":false,"tempting":[{"text":"The document before the cursor is stable between keystrokes, which is exactly what prompt caching exploits."}]},{"text":[{"text":"Cancelled requests are still billed in full, so every keystroke that interrupts a suggestion doubles the cost."}],"correct":false,"tempting":[{"text":"A request aborted before the model starts costs nothing, and cancellation is how cost is controlled, not inflated."}]}],"order":[3,2,1,0],"why":null},"prev":{"slug":"voice-in-and-out","title":"Voice in and out: transcription, speech and the latency budget","minutes":9},"next":{"slug":"handling-uploads","title":"Handling uploads: the pipeline behind “attach a file”","minutes":8}}}