Quick Answer Chips

Ready-made answers above the text box, picked by Jev from a fixed list after each reply

Overview

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:

  • the onboarding (/onboarding, /onboarding/talent, /onboarding/brand, /onboarding/agency);
  • the dashboard chats: Welcome, Update agent and Launch campaign;
  • the "Z & You" side of Test agent;
  • the chat with Z inside Conversations, and the notification cards;
  • the z-link visitor chat;
  • the admin playground.

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.

Flow

The chip sets

SetWhen ZChips
approveasks to approve or reject somethingApprove, Reject
go-aheadasks for the go-ahead before acting for the person (send, accept, launch, book, delete)Proceed, Cancel
proceedasks whether to move on, or whether the person has any question before moving onProceed
confirmstates an assumption and asks to confirm itThat's Correct
skipasks an optional questionSkip
retrysays something failedRetry
okgives news or a notice to acknowledge, not a short "Got it"OK
noneanything else, such as an open question or a short acknowledgementno chips
  • The labels come from the ZLY-2019 ticket. The list lives in QUICK_ANSWER_SETS (packages/z-agent/srv/src/quick-answers.ts), and changing it needs no other change.
  • Jev picks one set, not single chips. Its choice probabilities add up to 1 across all options, so chips picked one by one would rarely clear a bar.
  • Retry and Cancel are plain messages, like the others. They do not regenerate or cancel anything.
  • Cancel only comes with Proceed before Z acts for the person. A move-on question, like the onboarding's "Do you have any question before I move on?", gets Proceed alone: a Cancel there left the interview with nothing to move on to. If someone types cancel at that question anyway, the onboarding prompt has Z say it is fine and ask the question again.
  • OK stays off short acknowledgements like "Got it", so tapping it cannot start an OK and "Got it" loop.

How it works

Server

  • The browser chat routes pass 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.
  • With the flag on, the reply text streams as it arrives (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.
  • The wait for Jev is capped at 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.
  • Every Jev call is saved, including one that picks nothing or fails, with what the call cost. A call made inside a conversation is saved with that conversation.
  • A reply that ends on a client-side tool still waiting for the person (the research card) gets no chips: the card is how they answer.
  • onEnd stores the part with the reply, like data-context. participantVisibleParts keeps it, so the person in the chat receives it.

Client

  • readQuickAnswers reads the chips from a reply. visibleQuickAnswers decides whether to draw them.
  • Three chat panels draw 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.
  • No chips while a reply is streaming. In 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.
  • A reply still appears as it is written. The page applies those updates in short batches, about every 50ms, so a long reply stays usable. Scrolling or sending the next line while it arrives does not freeze the chat.
  • In 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.
  • The text box stays on screen. It is greyed out while Z is answering, and ready again as soon as the reply has finished, even before the chips appear. Chips never grey it out. In onboarding, the box is hidden instead while a research card is open, until the person presses Done.
  • A tap sends the label through the panel's own send, the same path as typing (in 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.
  • After a reload, the stored part brings the chips back if that reply is still the last message. In AgentChat they still wait until the newest line is in view.

Onboarding questions

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.

Key files

AreaFile
Sets, Jev pick, stream forwardingpackages/z-agent/srv/src/quick-answers.ts
Onboarding question typespackages/z-agent/srv/src/onboarding-chips.ts — see Canned chips
The quickAnswers flag and the reply streampackages/z-agent/srv/src/rooms.ts (streamRoomChat)
Jev classificationpackages/util-srv/src/classifyChoice.ts
Parts the person may receivepackages/z-agent/srv/src/participant-parts.ts
Reading the part, when to draw itpackages/z-agent/client/src/lib/quick-answers.ts
The pillspackages/z-agent/client/src/components/quick-answer-chips.tsx
Drawing and tappingpackages/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 pagepackages/z-agent/client/src/lib/chat-stream.ts

Testing

  • Server: 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.
  • Client: 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).