The partially wrong answer
By the time the user notices the agent misread the question, three paragraphs are already on screen — correcting an answer already rendered is a distinct interaction from asking a new one.
The user asked about flying out on Tuesday. Somewhere in the prompt the agent read Thursday, and it is now producing a fluent, confident, well-sourced answer about the wrong day. Award space, transfer partner, the whole recommendation, all of it correct and all of it useless.
Nothing failed. The status code was 200, no error event was emitted, the transport is fine, the tool worked, and the model did not refuse. Whatever taxonomy you build for the four ways a stream ends badly will not catch this, because this is the way a stream ends well and is still wrong.
Correcting is not asking
The distinction is not only a UX opinion; it exists at the API level. Vercel documents that sendMessage takes an optional message id, and that “if a messageId is provided, the message will be replaced (useful for editing)”. Vercel writes this documentation and sells the platform it leads to, so read it as a vendor describing its own product — but the fact it records is a structural one: sending and correcting are two code paths, and the library needed both.
const { sendMessage, messages } = useChat()
// New question:
await sendMessage({ text: 'What about business class?' })
// Correcting an already-rendered answer's prompt (same slot, replaced):
await sendMessage({ text: 'I meant Tuesday, not Thursday.', messageId: targetMessageId })If your UI has one path — every user utterance appends a new turn — then correcting a misread question and asking a follow-up look identical to your code and identical on screen. The user types “I meant Tuesday,” a second answer appears below the first, and now there are two complete-looking recommendations for two different days stacked in a transcript with nothing marking one as superseded.
Where people get burned
That stack is the actual danger on an advisory surface, and it outlives the conversation. The user scrolls up a day later, lands on the Thursday recommendation, and reads it as current. It was never retracted, never marked, never dimmed. It is a correct-looking answer to a question nobody asked, sitting in the history with the same visual weight as the real one. A correction that only adds is not a correction.
What the library does and does not do
Replacing a message at an id is a data operation, and that is the whole of what is documented. Every visible consequence is yours:
- Nothing marks the replaced message as having been edited. A user whose own question silently changes under them has lost the record of what they actually asked, which matters most on exactly the surfaces where people re-read the transcript.
- Nothing decides what happens to the assistant response that was already rendered against the old prompt.
- Nothing stops the in-flight generation. That is the stop button’s three pieces of wiring, and a correction issued while the wrong answer is still streaming needs them.
Assume none of the visual design is handled and you will be right.
Four decisions, and their trades
The answer still arriving. Stop it, or let it finish? Stopping is the obvious move and it costs you the ability to say “you may still want this” if the misread was partial. Letting it finish spends tokens on a known-wrong answer while the user watches. On a long answer, stop.
The wrong answer already on screen. Four options, in rough order of how much history they preserve: remove it entirely, collapse it behind a disclosure marked as superseded, keep it visible with a persistent marker, or leave it untouched. The last one is the default you get for free and the one that produces the stack above. Collapse is usually the right trade: the user can still see what they were shown, and it cannot be mistaken for the current answer at a glance.
The prompt. Replace it in place, so the transcript reads as one clean exchange and the misread never happened? Or append the correction as its own turn, so the transcript is an accurate record of what was said? Replacing reads better. Appending is more honest. This course’s own position, offered as a position: on an advisory surface where someone may act on what they read, or come back to it, keep the record and replace nothing silently.
The context sent to the model. Independent of all of the above, and routinely forgotten. If the superseded exchange stays in the history you send, the model sees itself confidently recommending Thursday and will tend to defend it. If you drop it, you have edited the conversation out from under a user who can still see it on screen. Pick one and know which.
Where the control lives
A design position, this course’s own rather than anything a source prescribes. The correction is about the assistant’s misreading, so the affordance belongs on the assistant’s message, at the moment of noticing, not only on the user’s bubble several screens up.
Most chat UIs put editing on the user’s own message, because that is where editing lives in every messaging app anyone has used. That analogy fails here. In a messaging app you edit your message because you made a mistake. Here the user was clear and the agent misread, and asking them to scroll back and rewrite a question that was already correct is the interface blaming them for its own error. A control on the answer — one that stops the stream, marks what is on screen as superseded, and puts the cursor in a composer prefilled with the original question — does the same job while pointing at the right culprit.
The three states that need distinct renderings, and there is no way around designing all three: current, superseded, and being corrected right now — the last one existing only because the answer might still be arriving while the user types the correction.
Retrieval check
Your correction stops the stream, replaces the user’s prompt in place, and re-asks. Name what the user lost.
Check your answer
The record of what they originally asked. The transcript now reads as though they asked about Tuesday all along and got a Tuesday answer, which is tidy and false. If they were mid-way through deciding whether the agent understands them, you deleted the evidence they were gathering.
The second loss is the superseded answer, if you removed it. Some of it may still have been useful — a transfer ratio does not depend on the day — and the user watched it arrive, so removing it without a trace reads as the interface hiding a mistake rather than correcting one. Collapsing it and marking it superseded costs one disclosure and keeps both.
Check your recall
Answer from memory — no scrolling back.
Hands on
Design and ship a correction path for the flight chatbot
Done when: A misread question can be corrected from the answer itself: the in-flight stream stops, the superseded answer is visibly superseded rather than removed or left looking current, the original question is still readable in the transcript, and you can state what the model now receives as history.
- Reproduce it. Ask a question the agent will misread — an ambiguous date is the reliable one — or force it by editing the prompt. You need the wrong answer streaming in front of you before any of this is designable.
- Add the control to the assistant message, not only to your own. It should be reachable at the moment of noticing, while the answer is still arriving.
- Make it stop the stream, using the wiring from the stop-button lesson. A correction that leaves the wrong answer generating is a correction the user has to wait out.
- Design the three states and build all of them: current, superseded, and being corrected. Superseded has to survive a scroll a day later without being mistaken for current. Verify that by scrolling back to it after doing something else.
- Decide what goes into the model’s context and write it in
ARTIFACT.md: does the superseded exchange stay in the history you send? Then test the answer to that by asking a follow-up and seeing whether the agent defends Thursday. - Record the four decisions — in-flight answer, superseded answer, prompt, context — as four sentences. Bring them into the chat. I will look for a correction that quietly rewrites the transcript and for a superseded answer that still looks current.
What this does not cover
This lesson deals with an answer that arrived intact and was wrong. Answers that arrive broken — transport dropped, provider errored, tool failed, model refused, all producing the identical symptom of text stopping under a status code that was already 200 — are the error-taxonomy lesson in the production module. Do not build one mechanism for both; the user’s question is different in each case.
Deciding which parts of an answer are safe to show before they are complete, so that a half-formed recommendation never reaches the screen in the first place, is the lesson on how much of a thought is safe to show, which opens the module on rendering a partial answer. That is prevention; this is repair, and you need both.
Measuring when users actually notice a misread question is user research this course has not done and will not fake. And the render cost of replacing a message mid-conversation — what a replacement does to a long transcript, and how to measure it — belongs to Front-end performance under streaming load. This course owns whether the correction is a correct interaction. That one owns what it costs to draw.
Read this next — primary source
useChatVercel — vendor documenting its own product (AI SDK). Free. Verified September 5, 2026 against v7, the current major
Read this reference for one specific thing: the shape of the hook’s returned API, and what having a distinct code path for replacing a message rather than sending a new one implies about the interaction. sendMessage takes an optional messageId that replaces instead of appending, regenerate replaces an assistant message, and stop, resumeStream and clearError sit beside them. Reading the whole surface at once is the fastest way to see which parts of this module the library has an opinion about and which parts — every visual consequence in this lesson — it leaves entirely to you.
Stuck, curious, or think this lesson is wrong? Ask your teaching agent. The lessons are the scaffold; the conversation is where the learning gets unstuck.