Skip to content

Relation Paths And Scopes

github-actions[bot] edited this page Aug 12, 2026 · 1 revision

Relation Paths And Scopes

Relation-aware features depend on the resolved registry that ToolBuilder builds from every registered model config.

Direct And Nested Relations

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:

  • author is configured on the root model
  • the related Author model is also registered in the same ToolBuilder
  • company is configured on Author

If a related model is not registered, the relation is dropped from the resolved schema.

Relation Path Depth

relationPathMaxDepth() limits dotted relation paths.

  • 1 means no nested relation hops
  • values below 2 effectively limit you to direct relations only for nested features
  • the default is 5

Which Relation Kinds Support Dotted Column Paths

Dotted column references such as author.name work only for relation kinds that the join planner can translate into SQL join hops:

  • belongsTo
  • hasOne
  • hasMany
  • belongsToMany

That support is used by:

  • where
  • expressions
  • select
  • groupBy
  • orderBy

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.

Expressions Across Relations

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.

Eager Loading vs Column Paths

with and withAggregate are not exactly the same as dotted column references:

  • with works with configured relation paths and applies related scopes
  • withAggregate works 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.

Scope Propagation

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.

Clone this wiki locally