agno 2.2.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 (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -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 +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -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 +1335 -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 +1160 -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 +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,349 @@
1
+ from typing import Any, Dict, List, Optional
2
+
3
+ from agno.tools import Toolkit
4
+ from agno.utils.log import log_debug, log_info, logger
5
+
6
+ try:
7
+ from moviepy import ColorClip, CompositeVideoClip, TextClip, VideoFileClip # type: ignore
8
+ except ImportError:
9
+ raise ImportError("`moviepy` not installed. Please install using `pip install moviepy ffmpeg`")
10
+
11
+
12
+ class MoviePyVideoTools(Toolkit):
13
+ """Tool for processing video files, extracting audio, transcribing and adding captions"""
14
+
15
+ def __init__(
16
+ self,
17
+ enable_process_video: bool = True,
18
+ enable_generate_captions: bool = True,
19
+ enable_embed_captions: bool = True,
20
+ all: bool = False,
21
+ **kwargs,
22
+ ):
23
+ tools: List[Any] = []
24
+ if enable_process_video or all:
25
+ tools.append(self.extract_audio)
26
+ if enable_generate_captions or all:
27
+ tools.append(self.create_srt)
28
+ if enable_embed_captions or all:
29
+ tools.append(self.embed_captions)
30
+
31
+ super().__init__(name="video_tools", tools=tools, **kwargs)
32
+
33
+ def split_text_into_lines(self, words: List[Dict]) -> List[Dict]:
34
+ """Split transcribed words into lines based on duration and length constraints
35
+ Args:
36
+ words: List of dictionaries containing word data with 'word', 'start', and 'end' keys
37
+ Returns:
38
+ List[Dict]: List of subtitle lines, each containing word, start time, end time, and text contents
39
+ """
40
+ MAX_CHARS = 30
41
+ MAX_DURATION = 2.5
42
+ MAX_GAP = 1.5
43
+
44
+ subtitles = []
45
+ line = []
46
+ line_duration = 0
47
+
48
+ for idx, word_data in enumerate(words):
49
+ line.append(word_data)
50
+ line_duration += word_data["end"] - word_data["start"]
51
+
52
+ temp = " ".join(item["word"] for item in line)
53
+
54
+ duration_exceeded = line_duration > MAX_DURATION
55
+ chars_exceeded = len(temp) > MAX_CHARS
56
+ maxgap_exceeded = idx > 0 and word_data["start"] - words[idx - 1]["end"] > MAX_GAP
57
+
58
+ if duration_exceeded or chars_exceeded or maxgap_exceeded:
59
+ if line:
60
+ subtitle_line = {
61
+ "word": " ".join(item["word"] for item in line),
62
+ "start": line[0]["start"],
63
+ "end": line[-1]["end"],
64
+ "textcontents": line,
65
+ }
66
+ subtitles.append(subtitle_line)
67
+ line = []
68
+ line_duration = 0
69
+
70
+ if line:
71
+ subtitle_line = {
72
+ "word": " ".join(item["word"] for item in line),
73
+ "start": line[0]["start"],
74
+ "end": line[-1]["end"],
75
+ "textcontents": line,
76
+ }
77
+ subtitles.append(subtitle_line)
78
+
79
+ return subtitles
80
+
81
+ def create_caption_clips(
82
+ self,
83
+ text_json: Dict,
84
+ frame_size: tuple,
85
+ font="Arial",
86
+ color="white",
87
+ highlight_color="yellow",
88
+ stroke_color="black",
89
+ stroke_width=1.5,
90
+ ) -> List[TextClip]:
91
+ """Create word-level caption clips with highlighting effects
92
+ Args:
93
+ text_json: Dictionary containing text and timing information
94
+ frame_size: Tuple of (width, height) for the video frame
95
+ font: Font family to use for captions
96
+ color: Base text color
97
+ highlight_color: Color for highlighted words
98
+ stroke_color: Color for text outline
99
+ stroke_width: Width of text outline
100
+ Returns:
101
+ List[TextClip]: List of MoviePy TextClip objects for each word and highlight
102
+ """
103
+ word_clips = []
104
+ x_pos = 0
105
+ y_pos = 0
106
+ line_width = 0
107
+
108
+ frame_width, frame_height = frame_size
109
+ x_buffer = frame_width * 0.1
110
+ max_line_width = frame_width - (2 * x_buffer)
111
+ fontsize = int(frame_height * 0.30)
112
+
113
+ full_duration = text_json["end"] - text_json["start"]
114
+
115
+ for word_data in text_json["textcontents"]:
116
+ duration = word_data["end"] - word_data["start"]
117
+
118
+ # Create base word clip using official TextClip parameters
119
+ word_clip = (
120
+ TextClip(
121
+ text=word_data["word"],
122
+ font=font,
123
+ font_size=int(fontsize),
124
+ color=color,
125
+ stroke_color=stroke_color,
126
+ stroke_width=int(stroke_width),
127
+ method="label",
128
+ )
129
+ .with_start(text_json["start"])
130
+ .with_duration(full_duration)
131
+ )
132
+
133
+ # Create space clip
134
+ space_clip = (
135
+ TextClip(text=" ", font=font, font_size=int(fontsize), color=color, method="label")
136
+ .with_start(text_json["start"])
137
+ .with_duration(full_duration)
138
+ )
139
+
140
+ word_width, word_height = word_clip.size
141
+ space_width = space_clip.size[0]
142
+
143
+ # Handle line wrapping
144
+ if line_width + word_width + space_width <= max_line_width:
145
+ word_clip = word_clip.with_position((x_pos + x_buffer, y_pos))
146
+ space_clip = space_clip.with_position((x_pos + word_width + x_buffer, y_pos))
147
+ x_pos += word_width + space_width
148
+ line_width += word_width + space_width
149
+ else:
150
+ x_pos = 0
151
+ y_pos += word_height + 10
152
+ line_width = word_width + space_width
153
+ word_clip = word_clip.with_position((x_buffer, y_pos))
154
+ space_clip = space_clip.with_position((word_width + x_buffer, y_pos))
155
+
156
+ word_clips.append(word_clip)
157
+ word_clips.append(space_clip)
158
+
159
+ # Create highlighted version
160
+ highlight_clip = (
161
+ TextClip(
162
+ text=word_data["word"],
163
+ font=font,
164
+ font_size=int(fontsize),
165
+ color=highlight_color,
166
+ stroke_color=stroke_color,
167
+ stroke_width=int(stroke_width),
168
+ method="label",
169
+ )
170
+ .with_start(word_data["start"])
171
+ .with_duration(duration)
172
+ .with_position(word_clip.pos)
173
+ )
174
+
175
+ word_clips.append(highlight_clip)
176
+
177
+ return word_clips
178
+
179
+ def parse_srt(self, srt_content: str) -> List[Dict]:
180
+ """Convert SRT formatted content into word-level timing data
181
+ Args:
182
+ srt_content: String containing SRT formatted subtitles
183
+ Returns:
184
+ List[Dict]: List of words with their timing information
185
+ """
186
+ words = []
187
+ lines = srt_content.strip().split("\n\n")
188
+
189
+ for block in lines:
190
+ if not block.strip():
191
+ continue
192
+
193
+ parts = block.split("\n")
194
+ if len(parts) < 3:
195
+ continue
196
+
197
+ # Parse timestamp line
198
+ timestamp = parts[1]
199
+ start_time, end_time = timestamp.split(" --> ")
200
+
201
+ # Convert timestamp to seconds
202
+ def time_to_seconds(time_str):
203
+ h, m, s = time_str.replace(",", ".").split(":")
204
+ return float(h) * 3600 + float(m) * 60 + float(s)
205
+
206
+ start = time_to_seconds(start_time)
207
+ end = time_to_seconds(end_time)
208
+
209
+ # Get text content (could be multiple lines)
210
+ text = " ".join(parts[2:])
211
+
212
+ # Split text into words and distribute timing
213
+ text_words = text.split()
214
+ if text_words:
215
+ time_per_word = (end - start) / len(text_words)
216
+
217
+ for i, word in enumerate(text_words):
218
+ word_start = start + (i * time_per_word)
219
+ word_end = word_start + time_per_word
220
+ words.append({"word": word, "start": word_start, "end": word_end})
221
+
222
+ return words
223
+
224
+ def extract_audio(self, video_path: str, output_path: str) -> str:
225
+ """Converts video to audio using MoviePy
226
+ Args:
227
+ video_path: Path to the video file
228
+ output_path: Path where the audio will be saved
229
+ Returns:
230
+ str: Path to the extracted audio file
231
+ """
232
+ try:
233
+ log_debug(f"Extracting audio from {video_path}")
234
+ video = VideoFileClip(video_path)
235
+ video.audio.write_audiofile(output_path)
236
+ log_info(f"Audio extracted to {output_path}")
237
+ return output_path
238
+ except Exception as e:
239
+ logger.error(f"Failed to extract audio: {str(e)}")
240
+ return f"Failed to extract audio: {str(e)}"
241
+
242
+ def create_srt(self, transcription: str, output_path: str) -> str:
243
+ """Save transcription text to SRT formatted file
244
+ Args:
245
+ transcription: Text transcription in SRT format
246
+ output_path: Path where the SRT file will be saved
247
+ Returns:
248
+ str: Path to the created SRT file, or error message if failed
249
+ """
250
+ try:
251
+ log_debug(f"Creating SRT file at {output_path}")
252
+ # Since we're getting SRT format from Whisper API now,
253
+ # we can just write it directly to file
254
+ with open(output_path, "w", encoding="utf-8") as f:
255
+ f.write(transcription)
256
+ return output_path
257
+ except Exception as e:
258
+ logger.error(f"Failed to create SRT file: {str(e)}")
259
+ return f"Failed to create SRT file: {str(e)}"
260
+
261
+ def embed_captions(
262
+ self,
263
+ video_path: str,
264
+ srt_path: str,
265
+ output_path: Optional[str] = None,
266
+ font_size: int = 24,
267
+ font_color: str = "white",
268
+ stroke_color: str = "black",
269
+ stroke_width: int = 1,
270
+ ) -> str:
271
+ """Create a new video with embedded scrolling captions and word-level highlighting
272
+ Args:
273
+ video_path: Path to the input video file
274
+ srt_path: Path to the SRT caption file
275
+ output_path: Path for the output video (optional)
276
+ font_size: Size of caption text
277
+ font_color: Color of caption text
278
+ stroke_color: Color of text outline
279
+ stroke_width: Width of text outline
280
+ Returns:
281
+ str: Path to the captioned video file, or error message if failed
282
+ """
283
+ try:
284
+ # If no output path provided, create one based on input video
285
+ if output_path is None:
286
+ output_path = video_path.rsplit(".", 1)[0] + "_captioned.mp4"
287
+
288
+ # Load video
289
+ video = VideoFileClip(video_path)
290
+
291
+ # Read caption file and parse SRT
292
+ with open(srt_path, "r", encoding="utf-8") as f:
293
+ srt_content = f.read()
294
+
295
+ # Parse SRT and get word timing
296
+ words = self.parse_srt(srt_content)
297
+
298
+ # Split into lines
299
+ subtitle_lines = self.split_text_into_lines(words)
300
+
301
+ all_caption_clips = []
302
+
303
+ # Create caption clips for each line
304
+ for line in subtitle_lines:
305
+ # Increase background height to accommodate larger text
306
+ bg_height = int(video.h * 0.15)
307
+ bg_clip = ColorClip(
308
+ size=(video.w, bg_height), color=(0, 0, 0), duration=line["end"] - line["start"]
309
+ ).with_opacity(0.6)
310
+
311
+ # Position background even closer to bottom (90% instead of 85%)
312
+ bg_position = ("center", int(video.h * 0.90))
313
+ bg_clip = bg_clip.with_start(line["start"]).with_position(bg_position)
314
+
315
+ # Create word clips
316
+ word_clips = self.create_caption_clips(line, (video.w, bg_height))
317
+
318
+ # Combine background and words
319
+ caption_composite = CompositeVideoClip([bg_clip] + word_clips, size=bg_clip.size).with_position(
320
+ bg_position
321
+ )
322
+
323
+ all_caption_clips.append(caption_composite)
324
+
325
+ # Combine video with all captions
326
+ final_video = CompositeVideoClip([video] + all_caption_clips, size=video.size)
327
+
328
+ # Write output with optimized settings
329
+ final_video.write_videofile(
330
+ output_path,
331
+ codec="libx264",
332
+ audio_codec="aac",
333
+ fps=video.fps,
334
+ preset="medium",
335
+ threads=4,
336
+ # Disable default progress bar
337
+ )
338
+
339
+ # Cleanup
340
+ video.close()
341
+ final_video.close()
342
+ for clip in all_caption_clips:
343
+ clip.close()
344
+
345
+ return output_path
346
+
347
+ except Exception as e:
348
+ logger.error(f"Failed to embed captions: {str(e)}")
349
+ return f"Failed to embed captions: {str(e)}"
agno/tools/neo4j.py ADDED
@@ -0,0 +1,134 @@
1
+ import os
2
+ from typing import Any, List, Optional
3
+
4
+ try:
5
+ from neo4j import GraphDatabase
6
+ except ImportError:
7
+ raise ImportError("`neo4j` not installed. Please install using `pip install neo4j`")
8
+
9
+ from agno.tools import Toolkit
10
+ from agno.utils.log import log_debug, logger
11
+
12
+
13
+ class Neo4jTools(Toolkit):
14
+ def __init__(
15
+ self,
16
+ uri: Optional[str] = None,
17
+ user: Optional[str] = None,
18
+ password: Optional[str] = None,
19
+ database: Optional[str] = None,
20
+ # Enable flags for <6 functions
21
+ enable_list_labels: bool = True,
22
+ enable_list_relationships: bool = True,
23
+ enable_get_schema: bool = True,
24
+ enable_run_cypher: bool = True,
25
+ all: bool = False,
26
+ **kwargs,
27
+ ):
28
+ """
29
+ Initialize the Neo4jTools toolkit.
30
+ Connection parameters (uri/user/password or host/port) can be provided.
31
+ If not provided, falls back to NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD env vars.
32
+
33
+ Args:
34
+ uri (Optional[str]): The Neo4j URI.
35
+ user (Optional[str]): The Neo4j username.
36
+ password (Optional[str]): The Neo4j password.
37
+ host (Optional[str]): The Neo4j host.
38
+ port (Optional[int]): The Neo4j port.
39
+ database (Optional[str]): The Neo4j database.
40
+ list_labels (bool): Whether to list node labels.
41
+ list_relationships (bool): Whether to list relationship types.
42
+ get_schema (bool): Whether to get the schema.
43
+ run_cypher (bool): Whether to run Cypher queries.
44
+ **kwargs: Additional keyword arguments.
45
+ """
46
+ # Determine the connection URI and credentials
47
+ uri = uri or os.getenv("NEO4J_URI", "bolt://localhost:7687")
48
+ user = user or os.getenv("NEO4J_USERNAME")
49
+ password = password or os.getenv("NEO4J_PASSWORD")
50
+
51
+ if user is None or password is None:
52
+ raise ValueError("Username or password for Neo4j not provided")
53
+
54
+ # Create the Neo4j driver
55
+ try:
56
+ self.driver = GraphDatabase.driver(uri, auth=(user, password)) # type: ignore
57
+ self.driver.verify_connectivity()
58
+ log_debug("Connected to Neo4j database")
59
+ except Exception as e:
60
+ logger.error(f"Failed to connect to Neo4j: {e}")
61
+ raise
62
+
63
+ self.database = database or "neo4j"
64
+
65
+ # Register toolkit methods as tools
66
+ tools: List[Any] = []
67
+ if all or enable_list_labels:
68
+ tools.append(self.list_labels)
69
+ if all or enable_list_relationships:
70
+ tools.append(self.list_relationship_types)
71
+ if all or enable_get_schema:
72
+ tools.append(self.get_schema)
73
+ if all or enable_run_cypher:
74
+ tools.append(self.run_cypher_query)
75
+ super().__init__(name="neo4j_tools", tools=tools, **kwargs)
76
+
77
+ def list_labels(self) -> list:
78
+ """
79
+ Retrieve all node labels present in the connected Neo4j database.
80
+ """
81
+ try:
82
+ log_debug("Listing node labels in Neo4j database")
83
+ with self.driver.session(database=self.database) as session:
84
+ result = session.run("CALL db.labels()")
85
+ labels = [record["label"] for record in result]
86
+ return labels
87
+ except Exception as e:
88
+ logger.error(f"Error listing labels: {e}")
89
+ return []
90
+
91
+ def list_relationship_types(self) -> list:
92
+ """
93
+ Retrieve all relationship types present in the connected Neo4j database.
94
+ """
95
+ try:
96
+ log_debug("Listing relationship types in Neo4j database")
97
+ with self.driver.session(database=self.database) as session:
98
+ result = session.run("CALL db.relationshipTypes()")
99
+ types = [record["relationshipType"] for record in result]
100
+ return types
101
+ except Exception as e:
102
+ logger.error(f"Error listing relationship types: {e}")
103
+ return []
104
+
105
+ def get_schema(self) -> list:
106
+ """
107
+ Retrieve a visualization of the database schema, including nodes and relationships.
108
+ """
109
+ try:
110
+ log_debug("Retrieving Neo4j schema visualization")
111
+ with self.driver.session(database=self.database) as session:
112
+ result = session.run("CALL db.schema.visualization()")
113
+ schema_data = result.data()
114
+ return schema_data
115
+ except Exception as e:
116
+ logger.error(f"Error getting Neo4j schema: {e}")
117
+ return []
118
+
119
+ def run_cypher_query(self, query: str) -> list:
120
+ """
121
+ Execute an arbitrary Cypher query against the connected Neo4j database.
122
+
123
+ Args:
124
+ query (str): The Cypher query string to execute.
125
+ """
126
+ try:
127
+ log_debug(f"Running Cypher query: {query}")
128
+ with self.driver.session(database=self.database) as session:
129
+ result = session.run(query) # type: ignore[arg-type]
130
+ data = result.data()
131
+ return data
132
+ except Exception as e:
133
+ logger.error(f"Error running Cypher query: {e}")
134
+ return []
@@ -0,0 +1,46 @@
1
+ from agno.tools import Toolkit
2
+ from agno.utils.log import log_debug
3
+
4
+ try:
5
+ from newspaper import Article
6
+ except ImportError:
7
+ raise ImportError("`newspaper3k` not installed. Please run `pip install newspaper3k lxml_html_clean`.")
8
+
9
+
10
+ class NewspaperTools(Toolkit):
11
+ """
12
+ Newspaper is a tool for getting the text of an article from a URL.
13
+ Args:
14
+ get_article_text (bool): Whether to get the text of an article from a URL.
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ enable_get_article_text: bool = True,
20
+ all: bool = False,
21
+ **kwargs,
22
+ ):
23
+ tools = []
24
+ if all or enable_get_article_text:
25
+ tools.append(self.get_article_text)
26
+
27
+ super().__init__(name="newspaper_toolkit", tools=tools, **kwargs)
28
+
29
+ def get_article_text(self, url: str) -> str:
30
+ """Get the text of an article from a URL.
31
+
32
+ Args:
33
+ url (str): The URL of the article.
34
+
35
+ Returns:
36
+ str: The text of the article.
37
+ """
38
+
39
+ try:
40
+ log_debug(f"Reading news: {url}")
41
+ article = Article(url)
42
+ article.download()
43
+ article.parse()
44
+ return article.text
45
+ except Exception as e:
46
+ return f"Error getting article text from {url}: {e}"
@@ -0,0 +1,93 @@
1
+ import json
2
+ from typing import Any, Dict, Optional
3
+
4
+ from agno.tools import Toolkit
5
+ from agno.utils.log import log_debug, logger
6
+
7
+ try:
8
+ import newspaper
9
+ except ImportError:
10
+ raise ImportError("`newspaper4k` not installed. Please run `pip install newspaper4k lxml_html_clean`.")
11
+
12
+
13
+ class Newspaper4kTools(Toolkit):
14
+ """
15
+ Newspaper4kTools is a toolkit for getting the text of an article from a URL.
16
+ Args:
17
+ enable_read_article (bool): Whether to read an article from a URL.
18
+ include_summary (bool): Whether to include the summary of an article.
19
+ article_length (Optional[int]): The length of the article to read.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ include_summary: bool = False,
25
+ article_length: Optional[int] = None,
26
+ enable_read_article: bool = True,
27
+ all: bool = False,
28
+ **kwargs,
29
+ ):
30
+ self.include_summary: bool = include_summary
31
+ self.article_length: Optional[int] = article_length
32
+
33
+ tools = []
34
+ if all or enable_read_article:
35
+ tools.append(self.read_article)
36
+
37
+ super().__init__(name="newspaper4k_tools", tools=tools, **kwargs)
38
+
39
+ def get_article_data(self, url: str) -> Optional[Dict[str, Any]]:
40
+ """Read and get article data from a URL.
41
+
42
+ Args:
43
+ url (str): The URL of the article.
44
+
45
+ Returns:
46
+ Dict[str, Any]: The article data.
47
+ """
48
+
49
+ try:
50
+ article = newspaper.article(url)
51
+ article_data = {}
52
+ if article.title:
53
+ article_data["title"] = article.title
54
+ if article.authors:
55
+ article_data["authors"] = article.authors
56
+ if article.text:
57
+ article_data["text"] = article.text
58
+ if self.include_summary and article.summary:
59
+ article_data["summary"] = article.summary
60
+
61
+ try:
62
+ if article.publish_date:
63
+ article_data["publish_date"] = article.publish_date.isoformat() if article.publish_date else None
64
+ except Exception:
65
+ pass
66
+
67
+ return article_data
68
+ except Exception as e:
69
+ logger.warning(f"Error reading article from {url}: {e}")
70
+ return None
71
+
72
+ def read_article(self, url: str) -> str:
73
+ """Use this function to read an article from a URL.
74
+
75
+ Args:
76
+ url (str): The URL of the article.
77
+
78
+ Returns:
79
+ str: JSON containing the article author, publish date, and text.
80
+ """
81
+
82
+ try:
83
+ log_debug(f"Reading news: {url}")
84
+ article_data = self.get_article_data(url)
85
+ if not article_data:
86
+ return f"Error reading article from {url}: No data found."
87
+
88
+ if self.article_length and "text" in article_data:
89
+ article_data["text"] = article_data["text"][: self.article_length]
90
+
91
+ return json.dumps(article_data, indent=2)
92
+ except Exception as e:
93
+ return f"Error reading article from {url}: {e}"