-
Notifications
You must be signed in to change notification settings - Fork 0
Relation Paths And Scopes
Relation-aware features depend on the resolved registry that ToolBuilder builds from every registered model config.
Direct relations come from relations([...]) on the current model.
Nested relations are derived from those direct relations plus the related models' own registered configs. That means a nested path such as author.company only exists when:
-
authoris configured on the root model - the related
Authormodel is also registered in the sameToolBuilder -
companyis configured onAuthor
If a related model is not registered, the relation is dropped from the resolved schema.
relationPathMaxDepth() limits dotted relation paths.
-
1means no nested relation hops - values below
2effectively limit you to direct relations only for nested features - the default is
5
Dotted column references such as author.name work only for relation kinds that the join planner can translate into SQL join hops:
belongsTohasOnehasManybelongsToMany
That support is used by:
whereexpressionsselectgroupByorderBy
Relation kinds such as morphOne, morphMany, morphTo, hasOneThrough, and hasManyThrough are not available as dotted column references.
These joins are derived from the requested relation-path columns. The current request shape does not let the agent declare arbitrary joins itself.
Named expressions can use relation-path columns too, with two important limits:
- expression columns must be numeric
- all columns inside one named expression must come from the root model or one single relation path
That means an expression can use price and discount, or lineItems.amount plus a literal, but not mix unrelated relation paths in one expression tree.
with and withAggregate are not exactly the same as dotted column references:
-
withworks with configured relation paths and applies related scopes -
withAggregateworks on configured direct relations only - dotted column references need a resolvable join path, which is a stricter requirement
This is why a relation can be valid for eager loading but still be invalid as a dotted where or select column.
Scopes are reused across relation-aware features:
- root scopes are applied to the root query
- related scopes are applied when eager loading relations
- related scopes are applied when running
withAggregate - relation-path joins carry the related model's scopes into the query planning context
That keeps AI-facing queries aligned with the same visibility and tenancy rules your application already uses elsewhere.