Code of Conduct
AI Policy
Is your feature request related to a problem? Please describe.
Different interface libraries (ash_graphql, ash_ai, ...) each need to control which fields are filterable when exposing read actions. Currently there's no standard way to do this at the Ash core level, which forces each interface to implement its own solution independently.
For example:
ash_graphql has filterable_fields at the GraphQL type level to control which attributes are exposed as filter arguments
ash_ai exposes read actions as MCP/LLM tools and needs the same kind of control — certain fields shouldn't be offered as filter options to an LLM
The core problem is that filter field control is fundamentally about "how should this action expose its data" — which is an action-level concern, not an interface-level concern. Having each interface reinvent this leads to duplicated configuration, inconsistency between interfaces, and the risk of accidentally exposing fields in one interface that were intentionally hidden in another.
Describe the solution you'd like
A filter_fields option on read actions that declares which fields are available for filtering:
read :list_public do
filter_fields [:name, :bio, genre: [:eq, :in]]
end
read :list_admin do
# all fields filterable (default behavior, no restriction)
end
Interface libraries would respect this as the baseline — a field not in filter_fields cannot be filtered through any interface. Interfaces could then optionally restrict further (e.g. hiding a field from GraphQL but keeping it available in MCP), but could never expand beyond what the action allows.
This gives action authors a single place to declare the filtering contract, and every interface inherits it automatically.
Describe alternatives you've considered
-
Attribute-level filterable?: false — Already exists in Ash for some contexts. Too coarse: it's global across all actions and interfaces. "This field should never be filterable anywhere" is a valid but narrow use case. Doesn't help when you want different filter sets for :list_public vs :list_admin.
-
Interface-level configuration (current state) — Each interface defines its own filter control (e.g. ash_graphql's filterable_fields). Works but leads to scattered configuration, duplication, and potential inconsistency. If you add a new interface, you have to remember to configure filtering there too.
Additional context
No response
Code of Conduct
AI Policy
Is your feature request related to a problem? Please describe.
Different interface libraries (ash_graphql, ash_ai, ...) each need to control which fields are filterable when exposing read actions. Currently there's no standard way to do this at the Ash core level, which forces each interface to implement its own solution independently.
For example:
ash_graphqlhasfilterable_fieldsat the GraphQL type level to control which attributes are exposed as filter argumentsash_aiexposes read actions as MCP/LLM tools and needs the same kind of control — certain fields shouldn't be offered as filter options to an LLMThe core problem is that filter field control is fundamentally about "how should this action expose its data" — which is an action-level concern, not an interface-level concern. Having each interface reinvent this leads to duplicated configuration, inconsistency between interfaces, and the risk of accidentally exposing fields in one interface that were intentionally hidden in another.
Describe the solution you'd like
A
filter_fieldsoption on read actions that declares which fields are available for filtering:Interface libraries would respect this as the baseline — a field not in
filter_fieldscannot be filtered through any interface. Interfaces could then optionally restrict further (e.g. hiding a field from GraphQL but keeping it available in MCP), but could never expand beyond what the action allows.This gives action authors a single place to declare the filtering contract, and every interface inherits it automatically.
Describe alternatives you've considered
Attribute-level
filterable?: false— Already exists in Ash for some contexts. Too coarse: it's global across all actions and interfaces. "This field should never be filterable anywhere" is a valid but narrow use case. Doesn't help when you want different filter sets for:list_publicvs:list_admin.Interface-level configuration (current state) — Each interface defines its own filter control (e.g. ash_graphql's
filterable_fields). Works but leads to scattered configuration, duplication, and potential inconsistency. If you add a new interface, you have to remember to configure filtering there too.Additional context
No response