agno 2.2.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1335 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1160 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,701 @@
1
+ import json
2
+ from dataclasses import dataclass
3
+ from os import getenv
4
+ from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Tuple, Type, Union
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from agno.exceptions import AgnoError, ModelProviderError
9
+ from agno.models.base import Model
10
+ from agno.models.message import Message
11
+ from agno.models.metrics import Metrics
12
+ from agno.models.response import ModelResponse
13
+ from agno.run.agent import RunOutput
14
+ from agno.utils.log import log_debug, log_error, log_warning
15
+
16
+ try:
17
+ from boto3 import client as AwsClient
18
+ from boto3.session import Session
19
+ from botocore.exceptions import ClientError
20
+ except ImportError:
21
+ raise ImportError("`boto3` not installed. Please install using `pip install boto3`")
22
+
23
+ try:
24
+ import aioboto3
25
+
26
+ AIOBOTO3_AVAILABLE = True
27
+ except ImportError:
28
+ aioboto3 = None
29
+ AIOBOTO3_AVAILABLE = False
30
+
31
+
32
+ BEDROCK_SUPPORTED_IMAGE_FORMATS = ["png", "jpeg", "webp", "gif"]
33
+ BEDROCK_SUPPORTED_VIDEO_FORMATS = ["mp4", "mov", "mkv", "webm", "flv", "mpeg", "mpg", "wmv", "three_gp"]
34
+ BEDROCK_SUPPORTED_FILE_FORMATS = ["pdf", "csv", "doc", "docx", "xls", "xlsx", "html", "txt", "md"]
35
+
36
+
37
+ @dataclass
38
+ class AwsBedrock(Model):
39
+ """
40
+ AWS Bedrock model.
41
+
42
+ To use this model, you need to either:
43
+ 1. Set the following environment variables:
44
+ - AWS_ACCESS_KEY_ID
45
+ - AWS_SECRET_ACCESS_KEY
46
+ - AWS_REGION
47
+ 2. Or provide a boto3 Session object
48
+
49
+ For async support, you also need aioboto3 installed:
50
+ pip install aioboto3
51
+
52
+ Not all Bedrock models support all features. See this documentation for more information: https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-supported-models-features.html
53
+
54
+ Args:
55
+ aws_region (Optional[str]): The AWS region to use.
56
+ aws_access_key_id (Optional[str]): The AWS access key ID to use.
57
+ aws_secret_access_key (Optional[str]): The AWS secret access key to use.
58
+ aws_sso_auth (Optional[str]): Removes the need for an access and secret access key by leveraging the current profile's authentication
59
+ session (Optional[Session]): A boto3 Session object to use for authentication.
60
+ """
61
+
62
+ id: str = "mistral.mistral-small-2402-v1:0"
63
+ name: str = "AwsBedrock"
64
+ provider: str = "AwsBedrock"
65
+
66
+ aws_sso_auth: Optional[bool] = False
67
+ aws_region: Optional[str] = None
68
+ aws_access_key_id: Optional[str] = None
69
+ aws_secret_access_key: Optional[str] = None
70
+ session: Optional[Session] = None
71
+
72
+ # Request parameters
73
+ max_tokens: Optional[int] = None
74
+ temperature: Optional[float] = None
75
+ top_p: Optional[float] = None
76
+ stop_sequences: Optional[List[str]] = None
77
+ request_params: Optional[Dict[str, Any]] = None
78
+
79
+ client: Optional[AwsClient] = None
80
+ async_client: Optional[Any] = None
81
+ async_session: Optional[Any] = None
82
+
83
+ def get_client(self) -> AwsClient:
84
+ """
85
+ Get the Bedrock client.
86
+
87
+ Returns:
88
+ AwsClient: The Bedrock client.
89
+ """
90
+ if self.client is not None:
91
+ return self.client
92
+
93
+ if self.session:
94
+ self.client = self.session.client("bedrock-runtime")
95
+ return self.client
96
+
97
+ self.aws_access_key_id = self.aws_access_key_id or getenv("AWS_ACCESS_KEY_ID")
98
+ self.aws_secret_access_key = self.aws_secret_access_key or getenv("AWS_SECRET_ACCESS_KEY")
99
+ self.aws_region = self.aws_region or getenv("AWS_REGION")
100
+
101
+ if self.aws_sso_auth:
102
+ self.client = AwsClient(service_name="bedrock-runtime", region_name=self.aws_region)
103
+ else:
104
+ if not self.aws_access_key_id or not self.aws_secret_access_key:
105
+ raise AgnoError(
106
+ message="AWS credentials not found. Please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables or provide a boto3 session.",
107
+ status_code=400,
108
+ )
109
+
110
+ self.client = AwsClient(
111
+ service_name="bedrock-runtime",
112
+ region_name=self.aws_region,
113
+ aws_access_key_id=self.aws_access_key_id,
114
+ aws_secret_access_key=self.aws_secret_access_key,
115
+ )
116
+ return self.client
117
+
118
+ def get_async_client(self):
119
+ """
120
+ Get the async Bedrock client context manager.
121
+
122
+ Returns:
123
+ The async Bedrock client context manager.
124
+ """
125
+ if not AIOBOTO3_AVAILABLE:
126
+ raise ImportError(
127
+ "`aioboto3` not installed. Please install using `pip install aioboto3` for async support."
128
+ )
129
+
130
+ if self.async_session is None:
131
+ self.aws_access_key_id = self.aws_access_key_id or getenv("AWS_ACCESS_KEY_ID")
132
+ self.aws_secret_access_key = self.aws_secret_access_key or getenv("AWS_SECRET_ACCESS_KEY")
133
+ self.aws_region = self.aws_region or getenv("AWS_REGION")
134
+
135
+ self.async_session = aioboto3.Session()
136
+
137
+ client_kwargs = {
138
+ "service_name": "bedrock-runtime",
139
+ "region_name": self.aws_region,
140
+ }
141
+
142
+ if self.aws_sso_auth:
143
+ pass
144
+ else:
145
+ if not self.aws_access_key_id or not self.aws_secret_access_key:
146
+ import os
147
+
148
+ env_access_key = os.environ.get("AWS_ACCESS_KEY_ID")
149
+ env_secret_key = os.environ.get("AWS_SECRET_ACCESS_KEY")
150
+ env_region = os.environ.get("AWS_REGION")
151
+
152
+ if env_access_key and env_secret_key:
153
+ self.aws_access_key_id = env_access_key
154
+ self.aws_secret_access_key = env_secret_key
155
+ if env_region:
156
+ self.aws_region = env_region
157
+ client_kwargs["region_name"] = self.aws_region
158
+
159
+ if self.aws_access_key_id and self.aws_secret_access_key:
160
+ client_kwargs.update(
161
+ {
162
+ "aws_access_key_id": self.aws_access_key_id,
163
+ "aws_secret_access_key": self.aws_secret_access_key,
164
+ }
165
+ )
166
+
167
+ return self.async_session.client(**client_kwargs)
168
+
169
+ def _format_tools_for_request(self, tools: Optional[List[Dict[str, Any]]]) -> List[Dict[str, Any]]:
170
+ """
171
+ Format the tools for the request.
172
+
173
+ Returns:
174
+ List[Dict[str, Any]]: The formatted tools.
175
+ """
176
+ parsed_tools = []
177
+ if tools is not None:
178
+ for tool_def in tools:
179
+ func_def = tool_def.get("function", {})
180
+ properties = {}
181
+ required = []
182
+
183
+ for param_name, param_info in func_def.get("parameters", {}).get("properties", {}).items():
184
+ properties[param_name] = param_info.copy()
185
+
186
+ if "description" not in properties[param_name]:
187
+ properties[param_name]["description"] = ""
188
+
189
+ if "null" not in (
190
+ param_info.get("type") if isinstance(param_info.get("type"), list) else [param_info.get("type")]
191
+ ):
192
+ required.append(param_name)
193
+
194
+ parsed_tools.append(
195
+ {
196
+ "toolSpec": {
197
+ "name": func_def.get("name") or "",
198
+ "description": func_def.get("description") or "",
199
+ "inputSchema": {"json": {"type": "object", "properties": properties, "required": required}},
200
+ }
201
+ }
202
+ )
203
+
204
+ return parsed_tools
205
+
206
+ def _get_inference_config(self) -> Dict[str, Any]:
207
+ """
208
+ Get the inference config.
209
+
210
+ Returns:
211
+ Dict[str, Any]: The inference config.
212
+ """
213
+ request_kwargs = {
214
+ "maxTokens": self.max_tokens,
215
+ "temperature": self.temperature,
216
+ "topP": self.top_p,
217
+ "stopSequences": self.stop_sequences,
218
+ }
219
+
220
+ return {k: v for k, v in request_kwargs.items() if v is not None}
221
+
222
+ def _format_messages(self, messages: List[Message]) -> Tuple[List[Dict[str, Any]], Optional[List[Dict[str, Any]]]]:
223
+ """
224
+ Format the messages for the request.
225
+
226
+ Returns:
227
+ Tuple[List[Dict[str, Any]], Optional[List[Dict[str, Any]]]]: The formatted messages.
228
+ """
229
+ formatted_messages: List[Dict[str, Any]] = []
230
+ system_message = None
231
+ for message in messages:
232
+ if message.role == "system":
233
+ system_message = [{"text": message.content}]
234
+ else:
235
+ formatted_message: Dict[str, Any] = {"role": message.role, "content": []}
236
+ # Handle tool results
237
+ if isinstance(message.content, list):
238
+ formatted_message["content"].extend(message.content)
239
+ elif message.tool_calls:
240
+ tool_use_content = []
241
+ for tool_call in message.tool_calls:
242
+ try:
243
+ # Parse arguments with error handling for empty or invalid JSON
244
+ arguments = tool_call["function"]["arguments"]
245
+ if not arguments or arguments.strip() == "":
246
+ tool_input = {}
247
+ else:
248
+ tool_input = json.loads(arguments)
249
+ except (json.JSONDecodeError, KeyError) as e:
250
+ log_warning(f"Failed to parse tool call arguments: {e}")
251
+ tool_input = {}
252
+
253
+ tool_use_content.append(
254
+ {
255
+ "toolUse": {
256
+ "toolUseId": tool_call["id"],
257
+ "name": tool_call["function"]["name"],
258
+ "input": tool_input,
259
+ }
260
+ }
261
+ )
262
+ formatted_message["content"].extend(tool_use_content)
263
+ else:
264
+ formatted_message["content"].append({"text": message.content})
265
+
266
+ if message.images:
267
+ for image in message.images:
268
+ if not image.content:
269
+ raise ValueError("Image content is required for AWS Bedrock.")
270
+ if not image.format:
271
+ raise ValueError("Image format is required for AWS Bedrock.")
272
+
273
+ if image.format not in BEDROCK_SUPPORTED_IMAGE_FORMATS:
274
+ raise ValueError(
275
+ f"Unsupported image format: {image.format}. "
276
+ f"Supported formats: {BEDROCK_SUPPORTED_IMAGE_FORMATS}"
277
+ )
278
+
279
+ formatted_message["content"].append(
280
+ {
281
+ "image": {
282
+ "format": image.format,
283
+ "source": {
284
+ "bytes": image.content,
285
+ },
286
+ }
287
+ }
288
+ )
289
+ if message.audio:
290
+ log_warning("Audio input is currently unsupported.")
291
+
292
+ if message.videos:
293
+ for video in message.videos:
294
+ if not video.content:
295
+ raise ValueError("Video content is required for AWS Bedrock.")
296
+ if not video.format:
297
+ raise ValueError("Video format is required for AWS Bedrock.")
298
+
299
+ if video.format not in BEDROCK_SUPPORTED_VIDEO_FORMATS:
300
+ raise ValueError(
301
+ f"Unsupported video format: {video.format}. "
302
+ f"Supported formats: {BEDROCK_SUPPORTED_VIDEO_FORMATS}"
303
+ )
304
+
305
+ formatted_message["content"].append(
306
+ {
307
+ "video": {
308
+ "format": video.format,
309
+ "source": {
310
+ "bytes": video.content,
311
+ },
312
+ }
313
+ }
314
+ )
315
+
316
+ if message.files:
317
+ for file in message.files:
318
+ if not file.content:
319
+ raise ValueError("File content is required for AWS Bedrock document input.")
320
+ if not file.format:
321
+ raise ValueError("File format is required for AWS Bedrock document input.")
322
+ if not file.name:
323
+ raise ValueError("File name is required for AWS Bedrock document input.")
324
+
325
+ if file.format not in BEDROCK_SUPPORTED_FILE_FORMATS:
326
+ raise ValueError(
327
+ f"Unsupported file format: {file.format}. "
328
+ f"Supported formats: {BEDROCK_SUPPORTED_FILE_FORMATS}"
329
+ )
330
+
331
+ formatted_message["content"].append(
332
+ {
333
+ "document": {
334
+ "format": file.format,
335
+ "name": file.name,
336
+ "source": {
337
+ "bytes": file.content,
338
+ },
339
+ }
340
+ }
341
+ )
342
+
343
+ formatted_messages.append(formatted_message)
344
+ # TODO: Add caching: https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-call.html
345
+ return formatted_messages, system_message
346
+
347
+ def invoke(
348
+ self,
349
+ messages: List[Message],
350
+ assistant_message: Message,
351
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
352
+ tools: Optional[List[Dict[str, Any]]] = None,
353
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
354
+ run_response: Optional[RunOutput] = None,
355
+ ) -> ModelResponse:
356
+ """
357
+ Invoke the Bedrock API.
358
+ """
359
+ try:
360
+ formatted_messages, system_message = self._format_messages(messages)
361
+
362
+ tool_config = None
363
+ if tools:
364
+ tool_config = {"tools": self._format_tools_for_request(tools)}
365
+
366
+ body = {
367
+ "system": system_message,
368
+ "toolConfig": tool_config,
369
+ "inferenceConfig": self._get_inference_config(),
370
+ }
371
+ body = {k: v for k, v in body.items() if v is not None}
372
+
373
+ if self.request_params:
374
+ log_debug(f"Calling {self.provider} with request parameters: {self.request_params}", log_level=2)
375
+ body.update(**self.request_params)
376
+
377
+ if run_response and run_response.metrics:
378
+ run_response.metrics.set_time_to_first_token()
379
+
380
+ assistant_message.metrics.start_timer()
381
+ response = self.get_client().converse(modelId=self.id, messages=formatted_messages, **body)
382
+ assistant_message.metrics.stop_timer()
383
+
384
+ model_response = self._parse_provider_response(response, response_format=response_format)
385
+
386
+ return model_response
387
+
388
+ except ClientError as e:
389
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
390
+ raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
391
+ except Exception as e:
392
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
393
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
394
+
395
+ def invoke_stream(
396
+ self,
397
+ messages: List[Message],
398
+ assistant_message: Message,
399
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
400
+ tools: Optional[List[Dict[str, Any]]] = None,
401
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
402
+ run_response: Optional[RunOutput] = None,
403
+ ) -> Iterator[ModelResponse]:
404
+ """
405
+ Invoke the Bedrock API with streaming.
406
+ """
407
+ try:
408
+ formatted_messages, system_message = self._format_messages(messages)
409
+
410
+ tool_config = None
411
+ if tools:
412
+ tool_config = {"tools": self._format_tools_for_request(tools)}
413
+
414
+ body = {
415
+ "system": system_message,
416
+ "toolConfig": tool_config,
417
+ "inferenceConfig": self._get_inference_config(),
418
+ }
419
+ body = {k: v for k, v in body.items() if v is not None}
420
+
421
+ if self.request_params:
422
+ body.update(**self.request_params)
423
+
424
+ if run_response and run_response.metrics:
425
+ run_response.metrics.set_time_to_first_token()
426
+
427
+ assistant_message.metrics.start_timer()
428
+
429
+ # Track current tool being built across chunks
430
+ current_tool: Dict[str, Any] = {}
431
+
432
+ for chunk in self.get_client().converse_stream(modelId=self.id, messages=formatted_messages, **body)[
433
+ "stream"
434
+ ]:
435
+ model_response, current_tool = self._parse_provider_response_delta(chunk, current_tool)
436
+ yield model_response
437
+
438
+ assistant_message.metrics.stop_timer()
439
+
440
+ except ClientError as e:
441
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
442
+ raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
443
+ except Exception as e:
444
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
445
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
446
+
447
+ async def ainvoke(
448
+ self,
449
+ messages: List[Message],
450
+ assistant_message: Message,
451
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
452
+ tools: Optional[List[Dict[str, Any]]] = None,
453
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
454
+ run_response: Optional[RunOutput] = None,
455
+ ) -> ModelResponse:
456
+ """
457
+ Async invoke the Bedrock API.
458
+ """
459
+ try:
460
+ formatted_messages, system_message = self._format_messages(messages)
461
+
462
+ tool_config = None
463
+ if tools:
464
+ tool_config = {"tools": self._format_tools_for_request(tools)}
465
+
466
+ body = {
467
+ "system": system_message,
468
+ "toolConfig": tool_config,
469
+ "inferenceConfig": self._get_inference_config(),
470
+ }
471
+ body = {k: v for k, v in body.items() if v is not None}
472
+
473
+ if self.request_params:
474
+ log_debug(f"Calling {self.provider} with request parameters: {self.request_params}", log_level=2)
475
+ body.update(**self.request_params)
476
+
477
+ if run_response and run_response.metrics:
478
+ run_response.metrics.set_time_to_first_token()
479
+
480
+ assistant_message.metrics.start_timer()
481
+
482
+ async with self.get_async_client() as client:
483
+ response = await client.converse(modelId=self.id, messages=formatted_messages, **body)
484
+
485
+ assistant_message.metrics.stop_timer()
486
+
487
+ model_response = self._parse_provider_response(response, response_format=response_format)
488
+
489
+ return model_response
490
+
491
+ except ClientError as e:
492
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
493
+ raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
494
+ except Exception as e:
495
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
496
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
497
+
498
+ async def ainvoke_stream(
499
+ self,
500
+ messages: List[Message],
501
+ assistant_message: Message,
502
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
503
+ tools: Optional[List[Dict[str, Any]]] = None,
504
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
505
+ run_response: Optional[RunOutput] = None,
506
+ ) -> AsyncIterator[ModelResponse]:
507
+ """
508
+ Async invoke the Bedrock API with streaming.
509
+ """
510
+ try:
511
+ formatted_messages, system_message = self._format_messages(messages)
512
+
513
+ tool_config = None
514
+ if tools:
515
+ tool_config = {"tools": self._format_tools_for_request(tools)}
516
+
517
+ body = {
518
+ "system": system_message,
519
+ "toolConfig": tool_config,
520
+ "inferenceConfig": self._get_inference_config(),
521
+ }
522
+ body = {k: v for k, v in body.items() if v is not None}
523
+
524
+ if self.request_params:
525
+ body.update(**self.request_params)
526
+
527
+ if run_response and run_response.metrics:
528
+ run_response.metrics.set_time_to_first_token()
529
+
530
+ assistant_message.metrics.start_timer()
531
+
532
+ # Track current tool being built across chunks
533
+ current_tool: Dict[str, Any] = {}
534
+
535
+ async with self.get_async_client() as client:
536
+ response = await client.converse_stream(modelId=self.id, messages=formatted_messages, **body)
537
+ async for chunk in response["stream"]:
538
+ model_response, current_tool = self._parse_provider_response_delta(chunk, current_tool)
539
+ yield model_response
540
+
541
+ assistant_message.metrics.stop_timer()
542
+
543
+ except ClientError as e:
544
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
545
+ raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
546
+ except Exception as e:
547
+ log_error(f"Unexpected error calling Bedrock API: {str(e)}")
548
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
549
+
550
+ # Overwrite the default from the base model
551
+ def format_function_call_results(
552
+ self, messages: List[Message], function_call_results: List[Message], **kwargs
553
+ ) -> None:
554
+ """
555
+ Handle the results of function calls.
556
+
557
+ Args:
558
+ messages (List[Message]): The list of conversation messages.
559
+ function_call_results (List[Message]): The results of the function calls.
560
+ **kwargs: Additional arguments including tool_ids.
561
+ """
562
+ if function_call_results:
563
+ tool_ids = kwargs.get("tool_ids", [])
564
+ tool_result_content: List = []
565
+
566
+ for _fc_message_index, _fc_message in enumerate(function_call_results):
567
+ # Use tool_call_id from message if tool_ids list is insufficient
568
+ tool_id = tool_ids[_fc_message_index] if _fc_message_index < len(tool_ids) else _fc_message.tool_call_id
569
+ tool_result = {
570
+ "toolUseId": tool_id,
571
+ "content": [{"json": {"result": _fc_message.content}}],
572
+ }
573
+ tool_result_content.append({"toolResult": tool_result})
574
+
575
+ messages.append(Message(role="user", content=tool_result_content))
576
+
577
+ def _parse_provider_response(self, response: Dict[str, Any], **kwargs) -> ModelResponse:
578
+ """
579
+ Parse the provider response.
580
+
581
+ Args:
582
+ response (Dict[str, Any]): The response from the provider.
583
+
584
+ Returns:
585
+ ModelResponse: The parsed response.
586
+ """
587
+ model_response = ModelResponse()
588
+
589
+ if "output" in response and "message" in response["output"]:
590
+ message = response["output"]["message"]
591
+ # Set the role of the message
592
+ model_response.role = message["role"]
593
+
594
+ # Get the content of the message
595
+ content = message["content"]
596
+
597
+ # Tools
598
+ if "stopReason" in response and response["stopReason"] == "tool_use":
599
+ model_response.tool_calls = []
600
+ model_response.extra = model_response.extra or {}
601
+ model_response.extra["tool_ids"] = []
602
+ for tool in content:
603
+ if "toolUse" in tool:
604
+ model_response.extra["tool_ids"].append(tool["toolUse"]["toolUseId"])
605
+ model_response.tool_calls.append(
606
+ {
607
+ "id": tool["toolUse"]["toolUseId"],
608
+ "type": "function",
609
+ "function": {
610
+ "name": tool["toolUse"]["name"],
611
+ "arguments": json.dumps(tool["toolUse"]["input"]),
612
+ },
613
+ }
614
+ )
615
+
616
+ # Extract text content if it's a list of dictionaries
617
+ if isinstance(content, list) and content and isinstance(content[0], dict):
618
+ content = [item.get("text", "") for item in content if "text" in item]
619
+ content = "\n".join(content) # Join multiple text items if present
620
+
621
+ model_response.content = content
622
+
623
+ if "usage" in response:
624
+ model_response.response_usage = self._get_metrics(response["usage"])
625
+
626
+ return model_response
627
+
628
+ def _parse_provider_response_delta(
629
+ self, response_delta: Dict[str, Any], current_tool: Dict[str, Any]
630
+ ) -> Tuple[ModelResponse, Dict[str, Any]]:
631
+ """Parse the provider response delta for streaming.
632
+
633
+ Args:
634
+ response_delta: The streaming response delta from AWS Bedrock
635
+ current_tool: The current tool being built across chunks
636
+
637
+ Returns:
638
+ Tuple[ModelResponse, Dict[str, Any]]: The parsed model response delta and updated current_tool
639
+ """
640
+ model_response = ModelResponse(role="assistant")
641
+
642
+ # Handle contentBlockStart - tool use start
643
+ if "contentBlockStart" in response_delta:
644
+ start = response_delta["contentBlockStart"]["start"]
645
+ if "toolUse" in start:
646
+ # Start a new tool
647
+ tool_use_data = start["toolUse"]
648
+ current_tool = {
649
+ "id": tool_use_data.get("toolUseId", ""),
650
+ "type": "function",
651
+ "function": {
652
+ "name": tool_use_data.get("name", ""),
653
+ "arguments": "", # Will be filled in subsequent deltas
654
+ },
655
+ }
656
+
657
+ # Handle contentBlockDelta - text content or tool input
658
+ elif "contentBlockDelta" in response_delta:
659
+ delta = response_delta["contentBlockDelta"]["delta"]
660
+ if "text" in delta:
661
+ model_response.content = delta["text"]
662
+ elif "toolUse" in delta and current_tool:
663
+ # Accumulate tool input
664
+ tool_input = delta["toolUse"].get("input", "")
665
+ if tool_input:
666
+ current_tool["function"]["arguments"] += tool_input
667
+
668
+ # Handle contentBlockStop - tool use complete
669
+ elif "contentBlockStop" in response_delta and current_tool:
670
+ # Tool is complete, add it to model response
671
+ model_response.tool_calls = [current_tool]
672
+ # Track tool_id in extra for format_function_call_results
673
+ model_response.extra = {"tool_ids": [current_tool["id"]]}
674
+ # Reset current_tool for next tool
675
+ current_tool = {}
676
+
677
+ # Handle metadata/usage information
678
+ elif "metadata" in response_delta or "messageStop" in response_delta:
679
+ body = response_delta.get("metadata") or response_delta.get("messageStop") or {}
680
+ if "usage" in body:
681
+ model_response.response_usage = self._get_metrics(body["usage"])
682
+
683
+ return model_response, current_tool
684
+
685
+ def _get_metrics(self, response_usage: Dict[str, Any]) -> Metrics:
686
+ """
687
+ Parse the given AWS Bedrock usage into an Agno Metrics object.
688
+
689
+ Args:
690
+ response_usage: Usage data from AWS Bedrock
691
+
692
+ Returns:
693
+ Metrics: Parsed metrics data
694
+ """
695
+ metrics = Metrics()
696
+
697
+ metrics.input_tokens = response_usage.get("inputTokens", 0) or 0
698
+ metrics.output_tokens = response_usage.get("outputTokens", 0) or 0
699
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
700
+
701
+ return metrics