# Stream an AI chat response (agent or task-editor mode)

> Source: https://docs.clonepartner.com/api-reference/ai/post-ai-chat/

`POST /api/ai/chat`

Stream an AI chat response (agent or task-editor mode)

**Operation ID:** `postAiChat`

## Authentication

### Option 1

- **BearerAuth** (`http bearer`)
  API key token. Create via POST /api/api-keys. Format: `envoy_<hex>`

### Option 2

- **CookieAuth** (`apiKey`)
  Session cookie set after login + TOTP verification

## Request body

The request body is required.

### `application/json`

- Type: `object`
- Properties:
  - `conversation_id` (`integer`)
  - `message` (`string`)
  - `messages` (`array<object>`)
    - Items:
      - Type: `object`
      - Properties:
        - `role` (`string`, `required`) — Request body roles are user/assistant only. Persisted conversation history may also contain role=summary rows from auto-compaction.
          - Description: Request body roles are user/assistant only. Persisted conversation history may also contain role=summary rows from auto-compaction.
          - Allowed values: `user`, `assistant`
        - `content` (`string | array<object>`, `required`)
          - One of:
            - Variant 1:
              - Type: `string`
            - Variant 2:
              - Type: `array<object>`
              - Items:
                - Type: `object`
  - `route_context` (`string`)
  - `references` (`array<object>`) — User-staged entity references (composer @-mentions / Add to chat). Invalid entries are ignored.
    - Description: User-staged entity references (composer @-mentions / Add to chat). Invalid entries are ignored.
    - Maximum items: 10
    - Items:
      - Type: `object`
      - Properties:
        - `type` (`string`, `required`)
          - Allowed values: `task`, `job`, `job_template`, `connector`, `trigger`, `dashboard`, `run`, `job_run`, `reference`, `account`
        - `id` (`string`, `required`)
        - `label` (`string`)
        - `connector_id` (`integer`) — Owning connector (account references only)
        - `integration` (`string`) — Integration slug (account references only)
  - `mode` (`string`)
    - Allowed values: `agent`, `task-editor`
  - `editor_kind` (`string`) — Which YAML editor is active when current_yaml is sent
    - Description: Which YAML editor is active when current_yaml is sent
    - Allowed values: `task`, `dashboard`
  - `connector_ids` (`array<integer>`)
    - Items:
      - Type: `integer`
  - `current_yaml` (`string`)
  - `model` (`string`) — Per-request model override. Must be one of the ids from GET /api/ai/status `models`; requests with an unknown model are rejected with 400.
  - `approvals` (`array<object>`)
    - Items:
      - Type: `object`
      - Properties:
        - `tool_use_id` (`string`)
        - `decision` (`string`)
          - Allowed values: `approved`, `rejected`
        - `method` (`string`)
        - `path` (`string`)

## Success responses

### 200

SSE stream events: text, thinking, thinking_signature, tool_call_start
(name + tool_use_id, emitted when the model opens a tool_use block and
its args are still being generated — lets the client show an in-progress
card immediately), tool_call,
tool_result, pending_approval, navigate, resource, title, conversation,
compaction (status start|done|skipped; done includes message_id + summary),
usage (context_tokens + context_window after each model response — drives
the UI context meter), done, error. The internal turns event is not
forwarded to the client.

**Content type:** `text/event-stream`

- Type: `string`

## Error responses

### 400

Validation error


### 501

AI not configured


## Examples

### cURL

```bash
curl --request POST \
  --url 'https://your-envoy.example.com/api/ai/chat' \
  --header 'Authorization: Bearer $API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "conversation_id": 0,
  "message": "string",
  "messages": [
    {
      "role": "user",
      "content": "string"
    }
  ],
  "route_context": "string",
  "references": [
    {
      "type": "task",
      "id": "string"
    }
  ]
}'
```

### JavaScript (fetch)

```javascript
const response = await fetch('https://your-envoy.example.com/api/ai/chat', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "conversation_id": 0,
    "message": "string",
    "messages": [
      {
        "role": "user",
        "content": "string"
      }
    ],
    "route_context": "string",
    "references": [
      {
        "type": "task",
        "id": "string"
      }
    ]
  }),
});

if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const data = response.status === 204 ? null : await response.json();
console.log(data);
```
