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/crawl4ai.py ADDED
@@ -0,0 +1,158 @@
1
+ import asyncio
2
+ from typing import Any, Dict, List, Optional, Union
3
+
4
+ from agno.tools import Toolkit
5
+ from agno.utils.log import log_debug, log_warning
6
+
7
+ try:
8
+ from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig
9
+ except ImportError:
10
+ raise ImportError("`crawl4ai` not installed. Please install using `pip install crawl4ai`")
11
+
12
+
13
+ class Crawl4aiTools(Toolkit):
14
+ def __init__(
15
+ self,
16
+ max_length: Optional[int] = 5000,
17
+ timeout: int = 60,
18
+ use_pruning: bool = False,
19
+ pruning_threshold: float = 0.48,
20
+ bm25_threshold: float = 1.0,
21
+ headless: bool = True,
22
+ wait_until: str = "domcontentloaded",
23
+ enable_crawl: bool = True,
24
+ all: bool = False,
25
+ **kwargs,
26
+ ):
27
+ tools = []
28
+ if all or enable_crawl:
29
+ tools.append(self.crawl)
30
+
31
+ super().__init__(name="crawl4ai_tools", tools=tools, **kwargs)
32
+ self.max_length = max_length
33
+ self.timeout = timeout
34
+ self.use_pruning = use_pruning
35
+ self.pruning_threshold = pruning_threshold
36
+ self.bm25_threshold = bm25_threshold
37
+ self.wait_until = wait_until
38
+ self.headless = headless
39
+
40
+ def _build_config(self, search_query: Optional[str] = None) -> Dict[str, Any]:
41
+ """Build CrawlerRunConfig parameters from toolkit settings."""
42
+ config_params = {
43
+ "page_timeout": self.timeout * 1000, # Convert to milliseconds
44
+ "wait_until": self.wait_until,
45
+ "cache_mode": "bypass", # Don't use cache for fresh results
46
+ "verbose": False,
47
+ }
48
+
49
+ # Handle content filtering
50
+ if self.use_pruning or search_query:
51
+ try:
52
+ from crawl4ai.content_filter_strategy import BM25ContentFilter, PruningContentFilter
53
+ from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator
54
+
55
+ if search_query:
56
+ # Use BM25 for query-specific extraction
57
+ content_filter = BM25ContentFilter(user_query=search_query, bm25_threshold=self.bm25_threshold)
58
+ log_debug(f"Using BM25ContentFilter for query: {search_query}")
59
+ else:
60
+ # Use pruning for general cleanup
61
+ content_filter = PruningContentFilter(
62
+ threshold=self.pruning_threshold, threshold_type="fixed", min_word_threshold=2
63
+ )
64
+ log_debug("Using PruningContentFilter for general cleanup")
65
+
66
+ config_params["markdown_generator"] = DefaultMarkdownGenerator(content_filter=content_filter)
67
+ log_debug("Using DefaultMarkdownGenerator with content_filter")
68
+ except ImportError:
69
+ # If advanced features not available, continue without them
70
+ log_warning("crawl4ai.content_filter_strategy or crawl4ai.markdown_generation_strategy not installed")
71
+ pass
72
+
73
+ return config_params
74
+
75
+ def crawl(self, url: Union[str, List[str]], search_query: Optional[str] = None) -> Union[str, Dict[str, str]]:
76
+ """
77
+ Crawl URLs and extract their text content.
78
+
79
+ Args:
80
+ url: Single URL string or list of URLs to crawl
81
+ search_query: Optional query string to filter content using BM25 algorithm
82
+
83
+ Returns:
84
+ The extracted text content from the URL(s)
85
+ """
86
+ if not url:
87
+ return "Error: No URL provided"
88
+
89
+ # Handle single URL
90
+ if isinstance(url, str):
91
+ return asyncio.run(self._async_crawl(url, search_query))
92
+
93
+ # Handle multiple URLs
94
+ results = {}
95
+ for single_url in url:
96
+ results[single_url] = asyncio.run(self._async_crawl(single_url, search_query))
97
+ return results
98
+
99
+ async def _async_crawl(self, url: str, search_query: Optional[str] = None) -> str:
100
+ """Crawl a single URL and extract content."""
101
+ try:
102
+ # Use BrowserConfig to suppress crawl4ai logs
103
+ browser_config = BrowserConfig(
104
+ headless=self.headless,
105
+ verbose=False,
106
+ )
107
+
108
+ async with AsyncWebCrawler(config=browser_config) as crawler:
109
+ # Build configuration from parameters
110
+ config_params = self._build_config(search_query)
111
+
112
+ config = CrawlerRunConfig(**config_params)
113
+ log_debug(f"Crawling {url} with config: {config}")
114
+ result = await crawler.arun(url=url, config=config)
115
+
116
+ # Process the result
117
+ if not result:
118
+ return "Error: No content found"
119
+
120
+ log_debug(f"Result attributes: {dir(result)}")
121
+ log_debug(f"Result success: {getattr(result, 'success', 'N/A')}")
122
+
123
+ # Try to get markdown content
124
+ content = ""
125
+ if hasattr(result, "fit_markdown") and result.fit_markdown:
126
+ content = result.fit_markdown
127
+ log_debug("Using fit_markdown")
128
+ elif hasattr(result, "markdown") and result.markdown:
129
+ if hasattr(result.markdown, "raw_markdown"):
130
+ content = result.markdown.raw_markdown
131
+ log_debug("Using markdown.raw_markdown")
132
+ else:
133
+ content = str(result.markdown)
134
+ log_debug("Using str(markdown)")
135
+ else:
136
+ # Try to get any text content
137
+ if hasattr(result, "text"):
138
+ content = result.text
139
+ log_debug("Using text attribute")
140
+ elif hasattr(result, "html"):
141
+ log_warning("Only HTML available, no markdown extracted")
142
+ return "Error: Could not extract markdown from page"
143
+
144
+ if not content:
145
+ log_warning(f"No content extracted. Result type: {type(result)}")
146
+ return "Error: No readable content extracted"
147
+
148
+ log_debug(f"Extracted content length: {len(content)}")
149
+
150
+ # Truncate if needed
151
+ if self.max_length and len(content) > self.max_length:
152
+ content = content[: self.max_length] + "..."
153
+
154
+ return content
155
+
156
+ except Exception as e:
157
+ log_warning(f"Exception during crawl: {str(e)}")
158
+ return f"Error crawling {url}: {str(e)}"
@@ -0,0 +1,185 @@
1
+ import csv
2
+ import json
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Optional, Union
5
+
6
+ from agno.tools import Toolkit
7
+ from agno.utils.log import log_debug, log_info, logger
8
+
9
+
10
+ class CsvTools(Toolkit):
11
+ def __init__(
12
+ self,
13
+ csvs: Optional[List[Union[str, Path]]] = None,
14
+ row_limit: Optional[int] = None,
15
+ duckdb_connection: Optional[Any] = None,
16
+ duckdb_kwargs: Optional[Dict[str, Any]] = None,
17
+ enable_read_csv_file: bool = True,
18
+ enable_list_csv_files: bool = True,
19
+ enable_get_columns: bool = True,
20
+ enable_query_csv_file: bool = True,
21
+ all: bool = False,
22
+ **kwargs,
23
+ ):
24
+ self.csvs: List[Path] = []
25
+ if csvs:
26
+ for _csv in csvs:
27
+ if isinstance(_csv, str):
28
+ self.csvs.append(Path(_csv))
29
+ elif isinstance(_csv, Path):
30
+ self.csvs.append(_csv)
31
+ else:
32
+ raise ValueError(f"Invalid csv file: {_csv}")
33
+ self.row_limit = row_limit
34
+ self.duckdb_connection: Optional[Any] = duckdb_connection
35
+ self.duckdb_kwargs: Optional[Dict[str, Any]] = duckdb_kwargs
36
+
37
+ tools: List[Any] = []
38
+ if all or enable_read_csv_file:
39
+ tools.append(self.read_csv_file)
40
+ if all or enable_list_csv_files:
41
+ tools.append(self.list_csv_files)
42
+ if all or enable_get_columns:
43
+ tools.append(self.get_columns)
44
+ if all or enable_query_csv_file:
45
+ try:
46
+ import duckdb # noqa: F401
47
+
48
+ tools.append(self.query_csv_file)
49
+ except ImportError:
50
+ logger.warning("`duckdb` not installed. Query functionality disabled.")
51
+
52
+ super().__init__(name="csv_tools", tools=tools, **kwargs)
53
+
54
+ def list_csv_files(self) -> str:
55
+ """Returns a list of available csv files
56
+
57
+ Returns:
58
+ str: List of available csv files
59
+ """
60
+ return json.dumps([_csv.stem for _csv in self.csvs])
61
+
62
+ def read_csv_file(self, csv_name: str, row_limit: Optional[int] = None) -> str:
63
+ """Use this function to read the contents of a csv file `name` without the extension.
64
+
65
+ Args:
66
+ csv_name (str): The name of the csv file to read without the extension.
67
+ row_limit (Optional[int]): The number of rows to return. None returns all rows. Defaults to None.
68
+
69
+ Returns:
70
+ str: The contents of the csv file if successful, otherwise returns an error message.
71
+ """
72
+ try:
73
+ if csv_name not in [_csv.stem for _csv in self.csvs]:
74
+ return f"File: {csv_name} not found, please use one of {self.list_csv_files()}"
75
+
76
+ log_info(f"Reading file: {csv_name}")
77
+ file_path = [_csv for _csv in self.csvs if _csv.stem == csv_name][0]
78
+
79
+ # Read the csv file
80
+ csv_data = []
81
+ _row_limit = row_limit or self.row_limit
82
+ with open(str(file_path), newline="") as csvfile:
83
+ reader = csv.DictReader(csvfile)
84
+ if _row_limit is not None:
85
+ csv_data = [row for row in reader][:_row_limit]
86
+ else:
87
+ csv_data = [row for row in reader]
88
+ return json.dumps(csv_data)
89
+ except Exception as e:
90
+ logger.error(f"Error reading csv: {e}")
91
+ return f"Error reading csv: {e}"
92
+
93
+ def get_columns(self, csv_name: str) -> str:
94
+ """Use this function to get the columns of the csv file `csv_name` without the extension.
95
+
96
+ Args:
97
+ csv_name (str): The name of the csv file to get the columns from without the extension.
98
+
99
+ Returns:
100
+ str: The columns of the csv file if successful, otherwise returns an error message.
101
+ """
102
+ try:
103
+ if csv_name not in [_csv.stem for _csv in self.csvs]:
104
+ return f"File: {csv_name} not found, please use one of {self.list_csv_files()}"
105
+
106
+ log_info(f"Reading columns from file: {csv_name}")
107
+ file_path = [_csv for _csv in self.csvs if _csv.stem == csv_name][0]
108
+
109
+ # Get the columns of the csv file
110
+ with open(str(file_path), newline="") as csvfile:
111
+ reader = csv.DictReader(csvfile)
112
+ columns = reader.fieldnames
113
+
114
+ return json.dumps(columns)
115
+ except Exception as e:
116
+ logger.error(f"Error getting columns: {e}")
117
+ return f"Error getting columns: {e}"
118
+
119
+ def query_csv_file(self, csv_name: str, sql_query: str) -> str:
120
+ """Use this function to run a SQL query on csv file `csv_name` without the extension.
121
+ The Table name is the name of the csv file without the extension.
122
+ The SQL Query should be a valid DuckDB SQL query.
123
+ Always wrap column names with double quotes if they contain spaces or special characters
124
+ Remember to escape the quotes in th e JSON string (use \")
125
+ Use single quotes for string values
126
+
127
+ Args:
128
+ csv_name (str): The name of the csv file to query
129
+ sql_query (str): The SQL Query to run on the csv file.
130
+
131
+ Returns:
132
+ str: The query results if successful, otherwise returns an error message.
133
+ """
134
+ try:
135
+ import duckdb
136
+
137
+ if csv_name not in [_csv.stem for _csv in self.csvs]:
138
+ return f"File: {csv_name} not found, please use one of {self.list_csv_files()}"
139
+
140
+ # Load the csv file into duckdb
141
+ log_info(f"Loading csv file: {csv_name}")
142
+ file_path = [_csv for _csv in self.csvs if _csv.stem == csv_name][0]
143
+
144
+ # Create duckdb connection
145
+ con = self.duckdb_connection
146
+ if not self.duckdb_connection:
147
+ con = duckdb.connect(**(self.duckdb_kwargs or {}))
148
+ if con is None:
149
+ logger.error("Error connecting to DuckDB")
150
+ return "Error connecting to DuckDB, please check the connection."
151
+
152
+ # Create a table from the csv file
153
+ con.execute(
154
+ f"CREATE TABLE {csv_name} AS SELECT * FROM read_csv('{file_path}', ignore_errors=false, auto_detect=true)"
155
+ )
156
+
157
+ # -*- Format the SQL Query
158
+ # Remove backticks
159
+ formatted_sql = sql_query.replace("`", "")
160
+ # If there are multiple statements, only run the first one
161
+ formatted_sql = formatted_sql.split(";")[0]
162
+ # -*- Run the SQL Query
163
+ log_info(f"Running query: {formatted_sql}")
164
+ query_result = con.sql(formatted_sql)
165
+ result_output = "No output"
166
+ if query_result is not None:
167
+ try:
168
+ results_as_python_objects = query_result.fetchall()
169
+ result_rows = []
170
+ for row in results_as_python_objects:
171
+ if len(row) == 1:
172
+ result_rows.append(str(row[0]))
173
+ else:
174
+ result_rows.append(",".join(str(x) for x in row))
175
+
176
+ result_data = "\n".join(result_rows)
177
+ result_output = ",".join(query_result.columns) + "\n" + result_data
178
+ except AttributeError:
179
+ result_output = str(query_result)
180
+
181
+ log_debug(f"Query result: {result_output}")
182
+ return result_output
183
+ except Exception as e:
184
+ logger.error(f"Error querying csv: {e}")
185
+ return f"Error querying csv: {e}"
agno/tools/dalle.py ADDED
@@ -0,0 +1,110 @@
1
+ from os import getenv
2
+ from typing import Any, List, Literal, Optional
3
+ from uuid import uuid4
4
+
5
+ from agno.media import Image
6
+ from agno.tools import Toolkit
7
+ from agno.tools.function import ToolResult
8
+ from agno.utils.log import log_debug, logger
9
+
10
+ try:
11
+ from openai import OpenAI
12
+ from openai.types.images_response import ImagesResponse
13
+ except ImportError:
14
+ raise ImportError("`openai` not installed. Please install using `pip install openai`")
15
+
16
+
17
+ class DalleTools(Toolkit):
18
+ def __init__(
19
+ self,
20
+ model: str = "dall-e-3",
21
+ n: int = 1,
22
+ size: Optional[Literal["256x256", "512x512", "1024x1024", "1792x1024", "1024x1792"]] = "1024x1024",
23
+ quality: Literal["standard", "hd"] = "standard",
24
+ style: Literal["vivid", "natural"] = "vivid",
25
+ api_key: Optional[str] = None,
26
+ enable_create_image: bool = True,
27
+ all: bool = False,
28
+ **kwargs,
29
+ ):
30
+ self.model = model
31
+ self.n = n
32
+ self.size = size
33
+ self.quality = quality
34
+ self.style = style
35
+ self.api_key = api_key or getenv("OPENAI_API_KEY")
36
+
37
+ # Validations
38
+ if model not in ["dall-e-3", "dall-e-2"]:
39
+ raise ValueError("Invalid model. Please choose from 'dall-e-3' or 'dall-e-2'.")
40
+ if size not in ["256x256", "512x512", "1024x1024", "1792x1024", "1024x1792"]:
41
+ raise ValueError(
42
+ "Invalid size. Please choose from '256x256', '512x512', '1024x1024', '1792x1024', '1024x1792'."
43
+ )
44
+ if quality not in ["standard", "hd"]:
45
+ raise ValueError("Invalid quality. Please choose from 'standard' or 'hd'.")
46
+ if not isinstance(n, int) or n <= 0:
47
+ raise ValueError("Invalid number of images. Please provide a positive integer.")
48
+ if model == "dall-e-3" and n > 1:
49
+ raise ValueError("Dall-e-3 only supports a single image generation.")
50
+
51
+ if not self.api_key:
52
+ logger.error("OPENAI_API_KEY not set. Please set the OPENAI_API_KEY environment variable.")
53
+
54
+ tools: List[Any] = []
55
+ if all or enable_create_image:
56
+ tools.append(self.create_image)
57
+
58
+ super().__init__(name="dalle", tools=tools, **kwargs)
59
+
60
+ # TODO:
61
+ # - Add support for response_format
62
+ # - Add support for saving images
63
+ # - Add support for editing images
64
+
65
+ def create_image(self, prompt: str) -> ToolResult:
66
+ """Use this function to generate an image for a prompt.
67
+
68
+ Args:
69
+ prompt (str): A text description of the desired image.
70
+
71
+ Returns:
72
+ ToolResult: Result containing the message and generated images.
73
+ """
74
+ if not self.api_key:
75
+ return ToolResult(content="Please set the OPENAI_API_KEY")
76
+
77
+ try:
78
+ client = OpenAI(api_key=self.api_key)
79
+ log_debug(f"Generating image using prompt: {prompt}")
80
+ response: ImagesResponse = client.images.generate(
81
+ prompt=prompt,
82
+ model=self.model,
83
+ n=self.n,
84
+ quality=self.quality,
85
+ size=self.size,
86
+ style=self.style,
87
+ )
88
+ log_debug("Image generated successfully")
89
+
90
+ generated_images = []
91
+ response_str = ""
92
+ if response.data:
93
+ for img in response.data:
94
+ if img.url:
95
+ image = Image(
96
+ id=str(uuid4()),
97
+ url=img.url,
98
+ original_prompt=prompt,
99
+ revised_prompt=img.revised_prompt,
100
+ )
101
+ generated_images.append(image)
102
+ response_str += f"Image has been generated at the URL {img.url}\n"
103
+
104
+ return ToolResult(
105
+ content=response_str or "No images were generated",
106
+ images=generated_images if generated_images else None,
107
+ )
108
+ except Exception as e:
109
+ logger.error(f"Failed to generate image: {e}")
110
+ return ToolResult(content=f"Error: {e}")