Two measured behaviours where the agent produces valid SQL that answers the wrong question, or
picks a number that decides the conclusion. Neither is a code bug. Both need a decision about what
we tell the model before anyone writes a fix, which is why they are together.
Both were measured with one model on one dataset. Treat the shapes as real and the
frequencies as indicative.
1. Multi-way breakdowns fan out — 2 of 5 runs wrong, 1 of 5 answers a different question
Asked to break a cohort-vs-population comparison down by neighbourhood, across five fresh threads:
| Runs |
Shape |
Correct? |
| 2/5 |
join two row-level relations on neighbourhood_cleansed, then GROUP BY |
no |
| 1/5 |
aggregated the population only, dropped the cohort entirely |
no |
| 2/5 |
UNION ALL of two independently aggregated sides |
yes |
The failing shape joins on a non-unique key before aggregating, so every population row is
duplicated once per cohort row in the same group. Verified exactly: Bernal Heights has 237 rated
listings and 25 in the cohort, and the query reported n_listings_all = 5925 = 237 × 25.
The nasty part: the averages stay correct, because uniform duplication preserves a mean. Only
the counts are wrong, so the output looks plausible and is half right.
This is not caused by making bm25_search composable, but it is invited by it. With ids in hand
the model aggregated correctly; thinking in relations, it reaches for a join. Both correct samples
used UNION ALL over independently aggregated sides. Aggregating each side first and then joining
on the group key would also be correct and was never tried.
Open question: should the SQL tool description name the safe shape? Untested — and there is a real
risk of over-instructing a model that gets it right 40% of the time unaided.
2. k is chosen arbitrarily and the conclusion moves with it
k came out as 100, 200, 500 and 5000 across runs — the last exceeding the corpus size. And the
measured effect depends on it:
| Cohort |
Avg rating |
| k=100, tight matches |
4.8236 |
| k=500 |
4.8023 |
| population |
4.8029 |
So the conclusion flips from "quiet-garden listings rate higher" to "no difference" purely on the
model's choice of k. BM25 k is a hard cutoff, not a relevance threshold, so the model is
choosing the answer when it chooses the cohort boundary — with nothing to base it on.
More damaging to credibility than the fan-out, because every individual run looks confident and
internally consistent.
Options, none obviously right:
- Guidance on
k in the tool description.
- A score threshold instead of, or alongside, a hard
k.
- Surfacing the score distribution so a cohort boundary can be justified rather than guessed.
- Accepting it, and requiring that any demo or doc built on a cohort states its
k.
Suggested approach
Run the experiment before changing anything. Both problems are description-level hypotheses, and
we already have a repeatable harness downstream (same six questions, fresh thread each time). A
wording change that is not measured against the current 40% baseline is not a fix, it is a guess.
Related: #58 (retrieval eval harness) would give this a proper measurement surface, though these
two are agent-behaviour questions rather than retrieval-quality ones.
Two measured behaviours where the agent produces valid SQL that answers the wrong question, or
picks a number that decides the conclusion. Neither is a code bug. Both need a decision about what
we tell the model before anyone writes a fix, which is why they are together.
Both were measured with one model on one dataset. Treat the shapes as real and the
frequencies as indicative.
1. Multi-way breakdowns fan out — 2 of 5 runs wrong, 1 of 5 answers a different question
Asked to break a cohort-vs-population comparison down by neighbourhood, across five fresh threads:
neighbourhood_cleansed, thenGROUP BYUNION ALLof two independently aggregated sidesThe failing shape joins on a non-unique key before aggregating, so every population row is
duplicated once per cohort row in the same group. Verified exactly: Bernal Heights has 237 rated
listings and 25 in the cohort, and the query reported
n_listings_all = 5925 = 237 × 25.The nasty part: the averages stay correct, because uniform duplication preserves a mean. Only
the counts are wrong, so the output looks plausible and is half right.
This is not caused by making
bm25_searchcomposable, but it is invited by it. With ids in handthe model aggregated correctly; thinking in relations, it reaches for a join. Both correct samples
used
UNION ALLover independently aggregated sides. Aggregating each side first and then joiningon the group key would also be correct and was never tried.
Open question: should the SQL tool description name the safe shape? Untested — and there is a real
risk of over-instructing a model that gets it right 40% of the time unaided.
2.
kis chosen arbitrarily and the conclusion moves with itkcame out as 100, 200, 500 and 5000 across runs — the last exceeding the corpus size. And themeasured effect depends on it:
So the conclusion flips from "quiet-garden listings rate higher" to "no difference" purely on the
model's choice of
k. BM25kis a hard cutoff, not a relevance threshold, so the model ischoosing the answer when it chooses the cohort boundary — with nothing to base it on.
More damaging to credibility than the fan-out, because every individual run looks confident and
internally consistent.
Options, none obviously right:
kin the tool description.k.k.Suggested approach
Run the experiment before changing anything. Both problems are description-level hypotheses, and
we already have a repeatable harness downstream (same six questions, fresh thread each time). A
wording change that is not measured against the current 40% baseline is not a fix, it is a guess.
Related: #58 (retrieval eval harness) would give this a proper measurement surface, though these
two are agent-behaviour questions rather than retrieval-quality ones.