TL;DR: A website chat agent looks like the easy sibling of a voice agent, and half of that is true. There is no latency budget worth the name, no telephony, no barge in, and the visitor types their own email address correctly. The other half is that every voice instinct you carry across is wrong. A visitor does not hang up, they leave, so there is no clean end to build the pipeline around. There is no transfer button, so a handoff is a written promise the back half has to keep. The agent can show things instead of saying them, and abuse costs the attacker nothing. I have built chat agents next to voice agents at Tested Media and Fortell AI. Here is what I change on the chat side.
The chat agent usually arrives as an afterthought. A client commissions a voice agent, sees it work, and asks whether "the same thing" can sit on the website. Technically, yes. At Tested Media the voice and chat agents for CallSetter AI were both built on Retell with GoHighLevel as the CRM, and at Fortell AI the chat agents for clinics, estate agents and garages ran against the same knowledge and tools as the phone lines. I have already written about which channel to build first. This is about what is different once you have decided to build the chat one, because "the same thing on the website" is exactly the phrase that produces a bad chat agent.
A chat agent worth deploying is the same four layers as a voice agent: front end, knowledge, tools, and a back half that turns the conversation into a lead, a booking or a task. The pipeline is shared. What changes is which layers are hard, and the answer is nearly the inverse of voice.
What chat gets for free
- Latency stops being the product. A caller listens to every millisecond of silence. A visitor sees a typing indicator. You can afford a larger model, a second retrieval pass, or a validation step before the answer goes out, none of which fit inside a phone turn.
- Turn taking disappears. No endpointing to tune, no background noise to fight.
- Identifiers arrive exact. An email address, a postcode, a registration plate: typed, not heard. The confirmation loop I build for capturing details on a phone line collapses to one shape check for typos.
- The conversation can pause. A visitor can reply an hour later without losing the thread. On a phone that is a dropped call.
The visitor does not hang up, they leave
A phone call has an end. The hangup is an event, and everything downstream hangs off it. The post call layer fails often enough, but at least it has a trigger.
A chat session has no such event. The visitor asks a question, gets the answer, switches tab, closes the laptop. There is no moment at which the conversation is over, only a moment at which you decide to treat it as over. That one fact reshapes the build.
The pipeline fires on idle, not on end. Pick an idle window, a few minutes for the lead record and longer for the summary, and make every write idempotent, because the visitor will come back after the pipeline has already run. A returning visitor updates the record. They never create a second one.
Ask for the contact detail at the first moment you need it, not before. The gate first widget, "enter your email to start chatting", kills engagement, and the never ask agent produces anonymous transcripts the client cannot act on. Answer the first question fully, then ask for a name and an email or mobile number at the point where the agent needs it to do something for the visitor: send the quote, hold the slot, have someone reply. Framed as the price of a specific service, people give it. Framed as a login, they leave.
Persist the session and offer a way back. A returning visitor should see their own thread, and a resume link by SMS or email turns a leave into a return.
Decide what counts as a conversation before launch. A page load that opened the widget is not one. Define the denominator first, or the dashboard will flatter you for months.
There is no transfer button
On a phone, escalation can mean a live transfer to a person right now, and the three exits are the spine of the design. In chat there is usually nobody at a live console, and there is definitely nobody at 11pm, which is exactly when the visitors are there.
So a chat handoff is a different object: a task in the CRM with a due time, a notification to a real person's phone, and a sentence to the visitor that says honestly when a human will reply and through which channel. "Someone will be in touch shortly" is the chat equivalent of the perfect call where nothing happened afterwards, and it is worse, because it was written down. GoHighLevel handles this well as the system of record, because the task, the contact and the transcript land in one place.
Office hours and after hours want different promises: a short reply time during the day, an honest "tomorrow morning" after it. And for anything urgent, a vet clinic or a garage with a breakdown line, chat must never be the emergency path. The right answer is a phone number the visitor can tap, because chat cannot transfer and should not pretend to.
The agent can show things
Voice must say. Chat can show. Most builds miss this because the prompt was copied from the phone agent.
Write for the screen, not the ear. Everything in writing prompts for speech inverts. A warm two sentence preamble that sounds natural on a phone reads as padding on a mobile screen. Short lines, a link where a link answers the question, and the answer in the first line.
Do not recite the website. The visitor has read the page. If the answer is the pricing page paraphrased, it has added nothing. Summarise in a line and link to it.
Offer finite choices as buttons. Three appointment slots as buttons remove both the typo and the model's discretion over what to display. Same principle as shaping a tool result for the mouth in the function calling layer, here for a thumb.
Buttons are not a menu: free text stays available at every step.
The knowledge layer carries more of the load
Visitors ask questions callers do not. Callers ring to book, to reschedule, to ask if the car is ready. Visitors ask how much, how long, whether you do the thing at all, where to park. They are earlier in the funnel, so the knowledge layer does more of the conversion work.
The website is the obvious source and the wrong one, because the visitor already read it. The useful knowledge is what the site does not say: the rough price range the receptionist quotes on the phone, what to bring to a first appointment, the honest answer to "how quickly". That is the content a staleness rule has to own, and the client has never written it down, so budget the time to extract it.
One thing is easier in writing: a refusal with a link is a fine answer. "I can't quote that here, but this page has the ranges" reads as competent in a chat window. Spoken, it sounds like a dodge.
Abuse is free
A caller pays for the call with their own time. A script pays nothing. The widget is a public endpoint that spends your tokens and calls your tools, and bots will find it.
What sits in front of every chat agent I ship: rate limits per session and per address, a cap on message length, a daily spend ceiling that degrades into "please email us" rather than a blank widget, and no write capable tool, booking or CRM update, until a contact detail has been captured. For anything consequential, a one time code by SMS or email before the write. Pasted text is untrusted, always. The risk lives in the capability list, not the prompt, and on a public widget that list should be shorter than on the phone line. Assume the prompt is public and keep nothing in it you would not put on the website.
Keep it one pipeline
The visitor who chats at 11pm and calls at 9am is one person. The only thing that merges them is the typed email or mobile number matching the record the phone agent captured. Same CRM, same definition of a qualified lead, same n8n workflows behind both doors. At Tested Media the client watched voice and chat as one feed, and that only worked because the definitions were shared before either channel launched.
The widget is part of your website
The website is the acquisition channel. A widget script that loads synchronously on every page costs the page speed that brought the visitor there. Load it deferred, after the page is interactive, and measure Core Web Vitals before and after installing it. Then test on a mid range phone with the keyboard open, because an input box that scrolls off screen ends the conversation.
The build order I use
- Pull the top ten questions from the contact form, site search and, if a voice agent exists, the phone transcripts.
- Build the knowledge layer first, with the answers the website does not give.
- Design the capture moment: which service earns the email, and how the agent asks.
- Wire the handoff as a CRM task with a promised reply time, then test that a human keeps the promise.
- Add booking as buttons over the same calendar tool the phone agent uses.
- Put the abuse limits in front before the widget goes on a public page.
- Embed it deferred and check page speed.
- Freeze a regression set of typed conversations, including pasted junk, a visitor who leaves halfway, and one who comes back the next day.
- Report engaged sessions, captured leads, bookings, and the drop off at the capture step.
"The same thing on the website" is right about the pipeline and wrong about everything the visitor touches. Keep the back half shared, and rebuild the front for a person who types, leaves, comes back, and expects to see an answer rather than hear one.
I build voice and chat AI agents for founders across the US, UK and Europe, wired into one pipeline so the phone call and the website visitor land in the same place. More about my work here, or book a call.