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

# Instrucciones de integración de AI Chat v2 API

> AI Dialogue API guide - Ace Data Cloud

AI Chat v2 API (`/aichat2/conversations`) es la nueva generación de interfaz de conversación, y es una versión completamente mejorada de [AI Chat API](https://platform.acedata.cloud/documents/aichat-conversations). Sobre la base de la simplicidad y las conversaciones multivuelta alojadas de v1, amplía:

* **Entrada de usuario multimodal**: mediante el campo estructurado `message`, envía directamente bloques de texto + imágenes + archivos, sin necesidad de adjuntarlos indirectamente primero mediante `references`.
* **Llamada de herramientas con agentes**: integra un conjunto de herramientas como búsqueda en internet, extracción de páginas web, lectura de archivos, etc., y puede montar servidores MCP autorizados por el usuario (Google Drive, Notion, Slack, GitHub, etc.); el modelo puede llamar autónomamente a herramientas varias veces en una sola solicitud para completar tareas complejas.
* **Eventos de streaming estructurados**: mediante `accept: text/event-stream` o `application/x-ndjson`, se pueden obtener eventos como `text_delta`, `tool_use`, `tool_result`, `thinking`, `citation`, `card`, `artifact`, etc., token por token, lo que facilita renderizarlos por separado en el frontend según el tipo correspondiente.
* **Interrumpible / reanudable**: cuando el modelo necesita que el usuario complemente información, emitirá un evento `ask_user_question` y se pausará; en la siguiente llamada, basta con rellenar la respuesta mediante `tool_results` para continuar.
* **Nuevas acciones CRUD**: en el mismo endpoint, completa `retrieve` / `retrieve_batch` / `update` / `delete` mediante el campo `action`, sin necesidad de una API adicional de gestión de conversaciones.
* **Lista de modelos en actualización continua**: por defecto integra modelos contemporáneos como GPT-5.4, Claude Opus 4.8, Claude Sonnet 4.6, Gemini 3.1 Pro, GLM 5.1, DeepSeek V4, Kimi K3, etc.

Al mismo tiempo, a nivel de cuerpo de solicitud es **totalmente compatible hacia atrás con v1**: pasando únicamente `model` + `question` (+ opcionalmente `stateful` / `id` / `references` / `preset`) se puede obtener una respuesta JSON `{answer, id}` equivalente a v1; por lo tanto, para migrar desde `/aichat/conversations` no es necesario reescribir el cliente, solo hay que cambiar la ruta a `/aichat2/conversations`.

> Si actualmente utilizas `/aichat/conversations`, la antigua interfaz seguirá prestando servicio y puedes migrar a tu propio ritmo.

## Proceso de solicitud

Para utilizar AI Chat v2 API, primero obtén tu API Token en la [consola de Ace Data Cloud](https://platform.acedata.cloud/console/applications) y guárdalo como respaldo.

![](https://cdn.acedata.cloud/dvc3cg.jpg)

Si aún no has iniciado sesión ni te has registrado, se te redirigirá automáticamente a la página de inicio de sesión para invitarte a registrarte e iniciar sesión; al completarlo, volverás automáticamente a la página actual.

**Un solo API Token permite llamar a todos los servicios de la plataforma, sin necesidad de solicitar uno por separado para cada servicio.** La primera solicitud incluye crédito gratuito, lo que permite probarlo sin coste; cuando el crédito sea insuficiente, puedes recargar saldo general en la [consola](https://platform.acedata.cloud/console/coin).

> 📘 Documentación completa: [AI Chat v2 API →](https://platform.acedata.cloud/documents/aichat2-conversations)

## Uso básico

El uso más sencillo es exactamente igual que v1: pasa `model` + `question` y obtén `{answer, id}`.

Ejemplo de CURL:

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "question": "用一句话介绍下 AceDataCloud。"
  }'
```

Resultado devuelto:

```json theme={null}
{
  "answer": "AceDataCloud 是一个聚合主流 AI 模型与多模态服务的统一 API 平台，开发者通过一个密钥即可调用 GPT、Claude、Gemini、Midjourney、Suno、Veo 等多家服务。",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Ejemplo de Python:

```python theme={null}
import requests

url = "https://api.acedata.cloud/aichat2/conversations"

headers = {
    "accept": "application/json",
    "authorization": "Bearer {token}",
    "content-type": "application/json",
}

payload = {
    "model": "gpt-5.4",
    "question": "用一句话介绍下 AceDataCloud。",
}

response = requests.post(url, json=payload, headers=headers)
print(response.json())
```

Los valores disponibles para `model` pueden verse directamente en el menú desplegable del panel Try de la derecha; las categorías comunes incluyen:

* OpenAI: `gpt-5.4-mini`, `gpt-5.4-nano`, `gpt-5.2-pro`, `gpt-5.1-all`, `gpt-5-all`, `gpt-4.1`, `gpt-4o`, `gpt-4o-image`, `o3`, `o4-mini`, etc.
* Anthropic: `claude-opus-4-8`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-opus-4-5-20251101`, `claude-sonnet-4-6`, `claude-sonnet-4-5-20250929`, `claude-haiku-4-5-20251001`, etc.
* Google: `gemini-3.1-pro-preview`, `gemini-3.1-pro-preview`, `gemini-3.1-flash-image`, `gemini-3.1-pro-preview`, `gemini-2.5-flash-lite`, etc.
* xAI: `grok-4`, etc.
* DeepSeek: `deepseek-v4-pro`, `deepseek-v4.1-flash`, `deepseek-v4-flash`, `deepseek-v3.2-exp`, `deepseek-r1-0528`, etc.
* Moonshot: `kimi-k3`, `kimi-k2.6`, `kimi-k2.5`, etc.
* Zhipu: `glm-5.3`, `glm-5.2`, `glm-5.1`, `glm-5`, `glm-5-turbo`, `glm-4.7`, `glm-4.5v`, etc.

Para las reglas de facturación específicas, consulta la tarjeta Pricing de la página del servicio.

## Conversación multivuelta

Al igual que en v1, pasa `stateful: true` para activar el guardado de la conversación; la API devolverá un `id`; en solicitudes posteriores, basta con incluir de nuevo el `id` para continuar la conversación, sin necesidad de mantener tú mismo el historial de messages.

Primera solicitud:

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "stateful": true,
    "question": "记住一个数字：42。"
  }'
```

Devuelve:

```json theme={null}
{
  "answer": "好的，我已经记住了 42。需要我用它做什么吗？",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Segunda solicitud, incluye el mismo `id`:

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "stateful": true,
    "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
    "question": "我刚才让你记住的数字是多少？"
  }'
```

```json theme={null}
{
  "answer": "你让我记住的数字是 42。",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

> `stateful` es `true` de forma predeterminada; omitirlo es equivalente a pasar explícitamente `true`. Si no deseas que el servidor guarde esta ronda de conversación, puedes establecer explícitamente `stateful: false`.

## Respuesta en streaming

v2 admite dos formatos de streaming, seleccionados según la cabecera `accept`:

| Escenario                                      | `accept`                           | Forma de los datos                                        |
| ---------------------------------------------- | ---------------------------------- | --------------------------------------------------------- |
| Frontend web / EventSource                     | `text/event-stream`                | `data: {json}\n\n`, la última línea es `data: [DONE]\n\n` |
| Servidor / CLI / análisis de streaming de Node | `application/x-ndjson`             | Un objeto JSON por línea                                  |
| No se necesita streaming                       | `application/json`（predeterminado） | Devuelve `{answer, id}` de una sola vez                   |

### Ejemplo de NDJSON

```python theme={null}
import json
import requests

url = "https://api.acedata.cloud/aichat2/conversations"

headers = {
    "accept": "application/x-ndjson",
    "authorization": "Bearer {token}",
    "content-type": "application/json",
}

payload = {
    "model": "gpt-5.4",
    "stateful": True,
    "question": "用三句话介绍杭州。",
}

with requests.post(url, json=payload, headers=headers, stream=True) as resp:
    answer = ""
    for line in resp.iter_lines():
        if not line:
            continue
        event = json.loads(line)
        if event.get("type") == "text_delta":
            # 与 v1 兼容：增量片段同时通过 delta_answer 字段提供
            answer += event["content"]
            print(event["delta_answer"], end="", flush=True)
        elif event.get("type") == "done":
            print()
            print("usage =", event.get("usage"))
```

Cada línea de NDJSON es un evento estructurado; el más común es `text_delta`:

```json theme={null}
{"type":"text_delta","content":"杭","delta_answer":"杭","id":"f2f4b3e8-..."}
{"type":"text_delta","content":"州","delta_answer":"州","id":"f2f4b3e8-..."}
{"type":"text_delta","content":"是","delta_answer":"是","id":"f2f4b3e8-..."}
...
{"type":"done","conversation_id":"f2f4b3e8-...","usage":{"prompt_tokens":21,"completion_tokens":58,"total_tokens":79},"terminal_reason":"natural_stop"}
```

### Ejemplo de SSE

El uso de `EventSource` en el navegador no admite cuerpos de solicitud personalizados; se recomienda usar `fetch` + análisis manual por segmentos de `\n\n`:

```javascript theme={null}
const resp = await fetch("https://api.acedata.cloud/aichat2/conversations", {
  method: "POST",
  headers: {
    accept: "text/event-stream",
    authorization: "Bearer {token}",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    model: "gpt-5.4",
    stateful: true,
    question: "用三句话介绍杭州。",
  }),
});

const reader = resp.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const blocks = buffer.split("\n\n");
  buffer = blocks.pop() ?? "";
  for (const block of blocks) {
    const dataLine = block.split("\n").find((l) => l.startsWith("data: "));
    if (!dataLine) continue;
    const payload = dataLine.slice(6);
    if (payload === "[DONE]") return;
    const event = JSON.parse(payload);
    if (event.type === "text_delta") process.stdout.write(event.content);
  }
}
```

### Tipos de eventos de streaming

| `type`              | Significado                                                                                                                                                                                                           |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text_delta`        | Fragmento de texto incremental de la respuesta del asistente. `content` es el contenido nuevo; para ser compatible con v1, el mismo evento también incluye `delta_answer` (igual a `content`) e `id`.                 |
| `thinking`          | El proceso de razonamiento del modelo (solo aparece cuando el modelo seleccionado expone reasoning).                                                                                                                  |
| `tool_use`          | El modelo decide llamar a una herramienta; el evento incluye `tool_id`, `tool_name`, `input`.                                                                                                                         |
| `tool_result`       | Resultado de la ejecución de la herramienta; se empareja con el `tool_use` anterior mediante `tool_id`, y `is_error` indica si falló.                                                                                 |
| `card`              | Tarjeta estructurada producida por una herramienta (como una imagen o una vista previa de enlace), apta para renderizarse directamente.                                                                               |
| `citation`          | Se utiliza para complementar la URL de la fuente citada del fragmento de texto correspondiente.                                                                                                                       |
| `ask_user_question` | Se emite cuando el modelo necesita que el usuario proporcione información adicional; la conversación entra en el estado `awaiting_user_input`. Consulta a continuación [reanudar una conversación pausada](#恢复暂停的对话). |
| `artifact`          | Producto independiente generado por el modelo (como un bloque de código o documento), que puede guardarse o descargarse.                                                                                              |
| `system_message`    | Información de aviso del sistema (no contenido del usuario ni del asistente), solo para avisos de UI.                                                                                                                 |
| `compact`           | Evento en el que se comprime el contexto interno; no requiere un tratamiento especial.                                                                                                                                |
| `error`             | Se produjo un error en esta ronda; `message` describe el contenido del error.                                                                                                                                         |
| `done`              | Finaliza la respuesta en streaming; incluye `usage` (con `prompt_tokens` / `completion_tokens` / `total_tokens`) y `terminal_reason`.                                                                                 |

Para los clientes que solo se preocupan por la respuesta final, concatenar el `content` de todos los `text_delta` equivale a `answer` en el modo `application/json`.

## Entrada multimodal

Si la entrada del usuario incluye imágenes o archivos, pasa `message` (un array) en lugar de `question`. Cada elemento del array es un bloque de contenido:

```json theme={null}
{
  "model": "gpt-5.4",
  "stateful": true,
  "message": [
    { "type": "text", "text": "这张图片里有几只猫？" },
    { "type": "image_url", "image_url": { "url": "https://cdn.acedata.cloud/cats.jpg" } }
  ]
}
```

Tipos de bloques compatibles:

* `text` — Texto normal; el campo `text` es obligatorio.
* `image_url` — Imagen; `image_url.url` es obligatorio.
* `file_url` — Archivo (PDF, CSV, TXT, etc.); `file_url.url` es obligatorio.

### Relación con `references` de v1

Para ser compatible con clientes antiguos, v2 sigue reconociendo el campo `references: ["https://...", ...]`:

* Si el sufijo de la URL es `jpg / jpeg / png / gif / bmp / webp / svg / heic / heif`, se convierte automáticamente en un bloque `image_url`;
* Otras extensiones se convierten en un bloque `file_url`;
* Si también se proporciona `question`, se antepone como un bloque `text`.

Por lo tanto, si solo quieres migrar desde v1 y no quieres modificar el cuerpo de la solicitud, basta con cambiar la ruta a `/aichat2/conversations`, y el uso original de `references` seguirá funcionando normalmente.

Si necesitas un control más preciso (por ejemplo, colocar varias imágenes entre textos, o si el orden es muy importante), usa directamente el array `message`.

## Llamadas a herramientas y MCP

La mejora principal de v2 es que el modelo puede llamar autónomamente a herramientas para completar tareas de varios pasos, **esto está habilitado de forma predeterminada**, y no requiere que el cliente haga ninguna configuración adicional en la solicitud. Escenarios comunes:

* El usuario pregunta «Ayúdame a buscar qué nuevas exposiciones hay recientemente en Shanghái» → el modelo llama a la búsqueda web integrada → organiza los resultados en una respuesta.
* El usuario pregunta «Lee este PDF y luego escribe un resumen» → el modelo llama a file\_read → escribe un resumen.
* El usuario ya ha autorizado Google Drive / GitHub / Notion, etc. en [Connections](https://platform.acedata.cloud/connections) → el modelo puede llamar a las herramientas MCP correspondientes para leer y escribir sus datos.

En el flujo NDJSON / SSE, las llamadas a herramientas se presentan mediante dos tipos de eventos: `tool_use` y `tool_result`, por ejemplo:

```json theme={null}
{"type":"tool_use","tool_id":"toolu_01ABCDEF","tool_name":"web_search","input":{"query":"上海 2026 春季展览"},"id":"f2f4b3e8-..."}
{"type":"tool_result","tool_id":"toolu_01ABCDEF","output":"...","is_error":false,"id":"f2f4b3e8-..."}
{"type":"text_delta","content":"目前","delta_answer":"目前","id":"f2f4b3e8-..."}
{"type":"text_delta","content":"上海","delta_answer":"上海","id":"f2f4b3e8-..."}
...
```

Si no quieres mostrar los detalles de las llamadas a herramientas en el frontend, basta con ignorar estos tipos de eventos: `tool_use` / `tool_result` / `card` / `citation`; la salida final del modelo seguirá fluyendo a través de `text_delta`.

`max_turns` puede limitar el máximo de rondas en que el modelo puede llamarse a sí mismo mediante herramientas en esta solicitud; el límite predeterminado lo determina la plataforma. Establecerlo bajo (por ejemplo, `max_turns: 1`) puede forzar una respuesta única y no permitir ninguna llamada a herramientas.

## Ejecución asíncrona y autorización sin supervisión

Si tu llamada proviene de un Webhook de alertas, CI/CD, sistema de monitorización u otras tareas de backend, puedes establecer `async: true` para que la interfaz devuelva inmediatamente un ID de tarea y continúe ejecutándose en segundo plano:

```json theme={null}
{
  "model": "gpt-5.5",
  "async": true,
  "question": "我的服务报警了，用个人微信通知微信群「AceDataCloud团队」……"
}
```

Ejemplo de respuesta:

```json theme={null}
{
  "task_id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "conversation_id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "status": "queued"
}
```

Después, puedes usar `action: retrieve` + `id` para consultar el resultado de la conversación; también puedes proporcionar `callback_url`, y cuando la tarea se complete, la plataforma hará POST de `{ status, answer, usage, error }` a tu dirección de callback. `callback_url` debe usar `http` / `https`, y no puede indicar directamente `localhost` ni una dirección literal de IP privada.

Normalmente no hay nadie que pueda hacer clic para confirmar las tareas en segundo plano. Si deseas que ciertos Skill o MCP Server ejecuten acciones como enviar, publicar o escribir en modo sin supervisión, pasa explícitamente una lista de preautorización en el cuerpo de la solicitud:

```json theme={null}
{
  "model": "gpt-5.5",
  "async": true,
  "allowed_skills": ["acedatacloud/personal-wechat"],
  "allowed_mcp_servers": [],
  "question": "我的服务报警了，用个人微信通知微信群「AceDataCloud团队」……"
}
```

Los valores en `allowed_skills` son los slug de los Skill conectados; los valores en `allowed_mcp_servers` son los slug de los MCP Server conectados. Los Skill / MCP Server que no estén incluidos en la preautorización en modo sin supervisión solo podrán seguir previsualizando, hacer dry-run o rechazar operaciones de escritura.

Si necesitas un control más granular, también puedes usar el objeto equivalente `unattended_policy`:

```json theme={null}
{
  "unattended_policy": {
    "allowed_skills": ["acedatacloud/personal-wechat"],
    "allowed_mcp_servers": [],
    "expires_at": 1790000000
  }
}
```

La preautorización son estas dos listas en sí mismas: una lista vacía significa que no se autoriza ninguna capacidad, sin necesidad de campos de activación adicionales.

Nota: la preautorización solo significa «esta solicitud permite que estas capacidades omitan la confirmación humana en modo sin supervisión». El Skill concreto debe seguir admitiendo `--unattended-confirm` o el mecanismo de seguridad correspondiente; de lo contrario, seguirá haciendo dry-run y no ejecutará directamente operaciones de escritura.

## Reanudar conversaciones pausadas

Algunas herramientas hacen que el modelo «vuelva a preguntar al usuario»; en ese momento, el modelo emitirá un evento `ask_user_question`, y la conversación quedará congelada en el estado `awaiting_user_input`:

```json theme={null}
{
  "type": "ask_user_question",
  "tool_id": "toolu_01XYZW",
  "tool_name": "ask_user_question",
  "question": "你希望生成的报告是中文还是英文？",
  "options": ["中文", "英文"],
  "id": "f2f4b3e8-..."
}
```

En el frontend, renderiza este evento como una tarjeta para que el usuario elija una respuesta y, a continuación, inicia la siguiente solicitud con el mismo `id`, rellenando la respuesta mediante `tool_results`:

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: text/event-stream' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "model": "gpt-5.4",
    "stateful": true,
    "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
    "tool_results": [
      {
        "tool_use_id": "toolu_01XYZW",
        "output": "中文"
      }
    ]
  }'
```

El `tool_use_id` en el cuerpo de la solicitud **debe** ser exactamente igual al `tool_id` del momento de la pausa; si no coincide, devolverá 400. Cuando `tool_results` existe simultáneamente en la solicitud, `question` / `message` / `references` se ignorarán todos.

Si el usuario decide abandonar esta pregunta, basta con pasar un nuevo `question` / `message`, y la plataforma marcará automáticamente la llamada a herramienta pausada como «omitida por el usuario».

## Gestión de conversaciones (CRUD)

v2 proporciona una gestión ligera de conversaciones mediante el campo `action` en el mismo endpoint, sin necesidad de abrir otra API.

### `action: retrieve` —— Obtener una conversación

```shell theme={null}
curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "action": "retrieve",
    "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
  }'
```

Devuelve el documento completo de la conversación (incluye el historial de `messages`, `model`, `title`, `tools_used`, etc.).

### `action: retrieve_batch` —— Listar resúmenes de conversaciones

```json theme={null}
{
  "action": "retrieve_batch",
  "model_group": "chatgpt",
  "limit": 20,
  "offset": 0
}
```

Devuelve `{ items: [...], total }`. **Los resúmenes no incluyen `messages`**, son adecuados para listas de barra lateral; si el usuario abre una conversación, use después `action: retrieve` para obtener por separado sus mensajes completos.

Parámetros de filtrado opcionales: `user_id`, `application_id`, `model_group`, `model`.

### `action: update` —— Cambiar el título o reescribir el historial

```json theme={null}
{
  "action": "update",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44",
  "title": "Plan de viaje a Hangzhou"
}
```

También se puede pasar `messages`, pero el servidor realizará una validación estricta del schema (debe tener la forma de `ToolUseContent` contraída); si no cumple, devolverá 400. Por lo general, solo se recomienda usarlo para cambiar `title`.

### `action: delete` —— Eliminar una conversación

```json theme={null}
{
  "action": "delete",
  "id": "f2f4b3e8-0c0a-4d3a-aaa2-7ff80c0a1c44"
}
```

Devuelve `{ id, success: true }`. No se puede recuperar después de eliminarla; confirme antes de realizar la llamada.

## Migración fluida desde v1

Si ya está utilizando [`/aichat/conversations`](https://platform.acedata.cloud/documents/aichat-conversations), migrar a v2 casi no requiere cambios de código:

1. Cambie la URL de `https://api.acedata.cloud/aichat/conversations` a `https://api.acedata.cloud/aichat2/conversations`.
2. Si antes enviaba nombres de modelos v1 (como `gpt-3.5`, `gpt-4-browsing`, etc.), al cambiar a v2 se recomienda actualizar a modelos contemporáneos (como `gpt-5.4`, `claude-opus-4-8`, `gemini-3.1-pro-preview`, etc.).
3. Los campos del flujo NDJSON mantienen compatibilidad con versiones anteriores: cada evento `text_delta` sigue incluyendo `delta_answer` e `id`, por lo que los clientes existentes que analizan `delta_answer` línea por línea no requieren cambios.

Después de la migración, puede habilitar según sea necesario las nuevas capacidades de v2 (`message` multimodal, SSE, llamadas a herramientas, CRUD mediante `action`), y avanzar al ritmo que prefiera.

## Manejo de errores

La respuesta de error se unifica como:

```json theme={null}
{
  "error": {
    "code": "chat_error",
    "message": "model service returned an error"
  },
  "trace_id": "2cf86e86-22a4-46e1-ac2f-032c0f2a4e89"
}
```

Errores comunes:

* `400 bad_request`: faltan campos obligatorios, `tool_use_id` no coincide, el schema de `messages` no es válido, etc.
* `401 invalid_token`: el encabezado `authorization` es incorrecto.
* `404 not_found`: la conversación correspondiente al `id` no existe al usar `action: retrieve / update / delete`.
* `429 too_many_requests`: se activó el límite de velocidad.
* `500 chat_error`: error del LLM ascendente o `completion_tokens=0` en esta ronda (se trata como no consumido y no se cobra).

En la respuesta de flujo, los errores se emiten como eventos `{"type":"error","message":"..."}`, tras lo cual el flujo finalizará inmediatamente.

## Conclusión

AI Chat v2 API, manteniendo la compatibilidad con v1, actualiza las conversaciones de «preguntas y respuestas de una sola ronda / múltiples rondas» a «conversaciones observables orientadas a agentes»: entrada multimodal, llamadas a herramientas, pausa / reanudación, eventos estructurados en flujo y CRUD integrado. Se recomienda usar directamente v2 para nuevas integraciones; las integraciones existentes de v1 pueden migrarse fluidamente por etapas. Si tiene alguna pregunta, no dude en ponerse en contacto con nuestro equipo de soporte técnico.
