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/toolkit.py CHANGED
@@ -1,43 +1,168 @@
1
1
  from collections import OrderedDict
2
- from typing import Any, Callable, Dict
2
+ from typing import Any, Callable, Dict, List, Optional
3
3
 
4
4
  from agno.tools.function import Function
5
- from agno.utils.log import logger
5
+ from agno.utils.log import log_debug, log_warning, logger
6
6
 
7
7
 
8
8
  class Toolkit:
9
- def __init__(self, name: str = "toolkit"):
9
+ # Set to True for toolkits that require connection management (e.g., database connections)
10
+ # When True, the Agent will automatically call connect() before using tools and close() after
11
+ _requires_connect: bool = False
12
+
13
+ def __init__(
14
+ self,
15
+ name: str = "toolkit",
16
+ tools: List[Callable] = [],
17
+ instructions: Optional[str] = None,
18
+ add_instructions: bool = False,
19
+ include_tools: Optional[list[str]] = None,
20
+ exclude_tools: Optional[list[str]] = None,
21
+ requires_confirmation_tools: Optional[list[str]] = None,
22
+ external_execution_required_tools: Optional[list[str]] = None,
23
+ stop_after_tool_call_tools: Optional[List[str]] = None,
24
+ show_result_tools: Optional[List[str]] = None,
25
+ cache_results: bool = False,
26
+ cache_ttl: int = 3600,
27
+ cache_dir: Optional[str] = None,
28
+ auto_register: bool = True,
29
+ ):
10
30
  """Initialize a new Toolkit.
11
31
 
12
32
  Args:
13
33
  name: A descriptive name for the toolkit
34
+ tools: List of tools to include in the toolkit
35
+ instructions: Instructions for the toolkit
36
+ add_instructions: Whether to add instructions to the toolkit
37
+ include_tools: List of tool names to include in the toolkit
38
+ exclude_tools: List of tool names to exclude from the toolkit
39
+ requires_confirmation_tools: List of tool names that require user confirmation
40
+ external_execution_required_tools: List of tool names that will be executed outside of the agent loop
41
+ cache_results (bool): Enable in-memory caching of function results.
42
+ cache_ttl (int): Time-to-live for cached results in seconds.
43
+ cache_dir (Optional[str]): Directory to store cache files. Defaults to system temp dir.
44
+ auto_register (bool): Whether to automatically register all methods in the class.
45
+ stop_after_tool_call_tools (Optional[List[str]]): List of function names that should stop the agent after execution.
46
+ show_result_tools (Optional[List[str]]): List of function names whose results should be shown.
14
47
  """
15
48
  self.name: str = name
49
+ self.tools: List[Callable] = tools
16
50
  self.functions: Dict[str, Function] = OrderedDict()
51
+ self.instructions: Optional[str] = instructions
52
+ self.add_instructions: bool = add_instructions
53
+
54
+ self.requires_confirmation_tools: list[str] = requires_confirmation_tools or []
55
+ self.external_execution_required_tools: list[str] = external_execution_required_tools or []
56
+
57
+ self.stop_after_tool_call_tools: list[str] = stop_after_tool_call_tools or []
58
+ self.show_result_tools: list[str] = show_result_tools or []
59
+
60
+ self._check_tools_filters(
61
+ available_tools=[tool.__name__ for tool in tools], include_tools=include_tools, exclude_tools=exclude_tools
62
+ )
63
+
64
+ self.include_tools = include_tools
65
+ self.exclude_tools = exclude_tools
66
+
67
+ self.cache_results: bool = cache_results
68
+ self.cache_ttl: int = cache_ttl
69
+ self.cache_dir: Optional[str] = cache_dir
70
+
71
+ # Automatically register all methods if auto_register is True
72
+ if auto_register and self.tools:
73
+ self._register_tools()
74
+
75
+ def _check_tools_filters(
76
+ self,
77
+ available_tools: List[str],
78
+ include_tools: Optional[list[str]] = None,
79
+ exclude_tools: Optional[list[str]] = None,
80
+ ) -> None:
81
+ """Check if `include_tools` and `exclude_tools` are valid"""
82
+ if include_tools or exclude_tools:
83
+ if include_tools:
84
+ missing_includes = set(include_tools) - set(available_tools)
85
+ if missing_includes:
86
+ raise ValueError(f"Included tool(s) not present in the toolkit: {', '.join(missing_includes)}")
87
+
88
+ if exclude_tools:
89
+ missing_excludes = set(exclude_tools) - set(available_tools)
90
+ if missing_excludes:
91
+ raise ValueError(f"Excluded tool(s) not present in the toolkit: {', '.join(missing_excludes)}")
92
+
93
+ if self.requires_confirmation_tools:
94
+ missing_requires_confirmation = set(self.requires_confirmation_tools) - set(available_tools)
95
+ if missing_requires_confirmation:
96
+ log_warning(
97
+ f"Requires confirmation tool(s) not present in the toolkit: {', '.join(missing_requires_confirmation)}"
98
+ )
17
99
 
18
- def register(self, function: Callable[..., Any], sanitize_arguments: bool = True):
100
+ if self.external_execution_required_tools:
101
+ missing_external_execution_required = set(self.external_execution_required_tools) - set(available_tools)
102
+ if missing_external_execution_required:
103
+ log_warning(
104
+ f"External execution required tool(s) not present in the toolkit: {', '.join(missing_external_execution_required)}"
105
+ )
106
+
107
+ def _register_tools(self) -> None:
108
+ """Register all tools."""
109
+ for tool in self.tools:
110
+ self.register(tool)
111
+
112
+ def register(self, function: Callable[..., Any], name: Optional[str] = None):
19
113
  """Register a function with the toolkit.
20
114
 
21
115
  Args:
22
116
  function: The callable to register
117
+ name: Optional custom name for the function
23
118
 
24
119
  Returns:
25
120
  The registered function
26
121
  """
27
122
  try:
123
+ tool_name = name or function.__name__
124
+ if self.include_tools is not None and tool_name not in self.include_tools:
125
+ return
126
+ if self.exclude_tools is not None and tool_name in self.exclude_tools:
127
+ return
128
+
28
129
  f = Function(
29
- name=function.__name__,
130
+ name=tool_name,
30
131
  entrypoint=function,
31
- sanitize_arguments=sanitize_arguments,
132
+ cache_results=self.cache_results,
133
+ cache_dir=self.cache_dir,
134
+ cache_ttl=self.cache_ttl,
135
+ requires_confirmation=tool_name in self.requires_confirmation_tools,
136
+ external_execution=tool_name in self.external_execution_required_tools,
137
+ stop_after_tool_call=tool_name in self.stop_after_tool_call_tools,
138
+ show_result=tool_name in self.show_result_tools or tool_name in self.stop_after_tool_call_tools,
32
139
  )
33
140
  self.functions[f.name] = f
34
- logger.debug(f"Function: {f.name} registered with {self.name}")
141
+ log_debug(f"Function: {f.name} registered with {self.name}")
35
142
  except Exception as e:
36
143
  logger.warning(f"Failed to create Function for: {function.__name__}")
37
144
  raise e
38
145
 
39
- def instructions(self) -> str:
40
- return ""
146
+ @property
147
+ def requires_connect(self) -> bool:
148
+ """Whether the toolkit requires connection management."""
149
+ return self._requires_connect
150
+
151
+ def connect(self) -> None:
152
+ """
153
+ Establish any required connections for the toolkit.
154
+ Override this method in subclasses that require connection management.
155
+ Called automatically by the Agent when _requires_connect is True.
156
+ """
157
+ pass
158
+
159
+ def close(self) -> None:
160
+ """
161
+ Close any open connections for the toolkit.
162
+ Override this method in subclasses that require connection management.
163
+ Called automatically by the Agent when _requires_connect is True.
164
+ """
165
+ pass
41
166
 
42
167
  def __repr__(self):
43
168
  return f"<{self.__class__.__name__} name={self.name} functions={list(self.functions.keys())}>"
@@ -0,0 +1,388 @@
1
+ import json
2
+ from typing import Any, Callable, Dict, List, Optional, Set
3
+
4
+ from agno.tools import Toolkit
5
+ from agno.utils.log import log_debug, logger
6
+
7
+ try:
8
+ from trafilatura import (
9
+ extract,
10
+ extract_metadata,
11
+ fetch_url,
12
+ html2txt,
13
+ )
14
+ from trafilatura.meta import reset_caches
15
+
16
+ # Import spider functionality
17
+ try:
18
+ from trafilatura.spider import focused_crawler
19
+
20
+ SPIDER_AVAILABLE = True
21
+ except ImportError:
22
+ SPIDER_AVAILABLE = False
23
+ logger.warning("Trafilatura spider module not available. Web crawling functionality will be disabled.")
24
+
25
+ except ImportError:
26
+ raise ImportError("`trafilatura` not installed. Please install using `pip install trafilatura`")
27
+
28
+
29
+ class TrafilaturaTools(Toolkit):
30
+ """
31
+ TrafilaturaTools is a toolkit for web scraping and text extraction.
32
+
33
+ Args:
34
+ output_format (str): Default output format for extractions. Options: 'txt', 'json', 'xml', 'markdown', 'csv', 'html', 'xmltei'.
35
+ include_comments (bool): Whether to extract comments along with main text by default.
36
+ include_tables (bool): Whether to include table content by default.
37
+ include_images (bool): Whether to include image information by default (experimental).
38
+ include_formatting (bool): Whether to preserve formatting by default.
39
+ include_links (bool): Whether to preserve links by default (experimental).
40
+ with_metadata (bool): Whether to include metadata in extractions by default.
41
+ favor_precision (bool): Whether to prefer precision over recall by default.
42
+ favor_recall (bool): Whether to prefer recall over precision by default.
43
+ target_language (Optional[str]): Default target language filter (ISO 639-1 format).
44
+ deduplicate (bool): Whether to remove duplicate segments by default.
45
+ max_tree_size (Optional[int]): Maximum tree size for processing.
46
+ max_crawl_urls (int): Maximum number of URLs to crawl per website.
47
+ max_known_urls (int): Maximum number of known URLs during crawling.
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ output_format: str = "txt",
53
+ include_comments: bool = True,
54
+ include_tables: bool = True,
55
+ include_images: bool = False,
56
+ include_formatting: bool = False,
57
+ include_links: bool = False,
58
+ with_metadata: bool = False,
59
+ favor_precision: bool = False,
60
+ favor_recall: bool = False,
61
+ target_language: Optional[str] = None,
62
+ deduplicate: bool = False,
63
+ max_tree_size: Optional[int] = None,
64
+ max_crawl_urls: int = 10,
65
+ max_known_urls: int = 100000,
66
+ # Tool enable flags for <6 functions
67
+ enable_extract_text: bool = True,
68
+ enable_extract_metadata_only: bool = True,
69
+ enable_html_to_text: bool = True,
70
+ enable_extract_batch: bool = True,
71
+ enable_crawl_website: bool = True,
72
+ all: bool = False,
73
+ **kwargs,
74
+ ):
75
+ self.output_format = output_format
76
+ self.include_comments = include_comments
77
+ self.include_tables = include_tables
78
+ self.include_images = include_images
79
+ self.include_formatting = include_formatting
80
+ self.include_links = include_links
81
+ self.with_metadata = with_metadata
82
+ self.favor_precision = favor_precision
83
+ self.favor_recall = favor_recall
84
+ self.target_language = target_language
85
+ self.deduplicate = deduplicate
86
+ self.max_tree_size = max_tree_size
87
+ self.max_crawl_urls = max_crawl_urls
88
+ self.max_known_urls = max_known_urls
89
+
90
+ tools: List[Callable] = []
91
+ if all or enable_extract_text:
92
+ tools.append(self.extract_text)
93
+ if all or enable_extract_metadata_only:
94
+ tools.append(self.extract_metadata_only)
95
+ if all or enable_html_to_text:
96
+ tools.append(self.html_to_text)
97
+ if all or enable_extract_batch:
98
+ tools.append(self.extract_batch)
99
+
100
+ if all or enable_crawl_website:
101
+ if not SPIDER_AVAILABLE:
102
+ logger.warning("Web crawling requested but spider module not available. Skipping crawler tool.")
103
+ else:
104
+ tools.append(self.crawl_website)
105
+
106
+ super().__init__(name="trafilatura_tools", tools=tools, **kwargs)
107
+
108
+ def _get_extraction_params(
109
+ self,
110
+ output_format: Optional[str] = None,
111
+ include_comments: Optional[bool] = None,
112
+ include_tables: Optional[bool] = None,
113
+ include_images: Optional[bool] = None,
114
+ include_formatting: Optional[bool] = None,
115
+ include_links: Optional[bool] = None,
116
+ with_metadata: Optional[bool] = None,
117
+ favor_precision: Optional[bool] = None,
118
+ favor_recall: Optional[bool] = None,
119
+ target_language: Optional[str] = None,
120
+ deduplicate: Optional[bool] = None,
121
+ max_tree_size: Optional[int] = None,
122
+ url_blacklist: Optional[Set[str]] = None,
123
+ author_blacklist: Optional[Set[str]] = None,
124
+ ) -> Dict[str, Any]:
125
+ """Helper method to build extraction parameters with fallbacks to instance defaults."""
126
+ return {
127
+ "output_format": output_format if output_format is not None else self.output_format,
128
+ "include_comments": include_comments if include_comments is not None else self.include_comments,
129
+ "include_tables": include_tables if include_tables is not None else self.include_tables,
130
+ "include_images": include_images if include_images is not None else self.include_images,
131
+ "include_formatting": include_formatting if include_formatting is not None else self.include_formatting,
132
+ "include_links": include_links if include_links is not None else self.include_links,
133
+ "with_metadata": with_metadata if with_metadata is not None else self.with_metadata,
134
+ "favor_precision": favor_precision if favor_precision is not None else self.favor_precision,
135
+ "favor_recall": favor_recall if favor_recall is not None else self.favor_recall,
136
+ "target_language": target_language if target_language is not None else self.target_language,
137
+ "deduplicate": deduplicate if deduplicate is not None else self.deduplicate,
138
+ "max_tree_size": max_tree_size if max_tree_size is not None else self.max_tree_size,
139
+ "url_blacklist": url_blacklist,
140
+ "author_blacklist": author_blacklist,
141
+ }
142
+
143
+ def extract_text(
144
+ self,
145
+ url: str,
146
+ output_format: Optional[str] = None,
147
+ ) -> str:
148
+ """
149
+ Extract main text content from a web page URL using Trafilatura.
150
+
151
+ Args:
152
+ url (str): The URL to extract content from.
153
+ output_format (Optional[str]): Output format. Options: 'txt', 'json', 'xml', 'markdown', 'csv', 'html', 'xmltei'.
154
+
155
+ Returns:
156
+ str: Extracted content in the specified format, or error message if extraction fails.
157
+ """
158
+ try:
159
+ log_debug(f"Extracting text from URL: {url}")
160
+
161
+ # Fetch the webpage content
162
+ html_content = fetch_url(url)
163
+ if not html_content:
164
+ return f"Error: Could not fetch content from URL: {url}"
165
+
166
+ # Get extraction parameters
167
+ params = self._get_extraction_params(output_format=output_format)
168
+
169
+ result = extract(html_content, url=url, **params)
170
+
171
+ if result is None:
172
+ return f"Error: Could not extract readable content from URL: {url}"
173
+
174
+ # Reset caches
175
+ reset_caches()
176
+
177
+ return result
178
+
179
+ except Exception as e:
180
+ logger.warning(f"Error extracting text from {url}: {e}")
181
+ return f"Error extracting text from {url}: {e}"
182
+
183
+ def extract_metadata_only(
184
+ self,
185
+ url: str,
186
+ as_json: bool = True,
187
+ ) -> str:
188
+ """
189
+ Extract only metadata from a web page URL.
190
+
191
+ Args:
192
+ url (str): The URL to extract metadata from.
193
+ as_json (bool): Whether to return metadata as JSON string.
194
+
195
+ Returns:
196
+ str: Extracted metadata as JSON string or formatted text.
197
+ """
198
+ try:
199
+ log_debug(f"Extracting metadata from URL: {url}")
200
+
201
+ # Fetch the webpage content
202
+ html_content = fetch_url(url)
203
+ if not html_content:
204
+ return f"Error: Could not fetch content from URL: {url}"
205
+
206
+ # Extract metadata
207
+ metadata_doc = extract_metadata(
208
+ html_content,
209
+ default_url=url,
210
+ extensive=True, # default
211
+ author_blacklist=None,
212
+ )
213
+
214
+ if metadata_doc is None:
215
+ return f"Error: Could not extract metadata from URL: {url}"
216
+
217
+ metadata_dict = metadata_doc.as_dict()
218
+
219
+ # Reset caches
220
+ reset_caches()
221
+
222
+ if as_json:
223
+ return json.dumps(metadata_dict, indent=2, default=str)
224
+ else:
225
+ return "\n".join(f"{key}: {value}" for key, value in metadata_dict.items())
226
+
227
+ except Exception as e:
228
+ logger.warning(f"Error extracting metadata from {url}: {e}")
229
+ return f"Error extracting metadata from {url}: {e}"
230
+
231
+ def crawl_website(
232
+ self,
233
+ homepage_url: str,
234
+ extract_content: bool = False,
235
+ ) -> str:
236
+ """
237
+ Crawl a website and optionally extract content from discovered pages.
238
+
239
+ Args:
240
+ homepage_url (str): The starting URL (preferably homepage) to crawl from.
241
+ extract_content (bool): Whether to extract content from discovered URLs.
242
+
243
+ Returns:
244
+ str: JSON containing crawl results and optionally extracted content.
245
+ """
246
+ if not SPIDER_AVAILABLE:
247
+ return "Error: Web crawling functionality not available. Trafilatura spider module could not be imported."
248
+
249
+ try:
250
+ log_debug(f"Starting website crawl from: {homepage_url}")
251
+
252
+ # Use instance configuration
253
+ max_seen = self.max_crawl_urls
254
+ max_known = self.max_known_urls
255
+ lang = self.target_language
256
+
257
+ # Perform focused crawling
258
+ to_visit, known_links = focused_crawler(
259
+ homepage=homepage_url,
260
+ max_seen_urls=max_seen,
261
+ max_known_urls=max_known,
262
+ lang=lang,
263
+ )
264
+
265
+ crawl_results = {
266
+ "homepage": homepage_url,
267
+ "to_visit": list(to_visit) if to_visit else [],
268
+ "known_links": list(known_links) if known_links else [],
269
+ "stats": {
270
+ "urls_to_visit": len(to_visit) if to_visit else 0,
271
+ "known_links_count": len(known_links) if known_links else 0,
272
+ },
273
+ }
274
+
275
+ # Optionally extract content from discovered URLs
276
+ if extract_content and known_links:
277
+ log_debug("Extracting content from discovered URLs")
278
+ extracted_content = {}
279
+
280
+ # Limit extraction to avoid overwhelming responses
281
+ urls_to_extract = list(known_links)[: min(10, len(known_links))]
282
+
283
+ for url in urls_to_extract:
284
+ try:
285
+ params = self._get_extraction_params()
286
+
287
+ html_content = fetch_url(url)
288
+ if html_content:
289
+ content = extract(html_content, url=url, **params)
290
+ if content:
291
+ extracted_content[url] = content
292
+ except Exception as e:
293
+ extracted_content[url] = f"Error extracting content: {e}"
294
+
295
+ crawl_results["extracted_content"] = extracted_content
296
+
297
+ # Reset caches
298
+ reset_caches()
299
+
300
+ return json.dumps(crawl_results, indent=2, default=str)
301
+
302
+ except Exception as e:
303
+ logger.warning(f"Error crawling website {homepage_url}: {e}")
304
+ return f"Error crawling website {homepage_url}: {e}"
305
+
306
+ def html_to_text(
307
+ self,
308
+ html_content: str,
309
+ clean: bool = True,
310
+ ) -> str:
311
+ """
312
+ Convert HTML content to plain text using Trafilatura's html2txt function.
313
+
314
+ Args:
315
+ html_content (str): The HTML content to convert.
316
+ clean (bool): Whether to remove potentially undesirable elements.
317
+
318
+ Returns:
319
+ str: Plain text extracted from HTML.
320
+ """
321
+ try:
322
+ log_debug("Converting HTML to text")
323
+
324
+ result = html2txt(html_content, clean=clean)
325
+
326
+ # Reset caches
327
+ reset_caches()
328
+
329
+ return result if result else "Error: Could not extract text from HTML content"
330
+
331
+ except Exception as e:
332
+ logger.warning(f"Error converting HTML to text: {e}")
333
+ return f"Error converting HTML to text: {e}"
334
+
335
+ def extract_batch(
336
+ self,
337
+ urls: List[str],
338
+ ) -> str:
339
+ """
340
+ Extract content from multiple URLs in batch.
341
+
342
+ Args:
343
+ urls (List[str]): List of URLs to extract content from.
344
+
345
+ Returns:
346
+ str: JSON containing batch extraction results.
347
+ """
348
+ try:
349
+ log_debug(f"Starting batch extraction for {len(urls)} URLs")
350
+
351
+ results = {}
352
+ failed_urls = []
353
+
354
+ for url in urls:
355
+ try:
356
+ params = self._get_extraction_params()
357
+
358
+ html_content = fetch_url(url)
359
+ if html_content:
360
+ content = extract(html_content, url=url, **params)
361
+ if content:
362
+ results[url] = content
363
+ else:
364
+ failed_urls.append(url)
365
+ else:
366
+ failed_urls.append(url)
367
+
368
+ except Exception as e:
369
+ failed_urls.append(url)
370
+ results[url] = f"Error: {e}"
371
+
372
+ # Reset caches after batch processing
373
+ reset_caches()
374
+
375
+ batch_results = {
376
+ "successful_extractions": len(results)
377
+ - len([k for k, v in results.items() if str(v).startswith("Error:")]),
378
+ "failed_extractions": len(failed_urls),
379
+ "total_urls": len(urls),
380
+ "results": results,
381
+ "failed_urls": failed_urls,
382
+ }
383
+
384
+ return json.dumps(batch_results, indent=2, default=str)
385
+
386
+ except Exception as e:
387
+ logger.warning(f"Error in batch extraction: {e}")
388
+ return f"Error in batch extraction: {e}"
agno/tools/trello.py CHANGED
@@ -1,9 +1,9 @@
1
1
  import json
2
2
  from os import getenv
3
- from typing import Optional
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
  from trello import TrelloClient # type: ignore
@@ -17,16 +17,8 @@ class TrelloTools(Toolkit):
17
17
  api_key: Optional[str] = None,
18
18
  api_secret: Optional[str] = None,
19
19
  token: Optional[str] = None,
20
- create_card: bool = True,
21
- get_board_lists: bool = True,
22
- move_card: bool = True,
23
- get_cards: bool = True,
24
- create_board: bool = True,
25
- create_list: bool = True,
26
- list_boards: bool = True,
20
+ **kwargs,
27
21
  ):
28
- super().__init__(name="trello")
29
-
30
22
  self.api_key = api_key or getenv("TRELLO_API_KEY")
31
23
  self.api_secret = api_secret or getenv("TRELLO_API_SECRET")
32
24
  self.token = token or getenv("TRELLO_TOKEN")
@@ -40,20 +32,17 @@ class TrelloTools(Toolkit):
40
32
  logger.error(f"Error initializing Trello client: {e}")
41
33
  self.client = None
42
34
 
43
- if create_card:
44
- self.register(self.create_card)
45
- if get_board_lists:
46
- self.register(self.get_board_lists)
47
- if move_card:
48
- self.register(self.move_card)
49
- if get_cards:
50
- self.register(self.get_cards)
51
- if create_board:
52
- self.register(self.create_board)
53
- if create_list:
54
- self.register(self.create_list)
55
- if list_boards:
56
- self.register(self.list_boards)
35
+ tools: List[Any] = [
36
+ self.create_card,
37
+ self.get_board_lists,
38
+ self.move_card,
39
+ self.get_cards,
40
+ self.create_board,
41
+ self.create_list,
42
+ self.list_boards,
43
+ ]
44
+
45
+ super().__init__(name="trello", tools=tools, **kwargs)
57
46
 
58
47
  def create_card(self, board_id: str, list_name: str, card_title: str, description: str = "") -> str:
59
48
  """
@@ -72,7 +61,7 @@ class TrelloTools(Toolkit):
72
61
  if not self.client:
73
62
  return "Trello client not initialized"
74
63
 
75
- logger.info(f"Creating card {card_title}")
64
+ log_info(f"Creating card {card_title}")
76
65
 
77
66
  board = self.client.get_board(board_id)
78
67
  target_list = None
@@ -106,6 +95,8 @@ class TrelloTools(Toolkit):
106
95
  if not self.client:
107
96
  return "Trello client not initialized"
108
97
 
98
+ log_debug(f"Getting lists for board {board_id}")
99
+
109
100
  board = self.client.get_board(board_id)
110
101
  lists = board.list_lists()
111
102
 
@@ -131,6 +122,8 @@ class TrelloTools(Toolkit):
131
122
  if not self.client:
132
123
  return "Trello client not initialized"
133
124
 
125
+ log_debug(f"Moving card {card_id} to list {list_id}")
126
+
134
127
  card = self.client.get_card(card_id)
135
128
  card.change_list(list_id)
136
129
 
@@ -153,6 +146,8 @@ class TrelloTools(Toolkit):
153
146
  if not self.client:
154
147
  return "Trello client not initialized"
155
148
 
149
+ log_debug(f"Getting cards for list {list_id}")
150
+
156
151
  trello_list = self.client.get_list(list_id)
157
152
  cards = trello_list.list_cards()
158
153
 
@@ -187,7 +182,7 @@ class TrelloTools(Toolkit):
187
182
  if not self.client:
188
183
  return "Trello client not initialized"
189
184
 
190
- logger.info(f"Creating board {name}")
185
+ log_info(f"Creating board {name}")
191
186
 
192
187
  board = self.client.add_board(board_name=name, default_lists=default_lists)
193
188
 
@@ -218,7 +213,7 @@ class TrelloTools(Toolkit):
218
213
  if not self.client:
219
214
  return "Trello client not initialized"
220
215
 
221
- logger.info(f"Creating list {list_name}")
216
+ log_info(f"Creating list {list_name}")
222
217
 
223
218
  board = self.client.get_board(board_id)
224
219
  new_list = board.add_list(name=list_name, pos=pos)
@@ -250,6 +245,8 @@ class TrelloTools(Toolkit):
250
245
  if not self.client:
251
246
  return "Trello client not initialized"
252
247
 
248
+ log_debug(f"Listing boards with filter: {board_filter}")
249
+
253
250
  boards = self.client.list_boards(board_filter=board_filter)
254
251
 
255
252
  boards_list = []