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.
{
"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": []
}
}| Campo | Qué adjunta | Scope adicional |
|---|---|---|
workspace_ids | Bibliotecas enteras. El modelo busca dentro cuando lo necesita. | libraries:read |
file_ids | Archivos concretos, sin traer su biblioteca entera. | libraries:read |
skill_ids | Instrucciones 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_ids | Conectores 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.
Qué podés adjuntar
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{
"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 endata. - 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.
{
"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.