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/apify.py CHANGED
@@ -1,121 +1,314 @@
1
+ import json
2
+ import string
1
3
  from os import getenv
2
- from typing import List, Optional
4
+ from typing import Any, Dict, List, Optional, Tuple, Union
5
+
6
+ import requests
3
7
 
4
8
  from agno.tools import Toolkit
5
- from agno.utils.log import logger
9
+ from agno.utils.log import log_info, logger
6
10
 
7
11
  try:
8
12
  from apify_client import ApifyClient
9
13
  except ImportError:
10
- raise ImportError("`apify_client` not installed. Please install using `pip install apify-client`")
14
+ raise ImportError("`apify-client` not installed. Please install using `pip install apify-client`")
11
15
 
12
16
 
13
17
  class ApifyTools(Toolkit):
14
- def __init__(
15
- self,
16
- api_key: Optional[str] = None,
17
- website_content_crawler: bool = True,
18
- web_scraper: bool = False,
19
- ):
20
- super().__init__(name="apify_tools")
21
-
22
- self.api_key = api_key or getenv("MY_APIFY_TOKEN")
23
- if not self.api_key:
24
- logger.error("No Apify API key provided")
25
-
26
- if website_content_crawler:
27
- self.register(self.website_content_crawler)
28
- if web_scraper:
29
- self.register(self.web_scrapper)
30
-
31
- def website_content_crawler(self, urls: List[str], timeout: Optional[int] = 60) -> str:
18
+ def __init__(self, actors: Optional[Union[str, List[str]]] = None, apify_api_token: Optional[str] = None):
19
+ """Initialize ApifyTools with specific Actors.
20
+
21
+ Args:
22
+ actors (Optional[Union[str, List[str]]]): Single Actor ID as string or list of Actor IDs to register as individual tools
23
+ apify_api_token (Optional[str]): Apify API token (defaults to APIFY_API_TOKEN env variable)
32
24
  """
33
- Crawls a website using Apify's website-content-crawler actor.
25
+ # Get API token from args or environment
26
+ self.apify_api_token = apify_api_token or getenv("APIFY_API_TOKEN")
27
+ if not self.apify_api_token:
28
+ raise ValueError("APIFY_API_TOKEN environment variable or apify_api_token parameter must be set")
29
+
30
+ self.client = create_apify_client(self.apify_api_token)
31
+
32
+ tools: List[Any] = []
33
+ if actors:
34
+ actor_list = [actors] if isinstance(actors, str) else actors
35
+ for actor_id in actor_list:
36
+ tools.append(actor_id)
37
+
38
+ super().__init__(name="ApifyTools", tools=[], auto_register=False)
39
+
40
+ for actor_id in tools:
41
+ self.register_actor(actor_id)
34
42
 
35
- :param urls: The URLs to crawl.
36
- :param timeout: The timeout for the crawling.
43
+ def register_actor(self, actor_id: str) -> None:
44
+ """Register an Apify Actor as a function in the toolkit.
37
45
 
38
- :return: The results of the crawling.
46
+ Args:
47
+ actor_id (str): ID of the Apify Actor to register (e.g., 'apify/web-scraper')
39
48
  """
40
- if self.api_key is None:
41
- return "No API key provided"
49
+ try:
50
+ # Get actor metadata
51
+ build = get_actor_latest_build(self.client, actor_id)
52
+ tool_name = actor_id_to_tool_name(actor_id)
53
+
54
+ # Get actor description
55
+ actor_description = build.get("actorDefinition", {}).get("description", "")
56
+ if len(actor_description) > MAX_DESCRIPTION_LEN:
57
+ actor_description = actor_description[:MAX_DESCRIPTION_LEN] + "...(TRUNCATED, TOO LONG)"
58
+
59
+ # Get input schema
60
+ actor_input = build.get("actorDefinition", {}).get("input")
61
+ if not actor_input:
62
+ raise ValueError(f"Input schema not found in the Actor build for Actor: {actor_id}")
63
+
64
+ properties, required = prune_actor_input_schema(actor_input)
65
+
66
+ # Create a wrapper function that calls the Actor
67
+ def actor_function(**kwargs) -> str:
68
+ """Actor function wrapper."""
69
+ try:
70
+ # Params are nested under 'kwargs' key
71
+ if len(kwargs) == 1 and "kwargs" in kwargs:
72
+ kwargs = kwargs["kwargs"]
73
+
74
+ log_info(f"Running Apify Actor {actor_id} with parameters: {kwargs}")
75
+
76
+ # Run the Actor directly with the client
77
+ details = self.client.actor(actor_id=actor_id).call(run_input=kwargs)
78
+ if details is None:
79
+ error_msg = (
80
+ f"Actor: {actor_id} was not started properly and details about the run were not returned"
81
+ )
82
+ raise ValueError(error_msg)
83
+
84
+ run_id = details.get("id")
85
+ if run_id is None:
86
+ error_msg = f"Run ID not found in the run details for Actor: {actor_id}"
87
+ raise ValueError(error_msg)
88
+
89
+ # Get the results
90
+ run = self.client.run(run_id=run_id)
91
+ results = run.dataset().list_items(clean=True).items
92
+
93
+ return json.dumps(results)
94
+
95
+ except Exception as e:
96
+ error_msg = f"Error running Apify Actor {actor_id}: {str(e)}"
97
+ logger.error(error_msg)
98
+ return json.dumps([{"error": error_msg}])
99
+
100
+ docstring = f"{actor_description}\n\nArgs:\n"
101
+
102
+ for param_name, param_info in properties.items():
103
+ param_type = param_info.get("type", "any")
104
+ param_desc = param_info.get("description", "No description available")
105
+ required_marker = "(required)" if param_name in required else "(optional)"
106
+ docstring += f" {param_name} ({param_type}): {required_marker} {param_desc}\n"
107
+
108
+ docstring += """
109
+ Returns:
110
+ str: JSON string containing the Actor's output dataset
111
+ """
112
+
113
+ # Update function metadata
114
+ actor_function.__name__ = tool_name
115
+ actor_function.__doc__ = docstring
116
+
117
+ # Register the function with the toolkit
118
+ self.register(actor_function)
119
+ # Fix params schema
120
+ self.functions[tool_name].parameters = props_to_json_schema(properties, required)
121
+ log_info(f"Registered Apify Actor '{actor_id}' as function '{tool_name}'")
122
+
123
+ except Exception as e:
124
+ logger.error(f"Failed to register Apify Actor '{actor_id}': {str(e)}")
125
+
126
+
127
+ # Constants
128
+ MAX_DESCRIPTION_LEN = 350
129
+ REQUESTS_TIMEOUT_SECS = 300
130
+ APIFY_API_ENDPOINT_GET_DEFAULT_BUILD = "https://api.apify.com/v2/acts/{actor_id}/builds/default"
131
+
132
+
133
+ # Utility functions
134
+ def props_to_json_schema(input_dict, required_fields=None):
135
+ schema: Dict[str, Any] = {"type": "object", "properties": {}, "required": required_fields or []}
136
+
137
+ def infer_array_item_type(prop):
138
+ type_map = {
139
+ "string": "string",
140
+ "int": "number",
141
+ "float": "number",
142
+ "dict": "object",
143
+ "list": "array",
144
+ "bool": "boolean",
145
+ "none": "null",
146
+ }
147
+ if prop.get("items", {}).get("type"):
148
+ return prop["items"]["type"]
149
+ if "prefill" in prop and prop["prefill"] and len(prop["prefill"]) > 0:
150
+ return type_map.get(type(prop["prefill"][0]).__name__.lower(), "string")
151
+ if "default" in prop and prop["default"] and len(prop["default"]) > 0:
152
+ return type_map.get(type(prop["default"][0]).__name__.lower(), "string")
153
+ return "string" # Fallback for arrays like searchStringsArray
154
+
155
+ for key, value in input_dict.items():
156
+ prop_schema: Dict[str, Any] = {}
157
+ prop_type = value.get("type")
158
+
159
+ if "enum" in value:
160
+ prop_schema["enum"] = value["enum"]
161
+
162
+ if "default" in value:
163
+ prop_schema["default"] = value["default"]
164
+ elif "prefill" in value:
165
+ prop_schema["default"] = value["prefill"]
166
+
167
+ if "description" in value:
168
+ prop_schema["description"] = value["description"]
169
+
170
+ # Handle Apify special types first
171
+ if prop_type == "object" and value.get("editor") == "proxy":
172
+ prop_schema["type"] = "object"
173
+ prop_schema["properties"] = {
174
+ "useApifyProxy": {
175
+ "title": "Use Apify Proxy",
176
+ "type": "boolean",
177
+ "description": "Whether to use Apify Proxy - ALWAYS SET TO TRUE.",
178
+ "default": True,
179
+ "examples": [True],
180
+ }
181
+ }
182
+ prop_schema["required"] = ["useApifyProxy"]
183
+ if "default" in value:
184
+ prop_schema["default"] = value["default"]
185
+
186
+ elif prop_type == "array" and value.get("editor") == "requestListSources":
187
+ prop_schema["type"] = "array"
188
+ prop_schema["items"] = {
189
+ "type": "object",
190
+ "title": "Request list source",
191
+ "description": "Request list source",
192
+ "properties": {
193
+ "url": {"title": "URL", "type": "string", "description": "URL of the request list source"}
194
+ },
195
+ }
42
196
 
43
- if urls is None:
44
- return "No URLs provided"
197
+ elif prop_type == "array":
198
+ prop_schema["type"] = "array"
199
+ prop_schema["items"] = {
200
+ "type": infer_array_item_type(value),
201
+ "title": value.get("title", "Item"),
202
+ "description": "Item",
203
+ }
45
204
 
46
- client = ApifyClient(self.api_key)
205
+ elif prop_type == "object":
206
+ prop_schema["type"] = "object"
207
+ if "default" in value:
208
+ prop_schema["default"] = value["default"]
209
+ prop_schema["properties"] = {}
210
+ for k, v in value.get("properties", value["default"]).items():
211
+ prop_type = v["type"] if isinstance(v, dict) else type(v).__name__.lower()
212
+ if prop_type == "bool":
213
+ prop_type = "boolean"
214
+ prop_schema["properties"][k] = {"type": prop_type}
47
215
 
48
- logger.debug(f"Crawling URLs: {urls}")
216
+ else:
217
+ prop_schema["type"] = prop_type
49
218
 
50
- formatted_urls = [{"url": url} for url in urls]
219
+ schema["properties"][key] = prop_schema
51
220
 
52
- run_input = {"startUrls": formatted_urls}
221
+ return schema
53
222
 
54
- run = client.actor("apify/website-content-crawler").call(run_input=run_input, timeout_secs=timeout)
55
223
 
56
- results: str = ""
224
+ def create_apify_client(token: str) -> ApifyClient:
225
+ """Create an Apify client instance with a custom user-agent.
57
226
 
58
- for item in client.dataset(run["defaultDatasetId"]).iterate_items():
59
- results += "Results for URL: " + item.get("url") + "\n"
60
- results += item.get("text") + "\n"
227
+ Args:
228
+ token (str): API token
61
229
 
62
- return results
230
+ Returns:
231
+ ApifyClient: Apify client instance
63
232
 
64
- def web_scrapper(self, urls: List[str], timeout: Optional[int] = 60) -> str:
65
- """
66
- Scrapes a website using Apify's web-scraper actor.
233
+ Raises:
234
+ ValueError: If the API token is not provided
235
+ """
236
+ if not token:
237
+ raise ValueError("API token is required to create an Apify client.")
67
238
 
68
- :param urls: The URLs to scrape.
69
- :param timeout: The timeout for the scraping.
239
+ client = ApifyClient(token)
240
+ if http_client := getattr(client.http_client, "httpx_client", None):
241
+ http_client.headers["user-agent"] += "; Origin/agno"
242
+ return client
70
243
 
71
- :return: The results of the scraping.
72
- """
73
- if self.api_key is None:
74
- return "No API key provided"
75
244
 
76
- if urls is None:
77
- return "No URLs provided"
245
+ def actor_id_to_tool_name(actor_id: str) -> str:
246
+ """Turn actor_id into a valid tool name.
78
247
 
79
- client = ApifyClient(self.api_key)
248
+ Args:
249
+ actor_id (str): Actor ID from Apify store
80
250
 
81
- logger.debug(f"Scrapping URLs: {urls}")
251
+ Returns:
252
+ str: A valid tool name
253
+ """
254
+ valid_chars = string.ascii_letters + string.digits + "_-"
255
+ return "apify_actor_" + "".join(char if char in valid_chars else "_" for char in actor_id)
82
256
 
83
- formatted_urls = [{"url": url} for url in urls]
84
257
 
85
- page_function_string = """
86
- async function pageFunction(context) {
87
- const $ = context.jQuery;
88
- const pageTitle = $('title').first().text();
89
- const h1 = $('h1').first().text();
90
- const first_h2 = $('h2').first().text();
91
- const random_text_from_the_page = $('p').first().text();
258
+ def get_actor_latest_build(apify_client: ApifyClient, actor_id: str) -> Dict[str, Any]:
259
+ """Get the latest build of an Actor from the default build tag.
92
260
 
93
- context.log.info(`URL: ${context.request.url}, TITLE: ${pageTitle}`);
261
+ Args:
262
+ apify_client (ApifyClient): An instance of the ApifyClient class
263
+ actor_id (str): Actor name from Apify store to run
94
264
 
95
- return {
96
- url: context.request.url,
97
- pageTitle,
98
- h1,
99
- first_h2,
100
- random_text_from_the_page
101
- };
102
- }
103
- """
265
+ Returns:
266
+ Dict[str, Any]: The latest build of the Actor
104
267
 
105
- run_input = {
106
- "pageFunction": page_function_string,
107
- "startUrls": formatted_urls,
108
- }
268
+ Raises:
269
+ ValueError: If the Actor is not found or the build data is not found
270
+ TypeError: If the build is not a dictionary
271
+ """
272
+ if not (actor := apify_client.actor(actor_id).get()):
273
+ raise ValueError(f"Actor {actor_id} not found.")
274
+
275
+ if not (actor_obj_id := actor.get("id")):
276
+ raise ValueError(f"Failed to get the Actor object ID for {actor_id}.")
277
+
278
+ url = APIFY_API_ENDPOINT_GET_DEFAULT_BUILD.format(actor_id=actor_obj_id)
279
+ response = requests.request("GET", url, timeout=REQUESTS_TIMEOUT_SECS)
280
+
281
+ build = response.json()
282
+ if not isinstance(build, dict):
283
+ raise TypeError(f"Failed to get the latest build of the Actor {actor_id}.")
284
+
285
+ if (data := build.get("data")) is None:
286
+ raise ValueError(f"Failed to get the latest build data of the Actor {actor_id}.")
287
+
288
+ return data
289
+
290
+
291
+ def prune_actor_input_schema(input_schema: Dict[str, Any]) -> Tuple[Dict[str, Any], List[str]]:
292
+ """Get the input schema from the Actor build and trim descriptions.
109
293
 
110
- run = client.actor("apify/web-scraper").call(run_input=run_input, timeout_secs=timeout)
294
+ Args:
295
+ input_schema (Dict[str, Any]): The input schema from the Actor build
111
296
 
112
- results: str = ""
297
+ Returns:
298
+ Tuple[Dict[str, Any], List[str]]: A tuple containing the pruned properties and required fields
299
+ """
300
+ properties = input_schema.get("properties", {})
301
+ required = input_schema.get("required", [])
113
302
 
114
- for item in client.dataset(run["defaultDatasetId"]).iterate_items():
115
- results += "Results for URL: " + item.get("url") + "\n"
116
- results += item.get("pageTitle") + "\n"
117
- results += item.get("h1") + "\n"
118
- results += item.get("first_h2") + "\n"
119
- results += item.get("random_text_from_the_page") + "\n"
303
+ properties_out: Dict[str, Any] = {}
304
+ for item, meta in properties.items():
305
+ properties_out[item] = {}
306
+ if desc := meta.get("description"):
307
+ properties_out[item]["description"] = (
308
+ desc[:MAX_DESCRIPTION_LEN] + "..." if len(desc) > MAX_DESCRIPTION_LEN else desc
309
+ )
310
+ for key_name in ("type", "default", "prefill", "enum"):
311
+ if value := meta.get(key_name):
312
+ properties_out[item][key_name] = value
120
313
 
121
- return results
314
+ return properties_out, required
@@ -3,7 +3,7 @@ from pathlib import Path
3
3
  from typing import Any, Dict, 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, logger
7
7
 
8
8
  try:
9
9
  import arxiv
@@ -17,16 +17,24 @@ except ImportError:
17
17
 
18
18
 
19
19
  class ArxivTools(Toolkit):
20
- def __init__(self, search_arxiv: bool = True, read_arxiv_papers: bool = True, download_dir: Optional[Path] = None):
21
- super().__init__(name="arxiv_tools")
22
-
20
+ def __init__(
21
+ self,
22
+ enable_search_arxiv: bool = True,
23
+ enable_read_arxiv_papers: bool = True,
24
+ all: bool = False,
25
+ download_dir: Optional[Path] = None,
26
+ **kwargs,
27
+ ):
23
28
  self.client: arxiv.Client = arxiv.Client()
24
29
  self.download_dir: Path = download_dir or Path(__file__).parent.joinpath("arxiv_pdfs")
25
30
 
26
- if search_arxiv:
27
- self.register(self.search_arxiv_and_return_articles)
28
- if read_arxiv_papers:
29
- self.register(self.read_arxiv_papers)
31
+ tools: List[Any] = []
32
+ if all or enable_search_arxiv:
33
+ tools.append(self.search_arxiv_and_return_articles)
34
+ if all or enable_read_arxiv_papers:
35
+ tools.append(self.read_arxiv_papers)
36
+
37
+ super().__init__(name="arxiv_tools", tools=tools, **kwargs)
30
38
 
31
39
  def search_arxiv_and_return_articles(self, query: str, num_articles: int = 10) -> str:
32
40
  """Use this function to search arXiv for a query and return the top articles.
@@ -39,7 +47,7 @@ class ArxivTools(Toolkit):
39
47
  """
40
48
 
41
49
  articles = []
42
- logger.info(f"Searching arxiv for: {query}")
50
+ log_debug(f"Searching arxiv for: {query}")
43
51
  for result in self.client.results(
44
52
  search=arxiv.Search(
45
53
  query=query,
@@ -83,7 +91,7 @@ class ArxivTools(Toolkit):
83
91
  download_dir.mkdir(parents=True, exist_ok=True)
84
92
 
85
93
  articles = []
86
- logger.info(f"Searching arxiv for: {id_list}")
94
+ log_debug(f"Searching arxiv for: {id_list}")
87
95
  for result in self.client.results(search=arxiv.Search(id_list=id_list)):
88
96
  try:
89
97
  article: Dict[str, Any] = {
@@ -100,9 +108,9 @@ class ArxivTools(Toolkit):
100
108
  "comment": result.comment,
101
109
  }
102
110
  if result.pdf_url:
103
- logger.info(f"Downloading: {result.pdf_url}")
111
+ log_debug(f"Downloading: {result.pdf_url}")
104
112
  pdf_path = result.download_pdf(dirpath=str(download_dir))
105
- logger.info(f"To: {pdf_path}")
113
+ log_debug(f"To: {pdf_path}")
106
114
  pdf_reader = PdfReader(pdf_path)
107
115
  article["content"] = []
108
116
  for page_number, page in enumerate(pdf_reader.pages, start=1):
agno/tools/aws_lambda.py CHANGED
@@ -1,3 +1,5 @@
1
+ from typing import Any, List
2
+
1
3
  from agno.tools import Toolkit
2
4
 
3
5
  try:
@@ -7,16 +9,28 @@ except ImportError:
7
9
 
8
10
 
9
11
  class AWSLambdaTools(Toolkit):
10
- name: str = "AWSLambdaTool"
11
- description: str = "A tool for interacting with AWS Lambda functions"
12
-
13
- def __init__(self, region_name: str = "us-east-1"):
14
- super().__init__()
12
+ def __init__(
13
+ self,
14
+ region_name: str = "us-east-1",
15
+ enable_list_functions: bool = True,
16
+ enable_invoke_function: bool = True,
17
+ all: bool = False,
18
+ **kwargs,
19
+ ):
15
20
  self.client = boto3.client("lambda", region_name=region_name)
16
- self.register(self.list_functions)
17
- self.register(self.invoke_function)
21
+
22
+ tools: List[Any] = []
23
+ if all or enable_list_functions:
24
+ tools.append(self.list_functions)
25
+ if all or enable_invoke_function:
26
+ tools.append(self.invoke_function)
27
+
28
+ super().__init__(name="aws-lambda", tools=tools, **kwargs)
18
29
 
19
30
  def list_functions(self) -> str:
31
+ """
32
+ List all AWS Lambda functions in the configured AWS account.
33
+ """
20
34
  try:
21
35
  response = self.client.list_functions()
22
36
  functions = [func["FunctionName"] for func in response["Functions"]]
@@ -25,6 +39,13 @@ class AWSLambdaTools(Toolkit):
25
39
  return f"Error listing functions: {str(e)}"
26
40
 
27
41
  def invoke_function(self, function_name: str, payload: str = "{}") -> str:
42
+ """
43
+ Invoke a specific AWS Lambda function with an optional JSON payload.
44
+
45
+ Args:
46
+ function_name (str): The name of the Lambda function to invoke.
47
+ payload (str): The JSON payload to send to the function. Defaults to "{}".
48
+ """
28
49
  try:
29
50
  response = self.client.invoke(FunctionName=function_name, Payload=payload)
30
51
  return f"Function invoked successfully. Status code: {response['StatusCode']}, Payload: {response['Payload'].read().decode('utf-8')}"
agno/tools/aws_ses.py ADDED
@@ -0,0 +1,66 @@
1
+ from typing import Optional
2
+
3
+ from agno.tools import Toolkit
4
+ from agno.utils.log import log_debug
5
+
6
+ try:
7
+ import boto3
8
+ except ImportError:
9
+ raise ImportError("boto3 is required for AWSSESTool. Please install it using `pip install boto3`.")
10
+
11
+
12
+ class AWSSESTool(Toolkit):
13
+ def __init__(
14
+ self,
15
+ sender_email: Optional[str] = None,
16
+ sender_name: Optional[str] = None,
17
+ region_name: str = "us-east-1",
18
+ enable_send_email: bool = True,
19
+ all: bool = False,
20
+ **kwargs,
21
+ ):
22
+ tools = []
23
+ if all or enable_send_email:
24
+ tools.append(self.send_email)
25
+ super().__init__(name="aws_ses_tool", tools=tools, **kwargs)
26
+ self.client = boto3.client("ses", region_name=region_name)
27
+ self.sender_email = sender_email
28
+ self.sender_name = sender_name
29
+
30
+ def send_email(self, subject: str, body: str, receiver_email: str) -> str:
31
+ """
32
+ Use this tool to send an email using AWS SES.
33
+
34
+ Args: subject: The subject of the email
35
+ body: The body of the email
36
+ receiver_email: The email address of the receiver
37
+ """
38
+ if not self.client:
39
+ raise Exception("AWS SES client not initialized. Please check the configuration.")
40
+ if not subject:
41
+ return "Email subject cannot be empty."
42
+ if not body:
43
+ return "Email body cannot be empty."
44
+ try:
45
+ response = self.client.send_email(
46
+ Source=f"{self.sender_name} <{self.sender_email}>",
47
+ Destination={
48
+ "ToAddresses": [receiver_email],
49
+ },
50
+ Message={
51
+ "Body": {
52
+ "Text": {
53
+ "Charset": "UTF-8",
54
+ "Data": body,
55
+ },
56
+ },
57
+ "Subject": {
58
+ "Charset": "UTF-8",
59
+ "Data": subject,
60
+ },
61
+ },
62
+ )
63
+ log_debug(f"Email sent with message ID: {response['MessageId']}")
64
+ return "Email sent successfully!"
65
+ except Exception as e:
66
+ raise Exception(f"Failed to send email: {e}")
agno/tools/baidusearch.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
6
6
 
7
7
  try:
8
8
  from baidusearch.baidusearch import search # type: ignore
@@ -35,15 +35,22 @@ class BaiduSearchTools(Toolkit):
35
35
  proxy: Optional[str] = None,
36
36
  timeout: Optional[int] = 10,
37
37
  debug: Optional[bool] = False,
38
+ enable_baidu_search: bool = True,
39
+ all: bool = False,
40
+ **kwargs,
38
41
  ):
39
- super().__init__(name="baidusearch")
40
42
  self.fixed_max_results = fixed_max_results
41
43
  self.fixed_language = fixed_language
42
44
  self.headers = headers
43
45
  self.proxy = proxy
44
46
  self.timeout = timeout
45
47
  self.debug = debug
46
- self.register(self.baidu_search)
48
+
49
+ tools = []
50
+ if all or enable_baidu_search:
51
+ tools.append(self.baidu_search)
52
+
53
+ super().__init__(name="baidusearch", tools=tools, **kwargs)
47
54
 
48
55
  def baidu_search(self, query: str, max_results: int = 5, language: str = "zh") -> str:
49
56
  """Execute Baidu search and return results
@@ -65,7 +72,7 @@ class BaiduSearchTools(Toolkit):
65
72
  except LookupError:
66
73
  language = "zh"
67
74
 
68
- logger.debug(f"Searching Baidu [{language}] for: {query}")
75
+ log_debug(f"Searching Baidu [{language}] for: {query}")
69
76
 
70
77
  results = search(keyword=query, num_results=max_results)
71
78