Fixes for YouTubeTools, PerplexitySearch, PubmedTools and InMemoryDb
October 19, 20261 min read
Agno fixes YouTubeTools, PerplexitySearch, PubmedTools and InMemoryDb in this release. Each block below shows real output from the previous release and this one, with mocks in place of the YouTube, Perplexity and PubMed HTTP calls.
YouTubeTools reads Shorts, live and mobile links
get_youtube_video_id accepted only youtube.com, www.youtube.com and youtu.be, and on YouTube only the /watch, /embed/ and /v/ paths. A Shorts link pasted into a chat came back as No video ID found. The parser now adds /shorts/ and /live/, the mobile, music and privacy-enhanced hosts, the youtube.com.br and youtube.co.uk hosts, and links typed without a scheme:
URL Before Now
https://www.youtube.com/shorts/BGQWPY4IigY None 'BGQWPY4IigY'
https://www.youtube.com/live/BGQWPY4IigY None 'BGQWPY4IigY'
https://m.youtube.com/watch?v=BGQWPY4IigY None 'BGQWPY4IigY'
https://music.youtube.com/watch?v=BGQWPY4IigY None 'BGQWPY4IigY'
https://www.youtube-nocookie.com/embed/BGQWPY4IigY None 'BGQWPY4IigY'
youtu.be/BGQWPY4IigY None 'BGQWPY4IigY'A link with an empty id, such as https://youtu.be/, used to yield an empty string. get_youtube_video_captions passed it to the transcript API and get_youtube_video_data asked oEmbed about watch?v=. All three tools now stop at No video ID found:
get_youtube_video_data("https://youtu.be/")
Before: requests https://www.youtube.com/oembed?format=json&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D
Now: 'No video ID found', no request
get_youtube_video_captions("https://youtu.be/")
Before: YouTubeTranscriptApi().fetch('')
Now: 'No video ID found', no requestPerplexitySearch and PubmedTools keep max_results=0
PerplexitySearch.search, PerplexitySearch.asearch and PubmedTools.search_pubmed read max_results or self.max_results. Python treats 0 as false, so an explicit 0 quietly became the toolkit default. They now fall back only when max_results is None:
Call Before Now
PerplexitySearch(max_results=5).search(q, max_results=0) sends 5 sends 0
PerplexitySearch(max_results=5).asearch(q, max_results=0) sends 5 sends 0
PubmedTools(max_results=3).search_pubmed(q, max_results=0) retmax=3 retmax=0InMemoryDb keeps its own copy of a memory
InMemoryDb.upsert_user_memory stored the dict from UserMemory.to_dict(), which shares the caller's topics list. Editing the UserMemory after the upsert rewrote the stored memory and every topic listing, with no second write. The upsert now stores a deep copy on both the insert and the update path, and upsert_memories inherits it:
db = InMemoryDb()
memory = UserMemory(memory_id="m1", user_id="alice", memory="Alice ships agents on Fridays", topics=["agents"])
db.upsert_user_memory(memory)
memory.topics.append("unsaved")
db.get_all_memory_topics(user_id="alice")
# Before: ['agents', 'unsaved']
# Now: ['agents']See the cookbook, and learn more about YouTubeTools, Perplexity, PubMed and in-memory storage in the documentation.
Frequently asked questions
Earlier releases of YouTubeTools recognised only youtube.com, www.youtube.com and youtu.be, and only the /watch, /embed/ and /v/ paths. It now also reads /shorts/ and /live/ paths, the m., music. and youtube-nocookie.com hosts, and links pasted without https://.
A link such as https://youtu.be/ makes get_youtube_video_captions, get_youtube_video_data and get_video_timestamps return No video ID found without calling YouTube. Earlier releases sent the empty id on to the transcript API or the oEmbed endpoint.
Yes. Both now send 0 as given. A missing max_results still falls back to the toolkit setting, which is 5 for PerplexitySearch and 10 for PubmedTools when you set none.
InMemoryDb.upsert_user_memory used to keep a reference to the topics list of the UserMemory you passed in, so appending to it later changed the stored memory. It now stores a deep copy, and upsert_memories gets the same copy for every memory.

