Transition a conversation's AI mode

Change a conversation's `ai_mode` between `ai`, `human`, and `closed`. Operators use this to take over from the AI dispatcher (`ai → human`), hand back to AI (`human → ai`), or terminate (`* → closed`). `closed` is terminal — the next inbound message starts a new conversation. Idempotent: PATCHing the same `ai_mode` returns the current state with `changed: false` and does NOT publish a `conversation.mode_changed` event. Audit row written to `conversation_mode_history`; SSE subscribers (the dashboard) receive the transition in near-real-time on the `/v1/conversations/{id}/stream` channel.

Authentication

AuthorizationBearer

Bearer authentication of the form Bearer <token>, where token is your auth token.

Path parameters

conversation_idstringRequired

Request

This endpoint expects an object.
ai_modeenumRequired

Target mode for this conversation. ai — the AI dispatcher handles inbound; human — operator has taken over; closed — conversation terminated, next inbound starts a new one.

Allowed values:
reasonstringOptional<=4096 characters

Operator-provided reason; recorded in the audit log.

Response

Mode transition applied (or no-op for same-mode PATCH)

conversation_idstring
from_modeenum

The mode BEFORE this transition. Equals to_mode on no-op PATCH.

to_modeenum
changed_atdatetime
changedboolean

false for same-mode PATCH (idempotent no-op, no audit row written).

reasonstring
actorstring

Identity of the caller that initiated the transition (e.g. api:key_xxx, ai_pipeline). Recorded in the audit log even when reason is empty.

Errors

404
Set Conversation Mode Request Not Found Error
409
Set Conversation Mode Request Conflict Error