Saltar al contenido principal

Bases de datos

Una tabla de Nirvai es una planilla con reglas. Se ve como filas y columnas, pero cada columna sabe qué está dispuesta a contener: una columna de estado acepta cuatro palabras y ninguna otra, una de responsable acepta personas que realmente trabajan contigo, una de vínculo acepta una fila específica de otra tabla específica. Tu asistente no puede escribir lo que se le ocurra en una celda — primero le pregunta a la columna. Todo lo de abajo corre a través de nirvai_execute en el área db; la gramática de alias está en la referencia de MCP.

Siempre por id, nunca por nombre

Casi seguro tienes dos tablas llamadas Leads — una del año pasado y la que realmente usas. Son tablas distintas con la misma etiqueta. Tu asistente resuelve primero el id estable de la tabla, y cada verbo de abajo se dirige por ese id, nunca por el nombre que vio en la conversación.


Los verbos

VerboPermisoQué hace
db.selectreadLee filas, con una cola SELECT-only en crudo — más abajo.
db.get_richreadLee el cuerpo de página de un registro: el documento que vive dentro de la fila.
db.insertwriteAgrega filas. Éxito parcial por fila: las buenas entran, las malas vuelven con su motivo.
db.updatewriteCambia las filas que cumplen una condición. Todo o nada — un valor inválido y no se escribe nada.
db.update_richwriteReemplaza el cuerpo de página de un registro. Protegido para no descartar medios en silencio.
db.editwriteCambia la estructura de la tabla — agregar, eliminar, cambiar el tipo o renombrar columnas.
db.create_databasecreateCrea un espacio nuevo para contener tablas.
db.create_tablecreateCrea una tabla dentro de un espacio, con sus columnas y vistas.
db.proposecreateRedacta una configuración revisable de varias tablas — un espacio, sus tablas, columnas y vistas. haces clic en Crear.
db.deletedestructivoRetenido. Se rechaza con cualquier token — borrar no es posible por la conexión.

El descubrimiento viene de las herramientas maestras: nirvai_list_resources para "qué tablas tengo", y nirvai_describe para "qué es exactamente esta" — sus columnas, sus valores permitidos, quién puede ser asignado, con qué tablas se vincula y tu nivel de permiso. Eso se lee en vivo, cada vez.

Dónde lo terminas tú

db.propose no construye nada. Te entrega una página en /external/databases/…, y una sola propuesta puede traer una configuración completa de varias tablas — un espacio más varias tablas, sus columnas y sus vistas. La página muestra una tarjeta por paquete, cada una con su propio botón de Crear.

  • Es un formulario, no un recibo. Cambia el tipo o el nombre de una columna, descarta una tabla que no quieres, y recién ahí crea — paquete por paquete, en el orden que prefieras.
  • Tienes que haber iniciado sesión, y solo tú puedes abrirla. Un enlace de propuesta no se comparte.
  • db.insert y db.update no pasan por una página de revisión. Las filas entran directo; la revisión protege la creación de estructura.
  • Una vez creado, al volver a abrirla verás Creado ✓ y no se hace una segunda copia — ver la referencia de MCP.

Lectura: db.select

condition es una cola SELECT-only en crudo — un WHERE, un ORDER BY, un LIMIT. Cualquier cosa que modificaría datos se rechaza de plano.

nirvai_execute(
alias = "db.select",
args = { table_session: "…",
condition: "WHERE status = 'Open' ORDER BY id DESC LIMIT 50",
columns: ["id", "name", "status", "owner"] },
description = "Listar los negocios abiertos, del más nuevo al más viejo"
)
→ { rows, row_count, truncated }

Siempre se aplica un techo de filas. truncated: true significa que había más — tu asistente pagina con su propio LIMIT/OFFSET en vez de suponer que vio todo.


Escribir valores: la gramática de valores etiquetados

Las columnas simples reciben un valor plano. Las columnas estructuradas reciben una etiqueta: un objeto pequeño cuya única clave empieza con $ y nombra qué tipo de cosa quieres decir.

Tipo de columnaCómo lo escribe tu asistente
texto, número, fecha, casilla, email, url, teléfono, calificación, moneda, progreso, colorEl valor plano — "Acme", 42, "2025-03-01", true
opción única / estado{"$select": "Open"} (o el texto de la opción a secas)
opciones múltiples{"$multi_select": ["Urgent", "Renewal"]}
persona{"$person": "jane@company.com"}
vínculo a otro registro{"$relation": {"table_session": "…", "record_id": 42}}
archivo{"$file": "quote.pdf"}
agente{"$agent": "…"}

Dos reglas lo hacen seguro. Las opciones son cerradas — las palabras que acepta una columna de opciones vienen de nirvai_describe, no de la imaginación de tu asistente, y un valor no listado se rechaza en vez de inventarse; lo mismo vale para un responsable que la tabla no puede asignar o un vínculo a una fila que no existe. Y los errores son estructurados, nunca errores crudos de la base de datos: recibes un motivo con nombre — INVALID_OPTION, PERSON_NOT_FOUND, UNKNOWN_COLUMN, PROTECTED_COLUMN, OUT_OF_RANGE, RELATION_RECORD_NOT_FOUND — con la columna y, cuando corresponde, el conjunto permitido. Una escritura fallida le dice a tu asistente cómo corregirse.

Las columnas protegidas nunca se escriben por esta vía

El id de un registro, sus fechas de creación y actualización, su cuerpo de página y su ícono, y todo lo que gestiona el sistema de tareas de agente nunca son escribibles por la vía de registros ni aparecen como campos escribibles. El cuerpo de página se lee y se escribe con db.get_rich / db.update_rich, que reemplaza el cuerpo completo — por eso tu asistente lo lee primero y se niega a descartar medios salvo que se lo indiques.


Ejemplo real: encontrar, aprender, leer, escribir

nirvai_list_resources(kind = "databases")
→ las tablas que tienes, cada una con su id estable

nirvai_describe(kind = "databases", ref = "<id de la tabla>")
→ columnas, opciones permitidas, asignables, relaciones, vistas, tu nivel de permiso

nirvai_execute(
alias = "db.select",
args = { table_session: "…", condition: "WHERE stage = 'Qualified' LIMIT 20" },
description = "Ver qué leads ya están calificados"
)

nirvai_execute(
alias = "db.insert",
args = { table_session: "…",
records: [{ "Company Name": "Acme",
"Stage": {"$select": "Qualified"},
"Owner": {"$person": "jane@company.com"},
"Value": 48000 }] },
description = "Agregar a Acme al pipeline como lead calificado"
)
→ { inserted_ids, inserted_count, row_errors }

El paso de describe no es cortesía opcional: es donde se confirma que "Qualified" es una opción real y que jane@company.com es alguien realmente asignable, antes de escribir nada.


Cambiar la estructura: db.edit

Agregar una columna es seguro. Eliminarla, cambiarle el tipo o renombrarla es destructivo — los datos que contiene se pierden. Por eso db.edit funciona en dos tiempos: primero una corrida en seco, que devuelve el plan de cambios (qué se agregaría, eliminaría, cambiaría de tipo o renombraría, y qué vistas guardadas se verían afectadas) y no toca nada; después la edición real, que para un cambio destructivo exige una confirmación explícita en la llamada y se rechaza sin ella. Se espera que tu asistente te muestre el plan antes de confirmar nada.


Límites y garantías

  • Tu nivel de permiso viene de la propiedad, no del token. Eres dueño de la tabla → acceso completo; eres admin de la organización → escritura; eres miembro de la organización → lectura. Una tabla en nivel lectura rechaza una escritura incluso cuando el token trae el permiso write. El nivel aparece en nirvai_describe.
  • insert es parcial, update es total. Insertar diez filas puede escribir ocho e informar dos; una actualización se aplica completa o no se aplica.
  • Nada se crea a tus espaldas. db.propose redacta una forma — espacios, tablas, columnas, vistas — nunca filas, nunca datos. Se vuelve real cuando haces clic en Crear, una sola vez; volver a abrir la página de revisión después la muestra como ya creada y no la crea de nuevo.
  • Borrar es imposible. db.delete se rechaza con cualquier token, siempre.
  • Las escrituras aparecen de inmediato en tu vista de tabla abierta y en el Feed de Actividad.

Siguiente paso