Zum Inhalt springen

Kernkonzepte

KonzeptKurz gefasst
WorkbookArbeitscontainer (≠ Datei). Bündelt Tabellen, Sheets, Versionen und Policies
SourceDie hochgeladene Originaldatei (immutable). auto (vollautomatisch) / staged (explizite Kontrolle: analyze → parse-spec anpassen → materialize)
TableTypisiertes, versioniertes Dataset mit Zeilen-IDs. Das Hauptobjekt für Agenten. Existiert als base (editierbar) und derived (Output eines Transforms)
TransformTemplate in SQL (Jinja2) oder Python. Bindet {{ arg }} über args an Eingabetabellen und erzeugt ein Output-Artifact. Die Einheit der Lineage
SheetDarstellungskomposition ohne eigene Daten. Blocks referenzieren Tabellen (n:m); render setzt daraus ein xlsx zusammen
ChartVom Agenten erzeugtes Chart. Trägt config und recipe (das Tool und die Parameter der Erzeugung)
Versionversions.commit(label) = unveränderliches Label auf einem Snapshot. revert stellt abgeleitete Tabellen über den Snapshot-Mechanismus wieder her (DAG-Re-Run) — Zeilenänderungen an base-Tabellen werden über die Historie des Edits-Logs verwaltet
JobHandle für asynchrone Operationen (z. B. Upload mit async=true). jobs.wait() oder der Webhook job.completed
WorkspaceGrenzobjekt (Mitglieder, Abrechnung, Governance). Entwickler können mehrere Workspaces über einen Account API key verwalten

Jeder Schreibvorgang erfordert expected_version (das etag der Tabelle). Bei Abweichung kommt 409 — das SDK wirft einen ConflictError. Es gibt keinen automatischen Retry (damit parallele Änderungen nicht stillschweigend überschrieben werden): Der Vertrag lautet neu lesen (rows() liefert edit_version) → Änderung erneut anwenden → erneut versuchen.

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"],
)

Das SDK setzt bei jedem mutierenden Aufruf automatisch einen Idempotency-Key (gleicher Key + gleicher Body spielt die erste Antwort erneut aus). Netzwerk-Retries führen nicht zu doppelter Anwendung. Wer HTTP direkt aufruft, setzt den Header selbst.

Promotion-Modell (raw verschwindet nicht stillschweigend)

Abschnitt betitelt „Promotion-Modell (raw verschwindet nicht stillschweigend)“

Der auto-Ingest erzeugt D2Bs strukturierte Tabellen aus einer originalgetreuen Raw-Kopie jedes Blatts. Die strukturierten Tabellen übernehmen den Dateinamen, die Raw-Tabellen werden auf state=archived herabgestuft (Registry und Lineage bleiben erhalten). Über tables.lineage() lässt sich bis zu den Raw-Tabellen zurückverfolgen, und tables.unarchive() materialisiert das Originalblatt bei Bedarf erneut. Mit structuring=defer landen die Raw-Tabellen zuerst, und dieselbe Promotion erfolgt, sobald die Strukturierung fertig ist; wurden bis dahin auf einer Raw-Tabelle Ableitungen erstellt, unterbleibt die Promotion automatisch (Downstream wird nicht zerstört).

Interaktive Schreibvorgänge wie Zeilenänderungen berechnen abgeleitete Tabellen downstream nicht sofort neu, sondern markieren sie als stale. Sichtbar wird das über freshness: {stale, stale_since} in GET .../tables/{name}; POST /workbooks/{id}/recompute (MCP: recompute_stale) berechnet gesammelt in Abhängigkeitsreihenfolge neu. Die Ausführung von Transforms propagiert eager (der Output ist immer frisch).

Policies aus Spalten-Tags × Rollen (mask / deny) werden auf der Datenebene erzwungen. Maskierte Spalten kommen als typisiertes NULL zurück und werden über masked_columns gemeldet. Mit GET .../tables/{name}/access lässt sich das vorab per Dry-Run prüfen. Dieselbe Policy wirkt bis in Export, Profile, MCP und die Preview der Rohdatei — Umgehungswege gibt es nicht (in einem governed Workbook werden preview / revise auf rohen Bytes abgelehnt).

Eine statische OpenAPI-Spezifikation kann den Inhalt einer Tabelle nicht typisieren (die Form einer Zeile hängt von den Daten ab). Deshalb lässt sich zur Laufzeit für jede Tabelle das „JSON Schema für eine Zeile“ abrufen:

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

In MCP: get_schema(..., include_json_schema=true). Das zurückgegebene Schema wird aus der Spaltenmenge nach Anwendung der Spalten-Policies erzeugt (deny-Spalten erscheinen nicht), mit additionalProperties: false, allen Zellen nullable und __d2b_row_id als „weggelassen = insert / angegeben = update“. Ein Agenten-Harness kann damit den Payload für upsert_rows schon bei der Generierung einschränken (constrained decoding).

  • snapshot: unveränderlicher Commit. POST /snapshots / POST /snapshots/{id}/restore
  • version: ein Name auf einem Snapshot (POST /versions, POST /versions/{label}/revert)
  • op log: zeichnet alle Mutationen geordnet auf (GET /ops). Zeilen-Ops lassen sich mit POST /ops/{id}/undo invers anwenden (die Historie ist append-only)
  • branch / merge: record_branch=true bei POST /export friert die Zeilen zum Exportzeitpunkt ein; die bearbeitete Datei wird mit POST /tables/{name}/merge per 3-way merge auf Zellebene mit Zeilen-ID als Schlüssel zusammengeführt. Auf beiden Seiten geänderte Zellen landen in der Conflict-Queue