5 · Evaluation & Trust — how it checks its own work¶
packages/dql-agent/src/agent-run-gates.ts·agent-run-engine.ts(trustStateFromEvaluations)
Every step is graded by an executable gate — a pure function that inspects the executor's result and returns evaluations with a severity and, when actionable, a machine repair action. The gates are what turn "the LLM said something" into "we verified it, and here's how much to trust it."
Gate anatomy¶
flowchart LR
R["Executor result<br/>(answer, SQL, result rows, artifacts)"] --> GATE["gate(context)"]
GATE --> E["AgentRunEvaluation[]"]
E --> F1["passed: boolean"]
E --> F2["severity: info | warning | blocking"]
E --> F3["suggestedRepair?: human text"]
E --> F4["repairAction?: { kind: retry | escalate, route?, hint? }"]
F2 & F4 -.->|"read by the loop"| DECIDE["repair · escalate · accept"]
Two kinds of checks: liveness + correctness¶
flowchart TD
subgraph Live["Liveness (did it run?)"]
L1["execution-error → repair the SQL (retry)"]
L2["no answer → escalate to research (blocking)"]
L3["grounding present?"]
end
subgraph Sem["Semantic correctness (is it right?)"]
S1["cardinality: scalar question → many rows?<br/>= fan-out / missing aggregation → retry"]
S2["grain / join correctness (roadmap)"]
end
ANSGATE["generatedAnswerGate"] --> Live
ANSGATE --> Sem
Liveness-only gates let wrong-but-runnable SQL pass. The semantic-correctness gate closes that
gap for the most common error: a scalar question ("what is total revenue?") that returns many
rows is almost always a fan-out join or a missing GROUP BY — it's flagged and repaired.
flowchart TD
Q["Question + result rows"] --> SC{"scalar-phrased?<br/>(not breakdown, not time-series)"}
SC -->|no| PASS["no semantic flag"]
SC -->|yes| RC{"rowCount over 1 ?"}
RC -->|no| PASS
RC -->|yes| CERTQ{"result already certified?"}
CERTQ -->|yes| PASS
CERTQ -->|no| FLAG["semantic-cardinality FAIL<br/>repairAction: retry<br/>'return a single aggregated value'"]
Guards against false positives (so it never wastes a repair on a correct answer):
- Breakdown questions ("top customers", "by region", "who…") → excluded.
- Time-series / window phrasings ("monthly total revenue", "running total", "month over month")
→ excluded (they are legitimately multi-row).
- Certified results → never second-guessed.
- Runs on generated_answer only — not on research (whose result is a bounded preview, not a
true row count).
Gate → trust map¶
flowchart TD
subgraph Gates
AG["answerGate<br/>(certified_answer)"]
GAG["generatedAnswerGate<br/>(generated_answer)<br/>= answerGate + semantic"]
RG["researchGate"]
SG["sqlCellGate"]
BG["blockDraftGate"]
APG["appBuildGate"]
end
AG & GAG & RG & SG & BG & APG --> TSE["trustStateFromEvaluations(route, evals, fallback)"]
TSE --> OUT["run.trustState"]
trustStateFromEvaluations:
- any blocking failed eval → blocked
- route certified_answer → certified
- route clarify → not_applicable
- route research / generated_answer AND catalog-grounding passed AND result-executed
passed → grounded
- else → the route's fallback (usually review_required).
The trust ladder¶
stateDiagram-v2
[*] --> blocked: can't ground / execute
[*] --> review_required: generated, unverified
[*] --> not_applicable: clarify / no-data question
blocked --> review_required: repaired
review_required --> grounded: executed cleanly on real data
grounded --> certified: 👤 human certifies (never automatic)
certified --> [*]
note right of grounded
"verified" — shown as a calm chip.
Grounded ≠ certified. AI never
self-promotes to certified.
end note
| State | Meaning | UI |
|---|---|---|
certified |
Answered from a governed metric you can trust | green shield "certified" |
grounded |
Verified against real data, pending certification | accent shield "verified" |
review_required |
Generated from governed data, not a metric yet | amber "review required" |
blocked |
Couldn't ground/execute it | red "blocked" |
not_applicable |
Clarify / not a data question | muted |
This is the graduated-trust contract: the loop can verify (grounded) but only a human can certify. See also
docs/architecture/graduated-trust.md.
→ Next: Self-correction