Documentación

Adjuntar recursos

Darle al turno bibliotecas, archivos, habilidades y conectores — y saber cuáles podés.

Un turno sin adjuntos usa el conocimiento del modelo y las reglas de la organización. Con adjuntos, además, recibe contexto tuyo: documentos que buscar, instrucciones que seguir, herramientas que usar.

JSON
{
  "content": "Resumí la política de devoluciones y redactá una respuesta al cliente.",
  "permission_mode": "auto",
  "attachments": {
    "workspace_ids": [31],
    "file_ids": [],
    "skill_ids": [147],
    "mcp_server_ids": []
  }
}
CampoQué adjuntaScope adicional
workspace_idsBibliotecas enteras. El modelo busca dentro cuando lo necesita.libraries:read
file_idsArchivos concretos, sin traer su biblioteca entera.libraries:read
skill_idsInstrucciones reutilizables que guían la respuesta. Si citan otros recursos, esos también se suman, dentro del alcance de la credencial (ver).skills:read
mcp_server_idsConectores cuyas herramientas el turno podrá ejecutar.connectors:use

Atención

chat:write autoriza conversar, no leer lo que se adjunte. Sin el scope compañero, el turno se rechaza con 403 api_token_scope_not_allowed y data.required_scopes nombra los que faltan. La validación ocurre antes de reservar la idempotencia, así que no te quema la key.

No adivines los ids. GET /chat/catalog devuelve exactamente lo que esta credencial puede usar, ya recortado por los permisos del usuario y por el alcance de la credencial.

curl -sS 'https://api.niucore.com/api/v1/chat/catalog' \
  -H "Authorization: Bearer $NIUCORE_ACCESS_TOKEN" | jq
JSON
{
  "models": [
    { "id": 17, "name": "GPT-4o", "code": "gpt-4o", "type": "COMPLETION" }
  ],
  "permission_modes": ["manual", "auto"],
  "libraries": [{ "id": 31, "name": "Procedimientos de soporte" }],
  "skills": [{ "id": 147, "name": "Redactar respuesta a cliente" }],
  "connectors": [{ "id": 8, "name": "gmail", "display_name": "Gmail" }]
}

Nota

Los bloques son condicionales por scope: sin libraries:read la clave libraries no viene — no viene vacía, no viene. Una lista vacía se leería como «no hay ninguna», y eso sería falso. Programá con catalog.libraries ?? [].

Elegir el modelo

model_id viaja por turno. Sin él se usa el del chat, y sin ese el de la empresa. Los ids válidos son los de catalog.models, que solo trae modelos de tipo COMPLETION: un modelo de embedding nunca aparece ahí, porque mandarlo produciría un turno que falla del otro lado.

Límites

  • Hasta 20 ids por tipo y 50 en total. Pasarse devuelve 422 api_v1_too_many_attachments, con el campo culpable en data.
  • Un id fuera del alcance de la credencial también rechaza el turno, y tampoco consume la idempotencia.
  • Adjuntar mucho no siempre es mejor: cada biblioteca agrega contexto que el modelo tiene que atravesar, y eso se paga en tokens.

Conectores

Adjuntar un mcp_server_id habilita las herramientas de ese conector para el turno — pero solo funcionan las que el usuario ya conectó desde la aplicación. Si el modelo intenta usar una sin autorizar, el turno se detiene con message.action_required de tipo auth_required, y desde la API la única salida es cancelarlo.

Sugerencia

Con conectores conviene permission_mode: "manual": una herramienta de Gmail o Calendar tiene efectos fuera de NiuCore, y aprobarla explícitamente es lo que evita sorpresas. Ver Interacciones.

Tu propio metadata

metadata es un objeto libre que se guarda con el turno y se devuelve tal cual en la respuesta y en el listado de mensajes. No llega al modelo: es para correlacionar de tu lado. Máximo 2048 bytes serializados.

JSON
{
  "content": "…",
  "metadata": {
    "ticket": "8842",
    "channel": "whatsapp",
    "customer_id": "c-91021"
  }
}

Es la forma recomendada de atar un turno de NiuCore a un registro tuyo: GET /chats/{id}/messages lo devuelve en cada mensaje, así que podés reconstruir la trazabilidad sin mantener una tabla de correspondencias.