AI data agents are getting good at producing executable SQL.
That is useful, but executable SQL is not the same thing as a correct business answer.
A query can compile, run successfully, return real rows, and still answer the wrong question because the agent selected the wrong metric definition, source table, relationship, grain, time field, or filter.
For production systems, this creates a different engineering requirement:
An AI data agent should not only generate an answer. It should preserve the evidence that produced it.
This article explores how to treat that evidence as a first-class artifact rather than an explanation generated after the fact.
## 1. Why SQL Accuracy Is an Incomplete Target
Consider this question:
What was net revenue by region last quarter?
The agent generates:
SELECT
c.region,
SUM(i.invoice_amount) AS net_revenue
FROM invoices i
JOIN customers c
ON i.customer_id = c.customer_id
WHERE i.invoice_date >= '2026-04-01'
AND i.invoice_date < '2026-07-01'
GROUP BY c.region;
The query is valid.
But suppose the enterprise definition is:
Net Revenue
=
Recognized Revenue
-
Refunds
-
Credits
and regional attribution is based on the billing account rather than the customer master.
The SQL engine cannot detect this error.
From the database's perspective, the query is correct.
From the business's perspective, it is wrong.
That gives us two different validation layers:
SQL Validity
=
Can this query execute?
Business Validity
=
Does this query represent the intended business question?
Production AI analytics needs both.
## 2. The Failure Surface Is Larger Than SQL Generation
A useful way to model an AI data query is:
Question
↓
Semantic Resolution
↓
Source Selection
↓
Relationship Selection
↓
Filter / Time Resolution
↓
SQL Generation
↓
Execution
↓
Answer
An error can occur at any stage.
For example:
Semantic Resolution
Revenue → Invoice Amount ❌
Source Selection
invoices ✓
Relationship Selection
invoice.customer_id → customer ✓
Time Resolution
invoice_date ❌
SQL Generation
Valid SQL ✓
Execution
Success ✓
If we evaluate only the final SQL syntax or execution status, the system appears healthy.
The real failure happened much earlier.
This is why AI data agents need evidence chains, not just query logs.
## 3. What Is an Evidence Chain?
An evidence chain records the artifacts and decisions that connect a user question to the final answer.
Conceptually:
User Question
│
▼
Business Definition
│
▼
Source Data
│
▼
Relationships
│
▼
Filters / Time Rules
│
▼
Generated SQL
│
▼
Execution Result
│
▼
Final Answer
The goal is not to create another verbose chain-of-thought log.
The goal is to preserve verifiable system artifacts.
That distinction matters.
Internal model reasoning is probabilistic and may not be suitable as an audit artifact.
A metric identifier, relationship identifier, SQL query, data-source identifier, and execution result are inspectable.
## 4. Evidence Should Be Structured
Instead of storing only:
question
sql
answer
store a structured evidence object.
For example:
{
"question": "What was net revenue by region last quarter?",
"semantic_resolution": {
"metric_id": "net_revenue",
"metric_version": "3.2",
"dimensions": ["billing_region"]
},
"sources": [
"orders",
"refunds",
"billing_accounts"
],
"relationships": [
{
"relationship_id": "rel_orders_billing_account",
"from": "orders.billing_account_id",
"to": "billing_accounts.account_id",
"status": "trusted"
}
],
"time": {
"field": "settlement_date",
"period": "last_quarter"
},
"sql": {
"query_id": "q_8271"
},
"execution": {
"result_id": "r_4412",
"status": "success"
},
"validation": {
"status": "passed"
}
}
Now the answer has provenance.
## 5. Capture Evidence During Execution, Not Afterward
A common anti-pattern is:
1. Agent generates answer
2. User asks "Why?"
3. LLM generates an explanation
That produces a narrative, not necessarily provenance.
The model may describe what it believes happened.
A stronger implementation captures evidence as each stage executes.
For example:
evidence = Evidence(question=question)
metric = resolve_metric(question)
evidence.metric_id = metric.id
evidence.metric_version = metric.version
dimension = resolve_dimension(question)
evidence.dimensions.append(dimension.id)
path = relationship_service.get_trusted_path(
metric=metric,
dimensions=[dimension]
)
evidence.relationship_ids.extend(path.relationship_ids)
sql = generate_sql(
question=question,
metric=metric,
dimensions=[dimension],
relationship_path=path
)
evidence.sql = sql
result = execute(sql)
evidence.execution_status = result.status
evidence.result_id = result.id
The evidence object is built from actual system events.
That makes it much more useful for debugging and audit.
6. Semantic Evidence
The first layer is semantic resolution.
If the user asks:
What was revenue last quarter?
the system should be able to show:
User Term:
Revenue
Resolved Metric:
Net Revenue
Version:
3.2
Definition:
Recognized Revenue - Refunds - Credits
This matters because business terms are often ambiguous.
The SQL may be technically perfect while using the wrong definition.
A metric version is particularly important.
If Revenue v3.1 and v3.2 differ, the evidence chain should preserve which version generated the answer.
## 7. Source Evidence
The next question is:
Which data actually contributed to the answer?
For example:
orders
refunds
billing_accounts
A production evidence record may also include fields:
{
"source": "orders",
"fields": [
"billing_account_id",
"recognized_amount",
"settlement_date"
]
}
This makes it possible to inspect whether the agent used an authoritative source rather than merely a semantically similar table.
## 8. Relationship Evidence
Multi-table queries require another layer of provenance.
Suppose the query joins:
orders
↓
billing_accounts
↓
region
The evidence should preserve why that path was selected.
At minimum:
{
"relationship_id": "rel_orders_billing_account",
"from": "orders.billing_account_id",
"to": "billing_accounts.account_id",
"status": "trusted"
}
More advanced systems could include relationship evidence such as:
Database Constraint
Naming Similarity
Value Inclusion
Uniqueness
Business Validation
The important point is that the agent is not silently inventing a join.
The relationship is inspectable.
## 9. Filter and Time Evidence
Filters are easy to overlook because they often appear as simple SQL predicates.
But they can completely change the business answer.
For example:
"last quarter"
might resolve to:
2026-04-01 → 2026-06-30
and use:
settlement_date
rather than:
invoice_date
The evidence record should preserve both.
For example:
{
"time_resolution": {
"business_period": "last_quarter",
"start": "2026-04-01",
"end": "2026-06-30",
"field": "settlement_date"
}
}
This makes temporal interpretation auditable.
## 10. Query Evidence
The SQL itself remains critical evidence.
But do not treat SQL as the entire explanation.
SQL is the executable consequence of upstream decisions.
A useful query record might include:
{
"query_id": "q_8271",
"sql_hash": "sha256:...",
"generated_at": "2026-08-20T09:15:00Z",
"metric_version": "3.2",
"relationship_ids": [
"rel_orders_billing_account"
]
}
This makes the query reproducible and connects it to the semantic and relationship state used during generation.
## 11. Execution Evidence
Execution success is useful evidence, just not sufficient evidence.
Capture:
Execution Status
Duration
Rows Returned
Data Source
Query Timestamp
Result Identifier
Potentially:
{
"status": "success",
"duration_ms": 842,
"rows_returned": 8,
"result_id": "r_4412"
}
This lets the system distinguish:
Bad SQL
from:
Valid SQL + Wrong Business Interpretation
## 12. Validation Should Check the Chain
Instead of asking only:
Did the SQL execute?
validation can inspect several layers.
### Semantic Validation
Was an approved metric definition used?
### Source Validation
Were authorized and current data sources used?
### Relationship Validation
Were joins based on trusted relationships?
### Filter Validation
Were required business filters applied?
### Query Validation
Did the SQL pass syntax and safety checks?
This produces a richer validation object:
{
"semantic": "passed",
"sources": "passed",
"relationships": "passed",
"filters": "passed",
"sql": "passed"
}
## 13. Why LLM-as-a-Judge Cannot Be the Only Validator
A second model can review generated SQL.
That is useful.
But consider:
Agent:
Revenue = invoice_amount
Judge:
The SQL correctly sums invoice_amount.
Both models agree.
Both can still be wrong relative to the enterprise definition.
Language models are good at evaluating logical consistency inside the context they receive.
They cannot recover enterprise truth that is missing from that context.
So:
You cannot verify a data answer with language alone.
Verification needs grounded evidence from semantic definitions, metadata, relationships, executed SQL, and query results.
## 14. Evidence Chains Improve Debugging
Suppose an answer is reported as incorrect.
Without structured evidence, the debugging workflow may be:
Reproduce Prompt
↓
Inspect Agent Logs
↓
Inspect SQL
↓
Guess What Went Wrong
With evidence:
Semantic Resolution PASS
Source Selection PASS
Relationship Selection FAIL
Filter Resolution PASS
SQL Validation PASS
Execution PASS
The engineering team immediately knows where to investigate.
This is especially valuable because many production NL2SQL failures happen before SQL generation.
## 15. Evidence Chains Improve Evaluation
Evidence also makes offline and online evaluation more granular.
Instead of only measuring:
Exact SQL Match
Execution Accuracy
Final Answer Accuracy
teams can measure:
Metric Resolution Accuracy
Source Selection Accuracy
Relationship Selection Accuracy
Filter Resolution Accuracy
Trusted Relationship Usage
SQL Validation Pass Rate
This turns a monolithic accuracy score into a diagnostic system.
If final-answer accuracy drops, the team can determine which layer caused the regression.
## 16. Evidence as an API Object
Evidence should not exist only in the UI.
It can be part of the agent API.
For example:
{
"answer": {
"metric": "Net Revenue",
"value": 27300000,
"currency": "USD"
},
"evidence": {
"metric": {
"id": "net_revenue",
"version": "3.2"
},
"sources": [
"orders",
"refunds",
"billing_accounts"
],
"relationships": [
"rel_orders_billing_account"
],
"query_id": "q_8271",
"validation": "passed"
}
}
Now downstream systems can choose how much evidence to expose.
## 17. Progressive Disclosure in the UI
Most business users do not want to read SQL after every question.
So the default UI can remain simple:
Net Revenue
$27.3M
✓ Evidence available
Then:
Why this answer?
can reveal:
Metric Definition
Source Data
Relationships
Filters
SQL
Validation
Different users can inspect different levels.
An executive may stop at the answer.
An analyst may inspect the metric and filters.
A data engineer may inspect joins and SQL.
## 18. Evidence Is Stronger Than Explanation
There is an important difference between:
Explainable
and:
Inspectable
An LLM can generate a convincing explanation.
An inspectable system exposes the artifacts that actually produced the answer.
For enterprise data, inspectability is often the stronger trust mechanism.
The user does not have to believe the explanation.
They can inspect the evidence.
## 19. A Practical Evidence Pipeline
A simplified architecture could look like:
User Question
│
▼
Semantic Resolver
│
├── metric_id
└── dimension_ids
│
▼
Relationship Resolver
│
└── relationship_ids
│
▼
Context Builder
│
▼
SQL Generator
│
└── query_id
│
▼
SQL Validator
│
▼
Query Executor
│
└── result_id
│
▼
Answer Generator
│
▼
Evidence Object
Every stage contributes structured evidence.
The evidence object becomes the trace that connects the original question to the final answer.
## 20. What Should Be Stored?
At minimum:
Question ID
User Question
Resolved Metric + Version
Resolved Dimensions
Source Tables / Fields
Relationship IDs
Filters
Time Interpretation
Generated SQL / Query ID
Execution Result ID
Validation Status
Timestamp
Depending on governance requirements, also consider:
Semantic Model Version
Relationship Model Version
Data Snapshot / Query Timestamp
Authorization Context
Agent Version
Model Version
This makes answers reproducible even as the system evolves.
## 21. A Better Definition of Production Readiness
For a prototype, this may be enough:
Question → SQL → Answer
For production enterprise AI, a stronger standard is:
Question
→ Governed Interpretation
→ Trusted Data Path
→ Executable Query
→ Traceable Result
→ Evidence-Backed Answer
The difference is not cosmetic.
It changes how the system can be trusted, evaluated, debugged, audited, and improved.
## Final Thoughts
AI data agents are rapidly improving at generating SQL.
But SQL generation is only one stage in a much larger correctness problem.
A production system should be able to answer two questions:
What is the answer?
and:
What evidence produced that answer?
That evidence should include the business definition, source data, relationships, filters, SQL, execution result, and validation state.
Not because every user wants to inspect every detail.
But because enterprise trust should be based on something stronger than model confidence.
A trustworthy data agent does not just return a number. It preserves the chain of evidence that makes the number verifiable.

Top comments (0)