An in-app AI assistant, not a chatbot: the part that actually changes
Most writing on this question argues about how autonomous the model is. For an iOS team the decisive difference is narrower, and you can check it by reading a file.

You have already ruled out the chat bubble. The harder question follows: if you are shipping an in-app AI assistant, not a chatbot, what is concretely different about it? Most writing on the question answers with autonomy — the assistant remembers more, plans more, does more. Every system described that way still writes paragraphs into a scrolling transcript.
For a native iOS team that answer is unusable, because nobody can check it. "Higher context awareness" does not survive a design review. The output contract does: what the model may emit, and what your app does with a line that breaks the rules. That is the hinge generative UI on iOS turns on, reached from the support side of the building rather than the rendering side.
What follows separates the distinction from the three things it gets confused with, shows one turn on the wire, and ends with five questions to ask of a vendor's files.
The short answer
An in-app AI assistant that is not a chatbot is one whose answers arrive as native screens rather than as text in a transcript. The model does not write prose for a bubble. It emits records drawn from a fixed catalogue, and the app draws them with views it already shipped. The distinction lives in the output contract, not in the model.
What "not a chatbot" is usually taken to mean
Three answers are in circulation. Each is partly right and none is the one you need.
More autonomy. The vendor glossaries define the difference by how much the model decides for itself: a chatbot handles scripted question-and-answer, an assistant carries context, an agent runs multi-step work. Microsoft's agents-versus-chatbots explainer, checked 6 August 2026, makes that argument and never discusses what the answer looks like when it lands. Autonomy is a separate axis. A fully autonomous agent that replies in prose is still a chatbot from the user's side of the glass.
Richer bubbles. Markdown tables, headings, a chart inside the thread. The assistant-ui examples, checked 6 August 2026, render charts, date pickers, contact forms and maps as interactive tool UIs. They are useful, and they are still inside the transcript. The test was never visual richness. It is whether the result behaves like the rest of your app: whether a row pushes a view, whether a value respects Dynamic Type, whether it scrolls the way everything else scrolls.
Deleting the text field. The overcorrection. A team reads "not a chatbot" as "no typing" and ships a grid of canned questions, which is a decision tree with better spacing. It discards the part of chat that worked: an open field where a customer states the problem in their own words.
The line that divides them is the output contract
A chatbot's output is valid if it is text. That is the whole specification, and it is why a wrong answer and a right answer look identical to your code — both are well-formed strings. Every safeguard sits outside the output: a classifier reading it afterwards, a prompt asking for restraint, a human sampling the logs next week.
Move the answer into records and validity becomes a property of the payload. A record either matches a declared shape or it does not. In Uzori's wire format that shape is one of 23 record types, and every definition carries additionalProperties: false — so a field the contract does not name is not quietly ignored, it makes the record invalid. Search the format for a colour, a font, a spacing value or a nesting field and there is nothing to find. That absence is why the model cannot author style.
The useful question about a generated answer is not "is it good?" It is "is it a shape my app declared?" Only one of those has an answer at runtime.
So rejection becomes possible. Text cannot be rejected: a paragraph about the wrong month parses as cleanly as one about the right month. A record naming an undeclared field fails on arrival, before anything is drawn.
Where the question comes from, if not a chat box
Dropping the transcript does not mean dropping the input. Output modality and input modality are separate decisions, and conflating them is what produces the menu. Four entry points do most of the work:
A plain question field. One line, no thread above it, no history below it. The customer types the problem; the answer replaces that screen rather than appending to a log.
A deep link from a notification. "Your bill is ready" already carries the question. The customer taps it and lands on the answer, having typed nothing.
An inline control beside the thing in question. A small "why did this change?" next to the charge. Context comes from where the control lives, not from a sentence the customer composes.
A follow-up the screen offers. In Uzori's format a continuation is a continue interaction holding an intent string and nothing else — no free text, no URL, no payload. The next turn is bounded before anyone taps it.
None of those is a chat window, and the first still involves typing.
What one turn actually looks like
A turn on the wire, taken from the shipped record schema rather than drawn as an illustration. Each line is a complete record, validated as it lands.
{"type":"screen_start","presentation":"guide","title":"Why your bill changed"}
{"type":"callout","tone":"information","body":"This bill covers 34 days because your plan renewed on 3 August."}
{"type":"steps_start","presentation":"timeline"}
{"type":"step_item","marker":"1","title":"Plan renewal","body":"Your monthly plan renewed mid-cycle, so this statement spans a longer period than the last one."}
{"type":"step_item","marker":"2","title":"Data add-on","body":"A one-off data pack was added on 11 August and billed for the remainder of the cycle."}
{"type":"steps_end"}
{"type":"handoff_bar","actions":[{"actionRef":"open_billing_detail"}]}
{"type":"screen_commit"}Four things about that stream are checkable by reading the schema, not by trusting a description:
- Every definition is closed.
additionalProperties: falseappears on all of them. A model that invents"colour": "red"on the callout produces an invalid record, not a red callout. toneis a four-value enum of meanings, not appearances. The model can say a line is a warning. What a warning looks like is decided client-side, in code you shipped.- The action carries a reference and nothing else.
handoff_bartakes at most two objects whose only permitted property isactionRef. No label field, no URL field: the model can request an action your app declared and cannot describe a new one. - Nothing is interactive until
screen_commit. Streaming content is draft content. If the turn is abandoned, the screen that was there before it comes back.
What has to be true before customers see this
The contract makes a failure visible. Four further properties decide whether it is also a safe one.
Validation runs before the bytes reach the device, in order. Schema, screen identity, navigation match, stream grammar state, grounding, cardinality. What passes is forwarded as the original bytes, so what renders is byte-identical to what was checked.
Invalid output is rejected, never repaired. Patching a bad record into the nearest legal shape does not produce the intended answer with a small error in it; it produces a screen nobody designed, shown as though somebody had. Uzori's server never repairs model output, and one bounded re-ask is permitted only when the first record fails and nothing has been forwarded.
Mutating verbs are disabled by default. GET and HEAD classify as read; everything else is off unless a human both allowlists the operation and classifies it read. That is an auditable two-step decision rather than a prompt instruction, enforced twice: the model is never handed a non-read tool, and the executor refuses one anyway.
The client re-validates on its own. The iOS reducer re-implements the grammar and keeps its own cardinality limits instead of trusting the server. The tighter of the two wins, so a server bug degrades into a dropped record, not an unreviewed screen.
Those mechanics are the subject of the validation articles on this blog.
Where a chat answer is still the right answer
Structure is not free, and three cases genuinely belong in a bubble.
Answers that fit in a sentence. "What time does support open?" does not need a screen. If most of your inbound questions resolve in one line, a text assistant is the right tool and this argument is overhead. The filter is the shape of the answer: a comparison, a set of figures or a timeline means text is compressing something out.
Anything that ends in a purchase. Read-only is load-bearing here. A commerce session ends in a write, so a read-first assistant hands the customer back to the checkout flow at the moment they were ready to buy.
Open-ended conversation. Some interactions are a dialogue whose turns build on each other. A generated screen answers a question; it is a poor container for a complaint that needs acknowledging.
Read-only is an asset in service and a liability in commerce. If your customers' hardest questions end in a purchase rather than an explanation, this is the wrong shape of tool.
The handoff is not a defeat either. The right ending for a hard question is often your existing flow, or a person, reached with the context already gathered.
How to tell which one a vendor is selling you
Five questions, each answerable from a file rather than a conversation:
- Can I read the output schema? If the answer is a description rather than a file, the output is text with formatting conventions, and conventions are not enforced.
- Does the schema have a field for colour, font, spacing or nesting? If it does, the model authors your design system. A prompt asking it not to is not a control.
- What happens to an invalid record? Dropped, patched, coerced, or the turn fails. Ask which, then ask where in the code that decision lives.
- Where does an action's destination come from? A model-emitted label and URL is a different object from a reference to an action your app already declared.
- Which HTTP verbs can the model reach, and who decided? "It only reads" is a claim. "Non-read verbs are off unless a named person allowlists the operation and classifies it" is a process you can audit.
A vendor who answers four of five from files is probably telling you the truth about the fifth.
Frequently asked questions
What is in-app customer support?
In-app customer support is help delivered inside the product a customer is already using, rather than in email, a phone queue or a separate web portal. Most published guidance covers the container: a help centre, a tooltip, a chat widget. On a phone the harder constraint is the answer itself, because a small screen punishes a long paragraph.
How does someone ask a question if there is no chat interface?
The same ways they already act in your app. A single-line question field with no thread attached, a deep link from a push notification with the question implied, an inline control next to the charge or order concerned, or a follow-up the answer screen offers. Removing the transcript does not require removing typing.
Does this replace the support tool we already have?
No, and treating it as a replacement is the common mistake. It sits in front of the questions whose honest answer has structure, and hands everything else to the flow or the person who already handles it. The handoff is part of the design rather than an escape hatch, which is why the wire format carries a record for it.
Can the assistant do things, or only answer questions?
In a read-first design it answers, and it triggers actions your app already declared — opening a screen, starting a flow you wrote. It does not call write endpoints on its own account. That constraint is what keeps the review conversation short, and why this shape suits account and service questions better than checkout.
Where to start
Take those five questions to whatever you are evaluating, including the version your own team proposes to build in a sprint. Three of them are answered by opening a schema file, which makes them cheap to ask and hard to answer vaguely.
If you would rather see the shape than read about it, send the question your customers ask most often to hello@uzori.ai and we will answer it as a generated screen against your own API.