# Schema & strictness

Tool schemas are generated from Python callables using Pydantic models.

Source: `../src/openai_resptools/schema.py`

## How schemas are built

1. `build_args_model(func)` creates a Pydantic model from the function signature and type hints.
2. `build_parameters_schema(model, strict=...)` converts the Pydantic JSON schema into the OpenAI tool `parameters` schema.
3. `ToolDef.from_callable(...)` bundles these into a `ToolDef`.

Source: `../src/openai_resptools/tool.py`

## strict=True behavior

When `strict=True` (the default for `ToolRegistry.tool()` and `ToolDef.from_callable(...)`):
- `additionalProperties` is set to `false`
- By default, all properties are forced into `required`
- For parameters that were optional in the function signature, the property schema is wrapped to allow `null`

This is implemented by:
- `force_all_required=True`
- `allow_null_for_optional=True`

in `build_parameters_schema(...)`.

## Why allow null for optional parameters

Many tool-calling flows benefit from schemas that:
- Keep a stable set of keys
- Let the model explicitly decide “not provided” as `null` rather than omitting keys

This can reduce argument-shape drift across multi-step calls.

## Non-strict mode

When `strict=False`:
- `additionalProperties` is not forced to `false`
- Only truly required fields (per Pydantic schema) appear in `required`

This can be useful if you want the model to include extra keys or you want to accept partial arguments more freely.

