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
agno/tools/oxylabs.py ADDED
@@ -0,0 +1,385 @@
1
+ import json
2
+ from os import getenv
3
+ from typing import Any, Callable, Dict, List, Optional
4
+ from urllib.parse import urlparse
5
+
6
+ from agno.tools import Toolkit
7
+ from agno.utils.log import log_debug, log_error, log_info
8
+
9
+ try:
10
+ from oxylabs import RealtimeClient
11
+ from oxylabs.sources.response import Response
12
+ from oxylabs.utils.types import render
13
+ except ImportError:
14
+ raise ImportError("Oxylabs SDK not found. Please install it with: pip install oxylabs")
15
+
16
+
17
+ class OxylabsTools(Toolkit):
18
+ def __init__(
19
+ self,
20
+ username: Optional[str] = None,
21
+ password: Optional[str] = None,
22
+ **kwargs,
23
+ ):
24
+ self.username = username or getenv("OXYLABS_USERNAME")
25
+ self.password = password or getenv("OXYLABS_PASSWORD")
26
+
27
+ if not self.username or not self.password:
28
+ raise ValueError(
29
+ "No Oxylabs credentials provided. Please set the OXYLABS_USERNAME and OXYLABS_PASSWORD environment variables or pass them to the OxylabsTools constructor."
30
+ )
31
+
32
+ try:
33
+ log_debug(f"Initializing Oxylabs client with username: {self.username[:5]}...")
34
+ self.client = RealtimeClient(self.username, self.password)
35
+ log_debug("Oxylabs client initialized successfully")
36
+ except Exception as e:
37
+ log_debug(f"Failed to initialize Oxylabs client: {e}")
38
+ raise
39
+
40
+ tools: List[Callable[..., str]] = [
41
+ self.search_google,
42
+ self.get_amazon_product,
43
+ self.search_amazon_products,
44
+ self.scrape_website,
45
+ ]
46
+
47
+ super().__init__(name="oxylabs_web_scraping", tools=tools, **kwargs)
48
+
49
+ def search_google(self, query: str, domain_code: str = "com") -> str:
50
+ """Search Google for a query.
51
+
52
+ Args:
53
+ query: Search query
54
+ domain_code: Google domain to search (e.g., "com", "co.uk", "de", default: "com")
55
+
56
+ Returns:
57
+ JSON of search results
58
+ """
59
+ try:
60
+ if not query or not isinstance(query, str) or len(query.strip()) == 0:
61
+ return self._error_response("search_google", "Query cannot be empty", {"query": query})
62
+
63
+ if not isinstance(domain_code, str) or len(domain_code) > 10:
64
+ return self._error_response("search_google", "Domain must be a valid string (e.g., 'com', 'co.uk')")
65
+
66
+ query = query.strip()
67
+ log_debug(f"Google search: '{query}' on google.{domain_code}")
68
+
69
+ response: Response = self.client.google.scrape_search(query=query, domain=domain_code, parse=True)
70
+
71
+ # Extract search results
72
+ search_results = []
73
+
74
+ if response.results and len(response.results) > 0:
75
+ result = response.results[0]
76
+
77
+ # Try parsed content first
78
+ if hasattr(result, "content_parsed") and result.content_parsed:
79
+ content = result.content_parsed
80
+ if hasattr(content, "results") and content.results:
81
+ raw_results = content.results.raw if hasattr(content.results, "raw") else {}
82
+ organic_results = raw_results.get("organic", [])
83
+
84
+ for item in organic_results:
85
+ search_results.append(
86
+ {
87
+ "title": item.get("title", "").strip(),
88
+ "url": item.get("url", "").strip(),
89
+ "description": item.get("desc", "").strip(),
90
+ "position": item.get("pos", 0),
91
+ }
92
+ )
93
+
94
+ if not search_results and hasattr(result, "content"):
95
+ raw_content = result.content
96
+ if isinstance(raw_content, dict) and "results" in raw_content:
97
+ organic_results = raw_content["results"].get("organic", [])
98
+ for item in organic_results:
99
+ search_results.append(
100
+ {
101
+ "title": item.get("title", "").strip(),
102
+ "url": item.get("url", "").strip(),
103
+ "description": item.get("desc", "").strip(),
104
+ "position": item.get("pos", 0),
105
+ }
106
+ )
107
+
108
+ response_data = {
109
+ "tool": "search_google",
110
+ "query": query,
111
+ "results": search_results,
112
+ }
113
+
114
+ log_info(f"Google search completed. Found {len(search_results)} results")
115
+ return json.dumps(response_data, indent=2)
116
+
117
+ except Exception as e:
118
+ error_msg = f"Google search failed: {str(e)}"
119
+ log_error(error_msg)
120
+ return self._error_response("search_google", error_msg, {"query": query})
121
+
122
+ def get_amazon_product(self, asin: str, domain_code: str = "com") -> str:
123
+ """Get detailed information about an Amazon product by ASIN.
124
+
125
+ Args:
126
+ asin: Amazon Standard Identification Number (10 alphanumeric characters, e.g., "B07FZ8S74R")
127
+ domain_code: Amazon domain (e.g., "com", "co.uk", "de", default: "com")
128
+
129
+ Returns:
130
+ JSON of product details
131
+ """
132
+ try:
133
+ if not asin or not isinstance(asin, str):
134
+ return self._error_response("get_amazon_product", "ASIN is required and must be a string")
135
+
136
+ asin = asin.strip().upper()
137
+ if len(asin) != 10 or not asin.isalnum():
138
+ return self._error_response(
139
+ "get_amazon_product",
140
+ f"Invalid ASIN format: {asin}. Must be 10 alphanumeric characters (e.g., 'B07FZ8S74R')",
141
+ )
142
+
143
+ if not isinstance(domain_code, str) or len(domain_code) > 10:
144
+ return self._error_response(
145
+ "get_amazon_product", "Domain must be a valid string (e.g., 'com', 'co.uk')"
146
+ )
147
+
148
+ log_debug(f"Amazon product lookup: ASIN {asin} on amazon.{domain_code}")
149
+
150
+ response: Response = self.client.amazon.scrape_product(query=asin, domain=domain_code, parse=True)
151
+
152
+ product_info = {"found": False, "asin": asin, "domain": f"amazon.{domain_code}"}
153
+
154
+ if response.results and len(response.results) > 0:
155
+ result = response.results[0]
156
+
157
+ if hasattr(result, "content") and result.content:
158
+ content = result.content
159
+ if isinstance(content, dict):
160
+ product_info.update(
161
+ {
162
+ "found": True,
163
+ "title": content.get("title", "").strip(),
164
+ "price": content.get("price", 0),
165
+ "currency": content.get("currency", ""),
166
+ "rating": content.get("rating", 0),
167
+ "reviews_count": content.get("reviews_count", 0),
168
+ "url": content.get("url", ""),
169
+ "description": content.get("description", "").strip(),
170
+ "stock_status": content.get("stock", "").strip(),
171
+ "brand": content.get("brand", "").strip(),
172
+ "images": content.get("images", [])[:3],
173
+ "bullet_points": content.get("bullet_points", [])[:5]
174
+ if content.get("bullet_points")
175
+ else [],
176
+ }
177
+ )
178
+
179
+ elif hasattr(result, "content_parsed") and result.content_parsed:
180
+ content = result.content_parsed
181
+ product_info.update(
182
+ {
183
+ "found": True,
184
+ "title": getattr(content, "title", "").strip(),
185
+ "price": getattr(content, "price", 0),
186
+ "currency": getattr(content, "currency", ""),
187
+ "rating": getattr(content, "rating", 0),
188
+ "reviews_count": getattr(content, "reviews_count", 0),
189
+ "url": getattr(content, "url", ""),
190
+ "description": getattr(content, "description", "").strip(),
191
+ "stock_status": getattr(content, "stock", "").strip(),
192
+ "brand": getattr(content, "brand", "").strip(),
193
+ "images": getattr(content, "images", [])[:3],
194
+ "bullet_points": getattr(content, "bullet_points", [])[:5]
195
+ if getattr(content, "bullet_points", None)
196
+ else [],
197
+ }
198
+ )
199
+
200
+ response_data = {
201
+ "tool": "get_amazon_product",
202
+ "asin": asin,
203
+ "product_info": product_info,
204
+ }
205
+
206
+ log_info(f"Amazon product lookup completed for ASIN {asin}")
207
+ return json.dumps(response_data, indent=2)
208
+
209
+ except Exception as e:
210
+ error_msg = f"Amazon product lookup failed: {str(e)}"
211
+ log_error(error_msg)
212
+ return self._error_response("get_amazon_product", error_msg, {"asin": asin})
213
+
214
+ def search_amazon_products(self, query: str, domain_code: str = "com") -> str:
215
+ """Search Amazon for products and return search results.
216
+
217
+ Args:
218
+ query: Product search query
219
+ domain_code: Amazon domain (e.g., "com", "co.uk", "de", default: "com")
220
+
221
+ Returns:
222
+ JSON string with search results containing:
223
+ - success: boolean indicating if search was successful
224
+ - query: the original search query
225
+ - total_products: number of products found
226
+ - products: list of product results with title, asin, price, rating, etc.
227
+ """
228
+ try:
229
+ if not query or not isinstance(query, str) or len(query.strip()) == 0:
230
+ return self._error_response("search_amazon_products", "Query cannot be empty")
231
+
232
+ if not isinstance(domain_code, str) or len(domain_code) > 10:
233
+ return self._error_response(
234
+ "search_amazon_products", "Domain must be a valid string (e.g., 'com', 'co.uk')"
235
+ )
236
+
237
+ query = query.strip()
238
+ log_info(f"Amazon search: '{query}' on amazon.{domain_code}")
239
+
240
+ response: Response = self.client.amazon.scrape_search(query=query, domain=domain_code, parse=True)
241
+
242
+ # Extract search results
243
+ products = []
244
+
245
+ if response.results and len(response.results) > 0:
246
+ result = response.results[0]
247
+
248
+ if hasattr(result, "content") and result.content:
249
+ content = result.content
250
+ if isinstance(content, dict) and "results" in content:
251
+ organic_results = content["results"].get("organic", [])
252
+
253
+ for item in organic_results:
254
+ products.append(
255
+ {
256
+ "title": item.get("title", "").strip(),
257
+ "asin": item.get("asin", "").strip(),
258
+ "price": item.get("price", 0),
259
+ "currency": item.get("currency", ""),
260
+ "rating": item.get("rating", 0),
261
+ "reviews_count": item.get("reviews_count", 0),
262
+ "url": item.get("url", "").strip(),
263
+ "position": item.get("pos", 0),
264
+ "image": item.get("image", "").strip(),
265
+ }
266
+ )
267
+
268
+ elif hasattr(result, "content_parsed") and result.content_parsed:
269
+ content = result.content_parsed
270
+ if hasattr(content, "results") and content.results:
271
+ if hasattr(content.results, "organic"):
272
+ organic_results = content.results.organic
273
+ for item in organic_results:
274
+ products.append(
275
+ {
276
+ "title": getattr(item, "title", "").strip(),
277
+ "asin": getattr(item, "asin", "").strip(),
278
+ "price": getattr(item, "price", 0),
279
+ "currency": getattr(item, "currency", ""),
280
+ "rating": getattr(item, "rating", 0),
281
+ "reviews_count": getattr(item, "reviews_count", 0),
282
+ "url": getattr(item, "url", "").strip(),
283
+ "position": getattr(item, "pos", 0),
284
+ "image": getattr(item, "image", "").strip(),
285
+ }
286
+ )
287
+
288
+ response_data = {
289
+ "tool": "search_amazon_products",
290
+ "query": query,
291
+ "products": products,
292
+ }
293
+
294
+ log_debug(f"Amazon search completed. Found {len(products)} products")
295
+ return json.dumps(response_data, indent=2)
296
+
297
+ except Exception as e:
298
+ error_msg = f"Amazon search failed: {str(e)}"
299
+ log_error(error_msg)
300
+ return self._error_response("search_amazon_products", error_msg, {"query": query})
301
+
302
+ def scrape_website(self, url: str, render_javascript: bool = False) -> str:
303
+ """Scrape content from any website URL.
304
+
305
+ Args:
306
+ url: Website URL to scrape (must start with http:// or ht ps://)
307
+ render_javascript: Whether to enable JavaScript rendering for dynamic content (default: False)
308
+
309
+ Returns:
310
+ JSON of results
311
+ """
312
+ try:
313
+ if not url or not isinstance(url, str):
314
+ return self._error_response("scrape_website", "URL is required and must be a string")
315
+
316
+ url = url.strip()
317
+ if not url.startswith(("http://", "https://")):
318
+ return self._error_response(
319
+ "scrape_website", f"Invalid URL format: {url}. Must start with http:// or https://"
320
+ )
321
+
322
+ try:
323
+ parsed_url = urlparse(url)
324
+ if not parsed_url.netloc:
325
+ return self._error_response("scrape_website", f"Invalid URL format: {url}. Missing domain name")
326
+ except Exception:
327
+ return self._error_response("scrape_website", f"Invalid URL format: {url}")
328
+
329
+ if not isinstance(render_javascript, bool):
330
+ return self._error_response("scrape_website", "render_javascript must be a boolean (True/False)")
331
+
332
+ log_debug(f"Website scraping: {url} (JS rendering: {render_javascript})")
333
+
334
+ response: Response = self.client.universal.scrape_url(
335
+ url=url, render=render.HTML if render_javascript else None, parse=True
336
+ )
337
+
338
+ content_info = {"url": url, "javascript_rendered": render_javascript}
339
+
340
+ if response.results and len(response.results) > 0:
341
+ result = response.results[0]
342
+ content = result.content
343
+ status_code = getattr(result, "status_code", None)
344
+
345
+ content_preview = ""
346
+ content_length = 0
347
+
348
+ if content:
349
+ try:
350
+ content_str = str(content)
351
+ content_length = len(content_str)
352
+ content_preview = content_str[:1000] if content_length > 1000 else content_str
353
+ content_info["scraped"] = True
354
+ except Exception as e:
355
+ log_debug(f"Could not process content: {e}")
356
+ content_preview = "Content available but processing failed"
357
+ content_info["scraped"] = False
358
+
359
+ content_info.update(
360
+ {
361
+ "status_code": status_code,
362
+ "content_length": content_length,
363
+ "content_preview": content_preview.strip(),
364
+ "has_content": content_length > 0,
365
+ }
366
+ )
367
+
368
+ response_data = {
369
+ "tool": "scrape_website",
370
+ "url": url,
371
+ "content_info": content_info,
372
+ }
373
+
374
+ log_debug(f"Website scraping completed for {url}")
375
+ return json.dumps(response_data, indent=2)
376
+
377
+ except Exception as e:
378
+ error_msg = f"Website scraping failed: {str(e)}"
379
+ log_error(error_msg)
380
+ return self._error_response("scrape_website", error_msg, {"url": url})
381
+
382
+ def _error_response(self, tool_name: str, error_message: str, context: Optional[Dict[str, Any]] = None) -> str:
383
+ """Generate a standardized error response."""
384
+ error_data = {"tool": tool_name, "error": error_message, "context": context or {}}
385
+ return json.dumps(error_data, indent=2)
agno/tools/pandas.py ADDED
@@ -0,0 +1,102 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from agno.tools import Toolkit
4
+ from agno.utils.log import log_debug, logger
5
+
6
+ try:
7
+ import pandas as pd
8
+ except ImportError:
9
+ raise ImportError("`pandas` not installed. Please install using `pip install pandas`.")
10
+
11
+
12
+ class PandasTools(Toolkit):
13
+ def __init__(
14
+ self,
15
+ enable_create_pandas_dataframe: bool = True,
16
+ enable_run_dataframe_operation: bool = True,
17
+ all: bool = False,
18
+ **kwargs,
19
+ ):
20
+ self.dataframes: Dict[str, pd.DataFrame] = {}
21
+
22
+ tools: List[Any] = []
23
+ if all or enable_create_pandas_dataframe:
24
+ tools.append(self.create_pandas_dataframe)
25
+ if all or enable_run_dataframe_operation:
26
+ tools.append(self.run_dataframe_operation)
27
+
28
+ super().__init__(name="pandas_tools", tools=tools, **kwargs)
29
+
30
+ def create_pandas_dataframe(
31
+ self, dataframe_name: str, create_using_function: str, function_parameters: Dict[str, Any]
32
+ ) -> str:
33
+ """Creates a pandas dataframe named `dataframe_name` by running a function `create_using_function` with the parameters `function_parameters`.
34
+ Returns the created dataframe name as a string if successful, otherwise returns an error message.
35
+
36
+ For Example:
37
+ - To create a dataframe `csv_data` by reading a CSV file, use: {"dataframe_name": "csv_data", "create_using_function": "read_csv", "function_parameters": {"filepath_or_buffer": "data.csv"}}
38
+ - To create a dataframe `csv_data` by reading a JSON file, use: {"dataframe_name": "json_data", "create_using_function": "read_json", "function_parameters": {"path_or_buf": "data.json"}}
39
+
40
+ :param dataframe_name: The name of the dataframe to create.
41
+ :param create_using_function: The function to use to create the dataframe.
42
+ :param function_parameters: The parameters to pass to the function.
43
+ :return: The name of the created dataframe if successful, otherwise an error message.
44
+ """
45
+ try:
46
+ log_debug(f"Creating dataframe: {dataframe_name}")
47
+ log_debug(f"Using function: {create_using_function}")
48
+ log_debug(f"With parameters: {function_parameters}")
49
+
50
+ if dataframe_name in self.dataframes:
51
+ return f"Dataframe already exists: {dataframe_name}"
52
+
53
+ # Create the dataframe
54
+ dataframe = getattr(pd, create_using_function)(**function_parameters)
55
+ if dataframe is None:
56
+ return f"Error creating dataframe: {dataframe_name}"
57
+ if not isinstance(dataframe, pd.DataFrame):
58
+ return f"Error creating dataframe: {dataframe_name}"
59
+ if dataframe.empty:
60
+ return f"Dataframe is empty: {dataframe_name}"
61
+ self.dataframes[dataframe_name] = dataframe
62
+ log_debug(f"Created dataframe: {dataframe_name}")
63
+ return dataframe_name
64
+ except Exception as e:
65
+ logger.error(f"Error creating dataframe: {e}")
66
+ return f"Error creating dataframe: {e}"
67
+
68
+ def run_dataframe_operation(self, dataframe_name: str, operation: str, operation_parameters: Dict[str, Any]) -> str:
69
+ """Runs an operation `operation` on a dataframe `dataframe_name` with the parameters `operation_parameters`.
70
+ Returns the result of the operation as a string if successful, otherwise returns an error message.
71
+
72
+ For Example:
73
+ - To get the first 5 rows of a dataframe `csv_data`, use: {"dataframe_name": "csv_data", "operation": "head", "operation_parameters": {"n": 5}}
74
+ - To get the last 5 rows of a dataframe `csv_data`, use: {"dataframe_name": "csv_data", "operation": "tail", "operation_parameters": {"n": 5}}
75
+
76
+ :param dataframe_name: The name of the dataframe to run the operation on.
77
+ :param operation: The operation to run on the dataframe.
78
+ :param operation_parameters: The parameters to pass to the operation.
79
+ :return: The result of the operation if successful, otherwise an error message.
80
+ """
81
+ try:
82
+ log_debug(f"Running operation: {operation}")
83
+ log_debug(f"On dataframe: {dataframe_name}")
84
+ log_debug(f"With parameters: {operation_parameters}")
85
+
86
+ # Get the dataframe
87
+ dataframe = self.dataframes.get(dataframe_name)
88
+
89
+ # Run the operation
90
+ result = getattr(dataframe, operation)(**operation_parameters)
91
+
92
+ log_debug(f"Ran operation: {operation}")
93
+ try:
94
+ try:
95
+ return result.to_string()
96
+ except AttributeError:
97
+ return str(result)
98
+ except Exception:
99
+ return "Operation ran successfully"
100
+ except Exception as e:
101
+ logger.error(f"Error running operation: {e}")
102
+ return f"Error running operation: {e}"