Ready-made answers above the text box, picked by Jev from a fixed list after each reply
A quick answer chip is a ready-made answer, shown as a pill right above the text box. Tapping it is the same as typing that answer and sending it (ZLY-2019).
Every chat with Z shows them:
/onboarding, /onboarding/talent, /onboarding/brand,
/onboarding/agency);Screens that are not a chat with Z show none: the "Z & them" side of Test agent (the agents talking to each other), the "Make me smarter" form opened from a bubble, SMS and email.
No model writes the chips. When Z finishes a reply, Jev picks which set from a
fixed list fits it, or none. The set travels on the reply as a
data-quick-answers part and is stored with it, so the chips come back after
a reload.
| Set | When Z | Chips |
|---|---|---|
approve | asks to approve or reject something | Approve, Reject |
go-ahead | asks for the go-ahead before acting for the person (send, accept, launch, book, delete) | Proceed, Cancel |
proceed | asks whether to move on, or whether the person has any question before moving on | Proceed |
confirm | states an assumption and asks to confirm it | That's Correct |
skip | asks an optional question | Skip |
retry | says something failed | Retry |
ok | gives news or a notice to acknowledge, not a short "Got it" | OK |
none | anything else, such as an open question or a short acknowledgement | no chips |
QUICK_ANSWER_SETS (packages/z-agent/srv/src/quick-answers.ts), and
changing it needs no other change.quickAnswers: true to streamRoomChat:
onboarding, visitor (z-link), my rooms, my room and the admin playground.
SMS, email, MCP scenarios, mock replay, the simulations and the scripts do
not, and a turn from any channel other than the web never gets chips.forwardReplyWithQuickAnswers). When the text is done,
selectQuickAnswers asks classifyChoice (Jev, with Gemini 3.1 Flash Lite
as the fallback) to choose among the sets and none. The chip part is
written just before finish. Onboarding tries the canned
chips first. When that list does not fit,
these generic sets still apply, so a move-on line still gets Proceed.QUICK_ANSWERS_TIMEOUT_MS (2 seconds): a
slower answer means no chips for that reply. Jev's pick must be at least 70%
sure, or there are no chips. A plain "would you take this as-is?" usually
lands at 75–80% for Approve, so a higher bar dropped it. A failure, none or an empty reply also means
no chips.onEnd stores the part with the reply, like data-context.
participantVisibleParts keeps it, so the person in the chat receives it.readQuickAnswers reads the chips from a reply. visibleQuickAnswers
decides whether to draw them.QuickAnswerChips in the row just above their text
box, only when the last message is Z's:
AgentChat: the onboarding, the dashboard chats, Test agent and the
z-link;NotificationChat: Conversations and the notification cards;ChatPane: the admin playground.AgentChat also not while a card
waits for an answer, the text box is hidden or replaced (sign-up,
onboarding confirm chips), the box is locked, or the login gate is up.AgentChat the chips also wait until the newest line is in view.
Scrolling up hides them and shows a round down arrow just above the text
box ("Scroll to the latest message"). Tapping it, or scrolling back by
hand, brings the chips back. The arrow shows whenever the reader has left
the newest line, including while Z is still writing and on a reply with
no chips. The playground and the notification cards do not have this
arrow.AgentChat, handleSend, also used by a queued send,
ZLY-1992). In the playground a tap leaves a half-typed message in the box.
The person's message becomes the last one, and the chips go away.AgentChat they still wait until the newest
line is in view.Onboarding does not replace this list. It tries the canned chips first: eight question types, with their own pills, a highlighted one, and a "Z recommends" line. Jev picks the type from the reply Z just wrote. Code owns the words.
When the reply is not one of those questions, these generic sets still apply, inside the same 2 second wait. A move-on line can still get Proceed alone. A canned match does not also ask for this list. A canned miss that already used the whole wait does not start a second pick. If neither list fits, there are no pills.
The canned bar is 0.4. This list stays at 0.7. Other chats use only this list. The eight types, the reason lines, and the fallback are on the canned chips page.
| Area | File |
|---|---|
| Sets, Jev pick, stream forwarding | packages/z-agent/srv/src/quick-answers.ts |
| Onboarding question types | packages/z-agent/srv/src/onboarding-chips.ts — see Canned chips |
The quickAnswers flag and the reply stream | packages/z-agent/srv/src/rooms.ts (streamRoomChat) |
| Jev classification | packages/util-srv/src/classifyChoice.ts |
| Parts the person may receive | packages/z-agent/srv/src/participant-parts.ts |
| Reading the part, when to draw it | packages/z-agent/client/src/lib/quick-answers.ts |
| The pills | packages/z-agent/client/src/components/quick-answer-chips.tsx |
| Drawing and tapping | packages/z-agent/client/src/components/agent-chat.tsx, packages/z-agent/client/src/notification-chat.tsx, packages/z-agent/client/src/components/chat-pane.tsx |
| How often a streaming reply updates the page | packages/z-agent/client/src/lib/chat-stream.ts |
quick-answers.test.ts (the sets, Jev's pick, the time limit, the
research card, the order of the chunks), onboarding-chips.test.ts, and
participant-parts.test.ts.lib/quick-answers.test.ts (reading the part and when it shows),
components/quick-answer-chips.test.tsx (the pills and a tap),
notification-chat.test.tsx (chips streamed with a reply, a tap sends the
next message) and components/chat-pane.test.tsx (the playground).