Symptom
"Filter this layer" requests send the agent into an endless set_filter loop until it hits the per-turn cap and gives up. Cleanly reproduced with "Show only no-take marine protected areas" (and "show turtle corridors") on 2026-06-14 with models minimax-m2 and glm-5.
The model derives the correct predicate in its reasoning (NO_TAKE = 'All') but emits set_filter {"layer_id": "wdpa/wdpa-marine", "filter": []} — an empty filter — 15+ times in a row. The empty filter applies as a no-op (it actually clears the layer's default REALM filter, so featuresInView rises 201→270), returns success:true, and the model retries forever. 29 empty set_filter calls that day, zero non-empty.
Root cause (not in this repo)
Weaker models can't serialize the nested MapLibre expression array into the structured tool-call argument, and geo-agent's set_filter silently accepts an empty [] as success. Tracked upstream in boettiger-lab/geo-agent#243 with two proposed framework fixes (empty-filter guard + a flat {property, op, value} filter path).
Not a data/encoding issue (NO_TAKE is a real PMTiles property; values confirmed via get_stac_details) and not the v3.10.0 security PR (#239) — the app runs v3.9.0, which predates it. This is not fixable in system-prompt.md: the model already has the right semantics, and filter-syntax guidance doesn't belong in the app prompt.
App-level work
Upstream
Symptom
"Filter this layer" requests send the agent into an endless
set_filterloop until it hits the per-turn cap and gives up. Cleanly reproduced with "Show only no-take marine protected areas" (and "show turtle corridors") on 2026-06-14 with modelsminimax-m2andglm-5.The model derives the correct predicate in its reasoning (
NO_TAKE = 'All') but emitsset_filter {"layer_id": "wdpa/wdpa-marine", "filter": []}— an empty filter — 15+ times in a row. The empty filter applies as a no-op (it actually clears the layer's default REALM filter, sofeaturesInViewrises 201→270), returnssuccess:true, and the model retries forever. 29 emptyset_filtercalls that day, zero non-empty.Root cause (not in this repo)
Weaker models can't serialize the nested MapLibre expression array into the structured tool-call argument, and geo-agent's
set_filtersilently accepts an empty[]as success. Tracked upstream in boettiger-lab/geo-agent#243 with two proposed framework fixes (empty-filter guard + a flat{property, op, value}filter path).Not a data/encoding issue (
NO_TAKEis a real PMTiles property; values confirmed viaget_stac_details) and not the v3.10.0 security PR (#239) — the app runs v3.9.0, which predates it. This is not fixable insystem-prompt.md: the model already has the right semantics, and filter-syntax guidance doesn't belong in the app prompt.App-level work
featuresInViewdropping to the no-take subset, no repeatedset_filter).Upstream