Guide tool search toward `load_capability`
Related to #5230.
Summary
- Clarify that
search_toolsdiscovers deferred tools that are not capability-owned, while capability-owned tools requireload_capabilityfirst. - When the built-in keyword search returns no directly searchable tools but the query matches tools behind unloaded capabilities, append a tagged
SystemPromptPartnaming up to three relevant capability IDs. - Keep the provider tool-search return schema, capability gating, and custom search-callable behavior unchanged.
Why an appended system message
The provider-native tool-search result schema has no supported field for capability suggestions. Putting this guidance in a separate append-only message avoids inventing wire keys, works through the existing provider message mapping, and does not mutate the stable instruction/cache prefix.
Harness boundary
Core owns this recovery because it controls capability gating and the normalized/provider message transcript. Harness can continue to announce tools after successful dynamic discovery; it should not duplicate this empty-search recovery. Together, the model sees either a successful discovery announcement or an explicit route back to load_capability, rather than an unexplained empty result.
Validation
uv run pytest tests/test_tool_search.py -q(199 passed)uv run pytest tests/test_capabilities.py -q(835 passed)PYRIGHT_PYTHON_IGNORE_WARNINGS=1 uv run pyright pydantic_ai_slim/pydantic_ai/toolsets/_tool_search.py tests/test_tool_search.py- pre-commit format, lint, cassette, and hygiene hooks
The repository-wide typecheck could not run in the isolated worktree because unrelated optional Harness/provider dependencies were unavailable; the changed implementation and test files pass targeted Pyright.
Checklist
- Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
- No breaking changes in accordance with the version policy.
- PR title is fit for the release changelog.