Tool fixes for schemas, SQLTools, FileTools, Google Calendar and search toolkits
October 8, 20261 min read
Agno ships six tool fixes in this release. Each block below shows real output from the previous release and from this one.
Tool schemas read Annotated hints
Agno's get_json_schema_for_arg builds the parameter schema the model reads for every tool. A tool that takes a dataclass with a field typed Annotated[int, Field(ge=0)] used to describe that field to the model as an empty object. The model then had no idea it should send a number. The schema for place_order(order: Order):
Before: {"quantity": {"type": "object", "properties": {}, "additionalProperties": false}, "note": {"type": "string"}}
Now: {"quantity": {"type": "integer"}, "note": {"type": "string"}}SQLTools keeps reserved characters in passwords
When you pass user, password, host, port and dialect, SQLTools builds the engine URL with SQLAlchemy's URL.create. Earlier releases formatted those parts into one string, so an @ in the password moved the rest of it into the host. For password="p@ssword" and host="db.internal":
Before: host: ssword@db.internal | password: p
Now: host: db.internal | password: p@sswordFileTools.replace_file_chunk checks its line range
replace_file_chunk now rejects a negative start, an end before the start, and an end past the last line, and it leaves the file untouched. Its line count skips the empty piece after a final newline, so no valid range can swallow that newline. On a file holding one\ntwo\nthree\n:
replace_file_chunk(start_line=2, end_line=1, chunk="X")
Before: 'notes.txt' file: 'one\ntwo\nX\nthree\n'
Now: 'Error patching file: require 0 <= start_line <= end_line' file: 'one\ntwo\nthree\n'
replace_file_chunk(start_line=1, end_line=9, chunk="X")
Before: 'notes.txt' file: 'one\nX'
Now: 'Error patching file: end_line must be less than 3' file: 'one\ntwo\nthree\n'GoogleCalendarTools slots end before closing time
find_available_slots compared only the hour of a slot's end with the closing hour, so with a 17:00 close it still offered a 45 minute slot from 16:30 to 17:15. It now compares the full end time with closing time on the slot's start date, which also stops a slot from crossing midnight. The last slots on an empty Friday with the default 9:00 to 17:00 hours:
Before: [('15:30', '16:15'), ('16:00', '16:45'), ('16:30', '17:15')]
Now: [('15:00', '15:45'), ('15:30', '16:15'), ('16:00', '16:45')]BaiduSearchTools, Searxng and SpiderTools honor a zero limit
These toolkits resolved their limit with or, which treats 0 like an unset value. BaiduSearchTools(fixed_max_results=0) and Searxng(fixed_max_results=0) then used the per-call max_results, and SpiderTools(max_results=0) used 5. They now check for None, so 0 returns no results. With a mocked backend that returns five hits:
Searxng(fixed_max_results=0).search_web("agno")
Before: results returned: 5
Now: results returned: 0
SpiderTools(max_results=0).search_web("agno")
Before: {'fetch_page_content': False, 'num': 5}
Now: {'fetch_page_content': False, 'num': 0}PerplexitySearch identifies Agno traffic
PerplexitySearch.search and asearch add an X-Pplx-Integration: agno header, which lets Perplexity attribute requests that come through the toolkit. The X- headers on a search request:
Before: {'X-Source': 'agno'}
Now: {'X-Source': 'agno', 'X-Pplx-Integration': 'agno'}See the FileTools cookbook, and learn more about tools from Python functions, SQLTools, FileTools, Google Calendar, Searxng, Baidu Search, Spider and Perplexity Search in the documentation.
Frequently asked questions
The JSON schema builder in earlier releases had no branch for typing.Annotated, so the hint fell through to {"type": "object", "properties": {}}. Agno now reads the first argument of Annotated, so the model sees {"type": "integer"}.
Earlier releases pasted the credentials into a URL string, so p@ssword split into the password p and the host ssword@db.internal. SQLTools now builds the connection with SQLAlchemy's URL.create, which keeps each part whole. A full db_url string is still parsed as you wrote it.
It returns an error string and leaves the file as it was. A negative or reversed range returns Error patching file: require 0 <= start_line <= end_line, and an end past the last line returns Error patching file: end_line must be less than <line count>.
Set Searxng(fixed_max_results=0), BaiduSearchTools(fixed_max_results=0) or SpiderTools(max_results=0). Earlier releases treated the zero as unset and used the default of 5.



