# Query Model ## Why `ToolBuilder` Exists Even when you only expose one model, `ToolBuilder` is the entrypoint on purpose. It freezes all participating model configs into one registry before any tool is created. That gives each tool a stable snapshot of: - its own final config - any other model configs needed for relation-aware features That matters because relation features are config-driven too. If a model exposes relations, those related models must also have tool configs in the same frozen registry. `ToolBuilder` is what makes that safe and deterministic instead of resolving relations ad hoc from loose model state. It is also the place where tools are actually created. Today it only emits `ReadModelTool` instances for models that opted in with `allowRead()`. ## Scope Behavior If you already use Eloquent scopes for visibility, tenancy, published-only records, or similar query restrictions, you can keep doing exactly that here. - The root model's configured scopes constrain the main query. - `with` applies the related model scopes for every direct and nested step in the eager-load path. - `withAggregate` applies the related model scopes for direct relation aggregates. ## Query Planning Pipeline Each read tool builds the request through a fixed handler pipeline: - `expressions` - `where` - `groupBy` - `withAggregate` - `with` - `select` - `distinct` - `orderBy` - derived relation joins - pagination That order matters because later steps depend on context created by earlier ones. For example: - named expressions must be registered before later clauses can reference them - `select` needs to know whether grouping is active - `orderBy` needs to know selected aliases and whether `distinct` is true - relation joins are derived from the relation-path columns requested elsewhere, not requested directly by the agent as a separate `join` clause ## What Gets Frozen The resolved registry captures: - the root model schema snapshot - configured scopes - configured direct relations - nested relation graph derived from other registered models - query limits such as `maxLimit`, `maxOffset`, and nesting depth If a configured relation points at a related model with no registered builder, the relation is dropped from the resolved schema and a warning is logged. This keeps the AI-facing query surface aligned with the same guardrails the rest of the application already uses.