feat(dq): add create_dq_job + prepare_create_dq_job MCP tools#88
feat(dq): add create_dq_job + prepare_create_dq_job MCP tools#88vvaks0 wants to merge 7 commits into
Conversation
| return &chip.Tool[Input, Output]{ | ||
| Name: "prepare_create_dq_job", | ||
| Title: "Prepare to Create Data Quality Job", | ||
| Description: "Read-only companion to create_dq_job. Walks the data-quality wizard's discovery chain — resolve the edge " + |
There was a problem hiding this comment.
@vvaks0 I would be careful with too many Collibra-coded words within this which LLMs might have a challenge understanding. I know this is a companion tool, but it might make sense to explain a bit more what create_dq_job is, as well as be more explicit with words like 'job', 'edge', etc
There was a problem hiding this comment.
@EricWarnerCollibra My one concern is that job might be too generic and could collide with other tools. Would you prefer we unpack dq to data_quality?
There was a problem hiding this comment.
@vvaks0 yes, for sure on the tool name. I also might suggest adding more detail in the description, as an LLM may be viewing this tool independently. Overall, a few examples of user questions per tool, especially ones that are vague, are really helpful for us to understand behavior via evaluations
|
@vvaks0 do we have tests on the DQ side to ensure these API contracts will not change and will fail if someone modifies? |
|
…imental, clarify descriptions Addresses review feedback on #88. - Drop the internal /jobs/name, /jobs/{name}/exists, and /jobs/{name}/validJobName calls. Naming now relies on the PUBLIC create API: omitting jobName lets the server auto-assign a collision-free name (returned in the response); a user-supplied name is validated client-side against the server's rules (charset + no leading hyphen). - Rename the tools to create_data_quality_job / prepare_create_data_quality_job and expand their descriptions with plain-language framing (job/edge/connection) plus example user requests, for better LLM comprehension and evaluations. - Gate both tools behind a new "data-quality" experimental feature (off by default), like the Data Product skills, since they write to Collibra. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Adds a guided, multi-turn data-quality job creation flow for DEV-197672.
prepare_create_dq_job (read-only) walks the discovery chain — resolve the
edge connection, detect the job type (PUSHDOWN/PULLUP) from its capabilities,
and enumerate data sources, schemas, tables and columns — returning a
ready-to-use plan. It also resolves the location from a catalog Table asset
(id / URL / name) for the table-asset-page entry point.
create_dq_job builds and submits the job via the PUBLIC DQ API
(POST /rest/dq/1.0/jobs) behind a confirm-checkpoint preview. It supports
column selection, a single-column row filter, row sampling, time-slice
scheduling (${rd}/${rdEnd} composed into a dialect-aware source query),
recurring schedules, monitors + adaptive settings, notifications, Pullup
sizing / Parallel JDBC, and Pushdown compute. Discovery uses internal BFF
endpoints (the public DQ API exposes no connection/edge metadata browse).
Validated end-to-end on a live stack: create -> persist -> run FINISHED.
Refs: DEV-197672
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…imental, clarify descriptions Addresses review feedback on #88. - Drop the internal /jobs/name, /jobs/{name}/exists, and /jobs/{name}/validJobName calls. Naming now relies on the PUBLIC create API: omitting jobName lets the server auto-assign a collision-free name (returned in the response); a user-supplied name is validated client-side against the server's rules (charset + no leading hyphen). - Rename the tools to create_data_quality_job / prepare_create_data_quality_job and expand their descriptions with plain-language framing (job/edge/connection) plus example user requests, for better LLM comprehension and evaluations. - Gate both tools behind a new "data-quality" experimental feature (off by default), like the Data Product skills, since they write to Collibra. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
749732a to
deb3c62
Compare
@aberkow Collibra Here is what I am going to propose internally but it will take a bit of time to work through it with the team as there is some team level messaging required here. |
@aberkowCollibra Done |
|
@EricWarnerCollibra @vvaks0 all changes requested have been made and verified. |
selectedColumns projects the chosen columns into the source query's SELECT list (falling back to SELECT * only when omitted), per dqColumnsPart in pkg/clients/dq_source_query.go. The schema description wrongly claimed it left the query as SELECT *. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
||
| // dqRowFilterPart mirrors the wizard's createRowFilterPart: `col op 'value'` (value single-quoted; | ||
| // BIGQUERY bare for numeric). For valueless operators (IS NULL / IS NOT NULL) the value is omitted. | ||
| func dqRowFilterPart(in DqSourceQueryInput, dialect string) string { |
There was a problem hiding this comment.
filterOperator/filterValue flow straight into the scan SQL — could an embedded quote or an odd operator break out of the query here?
| // that tells the agent whether it has everything needed to call create_data_quality_job, | ||
| // what's still missing (with the options to choose from), or what couldn't be | ||
| // resolved. It performs NO mutations. | ||
| package prepare_create_dq_job |
There was a problem hiding this comment.
Question on the tool split: did you consider baking this companion tool into create_data_quality_job instead of a separate prepare_ tool?
The create_data_quality_job already re-resolves the connection, job type, permissions, etc. itself, and it already has a status/confirm state machine — discovery could be one more state (incomplete + options when the location isn't fully specified).
We've had issues with the prepare_/create_ pairing and moved away from it (e.g. we removed prepare_add_business_term and made prepare_create_asset optional CC @bobby-smedley)
The problem is that it couples two tools through the LLM which is not guaranteed. Also, with users manually selecting tools in Maestro, this could potentially enable one without the other and get a broken flow.
One tool spanning discovery → preview → create would avoid both.
There was a problem hiding this comment.
Makes sense. Since Maestro shows individual tools instead of functional packages (like a plugin would), we can't make sure the user will select all the tools they need. I will look for a way to combine them.
There was a problem hiding this comment.
Cool 👍 I'm pushing for grouping tools (i.e. like functional packages) for a while now. We'll get there at some point.
dqRowFilterPart spliced filterValue and filterOperator straight into the scan query: the value was single-quoted but embedded quotes were left as-is (a value like `x' OR '1'='1` broke out of the literal), and the operator was used verbatim with no allow-list. - Escape the value as a SQL string literal (double embedded single quotes) via dqEscapeStringLiteral — the standard escape honored by Postgres/Oracle/MySQL/etc. - Add DqFilterOperators + IsAllowedDqFilterOperator (case-insensitive, whitespace-normalized) covering the wizard's set: = != <> > >= < <= LIKE IS NULL IS NOT NULL. The operator has no literal escape, so it must be one of these. Column names were already quoted via dqEscapeIdentifier. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fold the read-only prepare_create_data_quality_job discovery tool into create_data_quality_job so one tool spans discovery -> preview -> create, per review on #88. The prepare_/create_ split coupled two tools through the LLM and let Maestro enable one without the other (a broken flow). - New discover.go: resolves the location (connection -> data source -> schema -> table), enumerating options for the FIRST missing field (status=incomplete). Fields the caller supplies are trusted, so a fully-specified call is still a single build+preview with no extra browse round-trips. - Input: drop edgeSiteName/edgeConnectionName; add connection (UUID or name) + the tableAsset* resolvers; dataSource/schema/table optional. - Output: add discovery options and, on preview, the option catalogs (columns/monitors/adaptiveMonitorSettings/notifications) formerly surfaced at prepare's `ready` step. - Enforce the row-filter operator allow-list (clients.IsAllowedDqFilter- Operator) at the input layer. - Remove the prepare_create_dq_job package; update registration, the experimental help text, and internal doc strings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e-dq-job # Conflicts: # pkg/tools/register_test.go
The public create does not auto-assign a unique default name: an empty jobName is rejected, and a concrete existing name is upserted/re-run, so there is no conflict to react to. A default create for an existing table therefore silently re-ran the existing job instead of making a distinct one. Mirror the wizard (DatasetBll.getDatasetName) client-side, using public endpoints only: - clients.SearchDqJobNames: page the public GET /rest/dq/1.0/jobs search. - clients.NextAvailableDqJobName: base when free, else "base_N" for the smallest free N (first duplicate -> _1); ignores non-numeric suffixes. - clients.validatedDqDataset: port of getValidatedDataset (charset strip, data_quality_job fallback, 252 cap). - clients.ResolveAutoDqJobName ties them together. create_data_quality_job now resolves the name up front when jobName is omitted (reflected in both preview and create); an explicit name is validated and used as-is. Removed the dead 409-retry path. Added tool annotations (ReadOnly/Destructive/Idempotent/OpenWorld) matching the create_asset/create_assessment convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🎯 What does this PR do?
Adds a guided, multi-turn data-quality job creation flow for DEV-197672.
prepare_create_dq_job(read-only) walks the discovery chain — resolves the edge connection, detects the job type (PUSHDOWN/PULLUP) from its capabilities, and enumerates data sources, schemas, tables and columns — returning a ready-to-use plan. It also resolves the location from a catalog Table asset (id / URL / name) for the table-asset-page entry point.create_dq_jobbuilds and submits the job via the PUBLIC DQ API (POST /rest/dq/1.0/jobs) behind a confirm-checkpoint preview. Supports column selection, a single-column row filter, row sampling, time-slice scheduling (${rd}/${rdEnd}composed into a dialect-aware source query), recurring schedules, monitors + adaptive settings, notifications, Pullup sizing / Parallel JDBC, and Pushdown compute.Validated end-to-end on a live stack: create -> persist -> run FINISHED.
Refs: DEV-197672
✅ Checklist