Ir al contenido

Conceptos centrales

ConceptoEn una frase
WorkbookContenedor de trabajo (≠ archivo). Agrupa tablas, sheets, versiones y políticas
SourceEl archivo original subido (immutable). auto (todo automático) / staged (control explícito: analyze → corregir el parse-spec → materialize)
TableDataset tipado, con ID de fila y versionado. El objeto principal del agente. Hay base (editable) y derived (salida de un transform)
TransformPlantilla SQL (Jinja2) / Python. Liga {{ arg }} a las tablas de entrada vía args y produce un artifact de salida. La unidad del lineage
SheetComposición de presentación sin datos propios. Sus blocks referencian tablas (n:m) y render las compone en un xlsx
ChartChart creado por el agente. Tiene config y recipe (la herramienta y los parámetros con que se generó)
Versionversions.commit(label) = etiqueta inmutable sobre un snapshot. revert restaura las tablas derivadas con el mecanismo de snapshots (re-ejecución del DAG) — las ediciones de filas de las tablas base se gestionan en el historial del log de edits
JobHandle de una operación asíncrona (p. ej. upload con async=true). jobs.wait() o el webhook job.completed
WorkspaceObjeto frontera (miembros, facturación, gobernanza). Un desarrollador puede administrar varios workspaces con una Account API key

Toda escritura exige expected_version (el etag de la tabla). Si no coincide: 409 — el SDK lanza ConflictError. No hay reintento automático (para no sobrescribir en silencio una edición concurrente): el contrato es releer (rows() devuelve edit_version) → reaplicar → reintentar.

page = client.tables.rows(wb, "sales")
client.tables.upsert_rows(
wb, "sales",
rows=[{"__d2b_row_id": 3, "amount": 999}], # row_id present = update, absent = insert
expected_version=page["edit_version"],
)

El SDK adjunta automáticamente Idempotency-Key a toda llamada de mutación (la misma clave + el mismo body reproducen la respuesta original). Un reintento de red no aplica la operación dos veces. Si llamas al HTTP directamente, agrega el header por tu cuenta.

Modelo de promoción (el raw no desaparece en silencio)

Sección titulada «Modelo de promoción (el raw no desaparece en silencio)»

La ingesta auto construye las tablas estructuradas de D2B a partir de una copia raw fiel de cada hoja. Las tablas estructuradas toman el nombre del archivo y las tablas raw se degradan a state=archived (el registro y el lineage permanecen). Con tables.lineage() puedes remontarte hasta las tablas raw y, si hace falta, rematerializar la hoja original con tables.unarchive(). Con structuring=defer las tablas raw aterrizan primero y la misma promoción ocurre cuando termina la estructuración; si para entonces habías creado derivados sobre una tabla raw, la promoción se pospone automáticamente (no rompe lo que hay aguas abajo).

Las escrituras interactivas, como editar filas, no recalculan de inmediato las tablas derivadas aguas abajo: las marcan como stale. Se detecta en freshness: {stale, stale_since} de GET .../tables/{name}, y POST /workbooks/{id}/recompute (MCP recompute_stale) recalcula todo junto en orden de dependencias. La ejecución de un transform propaga de forma eager (la salida siempre está fresca).

Las políticas por etiqueta de columna × rol (mask / deny) se fuerzan en la capa de datos. Las columnas enmascaradas vuelven como NULL tipado y se anuncian en masked_columns. Puedes hacer un dry-run previo con GET .../tables/{name}/access. La misma política aplica a export, profile, MCP e incluso al preview del archivo crudo: no hay rutas para esquivarla (en un workbook con gobernanza, el preview / revise de bytes crudos se rechaza).

JSON Schema de fila (para constrained decoding)

Sección titulada «JSON Schema de fila (para constrained decoding)»

Un OpenAPI estático no puede tipar el contenido de las tablas (la forma de la fila depende de los datos). Por eso puedes obtener en tiempo de ejecución el “JSON Schema de una fila” de cada tabla:

GET /api/v1/workbooks/{wb}/tables/{name}/schema?format=json-schema

En MCP, get_schema(..., include_json_schema=true). El schema devuelto se genera desde el conjunto de columnas que queda tras aplicar las políticas (las columnas deny no aparecen), con additionalProperties: false, todas las celdas nullable y __d2b_row_id como “omitido = insert / presente = update”. Un harness de agente puede usarlo para restringir la generación del payload de upsert_rows (constrained decoding).

  • snapshot: commit inmutable. POST /snapshots / POST /snapshots/{id}/restore
  • version: un nombre sobre un snapshot (POST /versions, POST /versions/{label}/revert)
  • op log: registra toda mutación en orden (GET /ops). Un op de filas se revierte con POST /ops/{id}/undo (el historial es append-only)
  • branch / merge: con record_branch=true en POST /export se congelan las filas del momento de exportar, y el archivo editado se reincorpora con POST /tables/{name}/merge como 3-way merge a nivel de celda con el ID de fila como clave. Las celdas cambiadas en ambos lados van a la cola de conflicts