AI Control & Human Handoff
Control when the AI answers and when a human operator takes over the chat
Every chat has an AI control toggle so your client's team can let the assistant run on autopilot or step in manually whenever they need to.
The screenshot shows a conversation right after the AI invoked turnOffAiMode: the AI switch in the chat header is off, a banner reminds the operator they're replying manually, and the last message comes from a teammate.
Toggle AI mode
- Open any chat in Chats (dashboard or mobile app) and click the AI toggle — it switches immediately.
- Or via API:
PATCH /api/chats/{chatId}with{ "isUnderAiControl": false }(headerX-Access-Token: happ_your_token_here).
| State | Behavior |
|---|---|
AI On (isUnderAiControl: true) | Assistant automatically responds to new messages |
AI Off (isUnderAiControl: false) | Assistant pauses; messages wait in the dashboard for a human |
When AI is off, aiDisableReason records why:
| Reason | Description |
|---|---|
manual | A human disabled AI from the dashboard or API |
auto | The AI triggered turnOffAiMode to hand off |
insufficient_balance | The company ran out of credits; AI resumes by itself once the balance is positive |
Human handoff
The built-in turnOffAiMode tool is always available. When the AI decides it can't help, it calls the tool, isUnderAiControl is set to false, the chat surfaces in the dashboard as needing attention, and a CHAT_MODE_CHANGED WebSocket event notifies all clients. Wire up Telegram Push Notifications so the team's group is pinged on every handoff.
Guide it from the assistant prompt:
If the customer asks to speak to a human, or if you cannot resolve
their issue after 2 attempts, use the turnOffAiMode tool to transfer
the conversation to a human operator. Tell the customer that a team
member will respond shortly.Auto-resume and context window
- After an auto handoff the AI comes back by itself once the chat goes quiet. The delay is set per assistant (
aiAutoReturnDelayMinutes, 30 minutes by default). A manual disable never auto-resumes — a human has to switch it back on. - The context is a rolling window, not a fixed time slice: the assistant sees the tail of the conversation that fits the model's context budget, and everything before the last summary watermark is replaced by that summary. Older messages stay in the database and remain searchable through the built-in
searchPreviousConversationstool.
Transfer between assistants
PATCH /api/chats/{chatId} with { "assistantId": "new-assistant-uuid" }. The new assistant continues from the latest message; all history is preserved.
Message debouncing
Rapid bursts are batched: the platform waits 12 seconds of quiet after the last message before the assistant answers, and a chat whose oldest unanswered message is more than 30 seconds old is drained by a sweep that runs every minute. Customers routinely send an order in pieces, so only the completed burst triggers one reply. While an image or a voice message is still being recognised, the window is extended until the recognition lands.
WebSocket events
{
"type": "CHAT_MODE_CHANGED",
"payload": {
"chatId": "uuid",
"isUnderAiControl": false,
"aiDisableReason": "auto"
}
}Connect to wss://api.happ.tools for real-time updates.
Next
- Tools & webhook actions — how
turnOffAiModefits with other tools - Channels — where handoffs happen across messengers
- Assistants — configure who answers before handoff
Help me solve it
Happ answers right away and hands over to a manager when needed.