<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Databricks Data Quality - Agent Proposes, DQX Disposes in Community Articles</title>
    <link>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169752#M1602</link>
    <description>&lt;P&gt;Do you also retain the matching rule definitions alongside DQX's `rule_set_fingerprint`, so a later review can see exactly which checks were applied? Curious.&lt;/P&gt;</description>
    <pubDate>Thu, 24 Sep 2026 20:11:04 GMT</pubDate>
    <dc:creator>ivanvyd</dc:creator>
    <dc:date>2026-09-24T20:11:04Z</dc:date>
    <item>
      <title>Databricks Data Quality - Agent Proposes, DQX Disposes</title>
      <link>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169513#M1591</link>
      <description>&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;SPAN&gt;Every serious data platform grows a dead-letter table, and it always becomes a graveyard. Here is how we turned one into a self-healing queue — without letting a language model anywhere near the warehouse.&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Every data platform that takes quality seriously ends up with a dead-letter table. You run pre-commit checks, and the rows that fail don’t go into Silver — they go into quarantine. It is the responsible thing to do. It is also, in practice, where data goes to die.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Nobody wants to open the quarantine table. The rows that land there are, by definition, the annoying ones: a code with a stray alphabetic prefix, a timestamp in the wrong format, a duplicate that got emitted twice, a foreign key that doesn’t quite line up because one side trims whitespace and the other doesn’t. Fixing them is fiddly, one-off work, and the backlog only grows.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;We built a system that closes the loop. An LLM agent triages quarantined rows and proposes fixes. Those fixes are re-validated deterministically against the exact checks that quarantined the row in the first place. Only the rows that pass are merged back into Silver. Everything else escalates to a human review queue instead of looping forever.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;The interesting part isn’t the LLM. It’s the constraints around it.&lt;BR /&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;01&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;Two design principles&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Everything in the system falls out of two rules we decided not to break.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size="4" color="#333333"&gt;“&lt;EM&gt;The agent proposes. DQX disposes.”&lt;/EM&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#333333"&gt;&lt;FONT size="2"&gt;&lt;SPAN class=""&gt;&lt;FONT size="2"&gt;PRINCIPLE ONE&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size="3"&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;The agent never writes to Silver or Gold. Not once. Every agent-curated row is re-run through the same data-quality engine — we use&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://databrickslabs.github.io/dqx/" target="_blank" rel="noopener"&gt;DQX&lt;/A&gt;&lt;SPAN&gt;, the Databricks Labs quality framework — that quarantined it. If the “fix” doesn’t actually make the row pass the checks, it doesn’t get in. This keeps a hallucinated correction from silently corrupting the warehouse, and it makes the whole thing auditable: the gate is code, not vibes.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size="4" color="#333333"&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&lt;EM&gt;“Documented fixes beat guessed fixes.”&lt;/EM&gt;&lt;BR /&gt;&lt;FONT size="2"&gt;PRINCIPLE TWO&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;If a rule owner has already written down exactly how a violation should be remediated —&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;“primary-key collision on&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;customer_id: keep the row with the latest&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;updated_at, drop the rest”&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— then that fix is applied deterministically and the LLM never sees the row. The agent is the fallback for rules nobody has written a playbook for yet. It is not the default path.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;That second principle matters more than it sounds. The cheapest, most reliable, most auditable model call is the one you never make.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="KeerthiItigimat_0-1790129785984.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/31406i5A25641102E02696/image-size/large?v=v2&amp;amp;px=999" role="button" title="KeerthiItigimat_0-1790129785984.png" alt="KeerthiItigimat_0-1790129785984.png" /&gt;&lt;/span&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#808080"&gt;&lt;STRONG&gt;&lt;FONT color="#333333"&gt;Figure 1&lt;/FONT&gt;.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;The loop. A quarantined row is fixed by a documented playbook strategy or, failing that, by the agent — then re-validated against the identical DQX checks before anything touches Silver.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;02&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;The shape of the pipeline&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;The whole thing runs as a Databricks Workflow. Because a&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;For Each&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;task can only wrap a single task, not a sub-graph, the per-table pipeline is a child job that the parent fans out to — one child run per quarantine table.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="KeerthiItigimat_1-1790129900413.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/31407i4FDB3831171B1C85/image-size/large?v=v2&amp;amp;px=999" role="button" title="KeerthiItigimat_1-1790129900413.png" alt="KeerthiItigimat_1-1790129900413.png" /&gt;&lt;/span&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#808080"&gt;&lt;STRONG&gt;&lt;FONT color="#333333"&gt;Figure 2&lt;/FONT&gt;.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;The Workflow DAG. Parent discovers and fans out; each child run walks the same seven-stage path.&amp;nbsp;&lt;/SPAN&gt;06&lt;SPAN&gt;&amp;nbsp;runs on&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;at least one success&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;of reingest or a false gate, so every table produces an audit row either way.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="KeerthiItigimat_2-1790129972242.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/31408i2DFC6F4AEF03F463/image-size/large?v=v2&amp;amp;px=999" role="button" title="KeerthiItigimat_2-1790129972242.png" alt="KeerthiItigimat_2-1790129972242.png" /&gt;&lt;/span&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#808080"&gt;&lt;STRONG&gt;&lt;FONT color="#333333"&gt;Figure 3&lt;/FONT&gt;.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;A recreation of the parent job’s run graph in Databricks Workflows —&amp;nbsp;&lt;/SPAN&gt;discover&lt;SPAN&gt;, then a&amp;nbsp;&lt;/SPAN&gt;For&amp;nbsp;Each&lt;SPAN&gt;&amp;nbsp;fan-out to one child run per quarantine table. Table names and durations are illustrative.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;SPAN&gt;Each stage writes only to a control table — a review queue with one row per quarantined row per pass. Nothing touches Silver until the final merge, and that merge only ever sees rows that have already passed re-validation.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;03&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;Triage&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Pull the unprocessed rows from one quarantine table, dedupe to the latest quarantined version per row, and flatten the failure metadata. DQX records failures as an array of structs —&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;{name, message, …}&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— and triage flattens those names into a plain&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;array&amp;lt;string&amp;gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;of violated rule names, then seeds the review queue with status&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;pending.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;It also captures the business key at this moment. Reconstructing a natural key later, after the row has been patched, is guesswork; capturing it at quarantine time is not.&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;04&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;Playbook remediation — the deterministic half&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;This is where documented fixes get applied. Each dataset has a YAML file — not in the codebase, but in a Unity Catalog Volume, so adding or changing a rule needs no deploy:&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="KeerthiItigimat_3-1790130132909.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/31409iDD4E3BE790D5355D/image-size/large?v=v2&amp;amp;px=999" role="button" title="KeerthiItigimat_3-1790130132909.png" alt="KeerthiItigimat_3-1790130132909.png" /&gt;&lt;/span&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#333333"&gt;Entries run in priority order; the first one that matches a row wins. Three things we learned to bake in:&lt;/FONT&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;FONT color="#333333"&gt;&lt;STRONG&gt;where&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;predicates let one rule route by value.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;status = 'Duplicate'&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;goes to dedupe;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;status = 'Invalid'&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;has no entry, so it falls through to the agent. Same rule, different handling, driven by the data.&lt;/FONT&gt;&lt;/LI&gt;&lt;LI&gt;&lt;FONT color="#333333"&gt;&lt;STRONG&gt;reject_rows&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is a terminal state, not a failure.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;Some rows genuinely can’t be recovered. Dropping them is a decision the rule owner made on purpose, and it is recorded as such — not retried, not escalated, not seen by the agent.&lt;/FONT&gt;&lt;/LI&gt;&lt;LI&gt;&lt;FONT color="#333333"&gt;&lt;STRONG&gt;Dedup is configured only here.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;The agent never deduplicates. Choosing which of two near-identical rows survives is a business call with a documented tie-breaker, not something to infer.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;The strategy&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;functions&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;—&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;dedupe_keep_latest,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;standardize_value,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;fill_default,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;reject_rows&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— are code. A new&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;kind&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;of fix needs a deploy. A new&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;instance&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;of an existing kind is just a file upload. Behavior in code, policy in config: that split is what keeps the playbook maintainable by the people who own the rules rather than the people who own the pipeline.&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;05&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;Agent curation — the fallback&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Only rows with no playbook match reach the agent. And here is the decision that makes this effective:&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;EM&gt;&lt;FONT size="4"&gt;“One model call per distinct violation signature. Not per row.”&lt;/FONT&gt;&lt;BR /&gt;&lt;/EM&gt;&lt;FONT size="2"&gt;&lt;SPAN class=""&gt;THE COST MODEL&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size="3" color="#333333"&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;If 40,000 rows all failed the same check on the same column in the same way, that is&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;one&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;call. The model sees the rule name, the check function, the message, a sample of failing values, and up to five passing examples per flagged column. It returns a single deterministic&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;transform&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;per column, chosen from a fixed vocabulary:&lt;BR /&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="KeerthiItigimat_4-1790130422163.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/31410i8C37309F712406BE/image-size/large?v=v2&amp;amp;px=999" role="button" title="KeerthiItigimat_4-1790130422163.png" alt="KeerthiItigimat_4-1790130422163.png" /&gt;&lt;/span&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#333333"&gt;Spark then applies that transform to every row in the signature. The model does not see 40,000 rows, does not write 40,000 fixes, and does not get to invent an expression. It picks&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;lower_trim&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;for a casing problem or&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;regexp_replace&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;to strip a known prefix, and that is the entire surface area. Token cost is independent of quarantine volume.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Transforms can be&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;chained&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— strip a prefix,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;then&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;zero-pad — which covers most of the real formatting damage: typos, column shifts, date formats, casing, padding, regex-strippable junk. And we guard against no-ops: if the model proposes&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;left_pad&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;on a string already at the target length, that is not a fix, and it gets downgraded to an escalation.&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;06&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;The cross-table probe — no model at all&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Referential-integrity checks — a row in table A must match a row in table B — are common, and the LLM is bad at them. So before the agent is involved, a deterministic probe runs: on a sample, normalize the compared column (trim,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;lower_trim,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;upper_trim) on both sides of the join and check whether the mismatch clears. If a normalization resolves, say, 95% of the sample, propose that transform. If it doesn’t, escalate.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;A surprising fraction of “broken foreign keys” are just one side of a join carrying trailing whitespace.&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;07&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;The confidence gate&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;The agent attaches a confidence score to every&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;fix&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;decision. Between curation and application, a gate checks the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;minimum&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;confidence across the batch against a threshold. Above it: proceed to auto-apply. Below it: skip straight to audit, and those rows wait for a human.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;One low-confidence signature holds back the whole batch for that table. We would rather under-automate than merge a shaky fix.&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;08&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;Apply and re-validate&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;For rows that clear the gate: apply the patch, strip every bookkeeping column, and re-run the row through&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;approved_checks_for(silver_table)&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;same rules table&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;that quarantined it. Not a copy of the checks. Not a checks file that might have drifted. The same source. “Re-run the exact checks that quarantined it” is only true if both sides read from one place.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Rows that pass are staged. Rows that fail get&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;retry_count += 1&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and go back into the queue. After three failed attempts a row auto-escalates regardless of confidence. Nothing loops forever.&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;09&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;Reingest&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;A dynamic&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;MERGE INTO&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;Silver, keyed on the business key that triage captured, columns intersected with the target schema. Every reingested row is tagged with lineage:&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;agent_curated = true, the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;confidence&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;score, the run id, the timestamp. Downstream consumers who don’t trust agent-curated data can filter it out. That is their call to make, and we give them the column to make it with.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="KeerthiItigimat_5-1790130549577.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/31411i997C4E9C6E7DBD79/image-size/large?v=v2&amp;amp;px=999" role="button" title="KeerthiItigimat_5-1790130549577.png" alt="KeerthiItigimat_5-1790130549577.png" /&gt;&lt;/span&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#333333"&gt;&lt;FONT color="#808080"&gt;&lt;STRONG&gt;&lt;FONT color="#333333"&gt;Figure 4&lt;/FONT&gt;.&lt;/STRONG&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;FONT color="#808080"&gt;&amp;nbsp;The review queue — one row per quarantined row per pass. Terminal states in green/red, human work in amber.&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT color="#333333"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="KeerthiItigimat_6-1790130596298.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/31412iD5D385EE5F5A4C54/image-size/large?v=v2&amp;amp;px=999" role="button" title="KeerthiItigimat_6-1790130596298.png" alt="KeerthiItigimat_6-1790130596298.png" /&gt;&lt;/span&gt;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#333333"&gt;&lt;FONT color="#808080"&gt;&lt;STRONG&gt;&lt;FONT color="#333333"&gt;Figure 5&lt;/FONT&gt;.&lt;/STRONG&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;FONT color="#808080"&gt;&amp;nbsp;Illustrative outcome split for a single run. The playbook clears the bulk; the agent handles a couple hundred; a couple dozen reach a human.&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;10&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;Dry runs&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Because “an LLM will now edit rows that flow into our warehouse” is a sentence that makes people nervous, there are two ways to see what&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;would&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;happen without committing anything.&lt;/FONT&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;FONT color="#333333"&gt;A&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;read-only estimate&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;that computes the deterministic half for real — match, apply strategy, re-validate — and reports the agent half as a count only. The model is never called. One row per table into a report table, nothing else.&lt;/FONT&gt;&lt;/LI&gt;&lt;LI&gt;&lt;FONT color="#333333"&gt;A&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;full dry run&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;that runs the whole pipeline, calls the agent, writes the queue and the staging table — but holds the final&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;MERGE&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and instead reports the exact insert/update split against Silver.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;Run the first before you turn the system on. Run the second in staging when you want to see precisely what will land.&lt;/FONT&gt;&lt;/P&gt;&lt;H2&gt;&lt;FONT color="#333333"&gt;&lt;SPAN class=""&gt;&lt;FONT size="3"&gt;11&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;What this bought us&lt;/FONT&gt;&lt;/H2&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;The quarantine table stopped being a graveyard. On the first real run, the large majority of quarantined rows resolved deterministically — dedup and structural rejects that rule owners had already documented. A few hundred went to the agent. A couple dozen genuinely needed a human, and those are the ones a person should be looking at.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color="#333333"&gt;The lesson we keep relearning: the LLM is the least important component. The value is in the scaffolding — the deterministic-first routing, the fixed transform vocabulary, the re-validation gate, the retry cap, the confidence threshold, the dry runs. The agent is a fallback that turns “a human triages every weird row” into “a human triages the genuinely ambiguous ones.”&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT size="5" color="#008000"&gt;&lt;SPAN&gt;Agent proposes. DQX disposes. Silver stays clean.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;</description>
      <pubDate>Wed, 23 Sep 2026 02:40:25 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169513#M1591</guid>
      <dc:creator>KeerthiItigimat</dc:creator>
      <dc:date>2026-09-23T02:40:25Z</dc:date>
    </item>
    <item>
      <title>Re: Databricks Data Quality - Agent Proposes, DQX Disposes</title>
      <link>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169751#M1601</link>
      <description>&lt;P&gt;Thanks for sharing, &lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/229152"&gt;@KeerthiItigimat&lt;/a&gt;, what a great breakdown. How do you handle rules changing while rows are waiting in quarantine? Does remediation keep the original checks, use the latest approved rules, or run both?&lt;/P&gt;</description>
      <pubDate>Thu, 24 Sep 2026 20:10:16 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169751#M1601</guid>
      <dc:creator>ivanvyd</dc:creator>
      <dc:date>2026-09-24T20:10:16Z</dc:date>
    </item>
    <item>
      <title>Re: Databricks Data Quality - Agent Proposes, DQX Disposes</title>
      <link>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169752#M1602</link>
      <description>&lt;P&gt;Do you also retain the matching rule definitions alongside DQX's `rule_set_fingerprint`, so a later review can see exactly which checks were applied? Curious.&lt;/P&gt;</description>
      <pubDate>Thu, 24 Sep 2026 20:11:04 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169752#M1602</guid>
      <dc:creator>ivanvyd</dc:creator>
      <dc:date>2026-09-24T20:11:04Z</dc:date>
    </item>
    <item>
      <title>Re: Databricks Data Quality - Agent Proposes, DQX Disposes</title>
      <link>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169757#M1603</link>
      <description>&lt;P&gt;Thank you &lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/249473"&gt;@ivanvyd&lt;/a&gt;&amp;nbsp;. The remediation playbooks lets you decide how you want to handle this scenario. By default, it will try to apply the same rule that quarantined. If you want to apply the latest version of the rule, you have an option to override that in playbooks.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 24 Sep 2026 22:33:02 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169757#M1603</guid>
      <dc:creator>KeerthiItigimat</dc:creator>
      <dc:date>2026-09-24T22:33:02Z</dc:date>
    </item>
    <item>
      <title>Re: Databricks Data Quality - Agent Proposes, DQX Disposes</title>
      <link>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169758#M1604</link>
      <description>&lt;P&gt;The rule definition is available as part of the per row errors or warnings column. Additional metadta is stored along side rule fingerprint and is available for a later review.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 24 Sep 2026 22:51:21 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/databricks-data-quality-agent-proposes-dqx-disposes/m-p/169758#M1604</guid>
      <dc:creator>KeerthiItigimat</dc:creator>
      <dc:date>2026-09-24T22:51:21Z</dc:date>
    </item>
  </channel>
</rss>

