> ## Documentation Index
> Fetch the complete documentation index at: https://docs-platform.crewai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Conversational Flow Chat API

> Use the deployment chat endpoints to run multi-turn conversational Flows on CrewAI AMP

## Overview

Deployed conversational Flows expose a chat session API on the automation URL. Instead of a single `/kickoff` run, you create a session, send user messages as turns, optionally stream tokens and runtime events, and resume HITL pauses when a turn needs human feedback.

<Note>
  Conversational Flow chat is **experimental**. Endpoints are available only when the deployed Flow reports both `conversational: true` and `handle_turn: true` from [`GET /inspect`](#discover-chat-capability).
</Note>

For building the Flow itself (`conversational = True`, `handle_turn`, routers, tracing), see the open-source [Conversational Flows](https://docs.crewai.com/en/guides/flows/conversational-flows) guide.

## Prerequisites

1. Deploy a Flow automation that implements conversational turns (`handle_turn`).
2. Copy the bearer token from the automation **Status** tab (same token used for `/kickoff`).
3. Confirm chat is enabled via `/inspect` (below).

All requests use:

```bash theme={null}
Authorization: Bearer YOUR_FLOW_TOKEN
```

Base URL examples in this guide use `https://your-flow-url.crewai.com`.

## Discover chat capability

```bash theme={null}
curl -X GET \
  -H "Authorization: Bearer YOUR_FLOW_TOKEN" \
  https://your-flow-url.crewai.com/inspect
```

Look for `flow.chat`:

```json theme={null}
{
  "flow": {
    "chat": {
      "conversational": true,
      "handle_turn": true,
      "transports": ["webhook"],
      "experimental": true
    }
  }
}
```

If either flag is false, chat endpoints return `404` with `"Conversational flow chat is not available"`.

## End-to-end chat loop

<Steps>
  <Step title="Start a session">
    Create a chat session. Optionally register a completed-turn webhook and event webhooks for the session lifetime.

    ```bash theme={null}
    curl -X POST \
      -H "Authorization: Bearer YOUR_FLOW_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "completedTurnWebhookUrl": "https://your-server.com/webhooks/completed-turn",
        "webhooks": {
          "url": "https://your-server.com/webhooks/events",
          "events": ["*"],
          "realtime": false,
          "authentication": {
            "strategy": "bearer",
            "token": "my-secret-token"
          }
        }
      }' \
      https://your-flow-url.crewai.com/chat/start
    ```

    Response:

    ```json theme={null}
    { "session_id": "11111111-2222-3333-4444-555555555555" }
    ```

    An empty body (`{}` or no body) is valid when you do not need webhooks.
  </Step>

  <Step title="Send a user message">
    Queue one turn for the session:

    ```bash theme={null}
    curl -X POST \
      -H "Authorization: Bearer YOUR_FLOW_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "message": "Where is my order?",
        "stream": true
      }' \
      https://your-flow-url.crewai.com/chat/11111111-2222-3333-4444-555555555555/message
    ```

    Response:

    ```json theme={null}
    {
      "session_id": "11111111-2222-3333-4444-555555555555",
      "kickoff_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
      "status": "queued"
    }
    ```

    | Field            | Description                                                                                                                                                  |
    | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | `message`        | Required. Current user line for this turn.                                                                                                                   |
    | `stream`         | Default `true`. When `true`, token/event frames are published for WebSocket/SSE clients.                                                                     |
    | `messageHistory` | Optional fallback transcript (`[{ "role", "content" }, ...]`). Server-side session history is authoritative; this is used only when stored history is empty. |

    Roles accepted in `messageHistory`: `user`, `assistant`, `system`, `tool`.
  </Step>

  <Step title="Wait for the turn to finish">
    Poll the turn with the returned `kickoff_id` (same status API as a normal Flow kickoff):

    ```bash theme={null}
    curl -X GET \
      -H "Authorization: Bearer YOUR_FLOW_TOKEN" \
      https://your-flow-url.crewai.com/status/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
    ```

    Only one turn can be active per session. A second `/message` while `active_kickoff_id` is set returns `409`:

    ```json theme={null}
    {
      "detail": {
        "code": "session_busy",
        "kickoff_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
      }
    }
    ```

    Wait until history shows `active_kickoff_id: null` (or the turn reaches a terminal status / pause) before sending the next message.
  </Step>

  <Step title="Read session history">
    ```bash theme={null}
    curl -X GET \
      -H "Authorization: Bearer YOUR_FLOW_TOKEN" \
      https://your-flow-url.crewai.com/chat/11111111-2222-3333-4444-555555555555/history
    ```

    ```json theme={null}
    {
      "session_id": "11111111-2222-3333-4444-555555555555",
      "messages": [
        { "role": "user", "content": "Where is my order?" },
        { "role": "assistant", "content": "Your order is on the way." }
      ],
      "active_kickoff_id": null
    }
    ```
  </Step>
</Steps>

## Streaming a turn

Streaming is optional. Use it when a UI needs tokens or runtime events as the turn runs. Frames always include lifecycle types (`turn_started`, `turn_completed`, `turn_failed`, `token`, `error`). Additional `event` frames can be filtered with the `events` query parameter (`*` or a comma-separated list).

### Option A: HTTP message + SSE attach

1. `POST /chat/{session_id}/message` with `"stream": true`.
2. Attach to the active turn:

```bash theme={null}
curl -N \
  -H "Authorization: Bearer YOUR_FLOW_TOKEN" \
  "https://your-flow-url.crewai.com/chat/11111111-2222-3333-4444-555555555555/stream/events?events=*&last_event_id=0-0"
```

SSE returns `text/event-stream` JSON frames (`data: {...}`), plus keepalive comments. The stream ends on `turn_completed` or `turn_failed`.

If there is no active turn, this endpoint returns `409` (`No active chat turn`).

### Option B: WebSocket (attach or send)

```text theme={null}
wss://your-flow-url.crewai.com/chat/{session_id}/stream?token=YOUR_FLOW_TOKEN&events=*&last_event_id=0-0
```

Auth: pass the bearer token as the `token` query param, or as an `Authorization: Bearer ...` header when your client supports WebSocket headers.

Behavior:

* **Active turn already running** — the socket attaches and first emits `turn_started` with `data.status: "attached"`, then streams frames until a terminal type.
* **No active turn** — send a JSON message to queue a turn, then consume the stream:

```json theme={null}
{
  "message": "Where is my order?",
  "messageHistory": [],
  "events": "*",
  "lastEventId": "0-0"
}
```

The server responds with `turn_started` (`status: "queued"`) and then stream frames for that `kickoff_id`.

Use `last_event_id` / `lastEventId` to resume after disconnects.

### Example stream frames

```json theme={null}
{
  "type": "turn_started",
  "kickoff_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "session_id": "11111111-2222-3333-4444-555555555555",
  "data": { "status": "queued" }
}
```

```json theme={null}
{
  "type": "token",
  "kickoff_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "session_id": "11111111-2222-3333-4444-555555555555",
  "data": { "content": "Your order" }
}
```

```json theme={null}
{
  "type": "turn_completed",
  "kickoff_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "session_id": "11111111-2222-3333-4444-555555555555",
  "data": {}
}
```

## HITL inside a chat session

If a turn pauses for human feedback (`status` / state `PAUSED`), resume with the same Flow resume endpoint used for non-chat runs:

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer YOUR_FLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "flow_id": "FLOW_OR_SESSION_ID",
    "feedback": "approved"
  }' \
  https://your-flow-url.crewai.com/resume_feedback
```

Then poll the resume `kickoff_id` from the response. Wait until `/history` shows `active_kickoff_id: null` before sending the next chat message.

See [HITL Workflows](/platform/en/guides/human-in-the-loop) and [Flow HITL Management](/platform/en/features/flow-hitl-management) for platform review UX.

## API reference

| Method | Path                               | Purpose                                         |
| ------ | ---------------------------------- | ----------------------------------------------- |
| `GET`  | `/inspect`                         | Discover whether conversational chat is enabled |
| `POST` | `/chat/start`                      | Create a chat session                           |
| `POST` | `/chat/{session_id}/message`       | Queue a user turn                               |
| `GET`  | `/chat/{session_id}/history`       | Read messages and active turn id                |
| `GET`  | `/chat/{session_id}/stream/events` | SSE stream for the active turn                  |
| `WS`   | `/chat/{session_id}/stream`        | WebSocket stream (attach or send + stream)      |
| `GET`  | `/status/{kickoff_id}`             | Poll turn (or resume) execution status          |
| `POST` | `/resume_feedback`                 | Resume a paused HITL turn                       |

### Common errors

| Status | When                                                                                   |
| ------ | -------------------------------------------------------------------------------------- |
| `400`  | Empty `message`                                                                        |
| `404`  | Chat not enabled on this deployment, or unknown `session_id`                           |
| `409`  | Session already has an active turn (`session_busy`), or SSE attach with no active turn |
| `422`  | `session_id` is not a valid UUID                                                       |
| `503`  | Chat session or stream storage unavailable                                             |

## Related

<CardGroup cols={2}>
  <Card title="Conversational Flows" href="https://docs.crewai.com/en/guides/flows/conversational-flows" icon="comments">
    Build multi-turn Flows with `handle_turn`, routers, and tracing.
  </Card>

  <Card title="Kickoff Crew / Flow" href="/platform/en/guides/kickoff-crew" icon="flag-checkered">
    Single-run kickoff and status polling on a deployment URL.
  </Card>

  <Card title="Webhook Streaming" href="/platform/en/features/webhook-streaming" icon="webhook">
    Event webhook payload shape and authentication options.
  </Card>

  <Card title="Flow HITL Management" href="/platform/en/features/flow-hitl-management" icon="users-gear">
    Email-first human review for paused Flow steps.
  </Card>
</CardGroup>
