> This page is for Voice APIs.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://dev.hume.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://dev.hume.ai/_mcp/server.

# Control Plane

The EVI control plane is a configuration and orchestration API that works alongside your active Chat's data plane.
The reference Chat connection is the data plane that carries live audio and assistant responses. The control plane
lets you change how the session runs and observe it in real time, so you can update session settings, rotate provider
keys, and attach mirrors from trusted servers without exposing secrets or disrupting the live stream.

> **Tip**
>
> **Looking for sample code?** Visit our examples below to see how the control
> plane is consumed in practice.

#### [Python Example](https://github.com/HumeAI/hume-api-examples/tree/main/evi/evi-python-control-plane)

See the control plane API used to observe an active Chat in Python.

#### [Next.js Example](https://github.com/HumeAI/hume-api-examples/blob/main/evi/evi-next-js-app-router-quickstart/app/actions/set-llm-key.ts)

See the control plane implemented in our Next.js quickstart to securely set
a supplemental LLM API key.

## When to use the control plane

**Use the control plane when you:**

* Need to update an active chat without exposing secrets on the client. For example:
  * Setting a supplemental LLM API key
  * Updating the system prompt privately
* Want to mirror a chat to another service for observation, analytics, or moderation while it is running.
* Orchestrate multiple services that coordinate around a single EVI Chat session.

## Before you start

* You need an **active Chat** and its `chatId`.
* Authentication works the same as other HTTP and WSS endpoints:
  * `POST /chat/:chatId/send` expects an API key via the `X-Hume-Api-Key` header.
  * `WSS /chat/:chatId/connect` accepts an API key via header or an access token via query parameter.
* Control plane changes apply only to the chat identified by `chatId`.
* Only chats initialized with [`allow_connection`](/reference/speech-to-speech-evi/chat#request.query.allow_connection)
  can be connected to with `WSS /chat/:chatId/connect`

**Endpoints (control plane)**

<table>
  <tbody>
    <tr>
      <th width="36%">
         Endpoint 
      </th>

      <th>
         Purpose 
      </th>
    </tr>

    <tr>
      <td>
         

        `WSS /chat/:chatId/connect`

         
      </td>

      <td>
        Attach a secondary connection; receive full history on connect, then
        live events; bi-directional for non-audio
      </td>
    </tr>

    <tr>
      <td>
         

        `POST /chat/:chatId/send`

         
      </td>

      <td>
         Post messages to an active chat. 
      </td>
    </tr>
  </tbody>
</table>

> **Info**
>
> See the [API reference](/reference/speech-to-speech-evi/control-plane/send)
> for full schemas and parameter details.

## Connect to an existing chat

**Use `WSS /v0/evi/chat/:chatId/connect` to attach a secondary connection to a running Chat.**

The socket is bi-directional for non-audio (sending `audio_input` is not permitted). On connect you receive the full
session history, then live events in real time, using the same event schema as the reference Chat socket.

> **Info**
>
> You can only connect to a Chat that is *currently* active. Use the [chat history APIs](/reference/speech-to-speech-evi/chats/list-chats) to fetch
> transcripts for past sessions instead.

**Use cases**

* Observe and analyze events of an active Chat
* Complete tool use flows server-side

**See sample requests below**

#### TypeScript

```typescript maxLines=0
import { HumeClient } from "hume";

const hume = new HumeClient({ apiKey: process.env.HUME_API_KEY! });

export async function connectControlPlane(chatId: string) {
  const socket = await hume.empathicVoice.controlPlane.connect({
    chatId
  });

  // history is replayed first, then live events
  socket.on("message", (event) => {
    console.log("[control-plane]", event);
  });

  // optional lifecycle hooks
  socket.on("open", () => console.log("Control plane connected"));
  socket.on("close", () => console.log("Control plane closed"));

  return socket;
}
```

#### Python

```python maxLines=0
import os
import asyncio
from hume.client import AsyncHumeClient

client = AsyncHumeClient(api_key=os.environ["HUME_API_KEY"])

async def connect_control_plane(chat_id: str) -> None:
    async with client.empathic_voice.control_plane.connect(chat_id=chat_id) as ws:
        async for event in ws:
            print("[control-plane]", event)

# Example usage:
# asyncio.run(connect_control_plane("CHAT_ID"))
```

## Post messages to an active chat

**Use `POST /v0/evi/chat/:chatId/send` to send control messages to the active chat.**

You can send [any message type that the Chat accepts](/reference/speech-to-speech-evi/chat#send), except `audio_input`.
This includes updating session settings and any other publish messages supported by EVI.

**Use cases**

* Update the system prompt for the current session.
* Rotate or set a supplemental LLM API key server-side.
* Instruct EVI to communicate notifications from your server.

**See sample requests below**:

#### cURL

```curl maxLines=0
curl "https://api.hume.ai/v0/evi/chat/<CHAT_ID>/send" \
  -H "X-Hume-Api-Key: $HUME_API_KEY" \
  --json '{
    "type": "session_settings",
    "language_model_api_key": "<SUPPLEMENTAL_LLM_KEY>"
  }'
```

#### TypeScript

```typescript maxLines=0
import { HumeClient } from "hume";

const hume = new HumeClient({ apiKey: process.env.HUME_API_KEY! });

export async function setLlmKeyForChat(chatId: string) {
  await hume.empathicVoice.controlPlane.send(chatId, {
    type: "session_settings",
    languageModelApiKey: process.env.SUPPLEMENTAL_LLM_KEY!,
  });
}
```

#### Python

```python maxLines=0
import os
from hume import HumeClient

hume = HumeClient(api_key=os.environ["HUME_API_KEY"])

def set_llm_key_for_chat(chat_id: str) -> None:
    message = {
        "type": "session_settings",
        "language_model_api_key": os.getenv("SUPPLEMENTAL_LLM_KEY"),
    }
    hume.empathic_voice.control_plane.send(chat_id, message)
```

---