agno 0.1.2__py3-none-any.whl → 2.3.13__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 (723) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +44 -5
  3. agno/agent/agent.py +10531 -2975
  4. agno/api/agent.py +14 -53
  5. agno/api/api.py +7 -46
  6. agno/api/evals.py +22 -0
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -25
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +6 -9
  11. agno/api/schemas/evals.py +16 -0
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +10 -10
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +16 -0
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +22 -26
  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/compression/__init__.py +3 -0
  25. agno/compression/manager.py +247 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +946 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2781 -0
  33. agno/db/dynamo/schemas.py +442 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +2379 -0
  37. agno/db/firestore/schemas.py +181 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1791 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1312 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1777 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/manager.py +199 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/migrations/versions/v2_3_0.py +938 -0
  51. agno/db/mongo/__init__.py +17 -0
  52. agno/db/mongo/async_mongo.py +2760 -0
  53. agno/db/mongo/mongo.py +2597 -0
  54. agno/db/mongo/schemas.py +119 -0
  55. agno/db/mongo/utils.py +276 -0
  56. agno/db/mysql/__init__.py +4 -0
  57. agno/db/mysql/async_mysql.py +2912 -0
  58. agno/db/mysql/mysql.py +2923 -0
  59. agno/db/mysql/schemas.py +186 -0
  60. agno/db/mysql/utils.py +488 -0
  61. agno/db/postgres/__init__.py +4 -0
  62. agno/db/postgres/async_postgres.py +2579 -0
  63. agno/db/postgres/postgres.py +2870 -0
  64. agno/db/postgres/schemas.py +187 -0
  65. agno/db/postgres/utils.py +442 -0
  66. agno/db/redis/__init__.py +3 -0
  67. agno/db/redis/redis.py +2141 -0
  68. agno/db/redis/schemas.py +159 -0
  69. agno/db/redis/utils.py +346 -0
  70. agno/db/schemas/__init__.py +4 -0
  71. agno/db/schemas/culture.py +120 -0
  72. agno/db/schemas/evals.py +34 -0
  73. agno/db/schemas/knowledge.py +40 -0
  74. agno/db/schemas/memory.py +61 -0
  75. agno/db/singlestore/__init__.py +3 -0
  76. agno/db/singlestore/schemas.py +179 -0
  77. agno/db/singlestore/singlestore.py +2877 -0
  78. agno/db/singlestore/utils.py +384 -0
  79. agno/db/sqlite/__init__.py +4 -0
  80. agno/db/sqlite/async_sqlite.py +2911 -0
  81. agno/db/sqlite/schemas.py +181 -0
  82. agno/db/sqlite/sqlite.py +2908 -0
  83. agno/db/sqlite/utils.py +429 -0
  84. agno/db/surrealdb/__init__.py +3 -0
  85. agno/db/surrealdb/metrics.py +292 -0
  86. agno/db/surrealdb/models.py +334 -0
  87. agno/db/surrealdb/queries.py +71 -0
  88. agno/db/surrealdb/surrealdb.py +1908 -0
  89. agno/db/surrealdb/utils.py +147 -0
  90. agno/db/utils.py +118 -0
  91. agno/eval/__init__.py +24 -0
  92. agno/eval/accuracy.py +666 -276
  93. agno/eval/agent_as_judge.py +861 -0
  94. agno/eval/base.py +29 -0
  95. agno/eval/performance.py +779 -0
  96. agno/eval/reliability.py +241 -62
  97. agno/eval/utils.py +120 -0
  98. agno/exceptions.py +143 -1
  99. agno/filters.py +354 -0
  100. agno/guardrails/__init__.py +6 -0
  101. agno/guardrails/base.py +19 -0
  102. agno/guardrails/openai.py +144 -0
  103. agno/guardrails/pii.py +94 -0
  104. agno/guardrails/prompt_injection.py +52 -0
  105. agno/hooks/__init__.py +3 -0
  106. agno/hooks/decorator.py +164 -0
  107. agno/integrations/discord/__init__.py +3 -0
  108. agno/integrations/discord/client.py +203 -0
  109. agno/knowledge/__init__.py +5 -1
  110. agno/{document → knowledge}/chunking/agentic.py +22 -14
  111. agno/{document → knowledge}/chunking/document.py +2 -2
  112. agno/{document → knowledge}/chunking/fixed.py +7 -6
  113. agno/knowledge/chunking/markdown.py +151 -0
  114. agno/{document → knowledge}/chunking/recursive.py +15 -3
  115. agno/knowledge/chunking/row.py +39 -0
  116. agno/knowledge/chunking/semantic.py +91 -0
  117. agno/knowledge/chunking/strategy.py +165 -0
  118. agno/knowledge/content.py +74 -0
  119. agno/knowledge/document/__init__.py +5 -0
  120. agno/{document → knowledge/document}/base.py +12 -2
  121. agno/knowledge/embedder/__init__.py +5 -0
  122. agno/knowledge/embedder/aws_bedrock.py +343 -0
  123. agno/knowledge/embedder/azure_openai.py +210 -0
  124. agno/{embedder → knowledge/embedder}/base.py +8 -0
  125. agno/knowledge/embedder/cohere.py +323 -0
  126. agno/knowledge/embedder/fastembed.py +62 -0
  127. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  128. agno/knowledge/embedder/google.py +258 -0
  129. agno/knowledge/embedder/huggingface.py +94 -0
  130. agno/knowledge/embedder/jina.py +182 -0
  131. agno/knowledge/embedder/langdb.py +22 -0
  132. agno/knowledge/embedder/mistral.py +206 -0
  133. agno/knowledge/embedder/nebius.py +13 -0
  134. agno/knowledge/embedder/ollama.py +154 -0
  135. agno/knowledge/embedder/openai.py +195 -0
  136. agno/knowledge/embedder/sentence_transformer.py +63 -0
  137. agno/{embedder → knowledge/embedder}/together.py +1 -1
  138. agno/knowledge/embedder/vllm.py +262 -0
  139. agno/knowledge/embedder/voyageai.py +165 -0
  140. agno/knowledge/knowledge.py +3006 -0
  141. agno/knowledge/reader/__init__.py +7 -0
  142. agno/knowledge/reader/arxiv_reader.py +81 -0
  143. agno/knowledge/reader/base.py +95 -0
  144. agno/knowledge/reader/csv_reader.py +164 -0
  145. agno/knowledge/reader/docx_reader.py +82 -0
  146. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  147. agno/knowledge/reader/firecrawl_reader.py +201 -0
  148. agno/knowledge/reader/json_reader.py +88 -0
  149. agno/knowledge/reader/markdown_reader.py +137 -0
  150. agno/knowledge/reader/pdf_reader.py +431 -0
  151. agno/knowledge/reader/pptx_reader.py +101 -0
  152. agno/knowledge/reader/reader_factory.py +313 -0
  153. agno/knowledge/reader/s3_reader.py +89 -0
  154. agno/knowledge/reader/tavily_reader.py +193 -0
  155. agno/knowledge/reader/text_reader.py +127 -0
  156. agno/knowledge/reader/web_search_reader.py +325 -0
  157. agno/knowledge/reader/website_reader.py +455 -0
  158. agno/knowledge/reader/wikipedia_reader.py +91 -0
  159. agno/knowledge/reader/youtube_reader.py +78 -0
  160. agno/knowledge/remote_content/remote_content.py +88 -0
  161. agno/knowledge/reranker/__init__.py +3 -0
  162. agno/{reranker → knowledge/reranker}/base.py +1 -1
  163. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  164. agno/knowledge/reranker/infinity.py +195 -0
  165. agno/knowledge/reranker/sentence_transformer.py +54 -0
  166. agno/knowledge/types.py +39 -0
  167. agno/knowledge/utils.py +234 -0
  168. agno/media.py +439 -95
  169. agno/memory/__init__.py +16 -3
  170. agno/memory/manager.py +1474 -123
  171. agno/memory/strategies/__init__.py +15 -0
  172. agno/memory/strategies/base.py +66 -0
  173. agno/memory/strategies/summarize.py +196 -0
  174. agno/memory/strategies/types.py +37 -0
  175. agno/models/aimlapi/__init__.py +5 -0
  176. agno/models/aimlapi/aimlapi.py +62 -0
  177. agno/models/anthropic/__init__.py +4 -0
  178. agno/models/anthropic/claude.py +960 -496
  179. agno/models/aws/__init__.py +15 -0
  180. agno/models/aws/bedrock.py +686 -451
  181. agno/models/aws/claude.py +190 -183
  182. agno/models/azure/__init__.py +18 -1
  183. agno/models/azure/ai_foundry.py +489 -0
  184. agno/models/azure/openai_chat.py +89 -40
  185. agno/models/base.py +2477 -550
  186. agno/models/cerebras/__init__.py +12 -0
  187. agno/models/cerebras/cerebras.py +565 -0
  188. agno/models/cerebras/cerebras_openai.py +131 -0
  189. agno/models/cohere/__init__.py +4 -0
  190. agno/models/cohere/chat.py +306 -492
  191. agno/models/cometapi/__init__.py +5 -0
  192. agno/models/cometapi/cometapi.py +74 -0
  193. agno/models/dashscope/__init__.py +5 -0
  194. agno/models/dashscope/dashscope.py +90 -0
  195. agno/models/deepinfra/__init__.py +5 -0
  196. agno/models/deepinfra/deepinfra.py +45 -0
  197. agno/models/deepseek/__init__.py +4 -0
  198. agno/models/deepseek/deepseek.py +110 -9
  199. agno/models/fireworks/__init__.py +4 -0
  200. agno/models/fireworks/fireworks.py +19 -22
  201. agno/models/google/__init__.py +3 -7
  202. agno/models/google/gemini.py +1717 -662
  203. agno/models/google/utils.py +22 -0
  204. agno/models/groq/__init__.py +4 -0
  205. agno/models/groq/groq.py +391 -666
  206. agno/models/huggingface/__init__.py +4 -0
  207. agno/models/huggingface/huggingface.py +266 -538
  208. agno/models/ibm/__init__.py +5 -0
  209. agno/models/ibm/watsonx.py +432 -0
  210. agno/models/internlm/__init__.py +3 -0
  211. agno/models/internlm/internlm.py +20 -3
  212. agno/models/langdb/__init__.py +1 -0
  213. agno/models/langdb/langdb.py +60 -0
  214. agno/models/litellm/__init__.py +14 -0
  215. agno/models/litellm/chat.py +503 -0
  216. agno/models/litellm/litellm_openai.py +42 -0
  217. agno/models/llama_cpp/__init__.py +5 -0
  218. agno/models/llama_cpp/llama_cpp.py +22 -0
  219. agno/models/lmstudio/__init__.py +5 -0
  220. agno/models/lmstudio/lmstudio.py +25 -0
  221. agno/models/message.py +361 -39
  222. agno/models/meta/__init__.py +12 -0
  223. agno/models/meta/llama.py +502 -0
  224. agno/models/meta/llama_openai.py +79 -0
  225. agno/models/metrics.py +120 -0
  226. agno/models/mistral/__init__.py +4 -0
  227. agno/models/mistral/mistral.py +293 -393
  228. agno/models/nebius/__init__.py +3 -0
  229. agno/models/nebius/nebius.py +53 -0
  230. agno/models/nexus/__init__.py +3 -0
  231. agno/models/nexus/nexus.py +22 -0
  232. agno/models/nvidia/__init__.py +4 -0
  233. agno/models/nvidia/nvidia.py +22 -3
  234. agno/models/ollama/__init__.py +4 -2
  235. agno/models/ollama/chat.py +257 -492
  236. agno/models/openai/__init__.py +7 -0
  237. agno/models/openai/chat.py +725 -770
  238. agno/models/openai/like.py +16 -2
  239. agno/models/openai/responses.py +1121 -0
  240. agno/models/openrouter/__init__.py +4 -0
  241. agno/models/openrouter/openrouter.py +62 -5
  242. agno/models/perplexity/__init__.py +5 -0
  243. agno/models/perplexity/perplexity.py +203 -0
  244. agno/models/portkey/__init__.py +3 -0
  245. agno/models/portkey/portkey.py +82 -0
  246. agno/models/requesty/__init__.py +5 -0
  247. agno/models/requesty/requesty.py +69 -0
  248. agno/models/response.py +177 -7
  249. agno/models/sambanova/__init__.py +4 -0
  250. agno/models/sambanova/sambanova.py +23 -4
  251. agno/models/siliconflow/__init__.py +5 -0
  252. agno/models/siliconflow/siliconflow.py +42 -0
  253. agno/models/together/__init__.py +4 -0
  254. agno/models/together/together.py +21 -164
  255. agno/models/utils.py +266 -0
  256. agno/models/vercel/__init__.py +3 -0
  257. agno/models/vercel/v0.py +43 -0
  258. agno/models/vertexai/__init__.py +0 -1
  259. agno/models/vertexai/claude.py +190 -0
  260. agno/models/vllm/__init__.py +3 -0
  261. agno/models/vllm/vllm.py +83 -0
  262. agno/models/xai/__init__.py +2 -0
  263. agno/models/xai/xai.py +111 -7
  264. agno/os/__init__.py +3 -0
  265. agno/os/app.py +1027 -0
  266. agno/os/auth.py +244 -0
  267. agno/os/config.py +126 -0
  268. agno/os/interfaces/__init__.py +1 -0
  269. agno/os/interfaces/a2a/__init__.py +3 -0
  270. agno/os/interfaces/a2a/a2a.py +42 -0
  271. agno/os/interfaces/a2a/router.py +249 -0
  272. agno/os/interfaces/a2a/utils.py +924 -0
  273. agno/os/interfaces/agui/__init__.py +3 -0
  274. agno/os/interfaces/agui/agui.py +47 -0
  275. agno/os/interfaces/agui/router.py +147 -0
  276. agno/os/interfaces/agui/utils.py +574 -0
  277. agno/os/interfaces/base.py +25 -0
  278. agno/os/interfaces/slack/__init__.py +3 -0
  279. agno/os/interfaces/slack/router.py +148 -0
  280. agno/os/interfaces/slack/security.py +30 -0
  281. agno/os/interfaces/slack/slack.py +47 -0
  282. agno/os/interfaces/whatsapp/__init__.py +3 -0
  283. agno/os/interfaces/whatsapp/router.py +210 -0
  284. agno/os/interfaces/whatsapp/security.py +55 -0
  285. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  286. agno/os/mcp.py +293 -0
  287. agno/os/middleware/__init__.py +9 -0
  288. agno/os/middleware/jwt.py +797 -0
  289. agno/os/router.py +258 -0
  290. agno/os/routers/__init__.py +3 -0
  291. agno/os/routers/agents/__init__.py +3 -0
  292. agno/os/routers/agents/router.py +599 -0
  293. agno/os/routers/agents/schema.py +261 -0
  294. agno/os/routers/evals/__init__.py +3 -0
  295. agno/os/routers/evals/evals.py +450 -0
  296. agno/os/routers/evals/schemas.py +174 -0
  297. agno/os/routers/evals/utils.py +231 -0
  298. agno/os/routers/health.py +31 -0
  299. agno/os/routers/home.py +52 -0
  300. agno/os/routers/knowledge/__init__.py +3 -0
  301. agno/os/routers/knowledge/knowledge.py +1008 -0
  302. agno/os/routers/knowledge/schemas.py +178 -0
  303. agno/os/routers/memory/__init__.py +3 -0
  304. agno/os/routers/memory/memory.py +661 -0
  305. agno/os/routers/memory/schemas.py +88 -0
  306. agno/os/routers/metrics/__init__.py +3 -0
  307. agno/os/routers/metrics/metrics.py +190 -0
  308. agno/os/routers/metrics/schemas.py +47 -0
  309. agno/os/routers/session/__init__.py +3 -0
  310. agno/os/routers/session/session.py +997 -0
  311. agno/os/routers/teams/__init__.py +3 -0
  312. agno/os/routers/teams/router.py +512 -0
  313. agno/os/routers/teams/schema.py +257 -0
  314. agno/os/routers/traces/__init__.py +3 -0
  315. agno/os/routers/traces/schemas.py +414 -0
  316. agno/os/routers/traces/traces.py +499 -0
  317. agno/os/routers/workflows/__init__.py +3 -0
  318. agno/os/routers/workflows/router.py +624 -0
  319. agno/os/routers/workflows/schema.py +75 -0
  320. agno/os/schema.py +534 -0
  321. agno/os/scopes.py +469 -0
  322. agno/{playground → os}/settings.py +7 -15
  323. agno/os/utils.py +973 -0
  324. agno/reasoning/anthropic.py +80 -0
  325. agno/reasoning/azure_ai_foundry.py +67 -0
  326. agno/reasoning/deepseek.py +63 -0
  327. agno/reasoning/default.py +97 -0
  328. agno/reasoning/gemini.py +73 -0
  329. agno/reasoning/groq.py +71 -0
  330. agno/reasoning/helpers.py +24 -1
  331. agno/reasoning/ollama.py +67 -0
  332. agno/reasoning/openai.py +86 -0
  333. agno/reasoning/step.py +2 -1
  334. agno/reasoning/vertexai.py +76 -0
  335. agno/run/__init__.py +6 -0
  336. agno/run/agent.py +822 -0
  337. agno/run/base.py +247 -0
  338. agno/run/cancel.py +81 -0
  339. agno/run/requirement.py +181 -0
  340. agno/run/team.py +767 -0
  341. agno/run/workflow.py +708 -0
  342. agno/session/__init__.py +10 -0
  343. agno/session/agent.py +260 -0
  344. agno/session/summary.py +265 -0
  345. agno/session/team.py +342 -0
  346. agno/session/workflow.py +501 -0
  347. agno/table.py +10 -0
  348. agno/team/__init__.py +37 -0
  349. agno/team/team.py +9536 -0
  350. agno/tools/__init__.py +7 -0
  351. agno/tools/agentql.py +120 -0
  352. agno/tools/airflow.py +22 -12
  353. agno/tools/api.py +122 -0
  354. agno/tools/apify.py +276 -83
  355. agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
  356. agno/tools/aws_lambda.py +28 -7
  357. agno/tools/aws_ses.py +66 -0
  358. agno/tools/baidusearch.py +11 -4
  359. agno/tools/bitbucket.py +292 -0
  360. agno/tools/brandfetch.py +213 -0
  361. agno/tools/bravesearch.py +106 -0
  362. agno/tools/brightdata.py +367 -0
  363. agno/tools/browserbase.py +209 -0
  364. agno/tools/calcom.py +32 -23
  365. agno/tools/calculator.py +24 -37
  366. agno/tools/cartesia.py +187 -0
  367. agno/tools/{clickup_tool.py → clickup.py} +17 -28
  368. agno/tools/confluence.py +91 -26
  369. agno/tools/crawl4ai.py +139 -43
  370. agno/tools/csv_toolkit.py +28 -22
  371. agno/tools/dalle.py +36 -22
  372. agno/tools/daytona.py +475 -0
  373. agno/tools/decorator.py +169 -14
  374. agno/tools/desi_vocal.py +23 -11
  375. agno/tools/discord.py +32 -29
  376. agno/tools/docker.py +716 -0
  377. agno/tools/duckdb.py +76 -81
  378. agno/tools/duckduckgo.py +43 -40
  379. agno/tools/e2b.py +703 -0
  380. agno/tools/eleven_labs.py +65 -54
  381. agno/tools/email.py +13 -5
  382. agno/tools/evm.py +129 -0
  383. agno/tools/exa.py +324 -42
  384. agno/tools/fal.py +39 -35
  385. agno/tools/file.py +196 -30
  386. agno/tools/file_generation.py +356 -0
  387. agno/tools/financial_datasets.py +288 -0
  388. agno/tools/firecrawl.py +108 -33
  389. agno/tools/function.py +960 -122
  390. agno/tools/giphy.py +34 -12
  391. agno/tools/github.py +1294 -97
  392. agno/tools/gmail.py +922 -0
  393. agno/tools/google_bigquery.py +117 -0
  394. agno/tools/google_drive.py +271 -0
  395. agno/tools/google_maps.py +253 -0
  396. agno/tools/googlecalendar.py +607 -107
  397. agno/tools/googlesheets.py +377 -0
  398. agno/tools/hackernews.py +20 -12
  399. agno/tools/jina.py +24 -14
  400. agno/tools/jira.py +48 -19
  401. agno/tools/knowledge.py +218 -0
  402. agno/tools/linear.py +82 -43
  403. agno/tools/linkup.py +58 -0
  404. agno/tools/local_file_system.py +15 -7
  405. agno/tools/lumalab.py +41 -26
  406. agno/tools/mcp/__init__.py +10 -0
  407. agno/tools/mcp/mcp.py +331 -0
  408. agno/tools/mcp/multi_mcp.py +347 -0
  409. agno/tools/mcp/params.py +24 -0
  410. agno/tools/mcp_toolbox.py +284 -0
  411. agno/tools/mem0.py +193 -0
  412. agno/tools/memory.py +419 -0
  413. agno/tools/mlx_transcribe.py +11 -9
  414. agno/tools/models/azure_openai.py +190 -0
  415. agno/tools/models/gemini.py +203 -0
  416. agno/tools/models/groq.py +158 -0
  417. agno/tools/models/morph.py +186 -0
  418. agno/tools/models/nebius.py +124 -0
  419. agno/tools/models_labs.py +163 -82
  420. agno/tools/moviepy_video.py +18 -13
  421. agno/tools/nano_banana.py +151 -0
  422. agno/tools/neo4j.py +134 -0
  423. agno/tools/newspaper.py +15 -4
  424. agno/tools/newspaper4k.py +19 -6
  425. agno/tools/notion.py +204 -0
  426. agno/tools/openai.py +181 -17
  427. agno/tools/openbb.py +27 -20
  428. agno/tools/opencv.py +321 -0
  429. agno/tools/openweather.py +233 -0
  430. agno/tools/oxylabs.py +385 -0
  431. agno/tools/pandas.py +25 -15
  432. agno/tools/parallel.py +314 -0
  433. agno/tools/postgres.py +238 -185
  434. agno/tools/pubmed.py +125 -13
  435. agno/tools/python.py +48 -35
  436. agno/tools/reasoning.py +283 -0
  437. agno/tools/reddit.py +207 -29
  438. agno/tools/redshift.py +406 -0
  439. agno/tools/replicate.py +69 -26
  440. agno/tools/resend.py +11 -6
  441. agno/tools/scrapegraph.py +179 -19
  442. agno/tools/searxng.py +23 -31
  443. agno/tools/serpapi.py +15 -10
  444. agno/tools/serper.py +255 -0
  445. agno/tools/shell.py +23 -12
  446. agno/tools/shopify.py +1519 -0
  447. agno/tools/slack.py +56 -14
  448. agno/tools/sleep.py +8 -6
  449. agno/tools/spider.py +35 -11
  450. agno/tools/spotify.py +919 -0
  451. agno/tools/sql.py +34 -19
  452. agno/tools/tavily.py +158 -8
  453. agno/tools/telegram.py +18 -8
  454. agno/tools/todoist.py +218 -0
  455. agno/tools/toolkit.py +134 -9
  456. agno/tools/trafilatura.py +388 -0
  457. agno/tools/trello.py +25 -28
  458. agno/tools/twilio.py +18 -9
  459. agno/tools/user_control_flow.py +78 -0
  460. agno/tools/valyu.py +228 -0
  461. agno/tools/visualization.py +467 -0
  462. agno/tools/webbrowser.py +28 -0
  463. agno/tools/webex.py +76 -0
  464. agno/tools/website.py +23 -19
  465. agno/tools/webtools.py +45 -0
  466. agno/tools/whatsapp.py +286 -0
  467. agno/tools/wikipedia.py +28 -19
  468. agno/tools/workflow.py +285 -0
  469. agno/tools/{twitter.py → x.py} +142 -46
  470. agno/tools/yfinance.py +41 -39
  471. agno/tools/youtube.py +34 -17
  472. agno/tools/zendesk.py +15 -5
  473. agno/tools/zep.py +454 -0
  474. agno/tools/zoom.py +86 -37
  475. agno/tracing/__init__.py +12 -0
  476. agno/tracing/exporter.py +157 -0
  477. agno/tracing/schemas.py +276 -0
  478. agno/tracing/setup.py +111 -0
  479. agno/utils/agent.py +938 -0
  480. agno/utils/audio.py +37 -1
  481. agno/utils/certs.py +27 -0
  482. agno/utils/code_execution.py +11 -0
  483. agno/utils/common.py +103 -20
  484. agno/utils/cryptography.py +22 -0
  485. agno/utils/dttm.py +33 -0
  486. agno/utils/events.py +700 -0
  487. agno/utils/functions.py +107 -37
  488. agno/utils/gemini.py +426 -0
  489. agno/utils/hooks.py +171 -0
  490. agno/utils/http.py +185 -0
  491. agno/utils/json_schema.py +159 -37
  492. agno/utils/knowledge.py +36 -0
  493. agno/utils/location.py +19 -0
  494. agno/utils/log.py +221 -8
  495. agno/utils/mcp.py +214 -0
  496. agno/utils/media.py +335 -14
  497. agno/utils/merge_dict.py +22 -1
  498. agno/utils/message.py +77 -2
  499. agno/utils/models/ai_foundry.py +50 -0
  500. agno/utils/models/claude.py +373 -0
  501. agno/utils/models/cohere.py +94 -0
  502. agno/utils/models/llama.py +85 -0
  503. agno/utils/models/mistral.py +100 -0
  504. agno/utils/models/openai_responses.py +140 -0
  505. agno/utils/models/schema_utils.py +153 -0
  506. agno/utils/models/watsonx.py +41 -0
  507. agno/utils/openai.py +257 -0
  508. agno/utils/pickle.py +1 -1
  509. agno/utils/pprint.py +124 -8
  510. agno/utils/print_response/agent.py +930 -0
  511. agno/utils/print_response/team.py +1914 -0
  512. agno/utils/print_response/workflow.py +1668 -0
  513. agno/utils/prompts.py +111 -0
  514. agno/utils/reasoning.py +108 -0
  515. agno/utils/response.py +163 -0
  516. agno/utils/serialize.py +32 -0
  517. agno/utils/shell.py +4 -4
  518. agno/utils/streamlit.py +487 -0
  519. agno/utils/string.py +204 -51
  520. agno/utils/team.py +139 -0
  521. agno/utils/timer.py +9 -2
  522. agno/utils/tokens.py +657 -0
  523. agno/utils/tools.py +19 -1
  524. agno/utils/whatsapp.py +305 -0
  525. agno/utils/yaml_io.py +3 -3
  526. agno/vectordb/__init__.py +2 -0
  527. agno/vectordb/base.py +87 -9
  528. agno/vectordb/cassandra/__init__.py +5 -1
  529. agno/vectordb/cassandra/cassandra.py +383 -27
  530. agno/vectordb/chroma/__init__.py +4 -0
  531. agno/vectordb/chroma/chromadb.py +748 -83
  532. agno/vectordb/clickhouse/__init__.py +7 -1
  533. agno/vectordb/clickhouse/clickhousedb.py +554 -53
  534. agno/vectordb/couchbase/__init__.py +3 -0
  535. agno/vectordb/couchbase/couchbase.py +1446 -0
  536. agno/vectordb/lancedb/__init__.py +5 -0
  537. agno/vectordb/lancedb/lance_db.py +730 -98
  538. agno/vectordb/langchaindb/__init__.py +5 -0
  539. agno/vectordb/langchaindb/langchaindb.py +163 -0
  540. agno/vectordb/lightrag/__init__.py +5 -0
  541. agno/vectordb/lightrag/lightrag.py +388 -0
  542. agno/vectordb/llamaindex/__init__.py +3 -0
  543. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  544. agno/vectordb/milvus/__init__.py +3 -0
  545. agno/vectordb/milvus/milvus.py +966 -78
  546. agno/vectordb/mongodb/__init__.py +9 -1
  547. agno/vectordb/mongodb/mongodb.py +1175 -172
  548. agno/vectordb/pgvector/__init__.py +8 -0
  549. agno/vectordb/pgvector/pgvector.py +599 -115
  550. agno/vectordb/pineconedb/__init__.py +5 -1
  551. agno/vectordb/pineconedb/pineconedb.py +406 -43
  552. agno/vectordb/qdrant/__init__.py +4 -0
  553. agno/vectordb/qdrant/qdrant.py +914 -61
  554. agno/vectordb/redis/__init__.py +9 -0
  555. agno/vectordb/redis/redisdb.py +682 -0
  556. agno/vectordb/singlestore/__init__.py +8 -1
  557. agno/vectordb/singlestore/singlestore.py +771 -0
  558. agno/vectordb/surrealdb/__init__.py +3 -0
  559. agno/vectordb/surrealdb/surrealdb.py +663 -0
  560. agno/vectordb/upstashdb/__init__.py +5 -0
  561. agno/vectordb/upstashdb/upstashdb.py +718 -0
  562. agno/vectordb/weaviate/__init__.py +8 -0
  563. agno/vectordb/weaviate/index.py +15 -0
  564. agno/vectordb/weaviate/weaviate.py +1009 -0
  565. agno/workflow/__init__.py +23 -1
  566. agno/workflow/agent.py +299 -0
  567. agno/workflow/condition.py +759 -0
  568. agno/workflow/loop.py +756 -0
  569. agno/workflow/parallel.py +853 -0
  570. agno/workflow/router.py +723 -0
  571. agno/workflow/step.py +1564 -0
  572. agno/workflow/steps.py +613 -0
  573. agno/workflow/types.py +556 -0
  574. agno/workflow/workflow.py +4327 -514
  575. agno-2.3.13.dist-info/METADATA +639 -0
  576. agno-2.3.13.dist-info/RECORD +613 -0
  577. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
  578. agno-2.3.13.dist-info/licenses/LICENSE +201 -0
  579. agno/api/playground.py +0 -91
  580. agno/api/schemas/playground.py +0 -22
  581. agno/api/schemas/user.py +0 -22
  582. agno/api/schemas/workspace.py +0 -46
  583. agno/api/user.py +0 -160
  584. agno/api/workspace.py +0 -151
  585. agno/cli/auth_server.py +0 -118
  586. agno/cli/config.py +0 -275
  587. agno/cli/console.py +0 -88
  588. agno/cli/credentials.py +0 -23
  589. agno/cli/entrypoint.py +0 -571
  590. agno/cli/operator.py +0 -355
  591. agno/cli/settings.py +0 -85
  592. agno/cli/ws/ws_cli.py +0 -817
  593. agno/constants.py +0 -13
  594. agno/document/__init__.py +0 -1
  595. agno/document/chunking/semantic.py +0 -47
  596. agno/document/chunking/strategy.py +0 -31
  597. agno/document/reader/__init__.py +0 -1
  598. agno/document/reader/arxiv_reader.py +0 -41
  599. agno/document/reader/base.py +0 -22
  600. agno/document/reader/csv_reader.py +0 -84
  601. agno/document/reader/docx_reader.py +0 -46
  602. agno/document/reader/firecrawl_reader.py +0 -99
  603. agno/document/reader/json_reader.py +0 -43
  604. agno/document/reader/pdf_reader.py +0 -219
  605. agno/document/reader/s3/pdf_reader.py +0 -46
  606. agno/document/reader/s3/text_reader.py +0 -51
  607. agno/document/reader/text_reader.py +0 -41
  608. agno/document/reader/website_reader.py +0 -175
  609. agno/document/reader/youtube_reader.py +0 -50
  610. agno/embedder/__init__.py +0 -1
  611. agno/embedder/azure_openai.py +0 -86
  612. agno/embedder/cohere.py +0 -72
  613. agno/embedder/fastembed.py +0 -37
  614. agno/embedder/google.py +0 -73
  615. agno/embedder/huggingface.py +0 -54
  616. agno/embedder/mistral.py +0 -80
  617. agno/embedder/ollama.py +0 -57
  618. agno/embedder/openai.py +0 -74
  619. agno/embedder/sentence_transformer.py +0 -38
  620. agno/embedder/voyageai.py +0 -64
  621. agno/eval/perf.py +0 -201
  622. agno/file/__init__.py +0 -1
  623. agno/file/file.py +0 -16
  624. agno/file/local/csv.py +0 -32
  625. agno/file/local/txt.py +0 -19
  626. agno/infra/app.py +0 -240
  627. agno/infra/base.py +0 -144
  628. agno/infra/context.py +0 -20
  629. agno/infra/db_app.py +0 -52
  630. agno/infra/resource.py +0 -205
  631. agno/infra/resources.py +0 -55
  632. agno/knowledge/agent.py +0 -230
  633. agno/knowledge/arxiv.py +0 -22
  634. agno/knowledge/combined.py +0 -22
  635. agno/knowledge/csv.py +0 -28
  636. agno/knowledge/csv_url.py +0 -19
  637. agno/knowledge/document.py +0 -20
  638. agno/knowledge/docx.py +0 -30
  639. agno/knowledge/json.py +0 -28
  640. agno/knowledge/langchain.py +0 -71
  641. agno/knowledge/llamaindex.py +0 -66
  642. agno/knowledge/pdf.py +0 -28
  643. agno/knowledge/pdf_url.py +0 -26
  644. agno/knowledge/s3/base.py +0 -60
  645. agno/knowledge/s3/pdf.py +0 -21
  646. agno/knowledge/s3/text.py +0 -23
  647. agno/knowledge/text.py +0 -30
  648. agno/knowledge/website.py +0 -88
  649. agno/knowledge/wikipedia.py +0 -31
  650. agno/knowledge/youtube.py +0 -22
  651. agno/memory/agent.py +0 -392
  652. agno/memory/classifier.py +0 -104
  653. agno/memory/db/__init__.py +0 -1
  654. agno/memory/db/base.py +0 -42
  655. agno/memory/db/mongodb.py +0 -189
  656. agno/memory/db/postgres.py +0 -203
  657. agno/memory/db/sqlite.py +0 -193
  658. agno/memory/memory.py +0 -15
  659. agno/memory/row.py +0 -36
  660. agno/memory/summarizer.py +0 -192
  661. agno/memory/summary.py +0 -19
  662. agno/memory/workflow.py +0 -38
  663. agno/models/google/gemini_openai.py +0 -26
  664. agno/models/ollama/hermes.py +0 -221
  665. agno/models/ollama/tools.py +0 -362
  666. agno/models/vertexai/gemini.py +0 -595
  667. agno/playground/__init__.py +0 -3
  668. agno/playground/async_router.py +0 -421
  669. agno/playground/deploy.py +0 -249
  670. agno/playground/operator.py +0 -92
  671. agno/playground/playground.py +0 -91
  672. agno/playground/schemas.py +0 -76
  673. agno/playground/serve.py +0 -55
  674. agno/playground/sync_router.py +0 -405
  675. agno/reasoning/agent.py +0 -68
  676. agno/run/response.py +0 -112
  677. agno/storage/agent/__init__.py +0 -0
  678. agno/storage/agent/base.py +0 -38
  679. agno/storage/agent/dynamodb.py +0 -350
  680. agno/storage/agent/json.py +0 -92
  681. agno/storage/agent/mongodb.py +0 -228
  682. agno/storage/agent/postgres.py +0 -367
  683. agno/storage/agent/session.py +0 -79
  684. agno/storage/agent/singlestore.py +0 -303
  685. agno/storage/agent/sqlite.py +0 -357
  686. agno/storage/agent/yaml.py +0 -93
  687. agno/storage/workflow/__init__.py +0 -0
  688. agno/storage/workflow/base.py +0 -40
  689. agno/storage/workflow/mongodb.py +0 -233
  690. agno/storage/workflow/postgres.py +0 -366
  691. agno/storage/workflow/session.py +0 -60
  692. agno/storage/workflow/sqlite.py +0 -359
  693. agno/tools/googlesearch.py +0 -88
  694. agno/utils/defaults.py +0 -57
  695. agno/utils/filesystem.py +0 -39
  696. agno/utils/git.py +0 -52
  697. agno/utils/json_io.py +0 -30
  698. agno/utils/load_env.py +0 -19
  699. agno/utils/py_io.py +0 -19
  700. agno/utils/pyproject.py +0 -18
  701. agno/utils/resource_filter.py +0 -31
  702. agno/vectordb/singlestore/s2vectordb.py +0 -390
  703. agno/vectordb/singlestore/s2vectordb2.py +0 -355
  704. agno/workspace/__init__.py +0 -0
  705. agno/workspace/config.py +0 -325
  706. agno/workspace/enums.py +0 -6
  707. agno/workspace/helpers.py +0 -48
  708. agno/workspace/operator.py +0 -758
  709. agno/workspace/settings.py +0 -63
  710. agno-0.1.2.dist-info/LICENSE +0 -375
  711. agno-0.1.2.dist-info/METADATA +0 -502
  712. agno-0.1.2.dist-info/RECORD +0 -352
  713. agno-0.1.2.dist-info/entry_points.txt +0 -3
  714. /agno/{cli → db/migrations}/__init__.py +0 -0
  715. /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
  716. /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
  717. /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
  718. /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
  719. /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
  720. /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
  721. /agno/{reranker → utils/models}/__init__.py +0 -0
  722. /agno/{storage → utils/print_response}/__init__.py +0 -0
  723. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,9 @@
1
1
  import json
2
- import os
3
- from typing import Optional
2
+ from os import getenv
3
+ from typing import Any, List, Optional
4
4
 
5
5
  from agno.tools import Toolkit
6
- from agno.utils.log import logger
6
+ from agno.utils.log import log_debug, log_info, logger
7
7
 
8
8
  try:
9
9
  import tweepy
@@ -11,7 +11,7 @@ except ImportError:
11
11
  raise ImportError("`tweepy` not installed. Please install using `pip install tweepy`.")
12
12
 
13
13
 
14
- class TwitterTools(Toolkit):
14
+ class XTools(Toolkit):
15
15
  def __init__(
16
16
  self,
17
17
  bearer_token: Optional[str] = None,
@@ -19,9 +19,12 @@ class TwitterTools(Toolkit):
19
19
  consumer_secret: Optional[str] = None,
20
20
  access_token: Optional[str] = None,
21
21
  access_token_secret: Optional[str] = None,
22
+ include_post_metrics: bool = False,
23
+ wait_on_rate_limit: bool = False,
24
+ **kwargs,
22
25
  ):
23
26
  """
24
- Initialize the TwitterTools.
27
+ Initialize the XTools.
25
28
 
26
29
  Args:
27
30
  bearer_token Optional[str]: The bearer token for Twitter API.
@@ -29,76 +32,82 @@ class TwitterTools(Toolkit):
29
32
  consumer_secret Optional[str]: The consumer secret for Twitter API.
30
33
  access_token Optional[str]: The access token for Twitter API.
31
34
  access_token_secret Optional[str]: The access token secret for Twitter API.
35
+ include_post_metrics Optional[bool]: Whether to include post metrics in the search results.
36
+ wait_on_rate_limit Optional[bool]: Whether to wait on rate limit.
32
37
  """
33
- super().__init__(name="twitter")
34
-
35
- self.bearer_token = bearer_token or os.getenv("TWITTER_BEARER_TOKEN")
36
- self.consumer_key = consumer_key or os.getenv("TWITTER_CONSUMER_KEY")
37
- self.consumer_secret = consumer_secret or os.getenv("TWITTER_CONSUMER_SECRET")
38
- self.access_token = access_token or os.getenv("TWITTER_ACCESS_TOKEN")
39
- self.access_token_secret = access_token_secret or os.getenv("TWITTER_ACCESS_TOKEN_SECRET")
40
-
38
+ self.bearer_token = bearer_token or getenv("X_BEARER_TOKEN")
39
+ self.consumer_key = consumer_key or getenv("X_CONSUMER_KEY")
40
+ self.consumer_secret = consumer_secret or getenv("X_CONSUMER_SECRET")
41
+ self.access_token = access_token or getenv("X_ACCESS_TOKEN")
42
+ self.access_token_secret = access_token_secret or getenv("X_ACCESS_TOKEN_SECRET")
43
+ self.wait_on_rate_limit = wait_on_rate_limit
41
44
  self.client = tweepy.Client(
42
45
  bearer_token=self.bearer_token,
43
46
  consumer_key=self.consumer_key,
44
47
  consumer_secret=self.consumer_secret,
45
48
  access_token=self.access_token,
46
49
  access_token_secret=self.access_token_secret,
50
+ wait_on_rate_limit=self.wait_on_rate_limit,
47
51
  )
48
- self.auth = tweepy.OAuth1UserHandler(consumer_key, consumer_secret, access_token, access_token_secret)
49
- self.api = tweepy.API(self.auth)
50
- self.register(self.create_tweet)
51
- self.register(self.reply_to_tweet)
52
- self.register(self.send_dm)
53
- self.register(self.get_user_info)
54
- self.register(self.get_home_timeline)
52
+ self.include_post_metrics = include_post_metrics
53
+
54
+ tools: List[Any] = [
55
+ self.create_post,
56
+ self.reply_to_post,
57
+ self.send_dm,
58
+ self.get_user_info,
59
+ self.get_home_timeline,
60
+ self.search_posts,
61
+ ]
62
+
63
+ super().__init__(name="x", tools=tools, **kwargs)
55
64
 
56
- def create_tweet(self, text: str) -> str:
65
+ def create_post(self, text: str) -> str:
57
66
  """
58
- Create a new tweet.
67
+ Create a new X post.
59
68
 
60
69
  Args:
61
- text (str): The content of the tweet to create.
70
+ text (str): The content of the post to create.
62
71
 
63
72
  Returns:
64
- A JSON-formatted string containing the response from Twitter API with the created tweet details,
65
- or an error message if the tweet creation fails.
73
+ A JSON-formatted string containing the response from X API (Twitter API) with the created post details,
74
+ or an error message if the post creation fails.
66
75
  """
67
- logger.debug(f"Attempting to create tweet with text: {text}")
76
+ log_debug(f"Attempting to create post with text: {text}")
68
77
  try:
69
78
  response = self.client.create_tweet(text=text)
70
- tweet_id = response.data["id"]
79
+ post_id = response.data["id"]
71
80
  user = self.client.get_me().data
72
- tweet_url = f"https://twitter.com/{user.username}/status/{tweet_id}"
81
+ post_url = f"https://x.com/{user.username}/status/{post_id}"
73
82
 
74
- result = {"message": "Tweet successfully posted!", "url": tweet_url}
83
+ result = {"message": "Post successfully created!", "url": post_url}
75
84
  return json.dumps(result, indent=2)
76
85
  except tweepy.TweepyException as e:
77
- logger.error(f"Error creating tweet: {e}")
86
+ logger.error(f"Error creating post: {e}")
78
87
  return json.dumps({"error": str(e)})
79
88
 
80
- def reply_to_tweet(self, tweet_id: str, text: str) -> str:
89
+ def reply_to_post(self, post_id: str, text: str) -> str:
81
90
  """
82
- Reply to an existing tweet.
91
+ Reply to an existing post.
83
92
 
84
93
  Args:
85
- tweet_id (str): The ID of the tweet to reply to.
86
- text (str): The content of the reply tweet.
94
+ post_id (str): The ID of the post to reply to.
95
+ text (str): The content of the reply post.
87
96
 
88
97
  Returns:
89
- A JSON-formatted string containing the response from Twitter API with the reply tweet details,
98
+ A JSON-formatted string containing the response from Twitter API with the reply post details,
90
99
  or an error message if the reply fails.
91
100
  """
92
- logger.debug(f"Attempting to reply to {tweet_id} with text {text}")
101
+ log_debug(f"Attempting to reply to {post_id} with text {text}")
93
102
  try:
94
- response = self.client.create_tweet(text=text, in_reply_to_tweet_id=tweet_id)
103
+ response = self.client.create_tweet(text=text, in_reply_to_tweet_id=post_id)
95
104
  reply_id = response.data["id"]
96
105
  user = self.client.get_me().data
97
106
  reply_url = f"https://twitter.com/{user.username}/status/{reply_id}"
98
107
  result = {"message": "Reply successfully posted!", "url": reply_url}
99
108
  return json.dumps(result, indent=2)
100
109
  except tweepy.TweepyException as e:
101
- logger.error(f"Error replying to tweet: {e}")
110
+ logger.error(f"Error replying to post: {e}")
102
111
  return json.dumps({"error": str(e)})
103
112
 
104
113
  def send_dm(self, recipient: str, text: str) -> str:
@@ -113,18 +122,18 @@ class TwitterTools(Toolkit):
113
122
  A JSON-formatted string containing the response from Twitter API with the sent message details,
114
123
  or an error message if sending the DM fails.
115
124
  """
116
- logger.debug(f"Attempting to send DM to user {recipient}")
125
+ log_debug(f"Attempting to send DM to user {recipient}")
117
126
  try:
118
127
  # Check if recipient is a user ID (numeric) or username
119
128
  if not recipient.isdigit():
120
129
  # If it's not numeric, assume it's a username and get the user ID
121
130
  user = self.client.get_user(username=recipient)
122
- logger.debug(f"Attempting to send DM to user's id {user}")
131
+ log_debug(f"Attempting to send DM to user's id {user}")
123
132
  recipient_id = user.data.id
124
133
  else:
125
134
  recipient_id = recipient
126
135
 
127
- logger.debug(f"Attempting to send DM to user's id {recipient_id}")
136
+ log_debug(f"Attempting to send DM to user's id {recipient_id}")
128
137
  response = self.client.create_direct_message(participant_id=recipient_id, text=text)
129
138
  result = {
130
139
  "message": "Direct message sent successfully!",
@@ -134,7 +143,7 @@ class TwitterTools(Toolkit):
134
143
  }
135
144
  return json.dumps(result, indent=2)
136
145
  except tweepy.TweepyException as e:
137
- logger.error(f"Error sending DM: {e}")
146
+ logger.error(f"Error from X while sending DM: {e}")
138
147
  error_message = str(e)
139
148
  if "User not found" in error_message:
140
149
  error_message = f"User '{recipient}' not found. Please check the username or user ID."
@@ -156,7 +165,7 @@ class TwitterTools(Toolkit):
156
165
  including id, name, username, description, and follower/following counts,
157
166
  or an error message if fetching the information fails.
158
167
  """
159
- logger.debug("Fetching information about myself")
168
+ log_debug("Fetching information about myself")
160
169
  try:
161
170
  me = self.client.get_me(user_fields=["description", "public_metrics"])
162
171
  user_info = me.data.data
@@ -186,7 +195,7 @@ class TwitterTools(Toolkit):
186
195
  including id, name, username, description, and follower/following counts,
187
196
  or an error message if fetching the information fails.
188
197
  """
189
- logger.debug(f"Fetching information about user {username}")
198
+ log_debug(f"Fetching information about user {username}")
190
199
  try:
191
200
  user = self.client.get_user(username=username, user_fields=["description", "public_metrics"])
192
201
  user_info = user.data.data
@@ -216,7 +225,7 @@ class TwitterTools(Toolkit):
216
225
  including tweet id, text, creation time, and author id,
217
226
  or an error message if fetching the timeline fails.
218
227
  """
219
- logger.debug(f"Fetching home timeline, max results: {max_results}")
228
+ log_debug(f"Fetching home timeline, max results: {max_results}")
220
229
  try:
221
230
  tweets = self.client.get_home_timeline(
222
231
  max_results=max_results, tweet_fields=["created_at", "public_metrics"]
@@ -231,9 +240,96 @@ class TwitterTools(Toolkit):
231
240
  "author_id": tweet.author_id,
232
241
  }
233
242
  )
234
- logger.info(f"Successfully fetched {len(timeline)} tweets")
243
+ log_info(f"Successfully fetched {len(timeline)} tweets")
235
244
  result = {"home_timeline": timeline}
236
245
  return json.dumps(result, indent=2)
237
246
  except tweepy.TweepyException as e:
238
247
  logger.error(f"Error fetching home timeline: {e}")
239
248
  return json.dumps({"error": str(e)})
249
+
250
+ def search_posts(self, query: str, max_results: int = 10) -> str:
251
+ """
252
+ Search for tweets based on a search query.
253
+
254
+ Args:
255
+ query (str): The search query.
256
+ max_results (int): The maximum number of posts to retrieve.
257
+
258
+ Returns:
259
+ A list of posts matching the search query
260
+ """
261
+ try:
262
+ max_results = max(10, min(max_results, 100)) # range 10 - 100
263
+
264
+ log_debug(f"Searching for posts with query: {query}, bounded max results: {max_results}")
265
+ results = self.client.search_recent_tweets(
266
+ query=query,
267
+ max_results=max_results,
268
+ tweet_fields=[
269
+ "author_id",
270
+ "created_at",
271
+ "id",
272
+ "public_metrics",
273
+ "text",
274
+ ],
275
+ user_fields=["name", "username", "verified"],
276
+ )
277
+
278
+ users_data = {}
279
+ if hasattr(results, "includes") and "users" in results.includes:
280
+ for user in results.includes["users"]:
281
+ users_data[user.id] = {
282
+ "id": user.id,
283
+ "name": user.name,
284
+ "username": user.username,
285
+ "verified": getattr(user, "verified", False),
286
+ }
287
+ tweets = []
288
+
289
+ if results.data:
290
+ for tweet in results.data:
291
+ author_info = users_data.get(
292
+ tweet.author_id, {"id": tweet.author_id, "name": "Unknown", "username": "unknown"}
293
+ )
294
+
295
+ post_url = f"https://x.com/{author_info.get('username', 'unknown')}/status/{tweet.id}"
296
+
297
+ post_data = {
298
+ "id": tweet.id,
299
+ "text": tweet.text,
300
+ "created_at": tweet.created_at.strftime("%Y-%m-%d %H:%M:%S")
301
+ if hasattr(tweet, "created_at")
302
+ else None,
303
+ "author": author_info,
304
+ "url": post_url,
305
+ }
306
+ if self.include_post_metrics:
307
+ post_data["metrics"] = {
308
+ "retweet_count": tweet.public_metrics.get("retweet_count", 0)
309
+ if hasattr(tweet, "public_metrics")
310
+ else 0,
311
+ "reply_count": tweet.public_metrics.get("reply_count", 0)
312
+ if hasattr(tweet, "public_metrics")
313
+ else 0,
314
+ "like_count": tweet.public_metrics.get("like_count", 0)
315
+ if hasattr(tweet, "public_metrics")
316
+ else 0,
317
+ "quote_count": tweet.public_metrics.get("quote_count", 0)
318
+ if hasattr(tweet, "public_metrics")
319
+ else 0,
320
+ }
321
+ tweets.append(post_data)
322
+
323
+ log_info(f"Successfully found {len(tweets)} posts for query: {query}")
324
+ result = {"query": query, "count": len(tweets), "posts": tweets}
325
+ else:
326
+ log_info(f"No posts found for query: {query}")
327
+ result = {}
328
+ return json.dumps(result, indent=2)
329
+
330
+ except tweepy.TweepyException as e:
331
+ logger.error(f"Error searching posts: {e}")
332
+ return json.dumps({"error": str(e), "query": query})
333
+ except Exception as e:
334
+ logger.error(f"Unexpected error searching posts: {e}")
335
+ return json.dumps({"error": f"An unexpected error occurred: {str(e)}", "query": query})
agno/tools/yfinance.py CHANGED
@@ -1,6 +1,8 @@
1
1
  import json
2
+ from typing import Any, List, Optional
2
3
 
3
4
  from agno.tools import Toolkit
5
+ from agno.utils.log import log_debug
4
6
 
5
7
  try:
6
8
  import yfinance as yf
@@ -9,39 +11,29 @@ except ImportError:
9
11
 
10
12
 
11
13
  class YFinanceTools(Toolkit):
14
+ """
15
+ YFinanceTools is a toolkit for getting financial data from Yahoo Finance.
16
+ Includes all available financial data tools.
17
+ """
18
+
12
19
  def __init__(
13
20
  self,
14
- stock_price: bool = True,
15
- company_info: bool = False,
16
- stock_fundamentals: bool = False,
17
- income_statements: bool = False,
18
- key_financial_ratios: bool = False,
19
- analyst_recommendations: bool = False,
20
- company_news: bool = False,
21
- technical_indicators: bool = False,
22
- historical_prices: bool = False,
23
- enable_all: bool = False,
21
+ session: Optional[Any] = None,
22
+ **kwargs,
24
23
  ):
25
- super().__init__(name="yfinance_tools")
26
-
27
- if stock_price or enable_all:
28
- self.register(self.get_current_stock_price)
29
- if company_info or enable_all:
30
- self.register(self.get_company_info)
31
- if stock_fundamentals or enable_all:
32
- self.register(self.get_stock_fundamentals)
33
- if income_statements or enable_all:
34
- self.register(self.get_income_statements)
35
- if key_financial_ratios or enable_all:
36
- self.register(self.get_key_financial_ratios)
37
- if analyst_recommendations or enable_all:
38
- self.register(self.get_analyst_recommendations)
39
- if company_news or enable_all:
40
- self.register(self.get_company_news)
41
- if technical_indicators or enable_all:
42
- self.register(self.get_technical_indicators)
43
- if historical_prices or enable_all:
44
- self.register(self.get_historical_stock_prices)
24
+ tools: List[Any] = [
25
+ self.get_current_stock_price,
26
+ self.get_company_info,
27
+ self.get_stock_fundamentals,
28
+ self.get_income_statements,
29
+ self.get_key_financial_ratios,
30
+ self.get_analyst_recommendations,
31
+ self.get_company_news,
32
+ self.get_technical_indicators,
33
+ self.get_historical_stock_prices,
34
+ ]
35
+ self.session = session
36
+ super().__init__(name="yfinance_tools", tools=tools, **kwargs)
45
37
 
46
38
  def get_current_stock_price(self, symbol: str) -> str:
47
39
  """
@@ -54,7 +46,8 @@ class YFinanceTools(Toolkit):
54
46
  str: The current stock price or error message.
55
47
  """
56
48
  try:
57
- stock = yf.Ticker(symbol)
49
+ log_debug(f"Fetching current price for {symbol}")
50
+ stock = yf.Ticker(symbol, session=self.session)
58
51
  # Use "regularMarketPrice" for regular market hours, or "currentPrice" for pre/post market
59
52
  current_price = stock.info.get("regularMarketPrice", stock.info.get("currentPrice"))
60
53
  return f"{current_price:.4f}" if current_price else f"Could not fetch current price for {symbol}"
@@ -71,10 +64,12 @@ class YFinanceTools(Toolkit):
71
64
  str: JSON containing company profile and overview.
72
65
  """
73
66
  try:
74
- company_info_full = yf.Ticker(symbol).info
67
+ company_info_full = yf.Ticker(symbol, session=self.session).info
75
68
  if company_info_full is None:
76
69
  return f"Could not fetch company info for {symbol}"
77
70
 
71
+ log_debug(f"Fetching company info for {symbol}")
72
+
78
73
  company_info_cleaned = {
79
74
  "Name": company_info_full.get("shortName"),
80
75
  "Symbol": company_info_full.get("symbol"),
@@ -125,7 +120,8 @@ class YFinanceTools(Toolkit):
125
120
  str: The current stock price or error message.
126
121
  """
127
122
  try:
128
- stock = yf.Ticker(symbol)
123
+ log_debug(f"Fetching historical prices for {symbol}")
124
+ stock = yf.Ticker(symbol, session=self.session)
129
125
  historical_price = stock.history(period=period, interval=interval)
130
126
  return historical_price.to_json(orient="index")
131
127
  except Exception as e:
@@ -154,7 +150,8 @@ class YFinanceTools(Toolkit):
154
150
  - '52_week_low': The 52-week low price of the stock.
155
151
  """
156
152
  try:
157
- stock = yf.Ticker(symbol)
153
+ log_debug(f"Fetching fundamentals for {symbol}")
154
+ stock = yf.Ticker(symbol, session=self.session)
158
155
  info = stock.info
159
156
  fundamentals = {
160
157
  "symbol": symbol,
@@ -184,7 +181,8 @@ class YFinanceTools(Toolkit):
184
181
  dict: JSON containing income statements or an empty dictionary.
185
182
  """
186
183
  try:
187
- stock = yf.Ticker(symbol)
184
+ log_debug(f"Fetching income statements for {symbol}")
185
+ stock = yf.Ticker(symbol, session=self.session)
188
186
  financials = stock.financials
189
187
  return financials.to_json(orient="index")
190
188
  except Exception as e:
@@ -200,7 +198,8 @@ class YFinanceTools(Toolkit):
200
198
  dict: JSON containing key financial ratios.
201
199
  """
202
200
  try:
203
- stock = yf.Ticker(symbol)
201
+ log_debug(f"Fetching key financial ratios for {symbol}")
202
+ stock = yf.Ticker(symbol, session=self.session)
204
203
  key_ratios = stock.info
205
204
  return json.dumps(key_ratios, indent=2)
206
205
  except Exception as e:
@@ -216,7 +215,8 @@ class YFinanceTools(Toolkit):
216
215
  str: JSON containing analyst recommendations.
217
216
  """
218
217
  try:
219
- stock = yf.Ticker(symbol)
218
+ log_debug(f"Fetching analyst recommendations for {symbol}")
219
+ stock = yf.Ticker(symbol, session=self.session)
220
220
  recommendations = stock.recommendations
221
221
  return recommendations.to_json(orient="index")
222
222
  except Exception as e:
@@ -233,7 +233,8 @@ class YFinanceTools(Toolkit):
233
233
  str: JSON containing company news and press releases.
234
234
  """
235
235
  try:
236
- news = yf.Ticker(symbol).news
236
+ log_debug(f"Fetching company news for {symbol}")
237
+ news = yf.Ticker(symbol, session=self.session).news
237
238
  return json.dumps(news[:num_stories], indent=2)
238
239
  except Exception as e:
239
240
  return f"Error fetching company news for {symbol}: {e}"
@@ -250,7 +251,8 @@ class YFinanceTools(Toolkit):
250
251
  str: JSON containing technical indicators.
251
252
  """
252
253
  try:
253
- indicators = yf.Ticker(symbol).history(period=period)
254
+ log_debug(f"Fetching technical indicators for {symbol}")
255
+ indicators = yf.Ticker(symbol, session=self.session).history(period=period)
254
256
  return indicators.to_json(orient="index")
255
257
  except Exception as e:
256
258
  return f"Error fetching technical indicators for {symbol}: {e}"
agno/tools/youtube.py CHANGED
@@ -4,6 +4,7 @@ from urllib.parse import parse_qs, urlencode, urlparse
4
4
  from urllib.request import urlopen
5
5
 
6
6
  from agno.tools import Toolkit
7
+ from agno.utils.log import log_debug
7
8
 
8
9
  try:
9
10
  from youtube_transcript_api import YouTubeTranscriptApi
@@ -16,22 +17,26 @@ except ImportError:
16
17
  class YouTubeTools(Toolkit):
17
18
  def __init__(
18
19
  self,
19
- get_video_captions: bool = True,
20
- get_video_data: bool = True,
21
- get_video_timestamps: bool = True,
20
+ enable_get_video_captions: bool = True,
21
+ enable_get_video_data: bool = True,
22
+ enable_get_video_timestamps: bool = True,
23
+ all: bool = False,
22
24
  languages: Optional[List[str]] = None,
23
25
  proxies: Optional[Dict[str, Any]] = None,
26
+ **kwargs,
24
27
  ):
25
- super().__init__(name="youtube_tools")
26
-
27
28
  self.languages: Optional[List[str]] = languages
28
29
  self.proxies: Optional[Dict[str, Any]] = proxies
29
- if get_video_captions:
30
- self.register(self.get_youtube_video_captions)
31
- if get_video_data:
32
- self.register(self.get_youtube_video_data)
33
- if get_video_timestamps:
34
- self.register(self.get_video_timestamps)
30
+
31
+ tools: List[Any] = []
32
+ if all or enable_get_video_captions:
33
+ tools.append(self.get_youtube_video_captions)
34
+ if all or enable_get_video_data:
35
+ tools.append(self.get_youtube_video_data)
36
+ if all or enable_get_video_timestamps:
37
+ tools.append(self.get_video_timestamps)
38
+
39
+ super().__init__(name="youtube_tools", tools=tools, **kwargs)
35
40
 
36
41
  def get_youtube_video_id(self, url: str) -> Optional[str]:
37
42
  """Function to get the video ID from a YouTube URL.
@@ -70,6 +75,8 @@ class YouTubeTools(Toolkit):
70
75
  if not url:
71
76
  return "No URL provided"
72
77
 
78
+ log_debug(f"Getting video data for youtube video: {url}")
79
+
73
80
  try:
74
81
  video_id = self.get_youtube_video_id(url)
75
82
  except Exception:
@@ -112,6 +119,8 @@ class YouTubeTools(Toolkit):
112
119
  if not url:
113
120
  return "No URL provided"
114
121
 
122
+ log_debug(f"Getting captions for youtube video: {url}")
123
+
115
124
  try:
116
125
  video_id = self.get_youtube_video_id(url)
117
126
  except Exception:
@@ -124,12 +133,15 @@ class YouTubeTools(Toolkit):
124
133
  kwargs["languages"] = self.languages or ["en"]
125
134
  if self.proxies:
126
135
  kwargs["proxies"] = self.proxies
127
- captions = YouTubeTranscriptApi.get_transcript(video_id, **kwargs)
128
- # logger.debug(f"Captions for video {video_id}: {captions}")
136
+ if video_id is not None:
137
+ captions = YouTubeTranscriptApi().fetch(video_id, **kwargs)
138
+ else:
139
+ return "No video ID found"
129
140
  if captions:
130
- return " ".join(line["text"] for line in captions)
141
+ return " ".join(line.text for line in captions)
131
142
  return "No captions found for video"
132
143
  except Exception as e:
144
+ # log_info(f"Error getting captions for video {video_id}: {e}")
133
145
  return f"Error getting captions for video: {e}"
134
146
 
135
147
  def get_video_timestamps(self, url: str) -> str:
@@ -144,11 +156,16 @@ class YouTubeTools(Toolkit):
144
156
  if not url:
145
157
  return "No URL provided"
146
158
 
159
+ log_debug(f"Getting timestamps for youtube video: {url}")
160
+
147
161
  try:
148
162
  video_id = self.get_youtube_video_id(url)
149
163
  except Exception:
150
164
  return "Error getting video ID from URL, please provide a valid YouTube url"
151
165
 
166
+ if video_id is None:
167
+ return "No video ID found"
168
+
152
169
  try:
153
170
  kwargs: Dict = {}
154
171
  if self.languages:
@@ -156,12 +173,12 @@ class YouTubeTools(Toolkit):
156
173
  if self.proxies:
157
174
  kwargs["proxies"] = self.proxies
158
175
 
159
- captions = YouTubeTranscriptApi.get_transcript(video_id, **kwargs)
176
+ captions = YouTubeTranscriptApi().fetch(video_id, **kwargs)
160
177
  timestamps = []
161
178
  for line in captions:
162
- start = int(line["start"])
179
+ start = int(line.start)
163
180
  minutes, seconds = divmod(start, 60)
164
- timestamps.append(f"{minutes}:{seconds:02d} - {line['text']}")
181
+ timestamps.append(f"{minutes}:{seconds:02d} - {line.text}")
165
182
  return "\n".join(timestamps)
166
183
  except Exception as e:
167
184
  return f"Error generating timestamps: {e}"
agno/tools/zendesk.py CHANGED
@@ -1,10 +1,10 @@
1
1
  import json
2
2
  import re
3
3
  from os import getenv
4
- from typing import Optional
4
+ from typing import Any, List, Optional
5
5
 
6
6
  from agno.tools import Toolkit
7
- from agno.utils.log import logger
7
+ from agno.utils.log import log_debug, logger
8
8
 
9
9
  try:
10
10
  import requests
@@ -23,6 +23,9 @@ class ZendeskTools(Toolkit):
23
23
  username: Optional[str] = None,
24
24
  password: Optional[str] = None,
25
25
  company_name: Optional[str] = None,
26
+ enable_search_zendesk: bool = True,
27
+ all: bool = False,
28
+ **kwargs,
26
29
  ):
27
30
  """
28
31
  Initializes the ZendeskTools class with necessary authentication details
@@ -32,16 +35,21 @@ class ZendeskTools(Toolkit):
32
35
  username (str): The username for Zendesk API authentication.
33
36
  password (str): The password for Zendesk API authentication.
34
37
  company_name (str): The company name to form the base URL for API requests.
38
+ enable_search_zendesk (bool): Whether to enable the search functionality.
39
+ all (bool): Enable all functions.
35
40
  """
36
- super().__init__(name="zendesk_tools")
37
41
  self.username = username or getenv("ZENDESK_USERNAME")
38
- self.password = password or getenv("ZENDESK_PW")
42
+ self.password = password or getenv("ZENDESK_PASSWORD")
39
43
  self.company_name = company_name or getenv("ZENDESK_COMPANY_NAME")
40
44
 
41
45
  if not self.username or not self.password or not self.company_name:
42
46
  logger.error("Username, password, or company name not provided.")
43
47
 
44
- self.register(self.search_zendesk)
48
+ tools: List[Any] = []
49
+ if all or enable_search_zendesk:
50
+ tools.append(self.search_zendesk)
51
+
52
+ super().__init__(name="zendesk_tools", tools=tools, **kwargs)
45
53
 
46
54
  def search_zendesk(self, search_string: str) -> str:
47
55
  """
@@ -60,6 +68,8 @@ class ZendeskTools(Toolkit):
60
68
  if not self.username or not self.password or not self.company_name:
61
69
  return "Username, password, or company name not provided."
62
70
 
71
+ log_debug(f"Searching Zendesk for: {search_string}")
72
+
63
73
  auth = (self.username, self.password)
64
74
  url = f"https://{self.company_name}.zendesk.com/api/v2/help_center/articles/search.json?query={search_string}"
65
75
  try: