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 (
datasetIdset — common case): Queries the full data of a Cotera dataset resource.symboland the symbol-mode filter/sort fields are ignored. - Symbol mode (
symbolset — 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,symbolis ignored. - conditions
array(nullable, default:null): Structured filter conditions, ANDed together. Ignored whenqueryis 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_nullandis_not_nulltake no value;containsis 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 foris_null/is_not_null.
- column
- columns
array of strings(nullable, default:null): Output columns to return.nullor 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 SQLSELECT(orWITH … SELECT) selecting from the relation nameddataset— e.g.select name from dataset where id = '123'. Runs against every row, not a sample. Takes precedence overconditions. Must begin withSELECTorWITH; 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. Leavenullwhen 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 thefilterColumnsubstring filter. - dateColumn
string(nullable, default:null): Date column for an inclusive date-range filter. - startDate
string(nullable, default:null): Inclusive start date fordateColumn. - endDate
string(nullable, default:null): Inclusive end date fordateColumn. - sortColumn
string(nullable, default:null): Column to sort results by. - sortDirection
'asc' | 'desc'(nullable, default:null): Sort direction; defaults toascwhensortColumnis 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.
- rowCount
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:
datasetIdrefers 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
conditionsorcolumnsis 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. Leavenullto append new rows, or to address rows byrowId/rowKeyinstead. - 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 whenkeyColumnsis set. - rowId
string(nullable, default:null): An existing internal row id (fromcoco/dataset-read) writes into that row. Ignored whenkeyColumnsorrowKeyis set.null(and norowKey) appends a new row. - values
object(required): Column name to value (string,number,boolean, ornull). Only the columns named here are written; the rest of the row is left alone. Every column must already exist.
- rowKey
- idempotencyKey
string(nullable, default:null): Leavenull. 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.
- rowId
- 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 reportscellsWritten: 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: 0by design; success is signaled byrowsInserted,inserted,cellsWritten, and thesummarystring. (A previous version reportedcellsWritten: 0for 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, norowKey, nokeyColumns, and emptyvaluesreturns"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 nokeyColumnsreturns"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. SetidempotencyKeyto 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, useSELECT * 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.nullleaves no scheduled re-scan. - cadenceTimezone
string(nullable, default:null): IANA timezone the cadence cron is interpreted in.nulldefaults to UTC. Ignored whencadenceis null. - folderId
string(nullable, default:null): UUID of the folder to place the dataset in.nulluses 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 whenimportStatusis'failed', otherwisenull.
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
rowKeyColumnsis 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
importStatusis'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
importStatusis the settled state. generatesReceiptsis 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. Usecoco/dataset-read(itsautomationslist) orcoco/search-coterato find it. - scope
string(nullable, default:null): Which rows to run.nullis 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'sautomations.nullruns 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 toworkflowIds.- id
string: Workflow UUID. - name
string: Workflow display name.
- id
- triggersRun
number: Number of dataset triggers that had at least one targeted workflow. - dispatchedWorkflowRuns
number(nullable): (needs-runonly) Number of workflow runs actually dispatched.nullfor'all'. - replayedPairs
number(nullable): (allonly) Number of (trigger, workflow) pairs whose observed state was reset so the evaluator replays their rows.nullfor'needs-run'. - rowsConsidered
number(nullable): (needs-runonly) Number of rows scanned to find outstanding runs.nullfor'all'. - truncated
boolean:truewhenneeds-runhit the 5,000-row cap and some outstanding rows may not have been fired. Alwaysfalsefor'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
workflowIdsare 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. Usecoco/dataset-readorcoco/search-coterato find the UUID of the uploaded dataset. - name
string(nullable, default:null): Optional new display name for the dataset.nullkeeps 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: Alwaystrueon 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