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/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ from agno.tools.decorator import tool
2
+ from agno.tools.function import Function, FunctionCall
3
+ from agno.tools.toolkit import Toolkit
4
+
5
+ __all__ = [
6
+ "tool",
7
+ "Function",
8
+ "FunctionCall",
9
+ "Toolkit",
10
+ ]
agno/tools/agentql.py ADDED
@@ -0,0 +1,120 @@
1
+ from os import getenv
2
+ from typing import Any, List, Optional
3
+
4
+ from agno.tools import Toolkit
5
+ from agno.utils.log import log_info
6
+
7
+ try:
8
+ import agentql
9
+ from playwright.sync_api import sync_playwright
10
+ except ImportError:
11
+ raise ImportError("`agentql` not installed. Please install using `pip install agentql`")
12
+
13
+
14
+ class AgentQLTools(Toolkit):
15
+ def __init__(
16
+ self,
17
+ api_key: Optional[str] = None,
18
+ enable_scrape_website: bool = True,
19
+ enable_custom_scrape_website: bool = False,
20
+ all: bool = False,
21
+ agentql_query: str = "",
22
+ **kwargs,
23
+ ):
24
+ self.api_key = api_key or getenv("AGENTQL_API_KEY")
25
+ if not self.api_key:
26
+ raise ValueError("AGENTQL_API_KEY not set. Please set the AGENTQL_API_KEY environment variable.")
27
+
28
+ self.agentql_query = agentql_query
29
+
30
+ tools: List[Any] = []
31
+ if all or enable_scrape_website:
32
+ tools.append(self.scrape_website)
33
+ if all or enable_custom_scrape_website or (agentql_query and not all and not enable_custom_scrape_website):
34
+ if agentql_query:
35
+ log_info("Custom AgentQL query provided. Registering custom scrape function.")
36
+ tools.append(self.custom_scrape_website)
37
+
38
+ super().__init__(name="agentql_tools", tools=tools, **kwargs)
39
+
40
+ def scrape_website(self, url: str) -> str:
41
+ """
42
+ Scrape all text content from a website using AgentQL.
43
+
44
+ Args:
45
+ url (str): The URL of the website to scrape
46
+
47
+ Returns:
48
+ str: Extracted text content or error message
49
+ """
50
+ if not url:
51
+ return "No URL provided"
52
+
53
+ TEXT_SEARCH_QUERY = """
54
+ {
55
+ text_content[]
56
+ }
57
+ """
58
+
59
+ try:
60
+ with sync_playwright() as playwright, playwright.chromium.launch(headless=False) as browser:
61
+ page = agentql.wrap(browser.new_page())
62
+ page.goto(url)
63
+
64
+ try:
65
+ # Get response from AgentQL query
66
+ response = page.query_data(TEXT_SEARCH_QUERY)
67
+
68
+ # Extract text based on response format
69
+ if isinstance(response, dict) and "text_content" in response:
70
+ text_items = [item for item in response["text_content"] if item and item.strip()]
71
+
72
+ deduplicated = list(set(text_items))
73
+ return " ".join(deduplicated)
74
+
75
+ except Exception as e:
76
+ return f"Error extracting text: {e}"
77
+ except Exception as e:
78
+ return f"Error launching browser: {e}"
79
+
80
+ return "No text content found"
81
+
82
+ def custom_scrape_website(self, url: str) -> str:
83
+ """
84
+ Scrape a website using a custom AgentQL query.
85
+
86
+ Args:
87
+ url (str): The URL of the website to scrape
88
+
89
+ Returns:
90
+ str: Extracted text content or error message
91
+ """
92
+ if not url:
93
+ return "No URL provided"
94
+
95
+ if self.agentql_query == "":
96
+ return "Custom AgentQL query not provided. Please provide a custom AgentQL query."
97
+
98
+ try:
99
+ with sync_playwright() as playwright, playwright.chromium.launch(headless=False) as browser:
100
+ page = agentql.wrap(browser.new_page())
101
+ page.goto(url)
102
+
103
+ try:
104
+ # Get response from AgentQL query
105
+ response = page.query_data(self.agentql_query)
106
+
107
+ # Extract text based on response format
108
+ if isinstance(response, dict):
109
+ items = [item for item in response]
110
+ text_items = [text_item for text_item in items if text_item]
111
+
112
+ deduplicated = list(set(text_items))
113
+ return " ".join(deduplicated)
114
+
115
+ except Exception as e:
116
+ return f"Error extracting text: {e}"
117
+ except Exception as e:
118
+ return f"Error launching browser: {e}"
119
+
120
+ return "No text content found"
agno/tools/airflow.py ADDED
@@ -0,0 +1,69 @@
1
+ from pathlib import Path
2
+ from typing import Any, List, Optional, Union
3
+
4
+ from agno.tools import Toolkit
5
+ from agno.utils.log import log_debug, log_info, logger
6
+
7
+
8
+ class AirflowTools(Toolkit):
9
+ def __init__(
10
+ self,
11
+ dags_dir: Optional[Union[Path, str]] = None,
12
+ enable_save_dag_file: bool = True,
13
+ enable_read_dag_file: bool = True,
14
+ all: bool = False,
15
+ **kwargs,
16
+ ):
17
+ """
18
+ quick start to work with airflow : https://airflow.apache.org/docs/apache-airflow/stable/start.html
19
+ """
20
+
21
+ _dags_dir: Optional[Path] = None
22
+ if dags_dir is not None:
23
+ if isinstance(dags_dir, str):
24
+ _dags_dir = Path.cwd().joinpath(dags_dir)
25
+ else:
26
+ _dags_dir = dags_dir
27
+ self.dags_dir: Path = _dags_dir or Path.cwd()
28
+
29
+ tools: List[Any] = []
30
+ if all or enable_save_dag_file:
31
+ tools.append(self.save_dag_file)
32
+ if all or enable_read_dag_file:
33
+ tools.append(self.read_dag_file)
34
+
35
+ super().__init__(name="AirflowTools", tools=tools, **kwargs)
36
+
37
+ def save_dag_file(self, contents: str, dag_file: str) -> str:
38
+ """Saves python code for an Airflow DAG to a file called `dag_file` and returns the file path if successful.
39
+
40
+ :param contents: The contents of the DAG.
41
+ :param dag_file: The name of the file to save to.
42
+ :return: The file path if successful, otherwise returns an error message.
43
+ """
44
+ try:
45
+ file_path = self.dags_dir.joinpath(dag_file)
46
+ log_debug(f"Saving contents to {file_path}")
47
+ if not file_path.parent.exists():
48
+ file_path.parent.mkdir(parents=True, exist_ok=True)
49
+ file_path.write_text(contents)
50
+ log_info(f"Saved: {file_path}")
51
+ return str(file_path)
52
+ except Exception as e:
53
+ logger.error(f"Error saving to file: {e}")
54
+ return f"Error saving to file: {e}"
55
+
56
+ def read_dag_file(self, dag_file: str) -> str:
57
+ """Reads an Airflow DAG file `dag_file` and returns the contents if successful.
58
+
59
+ :param dag_file: The name of the file to read
60
+ :return: The contents of the file if successful, otherwise returns an error message.
61
+ """
62
+ try:
63
+ log_info(f"Reading file: {dag_file}")
64
+ file_path = self.dags_dir.joinpath(dag_file)
65
+ contents = file_path.read_text()
66
+ return str(contents)
67
+ except Exception as e:
68
+ logger.error(f"Error reading file: {e}")
69
+ return f"Error reading file: {e}"
agno/tools/api.py ADDED
@@ -0,0 +1,122 @@
1
+ import json
2
+ from typing import Any, Dict, List, Literal, Optional
3
+
4
+ from agno.tools import Toolkit
5
+ from agno.utils.log import log_debug, logger
6
+
7
+ try:
8
+ import requests
9
+ from requests.auth import HTTPBasicAuth
10
+ except ImportError:
11
+ raise ImportError("`requests` not installed. Please install using `pip install requests`")
12
+
13
+
14
+ class CustomApiTools(Toolkit):
15
+ def __init__(
16
+ self,
17
+ base_url: Optional[str] = None,
18
+ username: Optional[str] = None,
19
+ password: Optional[str] = None,
20
+ api_key: Optional[str] = None,
21
+ headers: Optional[Dict[str, str]] = None,
22
+ verify_ssl: bool = True,
23
+ timeout: int = 30,
24
+ enable_make_request: bool = True,
25
+ all: bool = False,
26
+ **kwargs,
27
+ ):
28
+ self.base_url = base_url
29
+ self.username = username
30
+ self.password = password
31
+ self.api_key = api_key
32
+ self.default_headers = headers or {}
33
+ self.verify_ssl = verify_ssl
34
+ self.timeout = timeout
35
+
36
+ tools: List[Any] = []
37
+ if all or enable_make_request:
38
+ tools.append(self.make_request)
39
+
40
+ super().__init__(name="api_tools", tools=tools, **kwargs)
41
+
42
+ def _get_auth(self) -> Optional[HTTPBasicAuth]:
43
+ """Get authentication object if credentials are provided."""
44
+ if self.username and self.password:
45
+ return HTTPBasicAuth(self.username, self.password)
46
+ return None
47
+
48
+ def _get_headers(self, additional_headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
49
+ """Combine default headers with additional headers."""
50
+ headers = self.default_headers.copy()
51
+ if self.api_key:
52
+ headers["Authorization"] = f"Bearer {self.api_key}"
53
+ if additional_headers:
54
+ headers.update(additional_headers)
55
+ return headers
56
+
57
+ def make_request(
58
+ self,
59
+ endpoint: str,
60
+ method: Literal["GET", "POST", "PUT", "DELETE", "PATCH"] = "GET",
61
+ params: Optional[Dict[str, Any]] = None,
62
+ data: Optional[Dict[str, Any]] = None,
63
+ headers: Optional[Dict[str, str]] = None,
64
+ json_data: Optional[Dict[str, Any]] = None,
65
+ ) -> str:
66
+ """Make an HTTP request to the API.
67
+
68
+ Args:
69
+ method (str): HTTP method (GET, POST, PUT, DELETE, PATCH)
70
+ endpoint (str): API endpoint (will be combined with base_url if set)
71
+ params (Optional[Dict[str, Any]]): Query parameters
72
+ data (Optional[Dict[str, Any]]): Form data to send
73
+ headers (Optional[Dict[str, str]]): Additional headers
74
+ json_data (Optional[Dict[str, Any]]): JSON data to send
75
+
76
+ Returns:
77
+ str: JSON string containing response data or error message
78
+ """
79
+ try:
80
+ if self.base_url:
81
+ url = f"{self.base_url.rstrip('/')}/{endpoint.lstrip('/')}"
82
+ else:
83
+ url = endpoint
84
+ log_debug(f"Making {method} request to {url}")
85
+
86
+ response = requests.request(
87
+ method=method,
88
+ url=url,
89
+ params=params,
90
+ data=data,
91
+ json=json_data,
92
+ headers=self._get_headers(headers),
93
+ auth=self._get_auth(),
94
+ verify=self.verify_ssl,
95
+ timeout=self.timeout,
96
+ )
97
+
98
+ try:
99
+ response_data = response.json()
100
+ except json.JSONDecodeError:
101
+ response_data = {"text": response.text}
102
+
103
+ result = {
104
+ "status_code": response.status_code,
105
+ "headers": dict(response.headers),
106
+ "data": response_data,
107
+ }
108
+
109
+ if not response.ok:
110
+ logger.error(f"Request failed with status {response.status_code}: {response.text}")
111
+ result["error"] = "Request failed"
112
+
113
+ return json.dumps(result, indent=2)
114
+
115
+ except requests.exceptions.RequestException as e:
116
+ error_message = f"Request failed: {str(e)}"
117
+ logger.error(error_message)
118
+ return json.dumps({"error": error_message}, indent=2)
119
+ except Exception as e:
120
+ error_message = f"Unexpected error: {str(e)}"
121
+ logger.error(error_message)
122
+ return json.dumps({"error": error_message}, indent=2)
agno/tools/apify.py ADDED
@@ -0,0 +1,314 @@
1
+ import json
2
+ import string
3
+ from os import getenv
4
+ from typing import Any, Dict, List, Optional, Tuple, Union
5
+
6
+ import requests
7
+
8
+ from agno.tools import Toolkit
9
+ from agno.utils.log import log_info, logger
10
+
11
+ try:
12
+ from apify_client import ApifyClient
13
+ except ImportError:
14
+ raise ImportError("`apify-client` not installed. Please install using `pip install apify-client`")
15
+
16
+
17
+ class ApifyTools(Toolkit):
18
+ def __init__(self, actors: Optional[Union[str, List[str]]] = None, apify_api_token: Optional[str] = None):
19
+ """Initialize ApifyTools with specific Actors.
20
+
21
+ Args:
22
+ actors (Optional[Union[str, List[str]]]): Single Actor ID as string or list of Actor IDs to register as individual tools
23
+ apify_api_token (Optional[str]): Apify API token (defaults to APIFY_API_TOKEN env variable)
24
+ """
25
+ # Get API token from args or environment
26
+ self.apify_api_token = apify_api_token or getenv("APIFY_API_TOKEN")
27
+ if not self.apify_api_token:
28
+ raise ValueError("APIFY_API_TOKEN environment variable or apify_api_token parameter must be set")
29
+
30
+ self.client = create_apify_client(self.apify_api_token)
31
+
32
+ tools: List[Any] = []
33
+ if actors:
34
+ actor_list = [actors] if isinstance(actors, str) else actors
35
+ for actor_id in actor_list:
36
+ tools.append(actor_id)
37
+
38
+ super().__init__(name="ApifyTools", tools=[], auto_register=False)
39
+
40
+ for actor_id in tools:
41
+ self.register_actor(actor_id)
42
+
43
+ def register_actor(self, actor_id: str) -> None:
44
+ """Register an Apify Actor as a function in the toolkit.
45
+
46
+ Args:
47
+ actor_id (str): ID of the Apify Actor to register (e.g., 'apify/web-scraper')
48
+ """
49
+ try:
50
+ # Get actor metadata
51
+ build = get_actor_latest_build(self.client, actor_id)
52
+ tool_name = actor_id_to_tool_name(actor_id)
53
+
54
+ # Get actor description
55
+ actor_description = build.get("actorDefinition", {}).get("description", "")
56
+ if len(actor_description) > MAX_DESCRIPTION_LEN:
57
+ actor_description = actor_description[:MAX_DESCRIPTION_LEN] + "...(TRUNCATED, TOO LONG)"
58
+
59
+ # Get input schema
60
+ actor_input = build.get("actorDefinition", {}).get("input")
61
+ if not actor_input:
62
+ raise ValueError(f"Input schema not found in the Actor build for Actor: {actor_id}")
63
+
64
+ properties, required = prune_actor_input_schema(actor_input)
65
+
66
+ # Create a wrapper function that calls the Actor
67
+ def actor_function(**kwargs) -> str:
68
+ """Actor function wrapper."""
69
+ try:
70
+ # Params are nested under 'kwargs' key
71
+ if len(kwargs) == 1 and "kwargs" in kwargs:
72
+ kwargs = kwargs["kwargs"]
73
+
74
+ log_info(f"Running Apify Actor {actor_id} with parameters: {kwargs}")
75
+
76
+ # Run the Actor directly with the client
77
+ details = self.client.actor(actor_id=actor_id).call(run_input=kwargs)
78
+ if details is None:
79
+ error_msg = (
80
+ f"Actor: {actor_id} was not started properly and details about the run were not returned"
81
+ )
82
+ raise ValueError(error_msg)
83
+
84
+ run_id = details.get("id")
85
+ if run_id is None:
86
+ error_msg = f"Run ID not found in the run details for Actor: {actor_id}"
87
+ raise ValueError(error_msg)
88
+
89
+ # Get the results
90
+ run = self.client.run(run_id=run_id)
91
+ results = run.dataset().list_items(clean=True).items
92
+
93
+ return json.dumps(results)
94
+
95
+ except Exception as e:
96
+ error_msg = f"Error running Apify Actor {actor_id}: {str(e)}"
97
+ logger.error(error_msg)
98
+ return json.dumps([{"error": error_msg}])
99
+
100
+ docstring = f"{actor_description}\n\nArgs:\n"
101
+
102
+ for param_name, param_info in properties.items():
103
+ param_type = param_info.get("type", "any")
104
+ param_desc = param_info.get("description", "No description available")
105
+ required_marker = "(required)" if param_name in required else "(optional)"
106
+ docstring += f" {param_name} ({param_type}): {required_marker} {param_desc}\n"
107
+
108
+ docstring += """
109
+ Returns:
110
+ str: JSON string containing the Actor's output dataset
111
+ """
112
+
113
+ # Update function metadata
114
+ actor_function.__name__ = tool_name
115
+ actor_function.__doc__ = docstring
116
+
117
+ # Register the function with the toolkit
118
+ self.register(actor_function)
119
+ # Fix params schema
120
+ self.functions[tool_name].parameters = props_to_json_schema(properties, required)
121
+ log_info(f"Registered Apify Actor '{actor_id}' as function '{tool_name}'")
122
+
123
+ except Exception as e:
124
+ logger.error(f"Failed to register Apify Actor '{actor_id}': {str(e)}")
125
+
126
+
127
+ # Constants
128
+ MAX_DESCRIPTION_LEN = 350
129
+ REQUESTS_TIMEOUT_SECS = 300
130
+ APIFY_API_ENDPOINT_GET_DEFAULT_BUILD = "https://api.apify.com/v2/acts/{actor_id}/builds/default"
131
+
132
+
133
+ # Utility functions
134
+ def props_to_json_schema(input_dict, required_fields=None):
135
+ schema: Dict[str, Any] = {"type": "object", "properties": {}, "required": required_fields or []}
136
+
137
+ def infer_array_item_type(prop):
138
+ type_map = {
139
+ "string": "string",
140
+ "int": "number",
141
+ "float": "number",
142
+ "dict": "object",
143
+ "list": "array",
144
+ "bool": "boolean",
145
+ "none": "null",
146
+ }
147
+ if prop.get("items", {}).get("type"):
148
+ return prop["items"]["type"]
149
+ if "prefill" in prop and prop["prefill"] and len(prop["prefill"]) > 0:
150
+ return type_map.get(type(prop["prefill"][0]).__name__.lower(), "string")
151
+ if "default" in prop and prop["default"] and len(prop["default"]) > 0:
152
+ return type_map.get(type(prop["default"][0]).__name__.lower(), "string")
153
+ return "string" # Fallback for arrays like searchStringsArray
154
+
155
+ for key, value in input_dict.items():
156
+ prop_schema: Dict[str, Any] = {}
157
+ prop_type = value.get("type")
158
+
159
+ if "enum" in value:
160
+ prop_schema["enum"] = value["enum"]
161
+
162
+ if "default" in value:
163
+ prop_schema["default"] = value["default"]
164
+ elif "prefill" in value:
165
+ prop_schema["default"] = value["prefill"]
166
+
167
+ if "description" in value:
168
+ prop_schema["description"] = value["description"]
169
+
170
+ # Handle Apify special types first
171
+ if prop_type == "object" and value.get("editor") == "proxy":
172
+ prop_schema["type"] = "object"
173
+ prop_schema["properties"] = {
174
+ "useApifyProxy": {
175
+ "title": "Use Apify Proxy",
176
+ "type": "boolean",
177
+ "description": "Whether to use Apify Proxy - ALWAYS SET TO TRUE.",
178
+ "default": True,
179
+ "examples": [True],
180
+ }
181
+ }
182
+ prop_schema["required"] = ["useApifyProxy"]
183
+ if "default" in value:
184
+ prop_schema["default"] = value["default"]
185
+
186
+ elif prop_type == "array" and value.get("editor") == "requestListSources":
187
+ prop_schema["type"] = "array"
188
+ prop_schema["items"] = {
189
+ "type": "object",
190
+ "title": "Request list source",
191
+ "description": "Request list source",
192
+ "properties": {
193
+ "url": {"title": "URL", "type": "string", "description": "URL of the request list source"}
194
+ },
195
+ }
196
+
197
+ elif prop_type == "array":
198
+ prop_schema["type"] = "array"
199
+ prop_schema["items"] = {
200
+ "type": infer_array_item_type(value),
201
+ "title": value.get("title", "Item"),
202
+ "description": "Item",
203
+ }
204
+
205
+ elif prop_type == "object":
206
+ prop_schema["type"] = "object"
207
+ if "default" in value:
208
+ prop_schema["default"] = value["default"]
209
+ prop_schema["properties"] = {}
210
+ for k, v in value.get("properties", value["default"]).items():
211
+ prop_type = v["type"] if isinstance(v, dict) else type(v).__name__.lower()
212
+ if prop_type == "bool":
213
+ prop_type = "boolean"
214
+ prop_schema["properties"][k] = {"type": prop_type}
215
+
216
+ else:
217
+ prop_schema["type"] = prop_type
218
+
219
+ schema["properties"][key] = prop_schema
220
+
221
+ return schema
222
+
223
+
224
+ def create_apify_client(token: str) -> ApifyClient:
225
+ """Create an Apify client instance with a custom user-agent.
226
+
227
+ Args:
228
+ token (str): API token
229
+
230
+ Returns:
231
+ ApifyClient: Apify client instance
232
+
233
+ Raises:
234
+ ValueError: If the API token is not provided
235
+ """
236
+ if not token:
237
+ raise ValueError("API token is required to create an Apify client.")
238
+
239
+ client = ApifyClient(token)
240
+ if http_client := getattr(client.http_client, "httpx_client", None):
241
+ http_client.headers["user-agent"] += "; Origin/agno"
242
+ return client
243
+
244
+
245
+ def actor_id_to_tool_name(actor_id: str) -> str:
246
+ """Turn actor_id into a valid tool name.
247
+
248
+ Args:
249
+ actor_id (str): Actor ID from Apify store
250
+
251
+ Returns:
252
+ str: A valid tool name
253
+ """
254
+ valid_chars = string.ascii_letters + string.digits + "_-"
255
+ return "apify_actor_" + "".join(char if char in valid_chars else "_" for char in actor_id)
256
+
257
+
258
+ def get_actor_latest_build(apify_client: ApifyClient, actor_id: str) -> Dict[str, Any]:
259
+ """Get the latest build of an Actor from the default build tag.
260
+
261
+ Args:
262
+ apify_client (ApifyClient): An instance of the ApifyClient class
263
+ actor_id (str): Actor name from Apify store to run
264
+
265
+ Returns:
266
+ Dict[str, Any]: The latest build of the Actor
267
+
268
+ Raises:
269
+ ValueError: If the Actor is not found or the build data is not found
270
+ TypeError: If the build is not a dictionary
271
+ """
272
+ if not (actor := apify_client.actor(actor_id).get()):
273
+ raise ValueError(f"Actor {actor_id} not found.")
274
+
275
+ if not (actor_obj_id := actor.get("id")):
276
+ raise ValueError(f"Failed to get the Actor object ID for {actor_id}.")
277
+
278
+ url = APIFY_API_ENDPOINT_GET_DEFAULT_BUILD.format(actor_id=actor_obj_id)
279
+ response = requests.request("GET", url, timeout=REQUESTS_TIMEOUT_SECS)
280
+
281
+ build = response.json()
282
+ if not isinstance(build, dict):
283
+ raise TypeError(f"Failed to get the latest build of the Actor {actor_id}.")
284
+
285
+ if (data := build.get("data")) is None:
286
+ raise ValueError(f"Failed to get the latest build data of the Actor {actor_id}.")
287
+
288
+ return data
289
+
290
+
291
+ def prune_actor_input_schema(input_schema: Dict[str, Any]) -> Tuple[Dict[str, Any], List[str]]:
292
+ """Get the input schema from the Actor build and trim descriptions.
293
+
294
+ Args:
295
+ input_schema (Dict[str, Any]): The input schema from the Actor build
296
+
297
+ Returns:
298
+ Tuple[Dict[str, Any], List[str]]: A tuple containing the pruned properties and required fields
299
+ """
300
+ properties = input_schema.get("properties", {})
301
+ required = input_schema.get("required", [])
302
+
303
+ properties_out: Dict[str, Any] = {}
304
+ for item, meta in properties.items():
305
+ properties_out[item] = {}
306
+ if desc := meta.get("description"):
307
+ properties_out[item]["description"] = (
308
+ desc[:MAX_DESCRIPTION_LEN] + "..." if len(desc) > MAX_DESCRIPTION_LEN else desc
309
+ )
310
+ for key_name in ("type", "default", "prefill", "enum"):
311
+ if value := meta.get(key_name):
312
+ properties_out[item][key_name] = value
313
+
314
+ return properties_out, required