agno 2.2.13__py3-none-any.whl → 2.4.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (383) hide show
  1. agno/agent/__init__.py +6 -0
  2. agno/agent/agent.py +5252 -3145
  3. agno/agent/remote.py +525 -0
  4. agno/api/api.py +2 -0
  5. agno/client/__init__.py +3 -0
  6. agno/client/a2a/__init__.py +10 -0
  7. agno/client/a2a/client.py +554 -0
  8. agno/client/a2a/schemas.py +112 -0
  9. agno/client/a2a/utils.py +369 -0
  10. agno/client/os.py +2669 -0
  11. agno/compression/__init__.py +3 -0
  12. agno/compression/manager.py +247 -0
  13. agno/culture/manager.py +2 -2
  14. agno/db/base.py +927 -6
  15. agno/db/dynamo/dynamo.py +788 -2
  16. agno/db/dynamo/schemas.py +128 -0
  17. agno/db/dynamo/utils.py +26 -3
  18. agno/db/firestore/firestore.py +674 -50
  19. agno/db/firestore/schemas.py +41 -0
  20. agno/db/firestore/utils.py +25 -10
  21. agno/db/gcs_json/gcs_json_db.py +506 -3
  22. agno/db/gcs_json/utils.py +14 -2
  23. agno/db/in_memory/in_memory_db.py +203 -4
  24. agno/db/in_memory/utils.py +14 -2
  25. agno/db/json/json_db.py +498 -2
  26. agno/db/json/utils.py +14 -2
  27. agno/db/migrations/manager.py +199 -0
  28. agno/db/migrations/utils.py +19 -0
  29. agno/db/migrations/v1_to_v2.py +54 -16
  30. agno/db/migrations/versions/__init__.py +0 -0
  31. agno/db/migrations/versions/v2_3_0.py +977 -0
  32. agno/db/mongo/async_mongo.py +1013 -39
  33. agno/db/mongo/mongo.py +684 -4
  34. agno/db/mongo/schemas.py +48 -0
  35. agno/db/mongo/utils.py +17 -0
  36. agno/db/mysql/__init__.py +2 -1
  37. agno/db/mysql/async_mysql.py +2958 -0
  38. agno/db/mysql/mysql.py +722 -53
  39. agno/db/mysql/schemas.py +77 -11
  40. agno/db/mysql/utils.py +151 -8
  41. agno/db/postgres/async_postgres.py +1254 -137
  42. agno/db/postgres/postgres.py +2316 -93
  43. agno/db/postgres/schemas.py +153 -21
  44. agno/db/postgres/utils.py +22 -7
  45. agno/db/redis/redis.py +531 -3
  46. agno/db/redis/schemas.py +36 -0
  47. agno/db/redis/utils.py +31 -15
  48. agno/db/schemas/evals.py +1 -0
  49. agno/db/schemas/memory.py +20 -9
  50. agno/db/singlestore/schemas.py +70 -1
  51. agno/db/singlestore/singlestore.py +737 -74
  52. agno/db/singlestore/utils.py +13 -3
  53. agno/db/sqlite/async_sqlite.py +1069 -89
  54. agno/db/sqlite/schemas.py +133 -1
  55. agno/db/sqlite/sqlite.py +2203 -165
  56. agno/db/sqlite/utils.py +21 -11
  57. agno/db/surrealdb/models.py +25 -0
  58. agno/db/surrealdb/surrealdb.py +603 -1
  59. agno/db/utils.py +60 -0
  60. agno/eval/__init__.py +26 -3
  61. agno/eval/accuracy.py +25 -12
  62. agno/eval/agent_as_judge.py +871 -0
  63. agno/eval/base.py +29 -0
  64. agno/eval/performance.py +10 -4
  65. agno/eval/reliability.py +22 -13
  66. agno/eval/utils.py +2 -1
  67. agno/exceptions.py +42 -0
  68. agno/hooks/__init__.py +3 -0
  69. agno/hooks/decorator.py +164 -0
  70. agno/integrations/discord/client.py +13 -2
  71. agno/knowledge/__init__.py +4 -0
  72. agno/knowledge/chunking/code.py +90 -0
  73. agno/knowledge/chunking/document.py +65 -4
  74. agno/knowledge/chunking/fixed.py +4 -1
  75. agno/knowledge/chunking/markdown.py +102 -11
  76. agno/knowledge/chunking/recursive.py +2 -2
  77. agno/knowledge/chunking/semantic.py +130 -48
  78. agno/knowledge/chunking/strategy.py +18 -0
  79. agno/knowledge/embedder/azure_openai.py +0 -1
  80. agno/knowledge/embedder/google.py +1 -1
  81. agno/knowledge/embedder/mistral.py +1 -1
  82. agno/knowledge/embedder/nebius.py +1 -1
  83. agno/knowledge/embedder/openai.py +16 -12
  84. agno/knowledge/filesystem.py +412 -0
  85. agno/knowledge/knowledge.py +4261 -1199
  86. agno/knowledge/protocol.py +134 -0
  87. agno/knowledge/reader/arxiv_reader.py +3 -2
  88. agno/knowledge/reader/base.py +9 -7
  89. agno/knowledge/reader/csv_reader.py +91 -42
  90. agno/knowledge/reader/docx_reader.py +9 -10
  91. agno/knowledge/reader/excel_reader.py +225 -0
  92. agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
  93. agno/knowledge/reader/firecrawl_reader.py +3 -2
  94. agno/knowledge/reader/json_reader.py +16 -22
  95. agno/knowledge/reader/markdown_reader.py +15 -14
  96. agno/knowledge/reader/pdf_reader.py +33 -28
  97. agno/knowledge/reader/pptx_reader.py +9 -10
  98. agno/knowledge/reader/reader_factory.py +135 -1
  99. agno/knowledge/reader/s3_reader.py +8 -16
  100. agno/knowledge/reader/tavily_reader.py +3 -3
  101. agno/knowledge/reader/text_reader.py +15 -14
  102. agno/knowledge/reader/utils/__init__.py +17 -0
  103. agno/knowledge/reader/utils/spreadsheet.py +114 -0
  104. agno/knowledge/reader/web_search_reader.py +8 -65
  105. agno/knowledge/reader/website_reader.py +16 -13
  106. agno/knowledge/reader/wikipedia_reader.py +36 -3
  107. agno/knowledge/reader/youtube_reader.py +3 -2
  108. agno/knowledge/remote_content/__init__.py +33 -0
  109. agno/knowledge/remote_content/config.py +266 -0
  110. agno/knowledge/remote_content/remote_content.py +105 -17
  111. agno/knowledge/utils.py +76 -22
  112. agno/learn/__init__.py +71 -0
  113. agno/learn/config.py +463 -0
  114. agno/learn/curate.py +185 -0
  115. agno/learn/machine.py +725 -0
  116. agno/learn/schemas.py +1114 -0
  117. agno/learn/stores/__init__.py +38 -0
  118. agno/learn/stores/decision_log.py +1156 -0
  119. agno/learn/stores/entity_memory.py +3275 -0
  120. agno/learn/stores/learned_knowledge.py +1583 -0
  121. agno/learn/stores/protocol.py +117 -0
  122. agno/learn/stores/session_context.py +1217 -0
  123. agno/learn/stores/user_memory.py +1495 -0
  124. agno/learn/stores/user_profile.py +1220 -0
  125. agno/learn/utils.py +209 -0
  126. agno/media.py +22 -6
  127. agno/memory/__init__.py +14 -1
  128. agno/memory/manager.py +223 -8
  129. agno/memory/strategies/__init__.py +15 -0
  130. agno/memory/strategies/base.py +66 -0
  131. agno/memory/strategies/summarize.py +196 -0
  132. agno/memory/strategies/types.py +37 -0
  133. agno/models/aimlapi/aimlapi.py +17 -0
  134. agno/models/anthropic/claude.py +434 -59
  135. agno/models/aws/bedrock.py +121 -20
  136. agno/models/aws/claude.py +131 -274
  137. agno/models/azure/ai_foundry.py +10 -6
  138. agno/models/azure/openai_chat.py +33 -10
  139. agno/models/base.py +1162 -561
  140. agno/models/cerebras/cerebras.py +120 -24
  141. agno/models/cerebras/cerebras_openai.py +21 -2
  142. agno/models/cohere/chat.py +65 -6
  143. agno/models/cometapi/cometapi.py +18 -1
  144. agno/models/dashscope/dashscope.py +2 -3
  145. agno/models/deepinfra/deepinfra.py +18 -1
  146. agno/models/deepseek/deepseek.py +69 -3
  147. agno/models/fireworks/fireworks.py +18 -1
  148. agno/models/google/gemini.py +959 -89
  149. agno/models/google/utils.py +22 -0
  150. agno/models/groq/groq.py +48 -18
  151. agno/models/huggingface/huggingface.py +17 -6
  152. agno/models/ibm/watsonx.py +16 -6
  153. agno/models/internlm/internlm.py +18 -1
  154. agno/models/langdb/langdb.py +13 -1
  155. agno/models/litellm/chat.py +88 -9
  156. agno/models/litellm/litellm_openai.py +18 -1
  157. agno/models/message.py +24 -5
  158. agno/models/meta/llama.py +40 -13
  159. agno/models/meta/llama_openai.py +22 -21
  160. agno/models/metrics.py +12 -0
  161. agno/models/mistral/mistral.py +8 -4
  162. agno/models/n1n/__init__.py +3 -0
  163. agno/models/n1n/n1n.py +57 -0
  164. agno/models/nebius/nebius.py +6 -7
  165. agno/models/nvidia/nvidia.py +20 -3
  166. agno/models/ollama/__init__.py +2 -0
  167. agno/models/ollama/chat.py +17 -6
  168. agno/models/ollama/responses.py +100 -0
  169. agno/models/openai/__init__.py +2 -0
  170. agno/models/openai/chat.py +117 -26
  171. agno/models/openai/open_responses.py +46 -0
  172. agno/models/openai/responses.py +110 -32
  173. agno/models/openrouter/__init__.py +2 -0
  174. agno/models/openrouter/openrouter.py +67 -2
  175. agno/models/openrouter/responses.py +146 -0
  176. agno/models/perplexity/perplexity.py +19 -1
  177. agno/models/portkey/portkey.py +7 -6
  178. agno/models/requesty/requesty.py +19 -2
  179. agno/models/response.py +20 -2
  180. agno/models/sambanova/sambanova.py +20 -3
  181. agno/models/siliconflow/siliconflow.py +19 -2
  182. agno/models/together/together.py +20 -3
  183. agno/models/vercel/v0.py +20 -3
  184. agno/models/vertexai/claude.py +124 -4
  185. agno/models/vllm/vllm.py +19 -14
  186. agno/models/xai/xai.py +19 -2
  187. agno/os/app.py +467 -137
  188. agno/os/auth.py +253 -5
  189. agno/os/config.py +22 -0
  190. agno/os/interfaces/a2a/a2a.py +7 -6
  191. agno/os/interfaces/a2a/router.py +635 -26
  192. agno/os/interfaces/a2a/utils.py +32 -33
  193. agno/os/interfaces/agui/agui.py +5 -3
  194. agno/os/interfaces/agui/router.py +26 -16
  195. agno/os/interfaces/agui/utils.py +97 -57
  196. agno/os/interfaces/base.py +7 -7
  197. agno/os/interfaces/slack/router.py +16 -7
  198. agno/os/interfaces/slack/slack.py +7 -7
  199. agno/os/interfaces/whatsapp/router.py +35 -7
  200. agno/os/interfaces/whatsapp/security.py +3 -1
  201. agno/os/interfaces/whatsapp/whatsapp.py +11 -8
  202. agno/os/managers.py +326 -0
  203. agno/os/mcp.py +652 -79
  204. agno/os/middleware/__init__.py +4 -0
  205. agno/os/middleware/jwt.py +718 -115
  206. agno/os/middleware/trailing_slash.py +27 -0
  207. agno/os/router.py +105 -1558
  208. agno/os/routers/agents/__init__.py +3 -0
  209. agno/os/routers/agents/router.py +655 -0
  210. agno/os/routers/agents/schema.py +288 -0
  211. agno/os/routers/components/__init__.py +3 -0
  212. agno/os/routers/components/components.py +475 -0
  213. agno/os/routers/database.py +155 -0
  214. agno/os/routers/evals/evals.py +111 -18
  215. agno/os/routers/evals/schemas.py +38 -5
  216. agno/os/routers/evals/utils.py +80 -11
  217. agno/os/routers/health.py +3 -3
  218. agno/os/routers/knowledge/knowledge.py +284 -35
  219. agno/os/routers/knowledge/schemas.py +14 -2
  220. agno/os/routers/memory/memory.py +274 -11
  221. agno/os/routers/memory/schemas.py +44 -3
  222. agno/os/routers/metrics/metrics.py +30 -15
  223. agno/os/routers/metrics/schemas.py +10 -6
  224. agno/os/routers/registry/__init__.py +3 -0
  225. agno/os/routers/registry/registry.py +337 -0
  226. agno/os/routers/session/session.py +143 -14
  227. agno/os/routers/teams/__init__.py +3 -0
  228. agno/os/routers/teams/router.py +550 -0
  229. agno/os/routers/teams/schema.py +280 -0
  230. agno/os/routers/traces/__init__.py +3 -0
  231. agno/os/routers/traces/schemas.py +414 -0
  232. agno/os/routers/traces/traces.py +549 -0
  233. agno/os/routers/workflows/__init__.py +3 -0
  234. agno/os/routers/workflows/router.py +757 -0
  235. agno/os/routers/workflows/schema.py +139 -0
  236. agno/os/schema.py +157 -584
  237. agno/os/scopes.py +469 -0
  238. agno/os/settings.py +3 -0
  239. agno/os/utils.py +574 -185
  240. agno/reasoning/anthropic.py +85 -1
  241. agno/reasoning/azure_ai_foundry.py +93 -1
  242. agno/reasoning/deepseek.py +102 -2
  243. agno/reasoning/default.py +6 -7
  244. agno/reasoning/gemini.py +87 -3
  245. agno/reasoning/groq.py +109 -2
  246. agno/reasoning/helpers.py +6 -7
  247. agno/reasoning/manager.py +1238 -0
  248. agno/reasoning/ollama.py +93 -1
  249. agno/reasoning/openai.py +115 -1
  250. agno/reasoning/vertexai.py +85 -1
  251. agno/registry/__init__.py +3 -0
  252. agno/registry/registry.py +68 -0
  253. agno/remote/__init__.py +3 -0
  254. agno/remote/base.py +581 -0
  255. agno/run/__init__.py +2 -4
  256. agno/run/agent.py +134 -19
  257. agno/run/base.py +49 -1
  258. agno/run/cancel.py +65 -52
  259. agno/run/cancellation_management/__init__.py +9 -0
  260. agno/run/cancellation_management/base.py +78 -0
  261. agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
  262. agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
  263. agno/run/requirement.py +181 -0
  264. agno/run/team.py +111 -19
  265. agno/run/workflow.py +2 -1
  266. agno/session/agent.py +57 -92
  267. agno/session/summary.py +1 -1
  268. agno/session/team.py +62 -115
  269. agno/session/workflow.py +353 -57
  270. agno/skills/__init__.py +17 -0
  271. agno/skills/agent_skills.py +377 -0
  272. agno/skills/errors.py +32 -0
  273. agno/skills/loaders/__init__.py +4 -0
  274. agno/skills/loaders/base.py +27 -0
  275. agno/skills/loaders/local.py +216 -0
  276. agno/skills/skill.py +65 -0
  277. agno/skills/utils.py +107 -0
  278. agno/skills/validator.py +277 -0
  279. agno/table.py +10 -0
  280. agno/team/__init__.py +5 -1
  281. agno/team/remote.py +447 -0
  282. agno/team/team.py +3769 -2202
  283. agno/tools/brandfetch.py +27 -18
  284. agno/tools/browserbase.py +225 -16
  285. agno/tools/crawl4ai.py +3 -0
  286. agno/tools/duckduckgo.py +25 -71
  287. agno/tools/exa.py +0 -21
  288. agno/tools/file.py +14 -13
  289. agno/tools/file_generation.py +12 -6
  290. agno/tools/firecrawl.py +15 -7
  291. agno/tools/function.py +94 -113
  292. agno/tools/google_bigquery.py +11 -2
  293. agno/tools/google_drive.py +4 -3
  294. agno/tools/knowledge.py +9 -4
  295. agno/tools/mcp/mcp.py +301 -18
  296. agno/tools/mcp/multi_mcp.py +269 -14
  297. agno/tools/mem0.py +11 -10
  298. agno/tools/memory.py +47 -46
  299. agno/tools/mlx_transcribe.py +10 -7
  300. agno/tools/models/nebius.py +5 -5
  301. agno/tools/models_labs.py +20 -10
  302. agno/tools/nano_banana.py +151 -0
  303. agno/tools/parallel.py +0 -7
  304. agno/tools/postgres.py +76 -36
  305. agno/tools/python.py +14 -6
  306. agno/tools/reasoning.py +30 -23
  307. agno/tools/redshift.py +406 -0
  308. agno/tools/shopify.py +1519 -0
  309. agno/tools/spotify.py +919 -0
  310. agno/tools/tavily.py +4 -1
  311. agno/tools/toolkit.py +253 -18
  312. agno/tools/websearch.py +93 -0
  313. agno/tools/website.py +1 -1
  314. agno/tools/wikipedia.py +1 -1
  315. agno/tools/workflow.py +56 -48
  316. agno/tools/yfinance.py +12 -11
  317. agno/tracing/__init__.py +12 -0
  318. agno/tracing/exporter.py +161 -0
  319. agno/tracing/schemas.py +276 -0
  320. agno/tracing/setup.py +112 -0
  321. agno/utils/agent.py +251 -10
  322. agno/utils/cryptography.py +22 -0
  323. agno/utils/dttm.py +33 -0
  324. agno/utils/events.py +264 -7
  325. agno/utils/hooks.py +111 -3
  326. agno/utils/http.py +161 -2
  327. agno/utils/mcp.py +49 -8
  328. agno/utils/media.py +22 -1
  329. agno/utils/models/ai_foundry.py +9 -2
  330. agno/utils/models/claude.py +20 -5
  331. agno/utils/models/cohere.py +9 -2
  332. agno/utils/models/llama.py +9 -2
  333. agno/utils/models/mistral.py +4 -2
  334. agno/utils/os.py +0 -0
  335. agno/utils/print_response/agent.py +99 -16
  336. agno/utils/print_response/team.py +223 -24
  337. agno/utils/print_response/workflow.py +0 -2
  338. agno/utils/prompts.py +8 -6
  339. agno/utils/remote.py +23 -0
  340. agno/utils/response.py +1 -13
  341. agno/utils/string.py +91 -2
  342. agno/utils/team.py +62 -12
  343. agno/utils/tokens.py +657 -0
  344. agno/vectordb/base.py +15 -2
  345. agno/vectordb/cassandra/cassandra.py +1 -1
  346. agno/vectordb/chroma/__init__.py +2 -1
  347. agno/vectordb/chroma/chromadb.py +468 -23
  348. agno/vectordb/clickhouse/clickhousedb.py +1 -1
  349. agno/vectordb/couchbase/couchbase.py +6 -2
  350. agno/vectordb/lancedb/lance_db.py +7 -38
  351. agno/vectordb/lightrag/lightrag.py +7 -6
  352. agno/vectordb/milvus/milvus.py +118 -84
  353. agno/vectordb/mongodb/__init__.py +2 -1
  354. agno/vectordb/mongodb/mongodb.py +14 -31
  355. agno/vectordb/pgvector/pgvector.py +120 -66
  356. agno/vectordb/pineconedb/pineconedb.py +2 -19
  357. agno/vectordb/qdrant/__init__.py +2 -1
  358. agno/vectordb/qdrant/qdrant.py +33 -56
  359. agno/vectordb/redis/__init__.py +2 -1
  360. agno/vectordb/redis/redisdb.py +19 -31
  361. agno/vectordb/singlestore/singlestore.py +17 -9
  362. agno/vectordb/surrealdb/surrealdb.py +2 -38
  363. agno/vectordb/weaviate/__init__.py +2 -1
  364. agno/vectordb/weaviate/weaviate.py +7 -3
  365. agno/workflow/__init__.py +5 -1
  366. agno/workflow/agent.py +2 -2
  367. agno/workflow/condition.py +12 -10
  368. agno/workflow/loop.py +28 -9
  369. agno/workflow/parallel.py +21 -13
  370. agno/workflow/remote.py +362 -0
  371. agno/workflow/router.py +12 -9
  372. agno/workflow/step.py +261 -36
  373. agno/workflow/steps.py +12 -8
  374. agno/workflow/types.py +40 -77
  375. agno/workflow/workflow.py +939 -213
  376. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
  377. agno-2.4.3.dist-info/RECORD +677 -0
  378. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
  379. agno/tools/googlesearch.py +0 -98
  380. agno/tools/memori.py +0 -339
  381. agno-2.2.13.dist-info/RECORD +0 -575
  382. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
  383. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
agno/tools/memory.py CHANGED
@@ -1,10 +1,11 @@
1
1
  import json
2
2
  from textwrap import dedent
3
- from typing import Any, Dict, List, Optional
3
+ from typing import Any, List, Optional
4
4
  from uuid import uuid4
5
5
 
6
6
  from agno.db.base import BaseDb
7
7
  from agno.db.schemas import UserMemory
8
+ from agno.run import RunContext
8
9
  from agno.tools import Toolkit
9
10
  from agno.utils.log import log_debug, log_error
10
11
 
@@ -62,7 +63,7 @@ class MemoryTools(Toolkit):
62
63
  **kwargs,
63
64
  )
64
65
 
65
- def think(self, session_state: Dict[str, Any], thought: str) -> str:
66
+ def think(self, run_context: RunContext, thought: str) -> str:
66
67
  """Use this tool as a scratchpad to reason about memory operations, refine your approach, brainstorm memory content, or revise your plan.
67
68
 
68
69
  Call `Think` whenever you need to figure out what to do next, analyze the user's requirements, plan memory operations, or decide on execution strategy.
@@ -75,14 +76,14 @@ class MemoryTools(Toolkit):
75
76
  log_debug(f"Memory Thought: {thought}")
76
77
 
77
78
  # Add the thought to the session state
78
- if session_state is None:
79
- session_state = {}
80
- if "memory_thoughts" not in session_state:
81
- session_state["memory_thoughts"] = []
82
- session_state["memory_thoughts"].append(thought)
79
+ if run_context.session_state is None:
80
+ run_context.session_state = {}
81
+ if "memory_thoughts" not in run_context.session_state:
82
+ run_context.session_state["memory_thoughts"] = []
83
+ run_context.session_state["memory_thoughts"].append(thought)
83
84
 
84
85
  # Return the full log of thoughts and the new thought
85
- thoughts = "\n".join([f"- {t}" for t in session_state["memory_thoughts"]])
86
+ thoughts = "\n".join([f"- {t}" for t in run_context.session_state["memory_thoughts"]])
86
87
  formatted_thoughts = dedent(
87
88
  f"""Memory Thoughts:
88
89
  {thoughts}
@@ -93,21 +94,21 @@ class MemoryTools(Toolkit):
93
94
  log_error(f"Error recording memory thought: {e}")
94
95
  return f"Error recording memory thought: {e}"
95
96
 
96
- def get_memories(self, session_state: Dict[str, Any]) -> str:
97
+ def get_memories(self, run_context: RunContext) -> str:
97
98
  """
98
99
  Use this tool to get a list of memories for the current user from the database.
99
100
  """
100
101
  try:
101
- # Get user info from session state
102
- user_id = session_state.get("current_user_id") if session_state else None
102
+ # Get user info from run context
103
+ user_id = run_context.user_id
103
104
 
104
105
  memories = self.db.get_user_memories(user_id=user_id)
105
106
 
106
107
  # Store the result in session state for analysis
107
- if session_state is None:
108
- session_state = {}
109
- if "memory_operations" not in session_state:
110
- session_state["memory_operations"] = []
108
+ if run_context.session_state is None:
109
+ run_context.session_state = {}
110
+ if "memory_operations" not in run_context.session_state:
111
+ run_context.session_state["memory_operations"] = []
111
112
 
112
113
  operation_result = {
113
114
  "operation": "get_memories",
@@ -115,7 +116,7 @@ class MemoryTools(Toolkit):
115
116
  "memories": [memory.to_dict() for memory in memories], # type: ignore
116
117
  "error": None,
117
118
  }
118
- session_state["memory_operations"].append(operation_result)
119
+ run_context.session_state["memory_operations"].append(operation_result)
119
120
 
120
121
  return json.dumps([memory.to_dict() for memory in memories], indent=2) # type: ignore
121
122
  except Exception as e:
@@ -124,7 +125,7 @@ class MemoryTools(Toolkit):
124
125
 
125
126
  def add_memory(
126
127
  self,
127
- session_state: Dict[str, Any],
128
+ run_context: RunContext,
128
129
  memory: str,
129
130
  topics: Optional[List[str]] = None,
130
131
  ) -> str:
@@ -140,8 +141,8 @@ class MemoryTools(Toolkit):
140
141
  try:
141
142
  log_debug(f"Adding memory: {memory}")
142
143
 
143
- # Get user and agent info from session state
144
- user_id = session_state.get("current_user_id") if session_state else None
144
+ # Get user info from run context
145
+ user_id = run_context.user_id
145
146
 
146
147
  # Create UserMemory object
147
148
  user_memory = UserMemory(
@@ -155,10 +156,10 @@ class MemoryTools(Toolkit):
155
156
  created_memory = self.db.upsert_user_memory(user_memory)
156
157
 
157
158
  # Store the result in session state for analysis
158
- if session_state is None:
159
- session_state = {}
160
- if "memory_operations" not in session_state:
161
- session_state["memory_operations"] = []
159
+ if run_context.session_state is None:
160
+ run_context.session_state = {}
161
+ if "memory_operations" not in run_context.session_state:
162
+ run_context.session_state["memory_operations"] = []
162
163
 
163
164
  memory_dict = created_memory.to_dict() if created_memory else None # type: ignore
164
165
 
@@ -168,7 +169,7 @@ class MemoryTools(Toolkit):
168
169
  "memory": memory_dict,
169
170
  "error": None,
170
171
  }
171
- session_state["memory_operations"].append(operation_result)
172
+ run_context.session_state["memory_operations"].append(operation_result)
172
173
 
173
174
  if created_memory:
174
175
  return json.dumps({"success": True, "operation": "add_memory", "memory": memory_dict}, indent=2)
@@ -183,7 +184,7 @@ class MemoryTools(Toolkit):
183
184
 
184
185
  def update_memory(
185
186
  self,
186
- session_state: Dict[str, Any],
187
+ run_context: RunContext,
187
188
  memory_id: str,
188
189
  memory: Optional[str] = None,
189
190
  topics: Optional[List[str]] = None,
@@ -221,10 +222,10 @@ class MemoryTools(Toolkit):
221
222
  updated_result = self.db.upsert_user_memory(updated_memory)
222
223
 
223
224
  # Store the result in session state for analysis
224
- if session_state is None:
225
- session_state = {}
226
- if "memory_operations" not in session_state:
227
- session_state["memory_operations"] = []
225
+ if run_context.session_state is None:
226
+ run_context.session_state = {}
227
+ if "memory_operations" not in run_context.session_state:
228
+ run_context.session_state["memory_operations"] = []
228
229
 
229
230
  memory_dict = updated_result.to_dict() if updated_result else None # type: ignore
230
231
 
@@ -234,7 +235,7 @@ class MemoryTools(Toolkit):
234
235
  "memory": memory_dict,
235
236
  "error": None,
236
237
  }
237
- session_state["memory_operations"].append(operation_result)
238
+ run_context.session_state["memory_operations"].append(operation_result)
238
239
 
239
240
  if updated_result:
240
241
  return json.dumps({"success": True, "operation": "update_memory", "memory": memory_dict}, indent=2)
@@ -249,7 +250,7 @@ class MemoryTools(Toolkit):
249
250
 
250
251
  def delete_memory(
251
252
  self,
252
- session_state: Dict[str, Any],
253
+ run_context: RunContext,
253
254
  memory_id: str,
254
255
  ) -> str:
255
256
  """Use this tool to delete a memory from the database.
@@ -275,10 +276,10 @@ class MemoryTools(Toolkit):
275
276
  self.db.delete_user_memory(memory_id)
276
277
 
277
278
  # Store the result in session state for analysis
278
- if session_state is None:
279
- session_state = {}
280
- if "memory_operations" not in session_state:
281
- session_state["memory_operations"] = []
279
+ if run_context.session_state is None:
280
+ run_context.session_state = {}
281
+ if "memory_operations" not in run_context.session_state:
282
+ run_context.session_state["memory_operations"] = []
282
283
 
283
284
  memory_dict = existing_memory.to_dict() if existing_memory else None # type: ignore
284
285
 
@@ -289,7 +290,7 @@ class MemoryTools(Toolkit):
289
290
  "deleted_memory": memory_dict,
290
291
  "error": None,
291
292
  }
292
- session_state["memory_operations"].append(operation_result)
293
+ run_context.session_state["memory_operations"].append(operation_result)
293
294
 
294
295
  return json.dumps(
295
296
  {
@@ -305,7 +306,7 @@ class MemoryTools(Toolkit):
305
306
  log_error(f"Error deleting memory: {e}")
306
307
  return json.dumps({"success": False, "operation": "delete_memory", "error": str(e)}, indent=2)
307
308
 
308
- def analyze(self, session_state: Dict[str, Any], analysis: str) -> str:
309
+ def analyze(self, run_context: RunContext, analysis: str) -> str:
309
310
  """Use this tool to evaluate whether the memory operations results are correct and sufficient.
310
311
  If not, go back to "Think" or use memory operations with refined parameters.
311
312
 
@@ -316,14 +317,14 @@ class MemoryTools(Toolkit):
316
317
  log_debug(f"Memory Analysis: {analysis}")
317
318
 
318
319
  # Add the analysis to the session state
319
- if session_state is None:
320
- session_state = {}
321
- if "memory_analysis" not in session_state:
322
- session_state["memory_analysis"] = []
323
- session_state["memory_analysis"].append(analysis)
320
+ if run_context.session_state is None:
321
+ run_context.session_state = {}
322
+ if "memory_analysis" not in run_context.session_state:
323
+ run_context.session_state["memory_analysis"] = []
324
+ run_context.session_state["memory_analysis"].append(analysis)
324
325
 
325
326
  # Return the full log of analysis and the new analysis
326
- analysis_log = "\n".join([f"- {a}" for a in session_state["memory_analysis"]])
327
+ analysis_log = "\n".join([f"- {a}" for a in run_context.session_state["memory_analysis"]])
327
328
  formatted_analysis = dedent(
328
329
  f"""Memory Analysis:
329
330
  {analysis_log}
@@ -338,7 +339,7 @@ class MemoryTools(Toolkit):
338
339
  You have access to the Think, Add Memory, Update Memory, Delete Memory, and Analyze tools that will help you manage user memories and analyze their operations. Use these tools as frequently as needed to successfully complete memory management tasks.
339
340
 
340
341
  ## How to use the Think, Memory Operations, and Analyze tools:
341
-
342
+
342
343
  1. **Think**
343
344
  - Purpose: A scratchpad for planning memory operations, brainstorming memory content, and refining your approach. You never reveal your "Think" content to the user.
344
345
  - Usage: Call `think` whenever you need to figure out what memory operations to perform, analyze requirements, or decide on strategy.
@@ -407,12 +408,12 @@ class MemoryTools(Toolkit):
407
408
  Analyze: Successfully deleted the outdated work schedule memory. The old information won't interfere with future scheduling requests.
408
409
 
409
410
  Final Answer: I've removed your old work schedule information. Feel free to share your new schedule when you're ready, and I'll store the updated information.
410
-
411
+
411
412
  #### Example 4: Retrieving Memories
412
413
 
413
414
  User: What have you remembered about me?
414
415
  Think: The user wants to retrieve memories about themselves. I should use the get_memories tool to retrieve the memories.
415
- Get Memories:
416
+ Get Memories:
416
417
  Analyze: Successfully retrieved the memories about the user. The memories are relevant to the user's preferences and activities.
417
418
 
418
419
  Final Answer: I've retrieved the memories about you. You like to hike in the mountains on weekends and travel to new places and experience different cultures. You are planning to travel to Africa in December.\
@@ -17,7 +17,7 @@ provides high-quality transcription capabilities.
17
17
 
18
18
  import json
19
19
  from pathlib import Path
20
- from typing import Any, Dict, List, Optional, Tuple, Union
20
+ from typing import Any, Dict, List, Optional, Union
21
21
 
22
22
  from agno.tools import Toolkit
23
23
  from agno.utils.log import log_info, logger
@@ -33,9 +33,10 @@ class MLXTranscribeTools(Toolkit):
33
33
  self,
34
34
  base_dir: Optional[Path] = None,
35
35
  enable_read_files_in_base_dir: bool = True,
36
+ restrict_to_base_dir: bool = True,
36
37
  path_or_hf_repo: str = "mlx-community/whisper-large-v3-turbo",
37
38
  verbose: Optional[bool] = None,
38
- temperature: Optional[Union[float, Tuple[float, ...]]] = None,
39
+ temperature: Optional[Union[float, tuple[float, ...]]] = None,
39
40
  compression_ratio_threshold: Optional[float] = None,
40
41
  logprob_threshold: Optional[float] = None,
41
42
  no_speech_threshold: Optional[float] = None,
@@ -50,10 +51,11 @@ class MLXTranscribeTools(Toolkit):
50
51
  all: bool = False,
51
52
  **kwargs,
52
53
  ):
53
- self.base_dir: Path = base_dir or Path.cwd()
54
+ self.base_dir: Path = (base_dir or Path.cwd()).resolve()
55
+ self.restrict_to_base_dir = restrict_to_base_dir
54
56
  self.path_or_hf_repo: str = path_or_hf_repo
55
57
  self.verbose: Optional[bool] = verbose
56
- self.temperature: Optional[Union[float, Tuple[float, ...]]] = temperature
58
+ self.temperature: Optional[Union[float, tuple[float, ...]]] = temperature
57
59
  self.compression_ratio_threshold: Optional[float] = compression_ratio_threshold
58
60
  self.logprob_threshold: Optional[float] = logprob_threshold
59
61
  self.no_speech_threshold: Optional[float] = no_speech_threshold
@@ -83,9 +85,10 @@ class MLXTranscribeTools(Toolkit):
83
85
  str: The transcribed text or an error message if the transcription fails.
84
86
  """
85
87
  try:
86
- audio_file_path = str(self.base_dir.joinpath(file_name))
87
- if audio_file_path is None:
88
- return "No audio file path provided"
88
+ safe, file_path = self._check_path(file_name, self.base_dir, self.restrict_to_base_dir)
89
+ if not safe:
90
+ return f"Error: Path '{file_name}' is outside the allowed base directory"
91
+ audio_file_path = str(file_path)
89
92
 
90
93
  log_info(f"Transcribing audio file {audio_file_path}")
91
94
  transcription_kwargs: Dict[str, Any] = {
@@ -12,12 +12,12 @@ from agno.utils.log import log_error, log_warning
12
12
 
13
13
 
14
14
  class NebiusTools(Toolkit):
15
- """Tools for interacting with Nebius AI Studio's text-to-image API"""
15
+ """Tools for interacting with Nebius Token Factory's text-to-image API"""
16
16
 
17
17
  def __init__(
18
18
  self,
19
19
  api_key: Optional[str] = None,
20
- base_url: str = "https://api.studio.nebius.com/v1",
20
+ base_url: str = "https://api.tokenfactory.nebius.com/v1",
21
21
  image_model: str = "black-forest-labs/flux-schnell",
22
22
  image_quality: Optional[str] = "standard",
23
23
  image_size: Optional[str] = "1024x1024",
@@ -26,11 +26,11 @@ class NebiusTools(Toolkit):
26
26
  all: bool = False,
27
27
  **kwargs,
28
28
  ):
29
- """Initialize Nebius AI Studio text-to-image tools.
29
+ """Initialize Nebius Token Factory text-to-image tools.
30
30
 
31
31
  Args:
32
32
  api_key: Nebius API key. If not provided, will look for NEBIUS_API_KEY environment variable.
33
- base_url: The base URL for the Nebius AI Studio API. This should be configured according to Nebius's documentation.
33
+ base_url: The base URL for the Nebius Token Factory API. This should be configured according to Nebius's documentation.
34
34
  image_model: The model to use for generation. Options include:
35
35
  - "black-forest-labs/flux-schnell" (fastest)
36
36
  - "black-forest-labs/flux-dev" (balanced)
@@ -69,7 +69,7 @@ class NebiusTools(Toolkit):
69
69
  agent: Agent,
70
70
  prompt: str,
71
71
  ) -> ToolResult:
72
- """Generate images based on a text prompt using Nebius AI Studio.
72
+ """Generate images based on a text prompt using Nebius Token Factory.
73
73
 
74
74
  Args:
75
75
  agent: The agent instance for adding images
agno/tools/models_labs.py CHANGED
@@ -4,10 +4,8 @@ from os import getenv
4
4
  from typing import Any, Dict, List, Optional, Union
5
5
  from uuid import uuid4
6
6
 
7
- from agno.agent import Agent
8
7
  from agno.media import Audio, Image, Video
9
8
  from agno.models.response import FileType
10
- from agno.team import Team
11
9
  from agno.tools import Toolkit
12
10
  from agno.tools.function import ToolResult
13
11
  from agno.utils.log import log_debug, log_info, logger
@@ -22,12 +20,14 @@ MODELS_LAB_URLS = {
22
20
  "MP4": "https://modelslab.com/api/v6/video/text2video",
23
21
  "MP3": "https://modelslab.com/api/v6/voice/music_gen",
24
22
  "GIF": "https://modelslab.com/api/v6/video/text2video",
23
+ "WAV": "https://modelslab.com/api/v6/voice/sfx",
25
24
  }
26
25
 
27
26
  MODELS_LAB_FETCH_URLS = {
28
27
  "MP4": "https://modelslab.com/api/v6/video/fetch",
29
28
  "MP3": "https://modelslab.com/api/v6/voice/fetch",
30
29
  "GIF": "https://modelslab.com/api/v6/video/fetch",
30
+ "WAV": "https://modelslab.com/api/v6/voice/fetch",
31
31
  }
32
32
 
33
33
 
@@ -78,6 +78,13 @@ class ModelsLabTools(Toolkit):
78
78
  "output_type": self.file_type.value,
79
79
  }
80
80
  base_payload |= video_template # Use |= instead of update()
81
+ elif self.file_type == FileType.WAV:
82
+ sfx_template = {
83
+ "duration": 10,
84
+ "output_format": "wav",
85
+ "temp": False,
86
+ }
87
+ base_payload |= sfx_template # Use |= instead of update()
81
88
  else:
82
89
  audio_template = {
83
90
  "base64": False,
@@ -101,7 +108,7 @@ class ModelsLabTools(Toolkit):
101
108
  elif self.file_type == FileType.GIF:
102
109
  image_artifact = Image(id=str(media_id), url=media_url)
103
110
  artifacts["images"].append(image_artifact)
104
- elif self.file_type == FileType.MP3:
111
+ elif self.file_type in [FileType.MP3, FileType.WAV]:
105
112
  audio_artifact = Audio(id=str(media_id), url=media_url)
106
113
  artifacts["audios"].append(audio_artifact)
107
114
 
@@ -131,7 +138,7 @@ class ModelsLabTools(Toolkit):
131
138
 
132
139
  return False
133
140
 
134
- def generate_media(self, agent: Union[Agent, Team], prompt: str) -> ToolResult:
141
+ def generate_media(self, prompt: str) -> ToolResult:
135
142
  """Generate media (video, image, or audio) given a prompt."""
136
143
  if not self.api_key:
137
144
  return ToolResult(content="Please set the MODELS_LAB_API_KEY")
@@ -157,7 +164,6 @@ class ModelsLabTools(Toolkit):
157
164
  return ToolResult(content=f"Error: {result['error']}")
158
165
 
159
166
  eta = result.get("eta")
160
- url_links = result.get("future_links")
161
167
  media_id = str(uuid4())
162
168
 
163
169
  # Collect all media artifacts
@@ -165,17 +171,21 @@ class ModelsLabTools(Toolkit):
165
171
  all_videos = []
166
172
  all_audios = []
167
173
 
174
+ if self.file_type == FileType.WAV:
175
+ url_links = result.get("output", [])
176
+ else:
177
+ url_links = result.get("future_links")
168
178
  for media_url in url_links:
169
179
  artifacts = self._create_media_artifacts(media_id, media_url, str(eta))
170
180
  all_images.extend(artifacts["images"])
171
181
  all_videos.extend(artifacts["videos"])
172
182
  all_audios.extend(artifacts["audios"])
173
183
 
174
- if self.wait_for_completion and isinstance(eta, int):
175
- if self._wait_for_media(media_id, eta):
176
- log_info("Media generation completed successfully")
177
- else:
178
- logger.warning("Media generation timed out")
184
+ if self.wait_for_completion and isinstance(eta, int):
185
+ if self._wait_for_media(media_id, eta):
186
+ log_info("Media generation completed successfully")
187
+ else:
188
+ logger.warning("Media generation timed out")
179
189
 
180
190
  # Return ToolResult with appropriate media artifacts
181
191
  return ToolResult(
@@ -0,0 +1,151 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from io import BytesIO
5
+ from typing import Any, List, Optional
6
+ from uuid import uuid4
7
+
8
+ from agno.media import Image
9
+ from agno.tools import Toolkit
10
+ from agno.tools.function import ToolResult
11
+ from agno.utils.log import log_debug, logger
12
+
13
+ try:
14
+ from google import genai
15
+ from google.genai import types
16
+ from PIL import Image as PILImage
17
+
18
+ except ImportError as exc:
19
+ missing = []
20
+ try:
21
+ from google.genai import types
22
+ except ImportError:
23
+ missing.append("google-genai")
24
+
25
+ try:
26
+ from PIL import Image as PILImage
27
+ except ImportError:
28
+ missing.append("Pillow")
29
+
30
+ raise ImportError(
31
+ f"Missing required package(s): {', '.join(missing)}. Install using: pip install {' '.join(missing)}"
32
+ ) from exc
33
+
34
+
35
+ # Note: Expand this list as new models become supported by the Google Content Generation API.
36
+ ALLOWED_MODELS = ["gemini-2.5-flash-image"]
37
+ ALLOWED_RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"]
38
+
39
+
40
+ class NanoBananaTools(Toolkit):
41
+ def __init__(
42
+ self,
43
+ model: str = "gemini-2.5-flash-image",
44
+ aspect_ratio: str = "1:1",
45
+ api_key: Optional[str] = None,
46
+ enable_create_image: bool = True,
47
+ **kwargs,
48
+ ):
49
+ self.model = model
50
+ self.aspect_ratio = aspect_ratio
51
+ self.api_key = api_key or os.getenv("GOOGLE_API_KEY")
52
+
53
+ # Validate model
54
+ if model not in ALLOWED_MODELS:
55
+ raise ValueError(f"Invalid model '{model}'. Supported: {', '.join(ALLOWED_MODELS)}")
56
+
57
+ if self.aspect_ratio not in ALLOWED_RATIOS:
58
+ raise ValueError(f"Invalid aspect_ratio '{self.aspect_ratio}'. Supported: {', '.join(ALLOWED_RATIOS)}")
59
+
60
+ if not self.api_key:
61
+ raise ValueError("GOOGLE_API_KEY not set. Export it: `export GOOGLE_API_KEY=<your-key>`")
62
+
63
+ tools: List[Any] = []
64
+ if enable_create_image:
65
+ tools.append(self.create_image)
66
+
67
+ super().__init__(name="nano_banana", tools=tools, **kwargs)
68
+
69
+ def create_image(self, prompt: str) -> ToolResult:
70
+ """Generate an image from a text prompt."""
71
+ try:
72
+ client = genai.Client(api_key=self.api_key)
73
+ log_debug(f"NanoBanana generating image with prompt: {prompt}")
74
+
75
+ cfg = types.GenerateContentConfig(
76
+ response_modalities=["IMAGE"],
77
+ image_config=types.ImageConfig(aspect_ratio=self.aspect_ratio),
78
+ )
79
+
80
+ response = client.models.generate_content(
81
+ model=self.model,
82
+ contents=[prompt], # type: ignore
83
+ config=cfg,
84
+ )
85
+
86
+ generated_images: List[Image] = []
87
+ response_str = ""
88
+
89
+ if not hasattr(response, "candidates") or not response.candidates:
90
+ logger.warning("No candidates in response")
91
+ return ToolResult(content="No images were generated in the response")
92
+
93
+ # Process each candidate
94
+ for candidate in response.candidates:
95
+ if not hasattr(candidate, "content") or not candidate.content or not candidate.content.parts:
96
+ continue
97
+
98
+ for part in candidate.content.parts:
99
+ if hasattr(part, "text") and part.text:
100
+ response_str += part.text + "\n"
101
+
102
+ if hasattr(part, "inline_data") and part.inline_data:
103
+ try:
104
+ # Extract image data from the blob
105
+ image_data = part.inline_data.data
106
+ mime_type = getattr(part.inline_data, "mime_type", "image/png")
107
+
108
+ if image_data:
109
+ pil_img = PILImage.open(BytesIO(image_data))
110
+
111
+ # Save to buffer with proper format
112
+ buffer = BytesIO()
113
+ image_format = "PNG" if "png" in mime_type.lower() else "JPEG"
114
+ pil_img.save(buffer, format=image_format)
115
+ buffer.seek(0)
116
+
117
+ agno_img = Image(
118
+ id=str(uuid4()),
119
+ content=buffer.getvalue(),
120
+ original_prompt=prompt,
121
+ )
122
+ generated_images.append(agno_img)
123
+
124
+ log_debug(f"Successfully processed image with ID: {agno_img.id}")
125
+ response_str += f"Image generated successfully (ID: {agno_img.id}).\n"
126
+
127
+ except Exception as img_exc:
128
+ logger.error(f"Failed to process image data: {img_exc}")
129
+ response_str += f"Failed to process image: {img_exc}\n"
130
+
131
+ if hasattr(response, "usage_metadata") and response.usage_metadata:
132
+ log_debug(
133
+ f"Token usage - Prompt: {response.usage_metadata.prompt_token_count}, "
134
+ f"Response: {response.usage_metadata.candidates_token_count}, "
135
+ f"Total: {response.usage_metadata.total_token_count}"
136
+ )
137
+
138
+ if generated_images:
139
+ return ToolResult(
140
+ content=response_str.strip() or "Image(s) generated successfully",
141
+ images=generated_images,
142
+ )
143
+ else:
144
+ return ToolResult(
145
+ content=response_str.strip() or "No images were generated",
146
+ images=None,
147
+ )
148
+
149
+ except Exception as exc:
150
+ logger.error(f"NanoBanana image generation failed: {exc}")
151
+ return ToolResult(content=f"Error generating image: {str(exc)}")
agno/tools/parallel.py CHANGED
@@ -41,7 +41,6 @@ class ParallelTools(Toolkit):
41
41
  include_domains (Optional[List[str]]): Default domains to restrict results to. Default is None.
42
42
  exclude_domains (Optional[List[str]]): Default domains to exclude from results. Default is None.
43
43
  max_age_seconds (Optional[int]): Default cache age threshold (minimum 600). Default is None.
44
- timeout_seconds (Optional[float]): Default timeout for content retrieval. Default is None.
45
44
  disable_cache_fallback (Optional[bool]): Default cache fallback behavior. Default is None.
46
45
  """
47
46
 
@@ -58,7 +57,6 @@ class ParallelTools(Toolkit):
58
57
  include_domains: Optional[List[str]] = None,
59
58
  exclude_domains: Optional[List[str]] = None,
60
59
  max_age_seconds: Optional[int] = None,
61
- timeout_seconds: Optional[float] = None,
62
60
  disable_cache_fallback: Optional[bool] = None,
63
61
  **kwargs,
64
62
  ):
@@ -73,7 +71,6 @@ class ParallelTools(Toolkit):
73
71
  self.include_domains = include_domains
74
72
  self.exclude_domains = exclude_domains
75
73
  self.max_age_seconds = max_age_seconds
76
- self.timeout_seconds = timeout_seconds
77
74
  self.disable_cache_fallback = disable_cache_fallback
78
75
 
79
76
  self.parallel_client = ParallelClient(
@@ -153,8 +150,6 @@ class ParallelTools(Toolkit):
153
150
  fetch_policy: Dict[str, Any] = {}
154
151
  if self.max_age_seconds is not None:
155
152
  fetch_policy["max_age_seconds"] = self.max_age_seconds
156
- if self.timeout_seconds is not None:
157
- fetch_policy["timeout_seconds"] = self.timeout_seconds
158
153
  if self.disable_cache_fallback is not None:
159
154
  fetch_policy["disable_cache_fallback"] = self.disable_cache_fallback
160
155
 
@@ -256,8 +251,6 @@ class ParallelTools(Toolkit):
256
251
  fetch_policy: Dict[str, Any] = {}
257
252
  if self.max_age_seconds is not None:
258
253
  fetch_policy["max_age_seconds"] = self.max_age_seconds
259
- if self.timeout_seconds is not None:
260
- fetch_policy["timeout_seconds"] = self.timeout_seconds
261
254
  if self.disable_cache_fallback is not None:
262
255
  fetch_policy["disable_cache_fallback"] = self.disable_cache_fallback
263
256