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
agno/tools/sql.py CHANGED
@@ -2,7 +2,7 @@ import json
2
2
  from typing import Any, Dict, List, Optional
3
3
 
4
4
  from agno.tools import Toolkit
5
- from agno.utils.log import logger
5
+ from agno.utils.log import log_debug, logger
6
6
 
7
7
  try:
8
8
  from sqlalchemy import Engine, create_engine
@@ -25,12 +25,12 @@ class SQLTools(Toolkit):
25
25
  schema: Optional[str] = None,
26
26
  dialect: Optional[str] = None,
27
27
  tables: Optional[Dict[str, Any]] = None,
28
- list_tables: bool = True,
29
- describe_table: bool = True,
30
- run_sql_query: bool = True,
28
+ enable_list_tables: bool = True,
29
+ enable_describe_table: bool = True,
30
+ enable_run_sql_query: bool = True,
31
+ all: bool = False,
32
+ **kwargs,
31
33
  ):
32
- super().__init__(name="sql_tools")
33
-
34
34
  # Get the database engine
35
35
  _engine: Optional[Engine] = db_engine
36
36
  if _engine is None and db_url is not None:
@@ -48,16 +48,20 @@ class SQLTools(Toolkit):
48
48
  self.db_engine: Engine = _engine
49
49
  self.Session: sessionmaker[Session] = sessionmaker(bind=self.db_engine)
50
50
 
51
+ self.schema = schema
52
+
51
53
  # Tables this toolkit can access
52
54
  self.tables: Optional[Dict[str, Any]] = tables
53
55
 
54
- # Register functions in the toolkit
55
- if list_tables:
56
- self.register(self.list_tables)
57
- if describe_table:
58
- self.register(self.describe_table)
59
- if run_sql_query:
60
- self.register(self.run_sql_query)
56
+ tools: List[Any] = []
57
+ if enable_list_tables or all:
58
+ tools.append(self.list_tables)
59
+ if enable_describe_table or all:
60
+ tools.append(self.describe_table)
61
+ if enable_run_sql_query or all:
62
+ tools.append(self.run_sql_query)
63
+
64
+ super().__init__(name="sql_tools", tools=tools, **kwargs)
61
65
 
62
66
  def list_tables(self) -> str:
63
67
  """Use this function to get a list of table names in the database.
@@ -69,8 +73,13 @@ class SQLTools(Toolkit):
69
73
  return json.dumps(self.tables)
70
74
 
71
75
  try:
72
- table_names = inspect(self.db_engine).get_table_names()
73
- logger.debug(f"table_names: {table_names}")
76
+ log_debug("listing tables in the database")
77
+ inspector = inspect(self.db_engine)
78
+ if self.schema:
79
+ table_names = inspector.get_table_names(schema=self.schema)
80
+ else:
81
+ table_names = inspector.get_table_names()
82
+ log_debug(f"table_names: {table_names}")
74
83
  return json.dumps(table_names)
75
84
  except Exception as e:
76
85
  logger.error(f"Error getting tables: {e}")
@@ -87,9 +96,15 @@ class SQLTools(Toolkit):
87
96
  """
88
97
 
89
98
  try:
90
- table_names = inspect(self.db_engine)
91
- table_schema = table_names.get_columns(table_name)
92
- return json.dumps([str(column) for column in table_schema])
99
+ log_debug(f"Describing table: {table_name}")
100
+ inspector = inspect(self.db_engine)
101
+ table_schema = inspector.get_columns(table_name, schema=self.schema)
102
+ return json.dumps(
103
+ [
104
+ {"name": column["name"], "type": str(column["type"]), "nullable": column["nullable"]}
105
+ for column in table_schema
106
+ ]
107
+ )
93
108
  except Exception as e:
94
109
  logger.error(f"Error getting table schema: {e}")
95
110
  return f"Error getting table schema: {e}"
@@ -122,7 +137,7 @@ class SQLTools(Toolkit):
122
137
  Returns:
123
138
  List[dict]: The result of the query.
124
139
  """
125
- logger.debug(f"Running sql |\n{sql}")
140
+ log_debug(f"Running sql |\n{sql}")
126
141
 
127
142
  with self.Session() as sess, sess.begin():
128
143
  result = sess.execute(text(sql))
agno/tools/tavily.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from os import getenv
3
- from typing import Any, Dict, Literal, Optional
3
+ from typing import Any, Dict, List, Literal, Optional
4
4
 
5
5
  from agno.tools import Toolkit
6
6
  from agno.utils.log import logger
@@ -15,30 +15,67 @@ class TavilyTools(Toolkit):
15
15
  def __init__(
16
16
  self,
17
17
  api_key: Optional[str] = None,
18
- search: bool = True,
18
+ enable_search: bool = True,
19
+ enable_search_context: bool = False,
20
+ enable_extract: bool = False,
21
+ all: bool = False,
19
22
  max_tokens: int = 6000,
20
23
  include_answer: bool = True,
21
24
  search_depth: Literal["basic", "advanced"] = "advanced",
25
+ extract_depth: Literal["basic", "advanced"] = "basic",
26
+ include_images: bool = False,
27
+ include_favicon: bool = False,
28
+ extract_timeout: Optional[int] = None,
29
+ extract_format: Literal["markdown", "text"] = "markdown",
22
30
  format: Literal["json", "markdown"] = "markdown",
23
- use_search_context: bool = False,
31
+ **kwargs,
24
32
  ):
25
- super().__init__(name="tavily_tools")
33
+ """Initialize TavilyTools with search and extract capabilities.
26
34
 
35
+ Args:
36
+ api_key: Tavily API key. If not provided, will use TAVILY_API_KEY env var.
37
+ enable_search: Enable web search functionality. Defaults to True.
38
+ enable_search_context: Use search context mode instead of regular search. Defaults to False.
39
+ enable_extract: Enable URL content extraction functionality. Defaults to False.
40
+ all: Enable all available tools. Defaults to False.
41
+ max_tokens: Maximum tokens for search results. Defaults to 6000.
42
+ include_answer: Include AI-generated answer in search results. Defaults to True.
43
+ search_depth: Search depth level - basic (1 credit) or advanced (2 credits). Defaults to "advanced".
44
+ extract_depth: Extract depth level - basic (1 credit/5 URLs) or advanced (2 credits/5 URLs). Defaults to "basic".
45
+ include_images: Include images in extracted content. Defaults to False.
46
+ include_favicon: Include favicon in extracted content. Defaults to False.
47
+ extract_timeout: Timeout in seconds for extraction requests. Defaults to None.
48
+ extract_format: Output format for extracted content - markdown or text. Defaults to "markdown".
49
+ format: Output format for search results - json or markdown. Defaults to "markdown".
50
+ **kwargs: Additional arguments passed to Toolkit.
51
+ """
27
52
  self.api_key = api_key or getenv("TAVILY_API_KEY")
28
53
  if not self.api_key:
29
54
  logger.error("TAVILY_API_KEY not provided")
30
55
 
31
56
  self.client: TavilyClient = TavilyClient(api_key=self.api_key)
32
57
  self.search_depth: Literal["basic", "advanced"] = search_depth
58
+ self.extract_depth: Literal["basic", "advanced"] = extract_depth
33
59
  self.max_tokens: int = max_tokens
34
60
  self.include_answer: bool = include_answer
61
+ self.include_images: bool = include_images
62
+ self.include_favicon: bool = include_favicon
63
+ self.extract_timeout: Optional[int] = extract_timeout
64
+ self.extract_format: Literal["markdown", "text"] = extract_format
35
65
  self.format: Literal["json", "markdown"] = format
36
66
 
37
- if search:
38
- if use_search_context:
39
- self.register(self.web_search_with_tavily)
67
+ tools: List[Any] = []
68
+
69
+ if enable_search or all:
70
+ if enable_search_context:
71
+ tools.append(self.web_search_with_tavily)
40
72
  else:
41
- self.register(self.web_search_using_tavily)
73
+ tools.append(self.web_search_using_tavily)
74
+
75
+ if enable_extract or all:
76
+ tools.append(self.extract_url_content)
77
+
78
+ super().__init__(name="tavily_tools", tools=tools, **kwargs)
42
79
 
43
80
  def web_search_using_tavily(self, query: str, max_results: int = 5) -> str:
44
81
  """Use this function to search the web for a given query.
@@ -102,3 +139,116 @@ class TavilyTools(Toolkit):
102
139
  return self.client.get_search_context(
103
140
  query=query, search_depth=self.search_depth, max_tokens=self.max_tokens, include_answer=self.include_answer
104
141
  )
142
+
143
+ def extract_url_content(self, urls: str) -> str:
144
+ """Extract content from one or more URLs using Tavily's Extract API.
145
+ This function retrieves the main content from web pages in markdown or text format.
146
+
147
+ Args:
148
+ urls (str): Single URL or multiple comma-separated URLs to extract content from.
149
+ Example: "https://example.com" or "https://example.com,https://another.com"
150
+
151
+ Returns:
152
+ str: Extracted content in the specified format (markdown or text).
153
+ For multiple URLs, returns combined content with URL headers.
154
+ Failed extractions are noted in the output.
155
+ """
156
+ # Parse URLs - handle both single and comma-separated multiple URLs
157
+ url_list = [url.strip() for url in urls.split(",") if url.strip()]
158
+
159
+ if not url_list:
160
+ return "Error: No valid URLs provided."
161
+
162
+ try:
163
+ # Prepare extract parameters
164
+ extract_params: Dict[str, Any] = {
165
+ "urls": url_list,
166
+ "depth": self.extract_depth,
167
+ }
168
+
169
+ # Add optional parameters if specified
170
+ if self.include_images:
171
+ extract_params["include_images"] = True
172
+ if self.include_favicon:
173
+ extract_params["include_favicon"] = True
174
+ if self.extract_timeout is not None:
175
+ extract_params["timeout"] = self.extract_timeout
176
+
177
+ # Call Tavily Extract API
178
+ response = self.client.extract(**extract_params)
179
+
180
+ # Process response based on format preference
181
+ if not response or "results" not in response:
182
+ return "Error: No content could be extracted from the provided URL(s)."
183
+
184
+ results = response.get("results", [])
185
+ if not results:
186
+ return "Error: No content could be extracted from the provided URL(s)."
187
+
188
+ # Format output
189
+ if self.extract_format == "markdown":
190
+ return self._format_extract_markdown(results)
191
+ elif self.extract_format == "text":
192
+ return self._format_extract_text(results)
193
+ else:
194
+ # Fallback to JSON if format is unrecognized
195
+ return json.dumps(results, indent=2)
196
+
197
+ except Exception as e:
198
+ logger.error(f"Error extracting content from URLs: {e}")
199
+ return f"Error extracting content: {str(e)}"
200
+
201
+ def _format_extract_markdown(self, results: List[Dict[str, Any]]) -> str:
202
+ """Format extraction results as markdown.
203
+
204
+ Args:
205
+ results: List of extraction result dictionaries from Tavily API.
206
+
207
+ Returns:
208
+ str: Formatted markdown content.
209
+ """
210
+ output = []
211
+
212
+ for result in results:
213
+ url = result.get("url", "Unknown URL")
214
+ raw_content = result.get("raw_content", "")
215
+ failed_reason = result.get("failed_reason")
216
+
217
+ if failed_reason:
218
+ output.append(f"## {url}\n\n **Extraction Failed**: {failed_reason}\n\n")
219
+ elif raw_content:
220
+ output.append(f"## {url}\n\n{raw_content}\n\n")
221
+ else:
222
+ output.append(f"## {url}\n\n*No content available*\n\n")
223
+
224
+ return "".join(output) if output else "No content extracted."
225
+
226
+ def _format_extract_text(self, results: List[Dict[str, Any]]) -> str:
227
+ """Format extraction results as plain text.
228
+
229
+ Args:
230
+ results: List of extraction result dictionaries from Tavily API.
231
+
232
+ Returns:
233
+ str: Formatted plain text content.
234
+ """
235
+ output = []
236
+
237
+ for result in results:
238
+ url = result.get("url", "Unknown URL")
239
+ raw_content = result.get("raw_content", "")
240
+ failed_reason = result.get("failed_reason")
241
+
242
+ output.append(f"URL: {url}")
243
+ output.append("-" * 80)
244
+
245
+ if failed_reason:
246
+ output.append(f"EXTRACTION FAILED: {failed_reason}")
247
+ elif raw_content:
248
+ output.append(raw_content)
249
+ else:
250
+ output.append("No content available")
251
+
252
+ output.append("\n")
253
+
254
+ return "\n".join(output) if output else "No content extracted."
agno/tools/telegram.py CHANGED
@@ -1,25 +1,34 @@
1
- import os
2
- from typing import Optional, Union
1
+ from os import getenv
2
+ from typing import Any, List, Optional, Union
3
3
 
4
4
  import httpx
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
 
10
10
  class TelegramTools(Toolkit):
11
11
  base_url = "https://api.telegram.org"
12
12
 
13
- def __init__(self, chat_id: Union[str, int], token: Optional[str] = None):
14
- super().__init__(name="telegram")
15
-
16
- self.token = token or os.getenv("TELEGRAM_TOKEN")
13
+ def __init__(
14
+ self,
15
+ chat_id: Union[str, int],
16
+ token: Optional[str] = None,
17
+ enable_send_message: bool = True,
18
+ all: bool = False,
19
+ **kwargs,
20
+ ):
21
+ self.token = token or getenv("TELEGRAM_TOKEN")
17
22
  if not self.token:
18
23
  logger.error("TELEGRAM_TOKEN not set. Please set the TELEGRAM_TOKEN environment variable.")
19
24
 
20
25
  self.chat_id = chat_id
21
26
 
22
- self.register(self.send_message)
27
+ tools: List[Any] = []
28
+ if all or enable_send_message:
29
+ tools.append(self.send_message)
30
+
31
+ super().__init__(name="telegram", tools=tools, **kwargs)
23
32
 
24
33
  def _call_post_method(self, method, *args, **kwargs):
25
34
  return httpx.post(f"{self.base_url}/bot{self.token}/{method}", *args, **kwargs)
@@ -30,6 +39,7 @@ class TelegramTools(Toolkit):
30
39
  :param message: The message to send.
31
40
  :return: The response from the API.
32
41
  """
42
+ log_debug(f"Sending telegram message: {message}")
33
43
  response = self._call_post_method("sendMessage", json={"chat_id": self.chat_id, "text": message})
34
44
  try:
35
45
  response.raise_for_status()
agno/tools/todoist.py ADDED
@@ -0,0 +1,218 @@
1
+ import json
2
+ from os import getenv
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ from agno.tools import Toolkit
6
+ from agno.utils.log import logger
7
+
8
+ try:
9
+ from todoist_api_python.api import TodoistAPI
10
+ except ImportError:
11
+ raise ImportError("`todoist-api-python` not installed. Please install using `pip install todoist-api-python`")
12
+
13
+
14
+ class TodoistTools(Toolkit):
15
+ """A toolkit for interacting with Todoist tasks and projects."""
16
+
17
+ def __init__(
18
+ self,
19
+ api_token: Optional[str] = None,
20
+ **kwargs,
21
+ ):
22
+ """Initialize the Todoist toolkit.
23
+
24
+ Args:
25
+ api_token: Optional Todoist API token. If not provided, will look for TODOIST_API_TOKEN env var
26
+ """
27
+ self.api_token = api_token or getenv("TODOIST_API_TOKEN")
28
+ if not self.api_token:
29
+ raise ValueError("TODOIST_API_TOKEN not set. Please set the TODOIST_API_TOKEN environment variable.")
30
+
31
+ self.api = TodoistAPI(self.api_token)
32
+
33
+ tools: List[Any] = [
34
+ self.create_task,
35
+ self.get_task,
36
+ self.update_task,
37
+ self.close_task,
38
+ self.delete_task,
39
+ self.get_active_tasks,
40
+ self.get_projects,
41
+ ]
42
+
43
+ super().__init__(name="todoist", tools=tools, **kwargs)
44
+
45
+ def _task_to_dict(self, task: Any) -> Dict[str, Any]:
46
+ """Convert a Todoist task to a dictionary with proper typing."""
47
+ task_dict: Dict[str, Any] = {
48
+ "id": task.id,
49
+ "content": task.content,
50
+ "description": task.description,
51
+ "project_id": task.project_id,
52
+ "section_id": task.section_id,
53
+ "parent_id": task.parent_id,
54
+ "order": task.order,
55
+ "priority": task.priority,
56
+ "url": task.url,
57
+ "creator_id": task.creator_id,
58
+ "created_at": task.created_at,
59
+ "labels": task.labels,
60
+ }
61
+ if hasattr(task, "comment_count"):
62
+ task_dict["comment_count"] = task.comment_count
63
+ if task.due:
64
+ task_dict["due"] = {
65
+ "date": task.due.date,
66
+ "string": task.due.string,
67
+ "lang": task.due.lang,
68
+ "is_recurring": task.due.is_recurring,
69
+ "timezone": task.due.timezone,
70
+ }
71
+ return task_dict
72
+
73
+ def create_task(
74
+ self,
75
+ content: str,
76
+ project_id: Optional[str] = None,
77
+ due_string: Optional[str] = None,
78
+ priority: Optional[int] = None,
79
+ labels: Optional[List[str]] = None,
80
+ ) -> str:
81
+ """
82
+ Create a new task in Todoist.
83
+
84
+ Args:
85
+ content: The task content/description
86
+ project_id: Optional ID of the project to add the task to
87
+ due_string: Optional due date in natural language (e.g., "tomorrow at 12:00")
88
+ priority: Optional priority level (1-4, where 4 is highest)
89
+ labels: Optional list of label names to apply to the task
90
+
91
+ Returns:
92
+ str: JSON string containing the created task
93
+ """
94
+ try:
95
+ task = self.api.add_task(
96
+ content=content, project_id=project_id, due_string=due_string, priority=priority, labels=labels or []
97
+ )
98
+ # Convert task to a dictionary and handle the Due object
99
+ task_dict = self._task_to_dict(task)
100
+ return json.dumps(task_dict, default=str)
101
+ except Exception as e:
102
+ logger.error(f"Failed to create task: {str(e)}")
103
+ return json.dumps({"error": str(e)})
104
+
105
+ def get_task(self, task_id: str) -> str:
106
+ """Get a specific task by ID."""
107
+ try:
108
+ task = self.api.get_task(task_id)
109
+ task_dict = self._task_to_dict(task)
110
+ return json.dumps(task_dict, default=str)
111
+ except Exception as e:
112
+ logger.error(f"Failed to get task: {str(e)}")
113
+ return json.dumps({"error": str(e)})
114
+
115
+ def update_task(
116
+ self,
117
+ task_id: str,
118
+ content: Optional[str] = None,
119
+ description: Optional[str] = None,
120
+ labels: Optional[List[str]] = None,
121
+ priority: Optional[int] = None,
122
+ due_string: Optional[str] = None,
123
+ due_date: Optional[str] = None,
124
+ due_datetime: Optional[str] = None,
125
+ due_lang: Optional[str] = None,
126
+ assignee_id: Optional[str] = None,
127
+ section_id: Optional[str] = None,
128
+ ) -> str:
129
+ """
130
+ Update an existing task with the specified parameters.
131
+
132
+ Args:
133
+ task_id: The ID of the task to update
134
+ content: The task content/name
135
+ description: The task description
136
+ labels: Array of label names
137
+ priority: Task priority from 1 (normal) to 4 (urgent)
138
+ due_string: Human readable date ("next Monday", "tomorrow", etc)
139
+ due_date: Specific date in YYYY-MM-DD format
140
+ due_datetime: Specific date and time in RFC3339 format
141
+ due_lang: 2-letter code specifying language of due_string ("en", "fr", etc)
142
+ assignee_id: The responsible user ID
143
+ section_id: ID of the section to move task to
144
+
145
+ Returns:
146
+ str: JSON string containing success status or error message
147
+ """
148
+ try:
149
+ # Build updates dictionary with only provided parameters
150
+ updates: Dict[str, Any] = {}
151
+ if content is not None:
152
+ updates["content"] = content
153
+ if description is not None:
154
+ updates["description"] = description
155
+ if labels is not None:
156
+ updates["labels"] = labels
157
+ if priority is not None:
158
+ updates["priority"] = priority
159
+ if due_string is not None:
160
+ updates["due_string"] = due_string
161
+ if due_date is not None:
162
+ updates["due_date"] = due_date
163
+ if due_datetime is not None:
164
+ updates["due_datetime"] = due_datetime
165
+ if due_lang is not None:
166
+ updates["due_lang"] = due_lang
167
+ if assignee_id is not None:
168
+ updates["assignee_id"] = assignee_id
169
+ if section_id is not None:
170
+ updates["section_id"] = section_id
171
+
172
+ success = self.api.update_task(task_id=task_id, **updates)
173
+ return json.dumps({"success": success})
174
+ except Exception as e:
175
+ error_msg = str(e)
176
+ logger.error(f"Failed to update task: {error_msg}")
177
+ return json.dumps({"error": error_msg})
178
+
179
+ def close_task(self, task_id: str) -> str:
180
+ """Mark a task as completed."""
181
+ try:
182
+ success = self.api.complete_task(task_id)
183
+ return json.dumps({"success": success})
184
+ except Exception as e:
185
+ logger.error(f"Failed to close task: {str(e)}")
186
+ return json.dumps({"error": str(e)})
187
+
188
+ def delete_task(self, task_id: str) -> str:
189
+ """Delete a task."""
190
+ try:
191
+ success = self.api.delete_task(task_id)
192
+ return json.dumps({"success": success})
193
+ except Exception as e:
194
+ logger.error(f"Failed to delete task: {str(e)}")
195
+ return json.dumps({"error": str(e)})
196
+
197
+ def get_active_tasks(self) -> str:
198
+ """Get all active (not completed) tasks."""
199
+ try:
200
+ tasks_response = self.api.get_tasks()
201
+ tasks = list(tasks_response)[0]
202
+ tasks_list = []
203
+ for task in tasks:
204
+ task_dict = self._task_to_dict(task)
205
+ tasks_list.append(task_dict)
206
+ return json.dumps(tasks_list, default=str)
207
+ except Exception as e:
208
+ logger.error(f"Failed to get active tasks: {str(e)}")
209
+ return json.dumps({"error": str(e)})
210
+
211
+ def get_projects(self) -> str:
212
+ """Get all projects."""
213
+ try:
214
+ projects = self.api.get_projects()
215
+ return json.dumps([project.__dict__ for project in projects])
216
+ except Exception as e:
217
+ logger.error(f"Failed to get projects: {str(e)}")
218
+ return json.dumps({"error": str(e)})