# AI Control & Human Handoff

Control when the AI answers and when a human operator takes over the chat

> Full REST + WebSocket API reference: https://api.happ.tools/reference

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.

<AiControlPageDemo />

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 [#toggle-ai-mode]

1. Open any chat in **Chats** (dashboard or mobile app) and click the **AI toggle** — it switches immediately.
2. Or via API: `PATCH /api/chats/{chatId}` with `{ "isUnderAiControl": false }` (header `X-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 [#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](/docs/integrations/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 [#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 `searchPreviousConversations` tool.

## Transfer between assistants [#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 [#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 [#websocket-events]

```json
{
  "type": "CHAT_MODE_CHANGED",
  "payload": {
    "chatId": "uuid",
    "isUnderAiControl": false,
    "aiDisableReason": "auto"
  }
}
```

Connect to `wss://api.happ.tools` for real-time updates.

**API:** [api.happ.tools/reference](https://api.happ.tools/reference)

## Next [#next]

* [Tools & webhook actions](/docs/agents/tools) — how `turnOffAiMode` fits with other tools
* [Channels](/docs/integrations/messengers) — where handoffs happen across messengers
* [Assistants](/docs/agents) — configure who answers before handoff
