agno 1.8.0__py3-none-any.whl → 2.0.0a1__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 (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2781 -4126
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +9 -64
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1749 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1438 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +888 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1051 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1417 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +10 -10
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1515 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/media.py +2 -2
  137. agno/memory/__init__.py +2 -10
  138. agno/memory/manager.py +1003 -148
  139. agno/models/aimlapi/__init__.py +2 -2
  140. agno/models/aimlapi/aimlapi.py +6 -6
  141. agno/models/anthropic/claude.py +129 -82
  142. agno/models/aws/bedrock.py +107 -175
  143. agno/models/aws/claude.py +64 -18
  144. agno/models/azure/ai_foundry.py +73 -23
  145. agno/models/base.py +347 -287
  146. agno/models/cerebras/cerebras.py +84 -27
  147. agno/models/cohere/chat.py +106 -98
  148. agno/models/dashscope/dashscope.py +14 -5
  149. agno/models/google/gemini.py +123 -53
  150. agno/models/groq/groq.py +97 -35
  151. agno/models/huggingface/huggingface.py +92 -27
  152. agno/models/ibm/watsonx.py +72 -13
  153. agno/models/litellm/chat.py +85 -13
  154. agno/models/message.py +38 -144
  155. agno/models/meta/llama.py +85 -49
  156. agno/models/metrics.py +120 -0
  157. agno/models/mistral/mistral.py +90 -21
  158. agno/models/ollama/__init__.py +0 -2
  159. agno/models/ollama/chat.py +84 -46
  160. agno/models/openai/chat.py +135 -27
  161. agno/models/openai/responses.py +233 -115
  162. agno/models/perplexity/perplexity.py +26 -2
  163. agno/models/portkey/portkey.py +0 -7
  164. agno/models/response.py +14 -8
  165. agno/models/utils.py +20 -0
  166. agno/models/vercel/__init__.py +2 -2
  167. agno/models/vercel/v0.py +1 -1
  168. agno/models/vllm/__init__.py +2 -2
  169. agno/models/vllm/vllm.py +3 -3
  170. agno/models/xai/xai.py +10 -10
  171. agno/os/__init__.py +3 -0
  172. agno/os/app.py +393 -0
  173. agno/os/auth.py +47 -0
  174. agno/os/config.py +103 -0
  175. agno/os/interfaces/agui/__init__.py +3 -0
  176. agno/os/interfaces/agui/agui.py +31 -0
  177. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  178. agno/{app → os/interfaces}/agui/utils.py +65 -28
  179. agno/os/interfaces/base.py +21 -0
  180. agno/os/interfaces/slack/__init__.py +3 -0
  181. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  182. agno/os/interfaces/slack/slack.py +33 -0
  183. agno/os/interfaces/whatsapp/__init__.py +3 -0
  184. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  185. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  186. agno/os/router.py +843 -0
  187. agno/os/routers/__init__.py +3 -0
  188. agno/os/routers/evals/__init__.py +3 -0
  189. agno/os/routers/evals/evals.py +204 -0
  190. agno/os/routers/evals/schemas.py +142 -0
  191. agno/os/routers/evals/utils.py +161 -0
  192. agno/os/routers/knowledge/__init__.py +3 -0
  193. agno/os/routers/knowledge/knowledge.py +413 -0
  194. agno/os/routers/knowledge/schemas.py +118 -0
  195. agno/os/routers/memory/__init__.py +3 -0
  196. agno/os/routers/memory/memory.py +179 -0
  197. agno/os/routers/memory/schemas.py +58 -0
  198. agno/os/routers/metrics/__init__.py +3 -0
  199. agno/os/routers/metrics/metrics.py +58 -0
  200. agno/os/routers/metrics/schemas.py +47 -0
  201. agno/os/routers/session/__init__.py +3 -0
  202. agno/os/routers/session/session.py +163 -0
  203. agno/os/schema.py +892 -0
  204. agno/{app/playground → os}/settings.py +8 -15
  205. agno/os/utils.py +270 -0
  206. agno/reasoning/azure_ai_foundry.py +4 -4
  207. agno/reasoning/deepseek.py +4 -4
  208. agno/reasoning/default.py +6 -11
  209. agno/reasoning/groq.py +4 -4
  210. agno/reasoning/helpers.py +4 -6
  211. agno/reasoning/ollama.py +4 -4
  212. agno/reasoning/openai.py +4 -4
  213. agno/run/{response.py → agent.py} +144 -72
  214. agno/run/base.py +44 -58
  215. agno/run/cancel.py +83 -0
  216. agno/run/team.py +133 -77
  217. agno/run/workflow.py +537 -12
  218. agno/session/__init__.py +10 -0
  219. agno/session/agent.py +244 -0
  220. agno/session/summary.py +225 -0
  221. agno/session/team.py +262 -0
  222. agno/{storage/session/v2 → session}/workflow.py +47 -24
  223. agno/team/__init__.py +15 -16
  224. agno/team/team.py +2967 -4243
  225. agno/tools/agentql.py +14 -5
  226. agno/tools/airflow.py +9 -4
  227. agno/tools/api.py +7 -3
  228. agno/tools/apify.py +2 -46
  229. agno/tools/arxiv.py +8 -3
  230. agno/tools/aws_lambda.py +7 -5
  231. agno/tools/aws_ses.py +7 -1
  232. agno/tools/baidusearch.py +4 -1
  233. agno/tools/bitbucket.py +4 -4
  234. agno/tools/brandfetch.py +14 -11
  235. agno/tools/bravesearch.py +4 -1
  236. agno/tools/brightdata.py +42 -22
  237. agno/tools/browserbase.py +13 -4
  238. agno/tools/calcom.py +12 -10
  239. agno/tools/calculator.py +10 -27
  240. agno/tools/cartesia.py +18 -13
  241. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  242. agno/tools/confluence.py +71 -18
  243. agno/tools/crawl4ai.py +7 -1
  244. agno/tools/csv_toolkit.py +9 -8
  245. agno/tools/dalle.py +18 -11
  246. agno/tools/daytona.py +13 -16
  247. agno/tools/decorator.py +6 -3
  248. agno/tools/desi_vocal.py +16 -7
  249. agno/tools/discord.py +11 -8
  250. agno/tools/docker.py +30 -42
  251. agno/tools/duckdb.py +34 -53
  252. agno/tools/duckduckgo.py +8 -7
  253. agno/tools/e2b.py +62 -62
  254. agno/tools/eleven_labs.py +35 -28
  255. agno/tools/email.py +4 -1
  256. agno/tools/evm.py +7 -1
  257. agno/tools/exa.py +19 -14
  258. agno/tools/fal.py +29 -29
  259. agno/tools/file.py +9 -8
  260. agno/tools/financial_datasets.py +25 -44
  261. agno/tools/firecrawl.py +22 -22
  262. agno/tools/function.py +68 -17
  263. agno/tools/giphy.py +22 -10
  264. agno/tools/github.py +48 -126
  265. agno/tools/gmail.py +46 -62
  266. agno/tools/google_bigquery.py +7 -6
  267. agno/tools/google_maps.py +11 -26
  268. agno/tools/googlesearch.py +7 -2
  269. agno/tools/googlesheets.py +21 -17
  270. agno/tools/hackernews.py +9 -5
  271. agno/tools/jina.py +5 -4
  272. agno/tools/jira.py +18 -9
  273. agno/tools/knowledge.py +31 -32
  274. agno/tools/linear.py +18 -33
  275. agno/tools/linkup.py +5 -1
  276. agno/tools/local_file_system.py +8 -5
  277. agno/tools/lumalab.py +31 -19
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +32 -14
  282. agno/tools/models/gemini.py +58 -31
  283. agno/tools/models/groq.py +29 -20
  284. agno/tools/models/nebius.py +27 -11
  285. agno/tools/models_labs.py +39 -15
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +134 -0
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +57 -26
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +62 -46
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +54 -41
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +95 -118
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/location.py +2 -2
  337. agno/utils/log.py +2 -2
  338. agno/utils/mcp.py +11 -5
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/claude.py +6 -4
  342. agno/utils/models/mistral.py +8 -7
  343. agno/utils/models/schema_utils.py +3 -3
  344. agno/utils/pprint.py +33 -32
  345. agno/utils/print_response/agent.py +779 -0
  346. agno/utils/print_response/team.py +1565 -0
  347. agno/utils/print_response/workflow.py +1451 -0
  348. agno/utils/prompts.py +14 -14
  349. agno/utils/reasoning.py +87 -0
  350. agno/utils/response.py +42 -42
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +356 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2394 -696
  383. agno-2.0.0a1.dist-info/METADATA +355 -0
  384. agno-2.0.0a1.dist-info/RECORD +514 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -698
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.0.dist-info/METADATA +0 -979
  568. agno-1.8.0.dist-info/RECORD +0 -565
  569. agno-1.8.0.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
agno/tools/neo4j.py ADDED
@@ -0,0 +1,134 @@
1
+ import os
2
+ from typing import Any, List, Optional
3
+
4
+ try:
5
+ from neo4j import GraphDatabase
6
+ except ImportError:
7
+ raise ImportError("`neo4j` not installed. Please install using `pip install neo4j`")
8
+
9
+ from agno.tools import Toolkit
10
+ from agno.utils.log import log_debug, logger
11
+
12
+
13
+ class Neo4jTools(Toolkit):
14
+ def __init__(
15
+ self,
16
+ uri: Optional[str] = None,
17
+ user: Optional[str] = None,
18
+ password: Optional[str] = None,
19
+ database: Optional[str] = None,
20
+ # Enable flags for <6 functions
21
+ enable_list_labels: bool = True,
22
+ enable_list_relationships: bool = True,
23
+ enable_get_schema: bool = True,
24
+ enable_run_cypher: bool = True,
25
+ all: bool = False,
26
+ **kwargs,
27
+ ):
28
+ """
29
+ Initialize the Neo4jTools toolkit.
30
+ Connection parameters (uri/user/password or host/port) can be provided.
31
+ If not provided, falls back to NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD env vars.
32
+
33
+ Args:
34
+ uri (Optional[str]): The Neo4j URI.
35
+ user (Optional[str]): The Neo4j username.
36
+ password (Optional[str]): The Neo4j password.
37
+ host (Optional[str]): The Neo4j host.
38
+ port (Optional[int]): The Neo4j port.
39
+ database (Optional[str]): The Neo4j database.
40
+ list_labels (bool): Whether to list node labels.
41
+ list_relationships (bool): Whether to list relationship types.
42
+ get_schema (bool): Whether to get the schema.
43
+ run_cypher (bool): Whether to run Cypher queries.
44
+ **kwargs: Additional keyword arguments.
45
+ """
46
+ # Determine the connection URI and credentials
47
+ uri = uri or os.getenv("NEO4J_URI", "bolt://localhost:7687")
48
+ user = user or os.getenv("NEO4J_USERNAME")
49
+ password = password or os.getenv("NEO4J_PASSWORD")
50
+
51
+ if user is None or password is None:
52
+ raise ValueError("Username or password for Neo4j not provided")
53
+
54
+ # Create the Neo4j driver
55
+ try:
56
+ self.driver = GraphDatabase.driver(uri, auth=(user, password)) # type: ignore
57
+ self.driver.verify_connectivity()
58
+ log_debug("Connected to Neo4j database")
59
+ except Exception as e:
60
+ logger.error(f"Failed to connect to Neo4j: {e}")
61
+ raise
62
+
63
+ self.database = database or "neo4j"
64
+
65
+ # Register toolkit methods as tools
66
+ tools: List[Any] = []
67
+ if all or enable_list_labels:
68
+ tools.append(self.list_labels)
69
+ if all or enable_list_relationships:
70
+ tools.append(self.list_relationship_types)
71
+ if all or enable_get_schema:
72
+ tools.append(self.get_schema)
73
+ if all or enable_run_cypher:
74
+ tools.append(self.run_cypher_query)
75
+ super().__init__(name="neo4j_tools", tools=tools, **kwargs)
76
+
77
+ def list_labels(self) -> list:
78
+ """
79
+ Retrieve all node labels present in the connected Neo4j database.
80
+ """
81
+ try:
82
+ log_debug("Listing node labels in Neo4j database")
83
+ with self.driver.session(database=self.database) as session:
84
+ result = session.run("CALL db.labels()")
85
+ labels = [record["label"] for record in result]
86
+ return labels
87
+ except Exception as e:
88
+ logger.error(f"Error listing labels: {e}")
89
+ return []
90
+
91
+ def list_relationship_types(self) -> list:
92
+ """
93
+ Retrieve all relationship types present in the connected Neo4j database.
94
+ """
95
+ try:
96
+ log_debug("Listing relationship types in Neo4j database")
97
+ with self.driver.session(database=self.database) as session:
98
+ result = session.run("CALL db.relationshipTypes()")
99
+ types = [record["relationshipType"] for record in result]
100
+ return types
101
+ except Exception as e:
102
+ logger.error(f"Error listing relationship types: {e}")
103
+ return []
104
+
105
+ def get_schema(self) -> list:
106
+ """
107
+ Retrieve a visualization of the database schema, including nodes and relationships.
108
+ """
109
+ try:
110
+ log_debug("Retrieving Neo4j schema visualization")
111
+ with self.driver.session(database=self.database) as session:
112
+ result = session.run("CALL db.schema.visualization()")
113
+ schema_data = result.data()
114
+ return schema_data
115
+ except Exception as e:
116
+ logger.error(f"Error getting Neo4j schema: {e}")
117
+ return []
118
+
119
+ def run_cypher_query(self, query: str) -> list:
120
+ """
121
+ Execute an arbitrary Cypher query against the connected Neo4j database.
122
+
123
+ Args:
124
+ query (str): The Cypher query string to execute.
125
+ """
126
+ try:
127
+ log_debug(f"Running Cypher query: {query}")
128
+ with self.driver.session(database=self.database) as session:
129
+ result = session.run(query) # type: ignore[arg-type]
130
+ data = result.data()
131
+ return data
132
+ except Exception as e:
133
+ logger.error(f"Error running Cypher query: {e}")
134
+ return []
agno/tools/newspaper.py CHANGED
@@ -14,9 +14,14 @@ class NewspaperTools(Toolkit):
14
14
  get_article_text (bool): Whether to get the text of an article from a URL.
15
15
  """
16
16
 
17
- def __init__(self, get_article_text: bool = True, **kwargs):
17
+ def __init__(
18
+ self,
19
+ enable_get_article_text: bool = True,
20
+ all: bool = False,
21
+ **kwargs,
22
+ ):
18
23
  tools = []
19
- if get_article_text:
24
+ if all or enable_get_article_text:
20
25
  tools.append(self.get_article_text)
21
26
 
22
27
  super().__init__(name="newspaper_toolkit", tools=tools, **kwargs)
agno/tools/newspaper4k.py CHANGED
@@ -14,19 +14,24 @@ class Newspaper4kTools(Toolkit):
14
14
  """
15
15
  Newspaper4kTools is a toolkit for getting the text of an article from a URL.
16
16
  Args:
17
- read_article (bool): Whether to read an article from a URL.
17
+ enable_read_article (bool): Whether to read an article from a URL.
18
18
  include_summary (bool): Whether to include the summary of an article.
19
19
  article_length (Optional[int]): The length of the article to read.
20
20
  """
21
21
 
22
22
  def __init__(
23
- self, read_article: bool = True, include_summary: bool = False, article_length: Optional[int] = None, **kwargs
23
+ self,
24
+ include_summary: bool = False,
25
+ article_length: Optional[int] = None,
26
+ enable_read_article: bool = True,
27
+ all: bool = False,
28
+ **kwargs,
24
29
  ):
25
30
  self.include_summary: bool = include_summary
26
31
  self.article_length: Optional[int] = article_length
27
32
 
28
33
  tools = []
29
- if read_article:
34
+ if all or enable_read_article:
30
35
  tools.append(self.read_article)
31
36
 
32
37
  super().__init__(name="newspaper4k_tools", tools=tools, **kwargs)
agno/tools/openai.py CHANGED
@@ -6,6 +6,7 @@ from agno.agent import Agent
6
6
  from agno.media import AudioArtifact, ImageArtifact
7
7
  from agno.team.team import Team
8
8
  from agno.tools import Toolkit
9
+ from agno.tools.function import ToolResult
9
10
  from agno.utils.log import log_debug, log_error, log_warning
10
11
 
11
12
  try:
@@ -20,7 +21,23 @@ OpenAITTSFormat = Literal["mp3", "opus", "aac", "flac", "wav", "pcm"]
20
21
 
21
22
 
22
23
  class OpenAITools(Toolkit):
23
- """Tools for interacting with OpenAIChat API"""
24
+ """Tools for interacting with OpenAI API.
25
+
26
+ Args:
27
+ api_key (str, optional): OpenAI API key. Retrieved from OPENAI_API_KEY env variable if not provided.
28
+ enable_transcription (bool): Enable audio transcription functionality. Default is True.
29
+ enable_image_generation (bool): Enable image generation functionality. Default is True.
30
+ enable_speech_generation (bool): Enable speech generation functionality. Default is True.
31
+ all (bool): Enable all tools. Overrides individual flags when True. Default is False.
32
+ transcription_model (str): Model to use for transcription. Default is "whisper-1".
33
+ text_to_speech_voice (OpenAIVoice): Voice to use for TTS. Default is "alloy".
34
+ text_to_speech_model (OpenAITTSModel): Model to use for TTS. Default is "tts-1".
35
+ text_to_speech_format (OpenAITTSFormat): Audio format for TTS. Default is "mp3".
36
+ image_model (str, optional): Model to use for image generation. Default is "dall-e-3".
37
+ image_quality (str, optional): Quality setting for image generation.
38
+ image_size (str, optional): Size setting for image generation.
39
+ image_style (str, optional): Style setting for image generation.
40
+ """
24
41
 
25
42
  def __init__(
26
43
  self,
@@ -28,6 +45,7 @@ class OpenAITools(Toolkit):
28
45
  enable_transcription: bool = True,
29
46
  enable_image_generation: bool = True,
30
47
  enable_speech_generation: bool = True,
48
+ all: bool = False,
31
49
  transcription_model: str = "whisper-1",
32
50
  text_to_speech_voice: OpenAIVoice = "alloy",
33
51
  text_to_speech_model: OpenAITTSModel = "tts-1",
@@ -53,11 +71,11 @@ class OpenAITools(Toolkit):
53
71
  self.image_size = image_size
54
72
 
55
73
  tools: List[Any] = []
56
- if enable_transcription:
74
+ if all or enable_transcription:
57
75
  tools.append(self.transcribe_audio)
58
- if enable_image_generation:
76
+ if all or enable_image_generation:
59
77
  tools.append(self.generate_image)
60
- if enable_speech_generation:
78
+ if all or enable_speech_generation:
61
79
  tools.append(self.generate_speech)
62
80
 
63
81
  super().__init__(name="openai_tools", tools=tools, **kwargs)
@@ -85,14 +103,15 @@ class OpenAITools(Toolkit):
85
103
 
86
104
  def generate_image(
87
105
  self,
88
- agent: Union[Agent, Team],
89
106
  prompt: str,
90
- ) -> str:
107
+ ) -> ToolResult:
91
108
  """Generate images based on a text prompt.
92
109
  Args:
93
110
  prompt (str): The text prompt to generate the image from.
94
111
  """
95
112
  try:
113
+ import base64
114
+
96
115
  extra_params = {
97
116
  "size": self.image_size,
98
117
  "quality": self.image_quality,
@@ -120,29 +139,38 @@ class OpenAITools(Toolkit):
120
139
  data = response.data[0]
121
140
  if data is None:
122
141
  log_warning("OpenAI API did not return any data.")
123
- return "Failed to generate image: No data received from API."
142
+ return ToolResult(content="Failed to generate image: No data received from API.")
143
+
124
144
  if hasattr(data, "b64_json") and data.b64_json:
125
145
  image_base64 = data.b64_json
126
146
  media_id = str(uuid4())
127
- # Store base64-encoded content as bytes for later saving
128
- agent.add_image(
129
- ImageArtifact(
130
- id=media_id,
131
- content=image_base64.encode("utf-8"),
132
- mime_type="image/png",
133
- )
147
+
148
+ # Decode base64 to bytes for proper storage
149
+ image_bytes = base64.b64decode(image_base64)
150
+
151
+ # Create ImageArtifact and return in ToolResult
152
+ image_artifact = ImageArtifact(
153
+ id=media_id,
154
+ content=image_bytes, # ← Store as bytes, not encoded string
155
+ mime_type="image/png",
156
+ original_prompt=prompt,
134
157
  )
135
- return "Image generated successfully."
136
- return "Failed to generate image: No content received from API."
158
+
159
+ return ToolResult(
160
+ content="Image generated successfully.",
161
+ images=[image_artifact],
162
+ )
163
+
164
+ return ToolResult(content="Failed to generate image: No content received from API.")
137
165
  except Exception as e:
138
166
  log_error(f"Failed to generate image using {self.image_model}: {e}")
139
- return f"Failed to generate image: {e}"
167
+ return ToolResult(content=f"Failed to generate image: {e}")
140
168
 
141
169
  def generate_speech(
142
170
  self,
143
171
  agent: Union[Agent, Team],
144
172
  text_input: str,
145
- ) -> str:
173
+ ) -> ToolResult: # Changed return type
146
174
  """Generate speech from text using OpenAI's Text-to-Speech API.
147
175
  Args:
148
176
  text_input (str): The text to synthesize into speech.
@@ -163,14 +191,17 @@ class OpenAITools(Toolkit):
163
191
  # Base64 encode the audio data
164
192
  base64_encoded_audio = base64.b64encode(audio_data).decode("utf-8")
165
193
 
166
- # Create and add AudioArtifact using base64_audio field
194
+ # Create AudioArtifact and return in ToolResult
167
195
  media_id = str(uuid4())
168
- agent.add_audio(
169
- AudioArtifact(
170
- id=media_id,
171
- base64_audio=base64_encoded_audio,
172
- )
196
+ audio_artifact = AudioArtifact(
197
+ id=media_id,
198
+ base64_audio=base64_encoded_audio,
199
+ mime_type=f"audio/{self.tts_format}",
200
+ )
201
+
202
+ return ToolResult(
203
+ content=f"Speech generated successfully with ID: {media_id}",
204
+ audios=[audio_artifact],
173
205
  )
174
- return f"Speech generated successfully with ID: {media_id}"
175
206
  except Exception as e:
176
- return f"Failed to generate speech: {str(e)}"
207
+ return ToolResult(content=f"Failed to generate speech: {str(e)}")
agno/tools/openbb.py CHANGED
@@ -17,11 +17,12 @@ class OpenBBTools(Toolkit):
17
17
  obb: Optional[Any] = None,
18
18
  openbb_pat: Optional[str] = None,
19
19
  provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = "yfinance",
20
- stock_price: bool = True,
21
- search_symbols: bool = False,
22
- company_news: bool = False,
23
- company_profile: bool = False,
24
- price_targets: bool = False,
20
+ enable_get_stock_price: bool = True,
21
+ enable_search_company_symbol: bool = False,
22
+ enable_get_company_news: bool = False,
23
+ enable_get_company_profile: bool = False,
24
+ enable_get_price_targets: bool = False,
25
+ all: bool = False,
25
26
  **kwargs,
26
27
  ):
27
28
  self.obb = obb or openbb_app
@@ -34,18 +35,18 @@ class OpenBBTools(Toolkit):
34
35
  self.provider: Literal["benzinga", "fmp", "intrinio", "polygon", "tiingo", "tmx", "yfinance"] = provider
35
36
 
36
37
  tools: List[Any] = []
37
- if stock_price:
38
+ if enable_get_stock_price or all:
38
39
  tools.append(self.get_stock_price)
39
- if search_symbols:
40
+ if enable_search_company_symbol or all:
40
41
  tools.append(self.search_company_symbol)
41
- if company_news:
42
+ if enable_get_company_news or all:
42
43
  tools.append(self.get_company_news)
43
- if company_profile:
44
+ if enable_get_company_profile or all:
44
45
  tools.append(self.get_company_profile)
45
- if price_targets:
46
+ if enable_get_price_targets or all:
46
47
  tools.append(self.get_price_targets)
47
48
 
48
- super().__init__(name="yfinance_tools", tools=tools, **kwargs)
49
+ super().__init__(name="openbb_tools", tools=tools, **kwargs)
49
50
 
50
51
  def get_stock_price(self, symbol: str) -> str:
51
52
  """Use this function to get the current stock price for a stock symbol or list of symbols.
agno/tools/opencv.py CHANGED
@@ -1,10 +1,12 @@
1
- import base64
2
1
  import time
2
+ from pathlib import Path
3
+ from typing import Callable, List
3
4
  from uuid import uuid4
4
5
 
5
6
  from agno.agent import Agent
6
7
  from agno.media import ImageArtifact, VideoArtifact
7
- from agno.tools.toolkit import Toolkit
8
+ from agno.tools import Toolkit
9
+ from agno.tools.function import ToolResult
8
10
  from agno.utils.log import log_debug, log_error, log_info
9
11
 
10
12
  try:
@@ -16,30 +18,40 @@ except ImportError:
16
18
  class OpenCVTools(Toolkit):
17
19
  """Tools for capturing images and videos from the webcam using OpenCV"""
18
20
 
19
- def __init__(self, show_preview=False, **kwargs):
21
+ def __init__(
22
+ self,
23
+ show_preview=False,
24
+ enable_capture_image: bool = True,
25
+ enable_capture_video: bool = True,
26
+ all: bool = False,
27
+ **kwargs,
28
+ ):
29
+ self.show_preview = show_preview
30
+
31
+ tools: List[Callable] = []
32
+ if all or enable_capture_image:
33
+ tools.append(self.capture_image)
34
+ if all or enable_capture_video:
35
+ tools.append(self.capture_video)
36
+
20
37
  super().__init__(
21
38
  name="opencv_tools",
22
- tools=[
23
- self.capture_image,
24
- self.capture_video,
25
- ],
39
+ tools=tools,
26
40
  **kwargs,
27
41
  )
28
42
 
29
- self.show_preview = show_preview
30
-
31
43
  def capture_image(
32
44
  self,
33
45
  agent: Agent,
34
46
  prompt: str = "Webcam capture",
35
- ) -> str:
47
+ ) -> ToolResult:
36
48
  """Capture an image from the webcam.
37
49
 
38
50
  Args:
39
51
  prompt (str): Description of the image capture. Defaults to "Webcam capture".
40
52
 
41
53
  Returns:
42
- str: A message indicating success or failure.
54
+ ToolResult: A ToolResult containing the captured image or error message.
43
55
  """
44
56
  try:
45
57
  log_debug("Initializing webcam for image capture...")
@@ -55,7 +67,7 @@ class OpenCVTools(Toolkit):
55
67
  if not cam.isOpened():
56
68
  error_msg = "Could not open webcam. Please ensure your terminal has camera permissions and the camera is not being used by another application."
57
69
  log_error(error_msg)
58
- return error_msg
70
+ return ToolResult(content=error_msg)
59
71
 
60
72
  try:
61
73
  cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
@@ -73,7 +85,7 @@ class OpenCVTools(Toolkit):
73
85
  if not ret:
74
86
  error_msg = "Failed to read frame from webcam"
75
87
  log_error(error_msg)
76
- return error_msg
88
+ return ToolResult(content=error_msg)
77
89
 
78
90
  cv2.imshow('Camera Preview - Press "c" to capture, "q" to quit', frame)
79
91
 
@@ -84,41 +96,42 @@ class OpenCVTools(Toolkit):
84
96
  break
85
97
  elif key == ord("q"):
86
98
  log_info("Capture cancelled by user")
87
- return "Image capture cancelled by user"
99
+ return ToolResult(content="Image capture cancelled by user")
88
100
  else:
89
101
  ret, captured_frame = cam.read()
90
102
  if not ret:
91
103
  error_msg = "Failed to capture image from webcam"
92
104
  log_error(error_msg)
93
- return error_msg
105
+ return ToolResult(content=error_msg)
94
106
 
95
107
  if captured_frame is None:
96
108
  error_msg = "No frame captured"
97
109
  log_error(error_msg)
98
- return error_msg
110
+ return ToolResult(content=error_msg)
99
111
 
100
112
  success, encoded_image = cv2.imencode(".png", captured_frame)
101
113
 
102
114
  if not success:
103
115
  error_msg = "Failed to encode captured image"
104
116
  log_error(error_msg)
105
- return error_msg
117
+ return ToolResult(content=error_msg)
106
118
 
107
119
  image_bytes = encoded_image.tobytes()
108
- base64_encoded_image = base64.b64encode(image_bytes)
109
-
110
120
  media_id = str(uuid4())
111
- agent.add_image(
112
- ImageArtifact(
113
- id=media_id,
114
- content=base64_encoded_image,
115
- original_prompt=prompt,
116
- mime_type="image/png",
117
- )
121
+
122
+ # Create ImageArtifact with raw bytes (not base64 encoded)
123
+ image_artifact = ImageArtifact(
124
+ id=media_id,
125
+ content=image_bytes, # Store as raw bytes
126
+ original_prompt=prompt,
127
+ mime_type="image/png",
118
128
  )
119
129
 
120
130
  log_debug(f"Successfully captured and attached image {media_id}")
121
- return "Image captured successfully"
131
+ return ToolResult(
132
+ content="Image captured successfully",
133
+ images=[image_artifact],
134
+ )
122
135
 
123
136
  finally:
124
137
  # Release the camera and close windows
@@ -129,14 +142,14 @@ class OpenCVTools(Toolkit):
129
142
  except Exception as e:
130
143
  error_msg = f"Error capturing image: {str(e)}"
131
144
  log_error(error_msg)
132
- return error_msg
145
+ return ToolResult(content=error_msg)
133
146
 
134
147
  def capture_video(
135
148
  self,
136
149
  agent: Agent,
137
150
  duration: int = 10,
138
151
  prompt: str = "Webcam video capture",
139
- ) -> str:
152
+ ) -> ToolResult:
140
153
  """Capture a video from the webcam.
141
154
 
142
155
  Args:
@@ -144,7 +157,7 @@ class OpenCVTools(Toolkit):
144
157
  prompt (str): Description of the video capture. Defaults to "Webcam video capture".
145
158
 
146
159
  Returns:
147
- str: A message indicating success or failure.
160
+ ToolResult: A ToolResult containing the captured video or error message.
148
161
  """
149
162
  try:
150
163
  log_debug("Initializing webcam for video capture...")
@@ -161,7 +174,7 @@ class OpenCVTools(Toolkit):
161
174
  if not cap.isOpened():
162
175
  error_msg = "Could not open webcam. Please ensure your terminal has camera permissions and the camera is not being used by another application."
163
176
  log_error(error_msg)
164
- return error_msg
177
+ return ToolResult(content=error_msg)
165
178
 
166
179
  try:
167
180
  frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
@@ -211,7 +224,7 @@ class OpenCVTools(Toolkit):
211
224
  if not out or not out.isOpened():
212
225
  error_msg = "Failed to initialize video writer with any codec"
213
226
  log_error(error_msg)
214
- return error_msg
227
+ return ToolResult(content=error_msg)
215
228
 
216
229
  start_time = time.time()
217
230
  frame_count = 0
@@ -227,7 +240,7 @@ class OpenCVTools(Toolkit):
227
240
  if not ret:
228
241
  error_msg = "Failed to capture video frame"
229
242
  log_error(error_msg)
230
- return error_msg
243
+ return ToolResult(content=error_msg)
231
244
 
232
245
  # Write the frame to the output file
233
246
  out.write(frame)
@@ -263,10 +276,11 @@ class OpenCVTools(Toolkit):
263
276
  out.release()
264
277
 
265
278
  # Verify the file was created and has content
266
- if not os.path.exists(temp_filepath) or os.path.getsize(temp_filepath) == 0:
279
+ temp_path = Path(temp_filepath)
280
+ if not temp_path.exists() or temp_path.stat().st_size == 0:
267
281
  error_msg = "Video file was not created or is empty"
268
282
  log_error(error_msg)
269
- return error_msg
283
+ return ToolResult(content=error_msg)
270
284
 
271
285
  # Read the video file and encode to base64
272
286
  with open(temp_filepath, "rb") as video_file:
@@ -275,23 +289,25 @@ class OpenCVTools(Toolkit):
275
289
  # Clean up temporary file
276
290
  os.unlink(temp_filepath)
277
291
 
278
- base64_encoded_video = base64.b64encode(video_bytes)
279
-
280
292
  media_id = str(uuid4())
281
- agent.add_video(
282
- VideoArtifact(
283
- id=media_id,
284
- content=base64_encoded_video,
285
- original_prompt=prompt,
286
- mime_type="video/mp4",
287
- )
293
+
294
+ # Create VideoArtifact with base64 encoded content
295
+ video_artifact = VideoArtifact(
296
+ id=media_id,
297
+ content=video_bytes,
298
+ original_prompt=prompt,
299
+ mime_type="video/mp4",
288
300
  )
289
301
 
290
302
  actual_duration = time.time() - start_time
291
303
  log_debug(
292
304
  f"Successfully captured and attached video {media_id} ({actual_duration:.1f}s, {frame_count} frames)"
293
305
  )
294
- return f"Video captured successfully and attached as artifact {media_id} ({actual_duration:.1f}s, {frame_count} frames, {successful_codec} codec)"
306
+
307
+ return ToolResult(
308
+ content=f"Video captured successfully and attached as artifact {media_id} ({actual_duration:.1f}s, {frame_count} frames, {successful_codec} codec)",
309
+ videos=[video_artifact],
310
+ )
295
311
 
296
312
  finally:
297
313
  if "cap" in locals():
@@ -302,4 +318,4 @@ class OpenCVTools(Toolkit):
302
318
  except Exception as e:
303
319
  error_msg = f"Error capturing video: {str(e)}"
304
320
  log_error(error_msg)
305
- return error_msg
321
+ return ToolResult(content=error_msg)
agno/tools/openweather.py CHANGED
@@ -18,20 +18,22 @@ class OpenWeatherTools(Toolkit):
18
18
  Args:
19
19
  api_key (Optional[str]): OpenWeatherMap API key. If not provided, will try to get from OPENWEATHER_API_KEY env var.
20
20
  units (str): Units of measurement. Options are 'standard', 'metric', and 'imperial'. Default is 'metric'.
21
- current_weather (bool): Enable current weather function. Default is True.
22
- forecast (bool): Enable forecast function. Default is True.
23
- air_pollution (bool): Enable air pollution function. Default is True.
24
- geocoding (bool): Enable geocoding function. Default is True.
21
+ enable_current_weather (bool): Enable current weather function. Default is True.
22
+ enable_forecast (bool): Enable forecast function. Default is True.
23
+ enable_air_pollution (bool): Enable air pollution function. Default is True.
24
+ enable_geocoding (bool): Enable geocoding function. Default is True.
25
+ all (bool): Enable all functions. Default is False.
25
26
  """
26
27
 
27
28
  def __init__(
28
29
  self,
29
30
  api_key: Optional[str] = None,
30
31
  units: str = "metric",
31
- current_weather: bool = True,
32
- forecast: bool = True,
33
- air_pollution: bool = True,
34
- geocoding: bool = True,
32
+ enable_current_weather: bool = True,
33
+ enable_forecast: bool = True,
34
+ enable_air_pollution: bool = True,
35
+ enable_geocoding: bool = True,
36
+ all: bool = False,
35
37
  **kwargs,
36
38
  ):
37
39
  self.api_key = api_key or getenv("OPENWEATHER_API_KEY")
@@ -45,13 +47,13 @@ class OpenWeatherTools(Toolkit):
45
47
  self.geo_url = "https://api.openweathermap.org/geo/1.0"
46
48
 
47
49
  tools: List[Any] = []
48
- if current_weather:
50
+ if enable_current_weather or all:
49
51
  tools.append(self.get_current_weather)
50
- if forecast:
52
+ if enable_forecast or all:
51
53
  tools.append(self.get_forecast)
52
- if air_pollution:
54
+ if enable_air_pollution or all:
53
55
  tools.append(self.get_air_pollution)
54
- if geocoding:
56
+ if enable_geocoding or all:
55
57
  tools.append(self.geocode_location)
56
58
 
57
59
  super().__init__(name="openweather_tools", tools=tools, **kwargs)