--- name: uru-datasets description: Create, inspect, query, change, restore, import, export, and use Uru Datasets with Uru tools, the Library, or Gems. --- # Uru Datasets Use the current Dataset tools and SDK. The server owns access, stable IDs, history, and saved writes. ## Agent workflow 1. Find a Dataset with `library_query`. 2. Read its metadata and schema with `dataset_get`. 3. Query rows with `dataset_query`. Use server filters, sort, pages, totals, and aggregates. 4. Change rows with `dataset_rows`. 5. Read saved changes with `dataset_history`. 6. Restore a supported saved state with `dataset_restore`. 7. For long work, use `dataset_jobs`, `dataset_job_get`, or `dataset_job_cancel`. Use `dataset_manage` with `op: create` to create a Dataset. Use `dataset_manage` with `op: update` to change metadata or schema. Use `dataset_external_source_get`, `dataset_external_source_put`, and `dataset_external_source_test` to manage a connected source. Use `dataset_external_source_sync` to start a refresh. It returns a command ID and job ID. Read [the contracts](references/contracts.md) before you poll, retry, or cancel that job. Use `dataset_sql` for one read-only SELECT or WITH statement. Use `dataset_sql_write` for one INSERT, UPDATE, or DELETE statement. A SQL write must name each Dataset and needs manage access. It changes at most 1,000 rows. Its changes to one Dataset save as one revision, or none of them save. Pass an `idempotency_key` with each SQL write, and reuse it only to recover that write after a lost reply. Read the SQL write rules in [the contracts](references/contracts.md). ## Files The Dataset Library screen imports and exports files. The current MCP and CLI tools do not offer a file import or export operation. If you only have Dataset tools and the file is available to you, map its columns to the Dataset schema and use bounded `dataset_rows` writes. Read the file limits and partial-save rules in [the contracts](references/contracts.md). ## Query rules - Use an exact schema name or stable property ID to name a field. - Schema properties hold the user's business data. A row is one record. - Use returned field values to answer the user. Show a row ID only when it helps the user identify or change a record. - `dataset_query` keeps record identity in `row_id` and customer values in `fields`. Use `fields.` for customer values, including a field named `id`. - In Gem SDK results, use `row.id` for record identity and `row.fields` for customer values. Use `row.id` when an advanced filter needs row identity. - Treat cursors as opaque. - Use server totals and aggregates for the full filtered set. - Use small pages for large Datasets. ## Row rules - Use `op: upsert` with `{row_id, fields}` row objects. - Set `row_id: null` to insert a row. Set it to the saved record UUID to update. - Put all customer values in `fields`, including fields named `id`, `row_id`, or `fields`. - Use `op: delete` with `row_ids` for a soft delete. - Use `op: restore` with `row_ids` to restore deleted rows. - A successful `dataset_rows` call means the database finished the change. - If a reply is lost, inspect current rows and history before you apply the write again. ## Gem SDK Hosted Gems use the `uru.datasets` context from `@uru-intelligence/app`. The SDK keeps business fields in `row.fields`; row identity, row version, and system timestamps stay in separate metadata fields. Preserve that boundary in Gem code and user output. ```ts const page = await uru.datasets.queryRows("sales", { where: [{ field: "status", op: "eq", value: "open" }], sort: [{ field: "amount", direction: "desc" }], limit: 50, }); const row = page.rows[0]; if (row?.rowVersion) { const mutation = datasetRowForMutation(row); await uru.datasets.upsertRowViews( "sales", [{ ...mutation, fields: { status: "won" } }], undefined, { idempotencyKey: `sales:${row.id}:${row.rowVersion}:status-won` }, ); } await uru.datasets.insertRows("sales", [{ name: "New account" }]); if (row) { await uru.datasets.deleteRows("sales", [row.id]); await uru.datasets.restoreRows("sales", [row.id]); } ``` `datasetRowForMutation(row)` keeps record identity and expected row version separate from customer fields. The example key uses the row ID, row version, and change. This gives each row and change a different key. Reuse the key only to recover the same write after a lost reply. Give a new intent a new key. Use `upsertRows` for flat inserts or simple writes; its `id` property names the record. Use `upsertRowViews` when customer fields include `id` or `fields`. Keep only the fields the user asked you to change. The SDK also supports `sqlWrite(sql, options)` for Gems that need SQL writes. Keep `dataset_mutation_allowed` false unless the Gem must write. Declare each Dataset binding in the Gem config. Do not ask the user for an Uru key or put a token in Gem source. Read [the exact contracts](references/contracts.md) for metadata, revisions, job IDs, file limits, and recovery.