Logo

Cotera Tools

Authentication Type: No Authentication
Description: Access and query datasets from your Cotera datagraph with powerful filtering capabilities.


Dataset Query Operations

Execute queries against datasets in your organization's datagraph.

Query Dataset

Query a Cotera dataset resource by id (full data, not the capped preview), or an ERA model relation by symbol from the org's datagraph. Exactly one of datasetId or symbol must be set.

Operation Type: Query (Read)

Query Modes:

  • Dataset-resource mode (datasetId set — common case): Queries the full data of a Cotera dataset resource. symbol and the symbol-mode filter/sort fields are ignored.
  • Symbol mode (symbol set — advanced): Queries an ERA model relation in the org's datagraph through the org's warehouse.

If neither datasetId nor symbol is provided, the tool errors: "Provide a dataset (datasetId) or an ERA model relation (symbol) to query."

Access Requirements: Dataset-resource mode requires write/edit access on the dataset. The load doubles as the access check — a caller without edit permission receives a terminal error.

Parameters:

Dataset-resource mode parameters:

  • datasetId string (nullable, default: null): UUID of a Cotera dataset resource to query. When set, symbol is ignored.
  • conditions array (nullable, default: null): Structured filter conditions, ANDed together. Ignored when query is set.
    • column string (required): The column to filter on.
    • op string (required): Comparison operator. One of: eq, neq, contains, gt, lt, gte, lte, is_null, is_not_null. is_null and is_not_null take no value; contains is a substring match (LIKE %value%). A value-taking operator with an empty or blank value is skipped.
    • value string (nullable): The comparison value; not used for is_null / is_not_null.
  • columns array of strings (nullable, default: null): Output columns to return. null or empty returns every column.
  • limit number (nullable, default: 100): Maximum rows to return. In dataset-resource mode results are additionally capped at 1,000 rows.
  • query string (nullable, default: null): Advanced: a single read-only SQL SELECT (or WITH … SELECT) selecting from the relation named dataset — e.g. select name from dataset where id = '123'. Runs against every row, not a sample. Takes precedence over conditions. Must begin with SELECT or WITH; multiple statements and mutating keywords (insert, update, delete, merge, drop, create, alter, truncate, grant, revoke, call, copy, execute, exec, vacuum, attach, pragma, set) are rejected.

Symbol mode parameters (ignored in dataset-resource mode):

  • symbol string (nullable, default: null): An ERA model relation symbol to query. Leave null when querying a dataset resource by id.
  • filterColumn string (nullable, default: null): Column to apply a substring (LIKE) filter on.
  • filterValue string (nullable, default: null): Value for the filterColumn substring filter.
  • dateColumn string (nullable, default: null): Date column for an inclusive date-range filter.
  • startDate string (nullable, default: null): Inclusive start date for dateColumn.
  • endDate string (nullable, default: null): Inclusive end date for dateColumn.
  • sortColumn string (nullable, default: null): Column to sort results by.
  • sortDirection 'asc' | 'desc' (nullable, default: null): Sort direction; defaults to asc when sortColumn is set.

Returns:

  • symbol string: A label for the source queried — the dataset's name in dataset-resource mode, the ERA symbol in symbol mode.
  • data array of objects: The matching rows.
  • metadata object:
    • rowCount number: Number of rows returned.
    • columns array of strings: The columns actually returned — the requested columns, or (when none were requested) the columns present in the returned rows; empty when no rows.

Behavior Notes:

Dataset-resource mode reads full data, not the capped preview:

  • CSV and manual datasets are queried via DuckDB over the whole parquet file, with pending grid edits folded in first — so recent in-app edits are visible.
  • Warehouse-backed datasets are queried against the customer's warehouse.

Condition columns and output columns are validated against the dataset's real columns before running — an unknown column returns a terminal error naming the missing column(s) and listing the available ones.

In symbol mode, filterColumn, dateColumn, sortColumn, and selected columns are validated against the relation's attributes — an unknown column returns a terminal error listing the available columns.

Error Cases:

  • datasetId refers to a dataset that does not exist → terminal error.
  • Dataset type does not support querying → terminal error.
  • Warehouse-backed dataset with no reachable warehouse connection → terminal error.
  • A column in conditions or columns is not present in the dataset → terminal error listing the missing column(s) and available ones.

Example Usage:

Dataset-resource mode with structured conditions and column selection:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "conditions": [
    { "column": "status", "op": "eq", "value": "open" },
    { "column": "amount", "op": "gt", "value": "1000" }
  ],
  "columns": ["id", "name", "amount"],
  "limit": 200
}

Advanced raw SELECT:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "query": "select name from dataset where id = '123'"
}

Symbol mode:

{
  "symbol": "customer_transactions",
  "filterColumn": "transaction_type",
  "filterValue": "purchase",
  "limit": 500
}

Dataset Write Operations

Write values into a dataset — update existing rows or append new ones.

Write to Dataset

Write values into a Cotera dataset: update rows selected by key columns (e.g. the row whose email is X), correct rows by id, or append new rows. Columns must already exist; add them first with coco/dataset-edit. Read the dataset first with coco/dataset-read to learn its columns and row ids.

Operation Type: Mutation (Write)

Access Requirements: Requires dataset write/edit access. The tool checks a precondition on the target dataset and returns a terminal error if the caller lacks access.

Parameters:

  • datasetId string (required): UUID of the dataset to write to.
  • keyColumns array of strings (nullable, default: null): Columns that identify which row to write to, e.g. ["email"]. Each row's values for these columns select the row; the remaining values are written into it. Leave null to append new rows, or to address rows by rowId / rowKey instead.
  • rows array of objects (required): Rows to write, up to 200 per call, applied as one atomic batch. To correct scattered cells, send one entry per row naming just the columns that change.
    • rowKey string (nullable, default: null): The dataset's declared row-key value — a business key like an email or account id, or a dataset trigger's __meta/rowKey. Resolved through the dataset's declared key columns, so it identifies the row by value whatever its type. Prefer this to write back to the row a dataset trigger fired for. Ignored when keyColumns is set.
    • rowId string (nullable, default: null): An existing internal row id (from coco/dataset-read) writes into that row. Ignored when keyColumns or rowKey is set. null (and no rowKey) appends a new row.
    • values object (required): Column name to value (string, number, boolean, or null). Only the columns named here are written; the rest of the row is left alone. Every column must already exist.
  • idempotencyKey string (nullable, default: null): Leave null. Repeating an identical write is deduplicated; set a different value here when you deliberately want to append a second identical row.

A row is addressed in one of four ways, most specific first: by keyColumns (selects it on values it already holds), by rowKey (the declared row-key value), by rowId (an internal id), or not at all, which appends.

Returns:

  • datasetId string: UUID of the dataset that was written to.
  • inserted array of objects: The rows appended by this call.
    • rowId string: Internal id of the newly appended row.
  • rowsInserted integer: Number of new rows appended.
  • rowsUpdated integer: Number of existing rows updated.
  • cellsWritten integer: Total cells written, counting both updates and inserts (an append of two values reports cellsWritten: 2).
  • summary string: A plain-language confirmation of what landed, e.g. "Wrote to dataset <id>: inserted 1 new row (2 cells written)." — suitable for relaying directly to the user.

Behavior Notes:

  • An update writes one cell per named column rather than replacing the row, so columns the caller did not mention keep their values instead of being nulled.
  • An append reports rowsUpdated: 0 by design; success is signaled by rowsInserted, inserted, cellsWritten, and the summary string. (A previous version reported cellsWritten: 0 for appends; it now counts insert cells too.)
  • A row that names no row and writes nothing is rejected with an actionable error instead of silently appending a blank row: a row with no rowId, no rowKey, no keyColumns, and empty values returns "Row N has no row identifier and no values, so it names no row and writes nothing...", and a row with an explicitly empty identifier and no keyColumns returns "Row N has an empty row identifier, so it names no row...".
  • Sending more than 200 rows in one call returns a terminal error asking you to split the write.
  • Repeating an identical write is deduplicated. The dedup key combines the invocation (the ATC run id) with any explicit idempotencyKey, so a Restate replay of the same workflow step folds to one write while a genuinely new run writes again. Set idempotencyKey to a new value to deliberately append a second identical row.

Example Usage:

Append a new row (keyColumns null):

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "keyColumns": null,
  "rows": [{ "values": { "email": "jane@acme.com", "status": "active" } }]
}

Returns:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "inserted": [{ "rowId": "r_01h..." }],
  "rowsInserted": 1,
  "rowsUpdated": 0,
  "cellsWritten": 2,
  "summary": "Wrote to dataset a1b2c3d4-e5f6-7890-abcd-ef1234567890: inserted 1 new row (2 cells written)."
}

Update the row whose email is jane@acme.com, addressed by keyColumns:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "keyColumns": ["email"],
  "rows": [{ "values": { "email": "jane@acme.com", "status": "churned" } }]
}

Returns rowsUpdated: 1, rowsInserted: 0, cellsWritten: 1, and summary: "Wrote to dataset ...: updated 1 existing row (1 cell written)."

A mixed batch — update one row by rowId and append another — in a single atomic call:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "keyColumns": null,
  "rows": [
    { "rowId": "r_01h...", "values": { "status": "renewed" } },
    { "values": { "email": "new@acme.com", "status": "trial" } }
  ]
}

Returns rowsUpdated: 1, rowsInserted: 1, cellsWritten: 2, and summary: "Wrote to dataset ...: updated 1 existing row and inserted 1 new row (2 cells written)."


Dataset Creation Operations

Create datasets seeded from your organization's connected warehouse.

Create Warehouse Dataset

Create a Cotera dataset seeded from a SELECT query run against the organization's connected warehouse. The dataset kind (Snowflake or Postgres) is determined automatically from the warehouse connection. Use this to build a dataset from existing warehouse tables; use coco/warehouse-schema to discover the available tables and columns first.

Operation Type: Query (Read)

Parameters:

  • name string (required): Name for the new dataset — e.g. "Enterprise accounts". Defaults to 'Untitled dataset' if an empty string is passed.
  • sourceQuery string (required): A single read-only SELECT in the connected warehouse's own SQL dialect, run verbatim against it. When the user wants the full table, use SELECT * FROM <schema>.<table> rather than enumerating columns.
  • rowKeyColumns array of strings (required): The columns of the query result that identify a row, in order (1–16 columns). Must be a stable business key — every column listed must be returned by the SELECT, or the seed fails.
  • cadence string (nullable, default: null): Optional cron expression for how often the dataset is re-scanned for warehouse changes. null leaves no scheduled re-scan.
  • cadenceTimezone string (nullable, default: null): IANA timezone the cadence cron is interpreted in. null defaults to UTC. Ignored when cadence is null.
  • folderId string (nullable, default: null): UUID of the folder to place the dataset in. null uses the conversation's folder when it has one.

Returns:

  • datasetId string: UUID of the created dataset.
  • name string: The dataset name as stored.
  • importId string: UUID of the warehouse seed import job.
  • importStatus string: Final status of the seed — one of 'importing', 'ready', or 'failed'. The tool waits for the seed to settle before returning, so this reflects the outcome.
  • importError string (nullable): The seed's failure reason when importStatus is 'failed', otherwise null.

Warehouse Kind Selection:

The dataset kind is resolved automatically from the organization's warehouse connection vendor:

  • Snowflake connection → Snowflake dataset
  • Postgres connection → Postgres dataset
  • BigQuery, Redshift, DuckDB → not supported; the tool returns a terminal error

Error Cases:

  • If the organization has no connected warehouse, the tool returns a terminal error asking the user to connect one (Settings → Warehouse).
  • If the connected warehouse vendor is not supported (BigQuery, Redshift, DuckDB), the tool returns a terminal error naming the vendor and supported options.
  • If rowKeyColumns is empty or exceeds 16 columns, the tool returns a terminal error.
  • If a declared row key column is not present in the query result, the seed fails and importStatus is 'failed'.

Behavior Notes:

  • The tool adds a Dataset artifact to the conversation once the dataset is created.
  • Because the seed runs asynchronously, do not read the dataset immediately after creation — the rows may not yet have arrived. The returned importStatus is the settled state.
  • generatesReceipts is false.

Example Usage:

Create a dataset from a Snowflake table, keyed by account ID:

{
  "name": "Enterprise accounts",
  "sourceQuery": "SELECT * FROM analytics.public.accounts WHERE tier = 'enterprise'",
  "rowKeyColumns": ["account_id"],
  "cadence": "0 6 * * *",
  "cadenceTimezone": "America/New_York"
}

Create a dataset from a Postgres table in a specific folder:

{
  "name": "Open support tickets",
  "sourceQuery": "SELECT id, subject, status, created_at FROM helpdesk.tickets WHERE status != 'closed'",
  "rowKeyColumns": ["id"],
  "folderId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Dataset Workflow Operations

Trigger and manage automated workflows bound to datasets.

Run Dataset Workflows

Run the workflows bound to a dataset over its rows — the chat equivalent of the dataset grid's Run menu. Use all to replay every matching row (including rows that already succeeded), or needs-run to fire only the rows that still need a run.

Operation Type: Mutation (Write)

Access Requirements: Requires dataset write/edit access. If the caller does not have edit permission on the dataset, the tool returns a terminal error.

Parameters:

  • datasetId string (required): UUID of the dataset whose bound workflows to run. Use coco/dataset-read (its automations list) or coco/search-cotera to find it.
  • scope string (nullable, default: null): Which rows to run. null is treated as 'all'.
    • 'all' — Replays every row that meets each trigger's criterion, including rows that already ran. Uses the same server-side replay as the dataset grid's "All rows" option: unbounded, crash-safe, and handles large datasets. Resets the observed trigger/workflow state for targeted pairs; the evaluator then re-runs rows over the next few minutes.
    • 'needs-run' — Force-fires only rows a workflow still owes a run: rows that have never run, went stale after the row changed, or were cancelled. Enumerates rows to find outstanding ones, so it is capped at 5,000 rows. Datasets larger than the cap must use 'all'.
  • workflowIds array of strings (nullable, default: null): UUIDs of the specific workflows to run, from the dataset's automations. null runs every workflow bound to the dataset. Any UUID not bound to this dataset is silently ignored.

Returns:

  • datasetId string: UUID of the dataset that was targeted.
  • scope string: The resolved scope ('all' or 'needs-run').
  • groupId string: UUID batch identifier shared by all workflow runs created by this call. Can be used to identify or cancel the runs later.
  • targetedWorkflows array of objects: Workflows actually targeted after narrowing to workflowIds.
    • id string: Workflow UUID.
    • name string: Workflow display name.
  • triggersRun number: Number of dataset triggers that had at least one targeted workflow.
  • dispatchedWorkflowRuns number (nullable): (needs-run only) Number of workflow runs actually dispatched. null for 'all'.
  • replayedPairs number (nullable): (all only) Number of (trigger, workflow) pairs whose observed state was reset so the evaluator replays their rows. null for 'needs-run'.
  • rowsConsidered number (nullable): (needs-run only) Number of rows scanned to find outstanding runs. null for 'all'.
  • truncated boolean: true when needs-run hit the 5,000-row cap and some outstanding rows may not have been fired. Always false for 'all'.
  • summary string: Human-readable sentence describing what ran (or why nothing ran), suitable for relaying directly to the user.

No-op Cases:

The following situations are not errors. The tool returns zero counts and a summary explaining why:

  • The dataset has no live automations watching it.
  • The dataset has automations but no workflows are bound to them yet.
  • The provided workflowIds are not bound to this dataset.

Example Usage:

Run all workflows on a dataset, replaying every matching row:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "scope": "all"
}

Run only the rows that still need a run, for a specific workflow:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "scope": "needs-run",
  "workflowIds": ["f1e2d3c4-b5a6-7890-1234-abcdef567890"]
}

Dataset Library Operations

Promote chat-scoped uploaded datasets into your organization's permanent dataset library.

Save Uploaded Dataset to Library

Promotes an existing chat-scoped uploaded dataset into the permanent library. The dataset already exists from the upload — this operation saves it to the library without copying rows or creating a new dataset. Use the coco/dataset-create tool only for net-new datasets; calling it on an already-uploaded dataset would duplicate the data.

Operation Type: Query (Read)

Authentication Type: No Authentication

Parameters:

  • datasetId string (required): UUID of the chat-scoped uploaded dataset to save into the library. Use coco/dataset-read or coco/search-cotera to find the UUID of the uploaded dataset.
  • name string (nullable, default: null): Optional new display name for the dataset. null keeps the current name (the original uploaded filename).

Returns:

  • datasetId string: The dataset ID of the promoted dataset.
  • name string: The dataset name — the provided name if supplied, otherwise the original uploaded filename.
  • promoted boolean: Always true on success.

Example Usage:

Promote an uploaded dataset, keeping its original filename as the name:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Promote an uploaded dataset and give it a new display name:

{
  "datasetId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Q3 Customer Survey Responses"
}

Common Use Cases

Data Exploration:

  • Query datasets to understand data structure and available columns
  • Explore sample data from various datasets in your organization's datagraph
  • Use filtering to examine specific subsets of data for pattern analysis

Data Debugging:

  • Investigate data quality issues by filtering for specific values or conditions
  • Verify data transformations by comparing input and output datasets
  • Check for missing or anomalous data patterns using targeted queries

Analytics and Reporting:

  • Extract filtered datasets for use in business intelligence and reporting tools
  • Query transaction data with date range or category filters for financial analysis
  • Retrieve customer data segments for targeted marketing campaign analysis

Development and Testing:

  • Access sample datasets during application development and testing
  • Validate data pipeline outputs by querying intermediate and final datasets
  • Monitor data freshness and completeness across different data sources in your datagraph