Summary
With where, discover() does not push the selector's type / model_id / location filters to the registry. It sends only the predicate, pages the whole fleet through it (LIST_PAGE_SIZE records per request), and applies the selector filters client-side afterwards. On a 10,000-device fleet a scoped state question such as
discover("device(model_id:legacy:warehouse_robotics/cleaner_bot_a,location:area-04)",
where="status.task_state == 'queued'")
produced 100 registry requests each evaluating the predicate over 10,000 records (about 2.6 s per page on our registry) — roughly 260 s for one tool call, and 45 requests at 8.5 s each for a heavier predicate. The model gave up and reported the fleet as unverifiable.
Observed 2026-09-15 in an LLM-agent benchmark (Codex Astra) against a registry that mirrors list_devices from #64.
Proposal
- When
where is present, still pass device_type / location derived from the selector (as the non-predicate path does) so the registry narrows before evaluating the predicate; or fold exact-match selector filters into the predicate as labels.type == ..., labels.location == ....
- Registry side: memoize the predicate result set per (filters, predicate, fleet version) across pages, or evaluate lazily per page over the pre-filtered list, so a paged predicate query costs O(scope) once rather than O(scope × pages).
- Consider a larger default page for predicate results (they carry only id, type, location) so a 10,000-match answer is not 100 round trips.
Workaround in our harness: the MCP layer ANDs the selector's exact filters into where, and the registry memoizes per fleet-state version.
Relates to #64, #65, #66.
Summary
With
where,discover()does not push the selector'stype/model_id/locationfilters to the registry. It sends only the predicate, pages the whole fleet through it (LIST_PAGE_SIZErecords per request), and applies the selector filters client-side afterwards. On a 10,000-device fleet a scoped state question such asproduced 100 registry requests each evaluating the predicate over 10,000 records (about 2.6 s per page on our registry) — roughly 260 s for one tool call, and 45 requests at 8.5 s each for a heavier predicate. The model gave up and reported the fleet as unverifiable.
Observed 2026-09-15 in an LLM-agent benchmark (Codex Astra) against a registry that mirrors
list_devicesfrom #64.Proposal
whereis present, still passdevice_type/locationderived from the selector (as the non-predicate path does) so the registry narrows before evaluating the predicate; or fold exact-match selector filters into the predicate aslabels.type == ...,labels.location == ....Workaround in our harness: the MCP layer ANDs the selector's exact filters into
where, and the registry memoizes per fleet-state version.Relates to #64, #65, #66.