---
title: "Chat API"
description: "Interactúa con tus minds mediante chat completions y conversaciones multi-turn."
---

# Chat API

Envía mensajes a tus minds y recibe respuestas generadas por IA. La Chat API soporta tanto completions sin estado como conversaciones multi-turn con estado, con gestión automática del historial.

## Chats con estado (recomendado)

Crea conversaciones persistentes en las que el servidor gestiona automáticamente el historial, la compresión de contexto y los resúmenes rodantes. No hace falta enviar el historial completo de mensajes en cada solicitud.

### Crear un Chat

Crea una nueva conversación con estado vinculada a un mind.

**Endpoint:** `POST /api/v1/chats`

Elige exactamente una selección no vacía: `mindId`, `mindIds` o `audienceIds`. Mezclarlas devuelve `400`; un array opcional vacío no reemplaza un Mind individual. Las mayúsculas de los UUID no importan y los duplicados se ignoran. Crear un chat admite hasta 1 MiB de JSON, incluido el escape; las solicitudes mayores devuelven `413` antes de consultar la base de datos o los derechos del plan. Las respuestas son privadas y no se almacenan en caché.

**Headers:**

```text
Authorization: Bearer minds_your_api_key
Content-Type: application/json
```

**Request body:**

```json
{
  "name": "My Conversation",
  "mindId": "your-mind-id"
}
```

<table>
<thead>
  <tr>
    <th>
      Parámetro
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Obligatorio
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        name
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Nombre visible del chat (default: "API Chat")
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mindId
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      Uno de estos campos
    </td>
    
    <td>
      UUID de un Mind. Indica <code>
        mindId
      </code>
      
      , un array <code>
        mindIds
      </code>
      
       no vacío o un array <code>
        audienceIds
      </code>
      
       no vacío; omitir los tres devuelve <code>
        400
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mindIds
      </code>
    </td>
    
    <td>
      string<span>
        
      </span>
    </td>
    
    <td>
      Uno de estos campos
    </td>
    
    <td>
      UUID de varios Minds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        audienceIds
      </code>
    </td>
    
    <td>
      string<span>
        
      </span>
    </td>
    
    <td>
      Uno de estos campos
    </td>
    
    <td>
      UUID de Audiences para un chat Study. La respuesta contiene <code>
        type: "study"
      </code>
      
       y <code>
        audiences
      </code>
      
       en lugar de <code>
        minds
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        responseThread
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Objeto opcional <code>
        { studyId, messageId }
      </code>
      
       para continuar una respuesta de Study con un Mind. Conserva el contexto y los archivos de origen autorizados. Devuelve <code>
        201
      </code>
      
       para un hilo nuevo o <code>
        200
      </code>
      
       al reanudar uno existente.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        description
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Descripción opcional
    </td>
  </tr>
</tbody>
</table>

**Respuesta (201):**

```json
{
  "data": {
    "id": "601af953-3837-49c1-a31e-4fdbfa82ac04",
    "name": "My Conversation",
    "description": null,
    "createdAt": "2026-04-04T12:45:24.078Z",
    "minds": [
      {
        "id": "4774888e-0a03-40d7-979b-39b47c4c049c",
        "name": "Ada Lovelace",
        "discipline": "mathematician and computer scientist"
      }
    ]
  }
}
```

### Enviar un mensaje

Envía un mensaje a un chat existente. El servidor gestiona automáticamente el historial de conversación, la compresión de la ventana de contexto y los resúmenes rodantes.

**Endpoint:** `POST /api/v1/chats/{chatId}/messages`

Los chats con uno o varios Minds respetan la política `knowledge_only` guardada de cada Mind y las restricciones de investigación web del espacio de trabajo. Un Mind restringido usa la pregunta actual, su persona entrenada y conocimiento relevante recuperado del Mind; su contexto de respuesta excluye herramientas internas y del cliente, contexto anterior del chat y fuentes copiadas de Study. La respuesta indica `metadata.knowledgeRetrieval.status` como `grounded` si se recuperó evidencia relevante, o `fallback` si no estaba disponible o falló la recuperación. Las respuestas de varios Minds lo indican por separado en los `metadata` de cada elemento de `messages[]`.

El permiso de investigación web del espacio de trabajo es independiente de `knowledge_only`: desactivarlo elimina las herramientas de búsqueda web y análisis de enlaces, pero conserva el material proporcionado y el historial para Minds con `auto`. El contexto restringido descrito arriba se aplica a Minds con `knowledge_only`.

La memoria incremental continúa después del ID del último mensaje incluido, en lugar de usar una posición que puede desplazarse al cambiar el contexto copiado de Study. Las filas de resumen generadas no cuentan como turnos; las notas de sistema del propietario siguen disponibles en los chats v1. Un resultado en segundo plano se descarta si otra solicitud ha modificado el resumen guardado que utilizó.

Si el resumen incremental falla o no devuelve una narración, el mecanismo de respaldo conserva el resumen anterior y los hechos almacenados válidos, y añade una breve síntesis del nuevo segmento. El mecanismo de respaldo incluye fragmentos de un máximo de 30 mensajes nuevos por actualización y solo avanza hasta esos mensajes. Los demás quedan pendientes para una actualización posterior. La compresión de solicitudes usa el mensaje de referencia guardado para no repetir fragmentos ya cubiertos, conservando los mensajes recientes, la evidencia destacada y el contexto copiado de Study.

El moderador identifica a los participantes por su ID de Mind. Los Minds con el mismo nombre visible siguen siendo candidatos distintos; los límites de turnos y la prevención de intervenciones consecutivas se aplican por ID. El moderador puede finalizar la discusión antes de que respondan todos los Minds.

Los fallos inesperados de generación devuelven un `500` genérico sin detalles del proveedor; las respuestas fallidas solicitan el reembolso de las unidades reservadas. Las respuestas ya generadas y los mensajes guardados no se revierten. Un rechazo explícito por capacidades del modelo sigue siendo `400` con `data.errorType: "unsupported_model_capability"`. En chats multi-Mind, el resumen opcional en segundo plano no retrasa una respuesta ya guardada ni la convierte en un error.

Los mensajes también tienen un límite JSON de 1 MiB; superarlo devuelve `413` antes de consultar la base de datos o los derechos del plan. Las respuestas son privadas y no se almacenan en caché. Solo puede escribir el propietario. Los workspaces gestionados verifican en cada solicitud el workspace actual y los permisos de los Minds/Audiences asociados; el acceso revocado devuelve `404` antes de guardar o facturar.

El ejemplo siguiente corresponde a un solo Mind. Los chats multi-Mind devuelven `messages[]`; los chats Study, `outputData`. Usa `role: "system"` para guardar una nota de contexto sin generación ni consumo del límite de mensajes; devuelve `{ messageId, role: "system" }`.

**Headers:**

```text
Authorization: Bearer minds_your_api_key
Content-Type: application/json
```

**Request body:**

```json
{
  "content": "What are the latest advancements in solar panel technology?"
}
```

<table>
<thead>
  <tr>
    <th>
      Parámetro
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Obligatorio
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        content
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      El texto del mensaje (alternativamente usa <code>
        message
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        model
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Sobrescribe el modelo de IA para este mensaje. Debe enviarse junto con <code>
        provider
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        provider
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Proveedor de IA para el override de modelo: <code>
        openai
      </code>
      
      , <code>
        anthropic
      </code>
      
       o <code>
        google
      </code>
      
      . Debe enviarse junto con <code>
        model
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        endUserName
      </code>
    </td>
    
    <td>
      string|null
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Nombre visible opcional del usuario final real para esta solicitud. Si se omite, es <code>
        null
      </code>
      
       o está vacío, Minds se dirige al usuario de forma neutral y no infiere un nombre del propietario de la API key o de la cuenta. Alias: <code>
        userDisplayName
      </code>
      
      , <code>
        userName
      </code>
      
      .
    </td>
  </tr>
</tbody>
</table>

La selección de modelo en chat con estado sigue este orden: override por solicitud, luego el proveedor preferido del equipo si está configurado y es elegible, y después el valor predeterminado del producto. En este endpoint, los overrides parciales se rechazan con `400 Bad Request`; envía `model` y `provider` juntos u omite ambos.

**Respuesta:**

```json
{
  "content": "Recent advancements in solar panel technology include perovskite cells with 30%+ efficiency...",
  "messageId": "cmnkbsddh00033v01ptk9t4et"
}
```

<table>
<thead>
  <tr>
    <th>
      Campo
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        content
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      La respuesta del mind
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        messageId
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      ID único del mensaje guardado
    </td>
  </tr>
</tbody>
</table>

### Ejemplo multi-turn

Con chats con estado, solo envías el mensaje nuevo cada vez. El servidor lo recuerda todo:

```bash
# Step 1: Create a chat
CHAT=$(curl -s -X POST "https://getminds.ai/api/v1/chats" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Research Session", "mindId": "your-mind-id" }')

CHAT_ID=$(echo $CHAT | jq -r '.data.id')

# Step 2: Send messages (server manages history automatically)
curl -X POST "https://getminds.ai/api/v1/chats/$CHAT_ID/messages" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "content": "What are the top marketing trends?" }'

# Step 3: Follow up (the mind remembers the previous exchange)
curl -X POST "https://getminds.ai/api/v1/chats/$CHAT_ID/messages" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Which of those would work best on a small budget?" }'
```

**Cómo funciona por debajo:**

- Cada mensaje se persiste en base de datos
- En chats con un solo Mind e historiales largos, los 8 mensajes más recientes conservan su contexto completo
- Los turnos anteriores usan un resumen guardado cuando está disponible, con fragmentos de los mensajes aún no cubiertos
- Los resúmenes pierden detalles; los historiales muy largos o mensajes grandes aún pueden alcanzar los límites de contexto del modelo.

### Eliminar un chat

`DELETE /api/v1/chats/{chatId}`

Solo el propietario puede eliminar permanentemente un chat y sus mensajes. Los Minds y Audiences se conservan. El éxito devuelve `204` sin cuerpo; no lo interpretes como JSON. Las credenciales ausentes o inválidas devuelven `401`, un chat de otro propietario `403` y un chat inexistente `404`, incluso si se eliminó o transfirió antes de la escritura final. Las respuestas usan `Cache-Control: private, no-store`.

---

## Completions sin estado

Para solicitudes puntuales o cuando quieres gestionar tú mismo el historial de conversación.

### Send Message

Envía mensajes a un mind y recibe respuestas.

**Endpoint:** `POST /api/v1/minds/{mindId}/completion`

**Headers:**

```text
Authorization: Bearer minds_your_api_key
Content-Type: application/json
```

### Request body

```json
{
  "messages": [
    {
      "role": "user",
      "content": "What are the latest advancements in solar panel technology?"
    }
  ]
}
```

### Parámetros

<table>
<thead>
  <tr>
    <th>
      Parámetro
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Obligatorio
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        messages
      </code>
    </td>
    
    <td>
      array
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Array de objetos de mensaje (<code>
        system
      </code>
      
      , <code>
        user
      </code>
      
      , <code>
        assistant
      </code>
      
       o <code>
        tool
      </code>
      
      ). Si se omite o es un array vacío, devuelve un saludo del mind acorde a su persona.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        messages[].role
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      <code>
        system
      </code>
      
      , <code>
        user
      </code>
      
      , <code>
        assistant
      </code>
      
      , <code>
        tool
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        messages[].content
      </code>
    </td>
    
    <td>
      string|array
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      Una cadena o un array de partes de contenido estructuradas. Obligatorio para todos los roles. Las cadenas de usuario deben incluir texto que no sea solo espacios. Para un resultado de herramienta, conserva <code>
        content
      </code>
      
       e incluye un <code>
        tool_call_id
      </code>
      
       que coincida con una llamada anterior del asistente. El rol <code>
        system
      </code>
      
       solo admite contenido de tipo cadena.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        model
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Sobrescribe el modelo de IA usado para esta solicitud. Ver <a href="#model-override">
        model override
      </a>
      
       abajo.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        provider
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Provider de IA para el model override: <code>
        openai
      </code>
      
      , <code>
        anthropic
      </code>
      
       o <code>
        google
      </code>
      
      . Se detecta automáticamente a partir del nombre del modelo cuando es posible.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        modelConnection
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      No
    </td>
    
    <td>
      <code>
        { "id", "revision" }
      </code>
      
       de una conexión de modelo del equipo verificada: tu propio endpoint escribe la respuesta. No se puede combinar con <code>
        model
      </code>
      
      /<code>
        provider
      </code>
      
      . Ver <a href="#your-own-model">
        tu propio modelo
      </a>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        endUserName
      </code>
    </td>
    
    <td>
      string|null
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Nombre visible opcional del usuario final real para esta solicitud. Si se omite, es <code>
        null
      </code>
      
       o está vacío, Minds se dirige al usuario de forma neutral y no infiere un nombre del propietario de la API key o de la cuenta. Alias: <code>
        userDisplayName
      </code>
      
      , <code>
        userName
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        language
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Pista para el idioma de la respuesta. Soportados: <code>
        en
      </code>
      
      , <code>
        de
      </code>
      
      , <code>
        es
      </code>
      
      , <code>
        fr
      </code>
      
      , <code>
        zh
      </code>
      
      , <code>
        tr
      </code>
      
      , <code>
        ar
      </code>
      
      , <code>
        ja
      </code>
      
      , <code>
        ko
      </code>
      
      . Las personas fuertes (p. ej., clones de figuras públicas con un idioma nativo fijo) pueden seguir respondiendo en el idioma de su persona.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        generateImage
      </code>
    </td>
    
    <td>
      boolean
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Si es <code>
        true
      </code>
      
      , habilita la generación de imágenes con IA en la respuesta cuando sea contextualmente apropiado
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        response_format
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Solicita output estructurado. Ver <a href="#structured-output">
        structured output
      </a>
      
       abajo.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tools
      </code>
    </td>
    
    <td>
      array
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Array de definiciones de tools definidas por el usuario. Ver <a href="#tool-calling">
        tool calling
      </a>
      
       abajo.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tool_choice
      </code>
    </td>
    
    <td>
      string|object
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Controla el comportamiento de llamada a tools. Ver <a href="#tool-choice-modes">
        tool choice modes
      </a>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        parallel_tool_calls
      </code>
    </td>
    
    <td>
      boolean
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Permite múltiples tool calls por turno (default: <code>
        true
      </code>
      
      ).
    </td>
  </tr>
</tbody>
</table>

### Respuesta

```json
{
  "messageId": "msg_550e840029b141d4a716446655440000",
  "content": "Recent advancements in solar panel technology include perovskite cells with 30%+ efficiency, bifacial panels that capture light from both sides, and integrated storage systems...",
  "metadata": {
    "ragCitations": [
      {
        "id": "abc123",
        "displaySource": "Mind knowledge",
        "similarity": 0.89
      }
    ]
  }
}
```

<table>
<thead>
  <tr>
    <th>
      Campo
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        messageId
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      Identificador único del mensaje para tracking
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        content
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      El texto de respuesta del mind (string JSON cuando se usa structured output)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        parsed
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      Objeto JSON parseado (solo presente cuando se usa <code>
        response_format
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tool_calls
      </code>
    </td>
    
    <td>
      array
    </td>
    
    <td>
      Array de solicitudes de tool call (solo presente cuando se invocan tools definidas por el usuario). Cada una tiene: <code>
        id
      </code>
      
      , <code>
        name
      </code>
      
      , <code>
        arguments
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        metadata
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      Metadatos opcionales (citas, imágenes)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        metadata.ragCitations
      </code>
    </td>
    
    <td>
      array
    </td>
    
    <td>
      Fuentes de knowledge y resultados de web search usados en la respuesta
    </td>
  </tr>
</tbody>
</table>

## Ejemplo de mensaje único

Haz una única pregunta:

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "What are the top 3 marketing trends for 2025?"
      }
    ]
  }'
```

## Conversación multi-turn

Mantén el contexto de la conversación incluyendo los mensajes previos:

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "What are the top marketing trends?"
      },
      {
        "role": "assistant",
        "content": "The top trends are AI personalization, short-form video, and community building..."
      },
      {
        "role": "user",
        "content": "How can I implement AI personalization on a budget?"
      }
    ]
  }'
```

**Tips para conversaciones multi-turn:**

- Incluye el historial completo de la conversación en cada solicitud
- El orden importa: los mensajes deben ir en orden cronológico
- Alterna entre los roles `user` y `assistant`
- El último mensaje siempre debe ser de `user`

## File attachments

Adjunta archivos, documentos, imágenes y links para aportar contexto a tus minds. Los minds reciben el contenido procesado como parte de la conversación.

### Adjuntar archivos

Añade archivos vía el array `metadata.attachedFiles` en tu mensaje de user:

Para completions sin estado, usa un archivo propio, una URL de archivo de chat con firma válida o contexto compartido mediante la Study de quien lo subió. Los archivos del espacio de trabajo sin autorización devuelven `403 Upload access denied` (un evento de error en streaming). Las URL HTTP(S) externas conservan su propio token de acceso; una ruta de almacenamiento arbitraria no se vuelve a firmar. Sustituye `your-user-id` por tu ID de usuario y usa la ruta devuelta por el endpoint de carga.

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "Please review this document and summarize the key points",
        "metadata": {
          "attachedFiles": [
            {
              "url": "https://example.com/quarterly-report.pdf",
              "name": "Q4 2025 Report",
              "type": "application/pdf"
            },
            {
              "path": "chat/your-user-id/meeting-notes.docx",
              "name": "Strategy Meeting Notes"
            }
          ]
        }
      }
    ]
  }'
```

### Formato del adjunto

Cada objeto de adjunto admite:

<table>
<thead>
  <tr>
    <th>
      Campo
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Obligatorio
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        url
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No*
    </td>
    
    <td>
      URL externa al archivo (HTTP/HTTPS)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        path
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No*
    </td>
    
    <td>
      Ruta de Supabase storage (firmada automáticamente)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        name
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Nombre visible del archivo
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        type
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Tipo MIME (p. ej., <code>
        application/pdf
      </code>
      
      , <code>
        image/png
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        description
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Descripción opcional
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        transcription
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Contenido de audio/vídeo pre-transcrito
    </td>
  </tr>
</tbody>
</table>

**Nota:** Proporciona `url` O `path`, no ambos.

### Tipos de archivo soportados

**Documentos:**

- PDF (`.pdf`) - Extracción de texto + OCR para páginas escaneadas
- Word (`.docx`) - Extracción de texto completo
- Texto (`.txt`, `.md`) - Contenido de texto directo
- CSV/Excel (`.csv`, `.xlsx`) - Extracción de tablas

**Imágenes:**

- PNG, JPG, WEBP - OCR + análisis visual
- Capacidades de visión para comprensión de imágenes

**URLs externas:**

- Páginas web obtenidas con Firecrawl (renderizado JS + screenshots)
- Conversión automática a markdown

### Procesamiento

Los archivos se procesan automáticamente antes de enviarse al mind:

1. **Download** - Los archivos se obtienen desde URL o Supabase storage
2. **Extract** - Se extrae el contenido (texto de PDFs, OCR de imágenes, etc.)
3. **Inject** - El contenido procesado se añade al contexto de la conversación
4. **Response** - El mind ve tanto tu mensaje como el contenido del archivo

**Límites de procesamiento:**

- Timeout: 30 segundos por archivo
- Los archivos se procesan en paralelo
- Los archivos que fallan muestran mensajes de fallback con manejo elegante

### Ejemplo con múltiples archivos

```json
{
  "messages": [
    {
      "role": "user",
      "content": "Compare these two proposals and recommend which one to pursue",
      "metadata": {
        "attachedFiles": [
          {
            "url": "https://example.com/proposal-a.pdf",
            "name": "Proposal A - Cloud Migration",
            "type": "application/pdf"
          },
          {
            "url": "https://example.com/proposal-b.pdf",
            "name": "Proposal B - On-Prem Upgrade",
            "type": "application/pdf"
          },
          {
            "path": "chat/your-user-id/budget-analysis.xlsx",
            "name": "Budget Comparison"
          }
        ]
      }
    }
  ]
}
```

### File attachments en el historial de conversación

Cuando continúes una conversación con archivos adjuntos, incluye el mensaje original con los adjuntos en el historial:

```json
{
  "messages": [
    {
      "role": "user",
      "content": "Analyze this sales data",
      "metadata": {
        "attachedFiles": [
          {
            "url": "https://example.com/sales-q4.csv",
            "name": "Q4 Sales Data"
          }
        ]
      }
    },
    {
      "role": "assistant",
      "content": "Based on the Q4 sales data, I can see that revenue increased by 23% compared to Q3..."
    },
    {
      "role": "user",
      "content": "What were the top 3 performing products?"
    }
  ]
}
```

**Nota:** Los archivos solo se procesan una vez al adjuntarse por primera vez. Los mensajes posteriores en la misma conversación referencian el contenido ya procesado.

### Links web

Para páginas web y contenido externo, usa el campo `url`:

```json
{
  "messages": [
    {
      "role": "user",
      "content": "Summarize the key findings from this research paper",
      "metadata": {
        "attachedFiles": [
          {
            "url": "https://arxiv.org/pdf/2103.12345.pdf",
            "name": "AI Research Paper",
            "type": "application/pdf"
          }
        ]
      }
    }
  ]
}
```

**Para páginas web en concreto:**

- Los sitios con mucho JavaScript se renderizan con Firecrawl
- Se capturan screenshots para contexto visual
- El contenido se convierte a markdown limpio

### Manejo de errores

Si el procesamiento del archivo falla:

- El mind recibe un mensaje de fallback indicando que el archivo se adjuntó pero el procesamiento falló
- La conversación continúa con normalidad
- Los errores de timeout muestran `[Processing timeout - file may be too large]`
- Otros errores muestran `[Processing failed - file uploaded but analysis unavailable]`

Esto asegura que los minds sepan que hubo intentos de adjuntos aunque el procesamiento falle.

## Mensaje inicial (saludo)

Si envías un array de messages vacío o no envías messages, el mind se presentará:

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": []
  }'
```

Respuesta:

```json
{
  "content": "Hi! I'm Sarah, a marketing director with 15 years of experience in B2B SaaS. I specialize in growth marketing and data-driven strategies. What can I help you with today?"
}
```

## Model override

Puedes sobrescribir opcionalmente el modelo de IA usado para una solicitud de completion sin estado pasando el parámetro `model`. Es útil para benchmarking, optimización de costes o testeo de comportamientos de distintos modelos. Los endpoints de chat con estado y paneles validan los overrides con más rigor: envía `model` y `provider` juntos.

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "What are your thoughts on sustainable packaging?"
      }
    ],
    "model": "gpt-6-luna"
  }'
```

Cuando no se especifica `model`, se usa el default del servidor.

### Providers

<table>
<thead>
  <tr>
    <th>
      Provider
    </th>
    
    <th>
      Valor
    </th>
    
    <th>
      Modelos de ejemplo
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      OpenAI
    </td>
    
    <td>
      <code>
        openai
      </code>
    </td>
    
    <td>
      <code>
        gpt-6-astra
      </code>
      
      , <code>
        gpt-6.1-sol
      </code>
      
      , <code>
        gpt-6-luna
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      Anthropic
    </td>
    
    <td>
      <code>
        anthropic
      </code>
    </td>
    
    <td>
      <code>
        claude-fable-5-1
      </code>
      
      , <code>
        claude-opus-5-5
      </code>
      
      , <code>
        claude-sonnet-5-5
      </code>
      
      , <code>
        claude-haiku-4-5-20251001
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      Google
    </td>
    
    <td>
      <code>
        google
      </code>
    </td>
    
    <td>
      <code>
        gemini-3.8-flash
      </code>
      
      , <code>
        gemini-3.5-flash-lite
      </code>
    </td>
  </tr>
</tbody>
</table>

Pasa uno de los modelos de la lista anterior. Los IDs retirados se redirigen (ver abajo); cualquier otro modelo devuelve `400 Bad Request`. El provider se detecta automáticamente a partir de los prefijos habituales de nombres de modelo (`claude-` → Anthropic, `gemini-` → Google, `gpt-`/`o1`/`o3`/`o4` → OpenAI).

### Your own model

Para usar un modelo con fine-tuning o autoalojado, un administrador del equipo lo añade como [conexión de modelo del equipo](/guide/team-model-connections) (protocolo OpenAI Chat Completions, OpenAI Responses o Anthropic Messages) y lo verifica. Después envía el ID de la conexión y su revisión actual en lugar de `model` y `provider`:

```json
{
  "messages": [...],
  "modelConnection": { "id": "3f6c1e2a-5b7d-4c1e-9a0f-2d8e4b6a1c90", "revision": 3 }
}
```

`GET /api/v1/model-connections` lista las conexiones de tu equipo con sus revisiones y capacidades verificadas. La conexión necesita texto y streaming, además de salida estructurada cuando envías `response_format` y llamadas a herramientas cuando la solicitud usa herramientas. Si tu endpoint falla, la solicitud falla: Minds nunca cambia a uno de sus propios modelos. Las imágenes y otros medios se rechazan con `MODEL_CONNECTION_MEDIA_UNVERIFIED`. Los mensajes de chat con estado (`/chats/{chatId}/messages`) no aceptan una conexión.

## Structured output

Solicita respuestas JSON garantizadas que coincidan con un schema específico usando el parámetro `response_format`. Sigue el patrón de structured output estilo OpenAI y es útil para extraer datos estructurados de las conversaciones.

### JSON Schema Mode

Fuerza al modelo a producir un JSON válido que coincida con tu schema:

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "Analyze the sentiment of this text: I love this product, it exceeded all my expectations!"
      }
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "sentiment_analysis",
        "description": "Sentiment analysis result",
        "schema": {
          "type": "object",
          "properties": {
            "sentiment": {
              "type": "string",
              "enum": ["positive", "negative", "neutral"]
            },
            "confidence": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "keywords": {
              "type": "array",
              "items": { "type": "string" }
            }
          },
          "required": ["sentiment", "confidence", "keywords"]
        }
      }
    }
  }'
```

Respuesta:

```json
{
  "content": "{\"sentiment\": \"positive\", \"confidence\": 0.95, \"keywords\": [\"love\", \"exceeded\", \"expectations\"]}",
  "parsed": {
    "sentiment": "positive",
    "confidence": 0.95,
    "keywords": ["love", "exceeded", "expectations"]
  }
}
```

### JSON Object Mode

Fuerza output JSON sin validación de schema:

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "List 3 marketing ideas as JSON"
      }
    ],
    "response_format": {
      "type": "json_object"
    }
  }'
```

### Tipos de Response Format

<table>
<thead>
  <tr>
    <th>
      Tipo
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        text
      </code>
    </td>
    
    <td>
      Output de texto por defecto (comportamiento actual)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        json_object
      </code>
    </td>
    
    <td>
      Fuerza output JSON válido sin validación de schema
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        json_schema
      </code>
    </td>
    
    <td>
      Fuerza output JSON que coincida con el schema proporcionado
    </td>
  </tr>
</tbody>
</table>

### Campos de JSON Schema

<table>
<thead>
  <tr>
    <th>
      Campo
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Obligatorio
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        name
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      Identificador del schema
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        description
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Descripción de lo que representa el schema
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        schema
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      Definición del JSON Schema
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        strict
      </code>
    </td>
    
    <td>
      boolean
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Fuerza adherencia estricta al schema (default: <code>
        true
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

### Funcionalidades de Schema soportadas

Se soportan las siguientes funcionalidades de JSON Schema:

- **Tipos**: `string`, `number`, `integer`, `boolean`, `array`, `object`, `null`
- **Restricciones**: `enum`, `minimum`, `maximum`, `minLength`, `maxLength`, `minItems`, `maxItems`
- **Estructura**: `properties`, `required`, `items`, `additionalProperties`
- **Metadatos**: `description` (usado para guiar al modelo)

### Notas

- Los tools (RAG, web search, etc.) funcionan con structured output — el mind puede seguir buscando en su knowledge base antes de generar la respuesta estructurada
- El campo `parsed` contiene el objeto JSON parseado por conveniencia; `content` contiene el string JSON en bruto
- Todos los providers principales (OpenAI, Anthropic, Google) soportan structured output
- Para schemas complejos, considera añadir campos `description` para guiar el output del modelo

## Tool calling

Permite a los minds llamar a tus funciones personalizadas durante las conversaciones. Sigue el patrón de function calling compatible con OpenAI y te permite extender las capacidades de los minds con tools y APIs externas.

### Cómo funciona

1. **Define tools**: Pasa definiciones de tools con nombres, descripciones y parámetros en JSON Schema
2. **El mind decide**: El mind determina cuándo llamar a tus tools en función de la conversación (o lo fuerzas con `tool_choice`)
3. **La API devuelve tool calls**: La respuesta incluye `tool_calls` con el nombre de la tool y los argumentos generados
4. **Ejecuta los tools**: Ejecutas los tools en tu aplicación y obtienes los resultados
5. **Envía los resultados de vuelta**: Incluye los resultados del tool en el siguiente mensaje con `role: "tool"`
6. **El mind responde**: El mind incorpora los resultados del tool en su respuesta final

### Ejemplo básico

**Solicitud con tools:**

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "What is the weather in Berlin?"
      }
    ],
    "tools": [
      {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {
              "type": "string",
              "description": "City name"
            },
            "units": {
              "type": "string",
              "enum": ["celsius", "fahrenheit"],
              "description": "Temperature units"
            }
          },
          "required": ["city"]
        }
      }
    ]
  }'
```

**Respuesta:**

```json
{
  "content": "",
  "tool_calls": [
    {
      "id": "call_abc123",
      "name": "get_weather",
      "arguments": {
        "city": "Berlin",
        "units": "celsius"
      }
    }
  ]
}
```

**Ejecuta el tool y envía los resultados de vuelta:**

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "What is the weather in Berlin?"
      },
      {
        "role": "assistant",
        "content": "",
        "tool_calls": [
          {
            "id": "call_abc123",
            "name": "get_weather",
            "arguments": {
              "city": "Berlin",
              "units": "celsius"
            }
          }
        ]
      },
      {
        "role": "tool",
        "tool_call_id": "call_abc123",
        "content": "{\"temperature\": 18, \"condition\": \"partly cloudy\", \"humidity\": 65}"
      }
    ],
    "tools": [
      {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
          "type": "object",
          "properties": {
            "city": { "type": "string" },
            "units": { "type": "string", "enum": ["celsius", "fahrenheit"] }
          },
          "required": ["city"]
        }
      }
    ]
  }'
```

**Respuesta final:**

```json
{
  "content": "The current weather in Berlin is 18°C and partly cloudy, with 65% humidity."
}
```

### Schema de definición de Tool

Cada tool debe seguir esta estructura:

```json
{
  "name": "tool_name",
  "description": "Clear description of when and how to use this tool",
  "parameters": {
    "type": "object",
    "properties": {
      "param1": {
        "type": "string",
        "description": "What this parameter does"
      }
    },
    "required": ["param1"]
  },
  "strict": true
}
```

**Campos obligatorios:**

<table>
<thead>
  <tr>
    <th>
      Campo
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        name
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      Nombre de la función. Debe ser único y no puede entrar en conflicto con los tools internos.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        description
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      Descripción clara de lo que hace el tool y cuándo usarlo. Esto guía la selección de tools del mind.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        parameters
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      JSON Schema que define los argumentos de la función.
    </td>
  </tr>
</tbody>
</table>

**Campos opcionales:**

<table>
<thead>
  <tr>
    <th>
      Campo
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        strict
      </code>
    </td>
    
    <td>
      boolean
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Fuerza validación estricta del schema para los argumentos.
    </td>
  </tr>
</tbody>
</table>

### Tool choice modes

Controla cuándo y cómo el mind llama a los tools usando el parámetro `tool_choice`:

<table>
<thead>
  <tr>
    <th>
      Valor
    </th>
    
    <th>
      Comportamiento
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        "auto"
      </code>
    </td>
    
    <td>
      El mind decide si llamar a tools (default)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        "required"
      </code>
    </td>
    
    <td>
      El mind debe llamar al menos a un tool antes de responder
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        "none"
      </code>
    </td>
    
    <td>
      Deshabilita la llamada a tools para este turno
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        {"name": "tool_name"}
      </code>
    </td>
    
    <td>
      Fuerza al mind a llamar a un tool específico
    </td>
  </tr>
</tbody>
</table>

**Ejemplos:**

```json
// Let the mind decide
{
  "messages": [...],
  "tools": [...],
  "tool_choice": "auto"
}

// Force a specific tool
{
  "messages": [...],
  "tools": [...],
  "tool_choice": {
    "name": "search_database"
  }
}

// Require at least one tool call
{
  "messages": [...],
  "tools": [...],
  "tool_choice": "required"
}
```

### Parallel tool calls

Por defecto, los minds pueden llamar a varios tools en un mismo turno para ganar eficiencia:

```json
{
  "content": "",
  "tool_calls": [
    {
      "id": "call_1",
      "name": "get_customer",
      "arguments": { "id": "CUST-001" }
    },
    {
      "id": "call_2",
      "name": "get_customer",
      "arguments": { "id": "CUST-002" }
    }
  ]
}
```

Para deshabilitar las llamadas en paralelo y forzar ejecución secuencial:

```json
{
  "messages": [...],
  "tools": [...],
  "parallel_tool_calls": false
}
```

### Formato del mensaje de Tool

Al enviar los resultados del tool de vuelta, usa el rol `tool`:

```json
{
  "role": "tool",
  "tool_call_id": "call_abc123",
  "content": "{\"result\": \"success\", \"data\": {...}}"
}
```

<table>
<thead>
  <tr>
    <th>
      Campo
    </th>
    
    <th>
      Tipo
    </th>
    
    <th>
      Obligatorio
    </th>
    
    <th>
      Descripción
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        role
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      Debe ser <code>
        "tool"
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tool_call_id
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      El <code>
        id
      </code>
      
       del tool call de la respuesta del assistant
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        content
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <strong>
        Sí
      </strong>
    </td>
    
    <td>
      Resultado de la ejecución del tool (normalmente un string JSON)
    </td>
  </tr>
</tbody>
</table>

Los resultados de herramientas van después del mensaje correspondiente del asistente, incluidos sus `tool_calls`. Repite el ID y el nombre de la llamada devueltos y envía cada resultado una sola vez. Los argumentos mal formados, IDs desconocidos, nombres de herramientas que no coinciden resultados duplicados y resultados del cliente ausentes devuelven `400` antes de generar.

### Tools internos vs tools de usuario

Minds tiene tools internos del lado del servidor que se ejecutan automáticamente:

<table>
<thead>
  <tr>
    <th>
      Tool interno
    </th>
    
    <th>
      Propósito
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        GET_SPARK_RAG
      </code>
    </td>
    
    <td>
      Busca en el knowledge base del mind
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        WEB_SEARCH
      </code>
    </td>
    
    <td>
      Busca en la web
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        GENERATE_IMAGE
      </code>
    </td>
    
    <td>
      Genera imágenes con IA
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        DISPLAY_IMAGE
      </code>
    </td>
    
    <td>
      Muestra imágenes de la memoria del mind
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        DOCUMENT_PROCESSING
      </code>
    </td>
    
    <td>
      Analiza archivos subidos
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ANALYZE_LINK
      </code>
    </td>
    
    <td>
      Obtiene y analiza URLs web
    </td>
  </tr>
</tbody>
</table>

**Diferencias clave:**

- **Tools internos**: Se ejecutan del lado del servidor; los resultados se incluyen en `content` y `metadata`. Nunca se devuelven en `tool_calls`.
- **Tools de usuario**: Se devuelven en `tool_calls` para que tú los ejecutes. Los resultados deben enviarse de vuelta como mensajes `tool`.

No puedes sobrescribir ni deshabilitar los tools internos. Los tools de usuario son **aditivos** — extienden las capacidades del mind.

### Ejemplo multi-tool completo

Un mind asistente legal con varios tools personalizados:

```bash
curl -X POST "https://getminds.ai/api/v1/minds/mind-id/completion" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "role": "user",
        "content": "Create a new case for Schmidt vs. Mueller and search for similar precedents"
      }
    ],
    "tools": [
      {
        "name": "create_case",
        "description": "Create a new legal case in the system",
        "parameters": {
          "type": "object",
          "properties": {
            "title": {
              "type": "string",
              "description": "Case title (parties involved)"
            },
            "practice_area": {
              "type": "string",
              "enum": ["corporate", "litigation", "employment", "ip"],
              "description": "Legal practice area"
            },
            "client_id": {
              "type": "string",
              "description": "Client identifier"
            }
          },
          "required": ["title", "practice_area"]
        }
      },
      {
        "name": "search_precedents",
        "description": "Search legal database for similar cases",
        "parameters": {
          "type": "object",
          "properties": {
            "keywords": {
              "type": "array",
              "items": { "type": "string" },
              "description": "Search keywords"
            },
            "practice_area": {
              "type": "string",
              "description": "Filter by practice area"
            },
            "max_results": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "description": "Maximum number of results"
            }
          },
          "required": ["keywords"]
        }
      }
    ],
    "parallel_tool_calls": true
  }'
```

**Respuesta con tool calls en paralelo:**

```json
{
  "content": "",
  "tool_calls": [
    {
      "id": "call_1",
      "name": "create_case",
      "arguments": {
        "title": "Schmidt vs. Mueller",
        "practice_area": "litigation"
      }
    },
    {
      "id": "call_2",
      "name": "search_precedents",
      "arguments": {
        "keywords": ["Schmidt", "Mueller"],
        "practice_area": "litigation",
        "max_results": 10
      }
    }
  ]
}
```

### Buenas prácticas

1. **Escribe descripciones claras**: El campo `description` es crítico. Sé específico sobre cuándo y por qué usar cada tool.```json
❌ "description": "Search database"
✅ "description": "Search the legal precedents database for similar cases based on keywords and practice area"
```
2. **Usa descripciones en los parámetros**: Ayuda al mind a entender qué hace cada parámetro.```json
"case_id": {
  "type": "string",
  "description": "Unique case identifier in format CASE-YYYY-NNNN"
}
```
3. **Apóyate en enums para valores restringidos**:```json
"status": {
  "type": "string",
  "enum": ["pending", "active", "closed", "archived"]
}
```
4. **Establece restricciones de validación**:```json
"priority": {
  "type": "integer",
  "minimum": 1,
  "maximum": 5,
  "description": "Priority level (1=lowest, 5=highest)"
}
```
5. **Activa el modo strict**: Mantén `strict: true` (default) para asegurar que el mind genere argumentos válidos.
6. **Devuelve resultados de tool estructurados**: Usa JSON para los resultados de tool para facilitar su parseo:```json
{
  "role": "tool",
  "tool_call_id": "call_123",
  "content": "{\"success\": true, \"case_id\": \"CASE-2026-001\", \"created_at\": \"2026-03-30T23:00:00Z\"}"
}
```
7. **Gestiona los errores con elegancia**: Devuelve los detalles del error en el resultado del tool:```json
{
  "role": "tool",
  "tool_call_id": "call_123",
  "content": "{\"success\": false, \"error\": \"Case already exists\", \"error_code\": \"DUPLICATE_CASE\"}"
}
```

### Limitaciones

- **Máximo 128 tools** por solicitud
- Los nombres de tool deben ser únicos y no pueden entrar en conflicto con los nombres de tools internos
- La ejecución del tool ocurre del lado del cliente — eres responsable de ejecutarlos y securizarlos
- Los resultados del tool deben enviarse de vuelta en el historial de conversación para que el mind responda

### Soporte de JSON Schema

El campo `parameters` soporta las funcionalidades estándar de JSON Schema:

**Tipos:**

- `string`, `number`, `integer`, `boolean`, `array`, `object`, `null`

**Validación:**

- `enum` — Restringe a valores específicos
- `minimum`, `maximum` — Cotas numéricas
- `minLength`, `maxLength` — Longitud de string
- `minItems`, `maxItems` — Tamaño de array
- `pattern` — Validación por regex
- `format` — Formatos de string (p. ej., `"date-time"`, `"email"`, `"uri"`)

**Estructura:**

- `properties` — Propiedades del objeto
- `required` — Campos obligatorios
- `items` — Schema del item del array
- `additionalProperties` — Permite/deshabilita propiedades extra

**Ejemplo con validación avanzada:**

```json
{
  "name": "schedule_meeting",
  "description": "Schedule a meeting with a client",
  "parameters": {
    "type": "object",
    "properties": {
      "title": {
        "type": "string",
        "minLength": 1,
        "maxLength": 200
      },
      "date": {
        "type": "string",
        "format": "date-time",
        "description": "Meeting date and time in ISO 8601 format"
      },
      "attendees": {
        "type": "array",
        "items": {
          "type": "string",
          "format": "email"
        },
        "minItems": 1,
        "maxItems": 20
      },
      "duration_minutes": {
        "type": "integer",
        "minimum": 15,
        "maximum": 480,
        "description": "Meeting duration (15-480 minutes)"
      }
    },
    "required": ["title", "date", "attendees"]
  }
}
```

## Cómo funciona

### 1. Carga de contexto

Cuando envías un mensaje, el mind:

- Carga su system prompt y configuración
- **Busca automáticamente en su knowledge base** información relevante
- Considera el historial de conversación

### 2. Procesamiento

El mind:

- Analiza tu mensaje en contexto
- **Fundamenta las respuestas en el knowledge recuperado** con citas
- Accede a tools adicionales (web search, generación de imágenes, etc.) si es necesario
- Formula una respuesta alineada con su personalidad

### 3. Generación de respuesta

El mind:

- Genera una respuesta que refleja su experiencia
- **Incluye citas** cuando usa el knowledge base o fuentes web
- Devuelve el mensaje con metadatos opcionales (citas, imágenes, etc.)

## Metadatos

Las respuestas pueden incluir metadatos adicionales:

### Imágenes

Cuando un mind genera o muestra imágenes:

```json
{
  "content": "Here are some logo concepts...",
  "metadata": {
    "images": [
      {
        "id": "img_123",
        "url": "https://...",
        "filename": "Logo Concept 1",
        "description": "Modern minimalist logo with blue gradient",
        "source": "generated"
      }
    ]
  }
}
```

### Citas de knowledge

Cuando un mind recupera información de su knowledge base o de una búsqueda web:

```json
{
  "content": "Based on recent research, solar panel efficiency has improved significantly...",
  "metadata": {
    "ragCitations": [
      {
        "id": "9bf44ab0-9d83-42ec-b941-c0ab7610e949",
        "displaySource": "Mind knowledge",
        "similarity": 0.85
      },
      {
        "id": "external-web-123",
        "displaySource": "https://example.com/solar-research",
        "similarity": 0.92
      }
    ]
  }
}
```

**Campos de la cita:**

- `id` - Identificador único de la fuente
- `displaySource` - Nombre legible de la fuente o URL
- `similarity` - Puntuación de relevancia (0-1) que indica cómo de bien coincide la fuente con la consulta

Los minds buscan automáticamente en su knowledge base antes de responder e incluyen citas cuando fundamentan sus respuestas en fuentes específicas.

## Control de acceso

Puedes chatear con minds que:

- **Tú posees** - Minds que has creado
- **Tienes acceso** - Minds compartidos contigo por miembros del equipo
- **Eres miembro** - Minds en team workspaces a los que perteneces
- **Minds públicos** - Minds accesibles públicamente

Intentar acceder a minds no autorizados devuelve:

```json
{
  "statusCode": 403,
  "statusMessage": "Access denied"
}
```

## Formatos de respuesta

### Respuesta de texto

La mayoría de las respuestas son texto plano:

```json
{
  "content": "Based on current trends, I recommend focusing on..."
}
```

### Respuesta estructurada

Algunos minds pueden devolver contenido estructurado:

```json
{
  "content": "Here's my analysis:\n\n1. Trend: AI Personalization\n   - Impact: High\n   - Timeline: 6-12 months\n\n2. Trend: Short-form Video\n   - Impact: Very High\n   - Timeline: Immediate"
}
```

### Respuesta vacía con metadatos

A veces solo se devuelven metadatos (p. ej., para generación de imágenes):

```json
{
  "content": "",
  "metadata": {
    "images": [...]
  }
}
```

## Buenas prácticas

### Sé específico

```text
❌ "Tell me about marketing"
✅ "What are the most cost-effective digital marketing channels for a B2B SaaS startup with a $5K monthly budget?"
```

### Aporta contexto

```text
✅ "We're launching a sustainable fashion brand targeting Gen Z. What social media strategy would you recommend?"
```

### Usa follow-ups

Aprovecha la memoria de la conversación:

```text
User: "What are the top trends?"
Assistant: "The top trends are..."
User: "Which of these would work best for a small budget?"
Assistant: "For a small budget, I'd focus on..."
```

### Referencia el knowledge

Si has subido knowledge, referénciate a él:

```text
✅ "Based on our brand guidelines, what tone should we use for this campaign?"
```

## Respuestas de error

### 400 Bad Request

Mind ID ausente o no válido:

```json
{
  "statusCode": 400,
  "statusMessage": "Mind ID is required"
}
```

Provider no soportado:

```json
{
  "statusCode": 400,
  "statusMessage": "Unsupported provider: 'invalid'. Supported providers: openai, anthropic, google."
}
```

Nombre de modelo ambiguo sin provider:

```json
{
  "statusCode": 400,
  "statusMessage": "Cannot auto-detect provider for model 'my-model'. Please specify a 'provider' parameter (openai, anthropic, or google)."
}
```

### 401 Unauthorized

API key no válida.

### 403 Forbidden

Acceso denegado al Mind:

```json
{
  "statusCode": 403,
  "statusMessage": "Access denied"
}
```

### 404 Not Found

El Mind no existe:

```json
{
  "statusCode": 404,
  "statusMessage": "Mind not found"
}
```

## Notas de uso

- La API v1 aplica un límite configurable por cuenta autenticada (300 solicitudes por minuto de forma predeterminada)
- Lee `RateLimit-Limit` y `RateLimit-Remaining`, y respeta `Retry-After` tras un `429`
- Limita las completions paralelas porque la generación consume recursos

## Siguientes pasos

- Comprende [latencia y rendimiento](/docs/api/latency)
- Aprende sobre [errores y rate limits](/docs/api/errors)
- Crea tu primer [mind](/docs/api/minds)
- Sube [knowledge](/docs/api/knowledge) para mejorar las respuestas
- Lee la [visión general de la API](/docs/api/overview)
