Live Agent Escalation via Directive
This document describes how to use a custom ai12z directive to hand off a conversation to a live agent when the live chat product does not support native WebSocket or real-time API integration.
The liveAgentHandoff directive is configured in the React LLM, not the Answer AI system prompt. The React LLM has access to the full conversation history and is responsible for writing the summary and emitting the directive at the right moment.
Use this pattern when your live chat provider (e.g. LibraryH3lp, Intercom without API, or similar) does not support WebSockets or a native AI-to-agent handoff API. If your live chat platform supports WebSockets (e.g. Salesforce Live Agent, Genesys, Intercom with API), a direct WebSocket integration is the better architecture — this directive approach is the alternative for simpler or more limited systems.
How It Works
When a user asks to speak with a live person:
- The React LLM detects the escalation intent
- The React LLM writes a short summary of the conversation
- The React LLM emits a
liveAgentHandoffdirective with a JSON data payload in its response - ai12z extracts the directive and removes it from the visible response text
- The
messageReceivedevent fires withliveAgentHandoffas a structured object - Your page JavaScript opens a handoff form or launches the live chat window with context
Directive Format
The directive uses the JSON backtick format to pass a structured payload:
[directive=liveAgentHandoff data=`{
"provider": "libraryh3lp",
"formId": "live-agent-handoff",
"handoffType": "liveChat",
"studentIntent": "speak_to_human",
"summary": "Brief 1-2 sentence summary of what the user asked about and what help they need",
"lastQuestion": "The user's most recent question"
}`]
The backend extracts this directive automatically, removes it from the visible answer, and delivers it to the client as data.liveAgentHandoff.
React LLM Prompt Instructions
Add the following to your React LLM configuration:
## Live Agent Handoff Directive
When the user asks to speak with a person, live agent, admissions counselor, representative, or human, emit the following directive.
The visible response should tell the user that you are connecting them with a live person and that you are passing along context about their question.
Directive format:
[directive=liveAgentHandoff data=`{
"provider": "libraryh3lp",
"formId": "live-agent-handoff",
"handoffType": "liveChat",
"studentIntent": "speak_to_human",
"summary": "Brief 1-2 sentence summary of what the user asked about and what help they need",
"lastQuestion": "The user's most recent question"
}`]
Only use this directive when the user clearly wants a human or live chat.
Do not expose the directive text to the user.
Client-Side Handler
Your page JavaScript listens for messageReceived and acts when liveAgentHandoff is present. The handler merges the AI-generated payload with live browser context (page URL, title, referrer) that the LLM cannot reliably know.
const bot = document.querySelector("ai12z-bot")
bot.addEventListener("messageReceived", (event) => {
const data = event.detail.data
if (!data.liveAgentHandoff) return
let handoff = data.liveAgentHandoff
// The directive value may arrive as a JSON string or already-parsed object
if (typeof handoff === "string") {
try {
handoff = JSON.parse(handoff)
} catch (e) {
console.error("Invalid liveAgentHandoff directive data", e)
handoff = {}
}
}
// Merge AI payload with live browser context
const handoffPayload = {
...handoff,
pageUrl: window.location.href,
pageTitle: document.title,
browserReferrer: document.referrer,
createdAt: new Date().toISOString(),
}
openLiveAgentHandoff(handoffPayload)
})
Example Handoff Function
Once the payload is assembled, open the live chat window with the page URL as the referrer, or open your own hosted handoff form first:
function openLiveAgentHandoff(handoffPayload) {
const liveChatBaseUrl =
"https://libraryh3lp.com/chat/your-queue@chat.libraryh3lp.com"
const params = new URLSearchParams({
skin: "your-skin-id",
referer: handoffPayload.pageUrl,
})
// Option 1 — Simple: go directly to live chat with page URL as referrer
const chatUrl = `${liveChatBaseUrl}?${params.toString()}`
window.open(chatUrl, "_blank")
// Option 2 — Richer: open your own handoff form first, prefilled with context
// The agent receives the summary before the user connects to live chat.
//
// showHandoffForm({
// summary: handoffPayload.summary,
// lastQuestion: handoffPayload.lastQuestion,
// pageUrl: handoffPayload.pageUrl,
// pageTitle: handoffPayload.pageTitle,
// liveChatUrl: chatUrl
// })
}
Example Payload
This is the full object delivered to messageReceived after the client merges the AI directive data with browser context:
{
"provider": "libraryh3lp",
"formId": "live-agent-handoff",
"handoffType": "liveChat",
"studentIntent": "speak_to_human",
"summary": "The user asked about graduate admissions deadlines and wants to confirm application requirements before the fall deadline.",
"lastQuestion": "Can I speak with someone in admissions?",
"pageUrl": "https://example.edu/graduate/admissions",
"pageTitle": "Graduate Admissions | Example University",
"browserReferrer": "https://example.edu/graduate/",
"createdAt": "2026-06-23T12:00:00.000Z"
}
End-to-End Flow
User asks for a human
→ React LLM detects escalation intent
→ React LLM writes short conversation summary
→ React LLM emits [directive=liveAgentHandoff data=`{...}`]
→ ai12z removes directive from visible response text
→ User sees: "I'll connect you with a live agent and pass along your context."
→ messageReceived fires with liveAgentHandoff object
→ JavaScript merges payload with window.location.href, document.title, document.referrer
→ Handoff form opens (optional) — prefilled with summary + page URL
→ User submits or is redirected directly to live chat
→ Live agent receives page URL as referrer and/or summary context
Why the Page URL Comes from JavaScript, Not the LLM
The LLM can approximate the page URL from conversation context but cannot reliably know the exact current URL. The browser always has the authoritative value. The recommended pattern is:
- Let the React LLM generate the conversation summary and intent fields
- Let the client-side handler inject
pageUrl,pageTitle,browserReferrer, andcreatedAt
This gives you accurate page context without relying on the LLM to track navigation state.
Related Documentation
- Directives Overview — How the directive system works, custom directive format, and backend processing
- AI-Driven Bad Actor Detection — Another React LLM directive
- AI-Driven URL Navigation — Answer AI directive for page navigation