agno 1.8.2__py3-none-any.whl → 2.0.0__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 (589) hide show
  1. agno/agent/__init__.py +19 -27
  2. agno/agent/agent.py +3143 -4170
  3. agno/api/agent.py +11 -67
  4. agno/api/api.py +5 -46
  5. agno/api/evals.py +8 -19
  6. agno/api/os.py +17 -0
  7. agno/api/routes.py +6 -41
  8. agno/api/schemas/__init__.py +9 -0
  9. agno/api/schemas/agent.py +5 -21
  10. agno/api/schemas/evals.py +7 -16
  11. agno/api/schemas/os.py +14 -0
  12. agno/api/schemas/team.py +5 -21
  13. agno/api/schemas/utils.py +21 -0
  14. agno/api/schemas/workflows.py +11 -7
  15. agno/api/settings.py +53 -0
  16. agno/api/team.py +11 -66
  17. agno/api/workflow.py +28 -0
  18. agno/cloud/aws/base.py +214 -0
  19. agno/cloud/aws/s3/__init__.py +2 -0
  20. agno/cloud/aws/s3/api_client.py +43 -0
  21. agno/cloud/aws/s3/bucket.py +195 -0
  22. agno/cloud/aws/s3/object.py +57 -0
  23. agno/db/__init__.py +24 -0
  24. agno/db/base.py +245 -0
  25. agno/db/dynamo/__init__.py +3 -0
  26. agno/db/dynamo/dynamo.py +1743 -0
  27. agno/db/dynamo/schemas.py +278 -0
  28. agno/db/dynamo/utils.py +684 -0
  29. agno/db/firestore/__init__.py +3 -0
  30. agno/db/firestore/firestore.py +1432 -0
  31. agno/db/firestore/schemas.py +130 -0
  32. agno/db/firestore/utils.py +278 -0
  33. agno/db/gcs_json/__init__.py +3 -0
  34. agno/db/gcs_json/gcs_json_db.py +1001 -0
  35. agno/db/gcs_json/utils.py +194 -0
  36. agno/db/in_memory/__init__.py +3 -0
  37. agno/db/in_memory/in_memory_db.py +882 -0
  38. agno/db/in_memory/utils.py +172 -0
  39. agno/db/json/__init__.py +3 -0
  40. agno/db/json/json_db.py +1045 -0
  41. agno/db/json/utils.py +196 -0
  42. agno/db/migrations/v1_to_v2.py +162 -0
  43. agno/db/mongo/__init__.py +3 -0
  44. agno/db/mongo/mongo.py +1416 -0
  45. agno/db/mongo/schemas.py +77 -0
  46. agno/db/mongo/utils.py +204 -0
  47. agno/db/mysql/__init__.py +3 -0
  48. agno/db/mysql/mysql.py +1719 -0
  49. agno/db/mysql/schemas.py +124 -0
  50. agno/db/mysql/utils.py +297 -0
  51. agno/db/postgres/__init__.py +3 -0
  52. agno/db/postgres/postgres.py +1710 -0
  53. agno/db/postgres/schemas.py +124 -0
  54. agno/db/postgres/utils.py +280 -0
  55. agno/db/redis/__init__.py +3 -0
  56. agno/db/redis/redis.py +1367 -0
  57. agno/db/redis/schemas.py +109 -0
  58. agno/db/redis/utils.py +288 -0
  59. agno/db/schemas/__init__.py +3 -0
  60. agno/db/schemas/evals.py +33 -0
  61. agno/db/schemas/knowledge.py +40 -0
  62. agno/db/schemas/memory.py +46 -0
  63. agno/db/singlestore/__init__.py +3 -0
  64. agno/db/singlestore/schemas.py +116 -0
  65. agno/db/singlestore/singlestore.py +1712 -0
  66. agno/db/singlestore/utils.py +326 -0
  67. agno/db/sqlite/__init__.py +3 -0
  68. agno/db/sqlite/schemas.py +119 -0
  69. agno/db/sqlite/sqlite.py +1676 -0
  70. agno/db/sqlite/utils.py +268 -0
  71. agno/db/utils.py +88 -0
  72. agno/eval/__init__.py +14 -0
  73. agno/eval/accuracy.py +154 -48
  74. agno/eval/performance.py +88 -23
  75. agno/eval/reliability.py +73 -20
  76. agno/eval/utils.py +23 -13
  77. agno/integrations/discord/__init__.py +3 -0
  78. agno/{app → integrations}/discord/client.py +10 -10
  79. agno/knowledge/__init__.py +2 -2
  80. agno/{document → knowledge}/chunking/agentic.py +2 -2
  81. agno/{document → knowledge}/chunking/document.py +2 -2
  82. agno/{document → knowledge}/chunking/fixed.py +3 -3
  83. agno/{document → knowledge}/chunking/markdown.py +2 -2
  84. agno/{document → knowledge}/chunking/recursive.py +2 -2
  85. agno/{document → knowledge}/chunking/row.py +2 -2
  86. agno/knowledge/chunking/semantic.py +59 -0
  87. agno/knowledge/chunking/strategy.py +121 -0
  88. agno/knowledge/content.py +74 -0
  89. agno/knowledge/document/__init__.py +5 -0
  90. agno/{document → knowledge/document}/base.py +12 -2
  91. agno/knowledge/embedder/__init__.py +5 -0
  92. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  93. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  94. agno/{embedder → knowledge/embedder}/base.py +6 -0
  95. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  96. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  97. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  98. agno/{embedder → knowledge/embedder}/google.py +74 -1
  99. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  100. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  101. agno/knowledge/embedder/langdb.py +22 -0
  102. agno/knowledge/embedder/mistral.py +139 -0
  103. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  104. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  105. agno/knowledge/embedder/openai.py +223 -0
  106. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  107. agno/{embedder → knowledge/embedder}/together.py +1 -1
  108. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  109. agno/knowledge/knowledge.py +1551 -0
  110. agno/knowledge/reader/__init__.py +7 -0
  111. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  112. agno/knowledge/reader/base.py +88 -0
  113. agno/{document → knowledge}/reader/csv_reader.py +47 -65
  114. agno/knowledge/reader/docx_reader.py +83 -0
  115. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  116. agno/{document → knowledge}/reader/json_reader.py +30 -9
  117. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  118. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  119. agno/knowledge/reader/reader_factory.py +268 -0
  120. agno/knowledge/reader/s3_reader.py +101 -0
  121. agno/{document → knowledge}/reader/text_reader.py +31 -10
  122. agno/knowledge/reader/url_reader.py +128 -0
  123. agno/knowledge/reader/web_search_reader.py +366 -0
  124. agno/{document → knowledge}/reader/website_reader.py +37 -10
  125. agno/knowledge/reader/wikipedia_reader.py +59 -0
  126. agno/knowledge/reader/youtube_reader.py +78 -0
  127. agno/knowledge/remote_content/remote_content.py +88 -0
  128. agno/{reranker → knowledge/reranker}/base.py +1 -1
  129. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  130. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  131. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  132. agno/knowledge/types.py +30 -0
  133. agno/knowledge/utils.py +169 -0
  134. agno/media.py +269 -268
  135. agno/memory/__init__.py +2 -10
  136. agno/memory/manager.py +1003 -148
  137. agno/models/aimlapi/__init__.py +2 -2
  138. agno/models/aimlapi/aimlapi.py +6 -6
  139. agno/models/anthropic/claude.py +128 -72
  140. agno/models/aws/bedrock.py +107 -175
  141. agno/models/aws/claude.py +64 -18
  142. agno/models/azure/ai_foundry.py +73 -23
  143. agno/models/base.py +346 -290
  144. agno/models/cerebras/cerebras.py +84 -27
  145. agno/models/cohere/chat.py +106 -98
  146. agno/models/google/gemini.py +105 -46
  147. agno/models/groq/groq.py +97 -35
  148. agno/models/huggingface/huggingface.py +92 -27
  149. agno/models/ibm/watsonx.py +72 -13
  150. agno/models/litellm/chat.py +85 -13
  151. agno/models/message.py +46 -151
  152. agno/models/meta/llama.py +85 -49
  153. agno/models/metrics.py +120 -0
  154. agno/models/mistral/mistral.py +90 -21
  155. agno/models/ollama/__init__.py +0 -2
  156. agno/models/ollama/chat.py +85 -47
  157. agno/models/openai/chat.py +154 -37
  158. agno/models/openai/responses.py +178 -105
  159. agno/models/perplexity/perplexity.py +26 -2
  160. agno/models/portkey/portkey.py +0 -7
  161. agno/models/response.py +15 -9
  162. agno/models/utils.py +20 -0
  163. agno/models/vercel/__init__.py +2 -2
  164. agno/models/vercel/v0.py +1 -1
  165. agno/models/vllm/__init__.py +2 -2
  166. agno/models/vllm/vllm.py +3 -3
  167. agno/models/xai/xai.py +10 -10
  168. agno/os/__init__.py +3 -0
  169. agno/os/app.py +497 -0
  170. agno/os/auth.py +47 -0
  171. agno/os/config.py +103 -0
  172. agno/os/interfaces/agui/__init__.py +3 -0
  173. agno/os/interfaces/agui/agui.py +31 -0
  174. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  175. agno/{app → os/interfaces}/agui/utils.py +65 -28
  176. agno/os/interfaces/base.py +21 -0
  177. agno/os/interfaces/slack/__init__.py +3 -0
  178. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  179. agno/os/interfaces/slack/slack.py +32 -0
  180. agno/os/interfaces/whatsapp/__init__.py +3 -0
  181. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  182. agno/os/interfaces/whatsapp/whatsapp.py +29 -0
  183. agno/os/mcp.py +235 -0
  184. agno/os/router.py +1400 -0
  185. agno/os/routers/__init__.py +3 -0
  186. agno/os/routers/evals/__init__.py +3 -0
  187. agno/os/routers/evals/evals.py +393 -0
  188. agno/os/routers/evals/schemas.py +142 -0
  189. agno/os/routers/evals/utils.py +161 -0
  190. agno/os/routers/knowledge/__init__.py +3 -0
  191. agno/os/routers/knowledge/knowledge.py +850 -0
  192. agno/os/routers/knowledge/schemas.py +118 -0
  193. agno/os/routers/memory/__init__.py +3 -0
  194. agno/os/routers/memory/memory.py +410 -0
  195. agno/os/routers/memory/schemas.py +58 -0
  196. agno/os/routers/metrics/__init__.py +3 -0
  197. agno/os/routers/metrics/metrics.py +178 -0
  198. agno/os/routers/metrics/schemas.py +47 -0
  199. agno/os/routers/session/__init__.py +3 -0
  200. agno/os/routers/session/session.py +536 -0
  201. agno/os/schema.py +945 -0
  202. agno/{app/playground → os}/settings.py +7 -15
  203. agno/os/utils.py +270 -0
  204. agno/reasoning/azure_ai_foundry.py +4 -4
  205. agno/reasoning/deepseek.py +4 -4
  206. agno/reasoning/default.py +6 -11
  207. agno/reasoning/groq.py +4 -4
  208. agno/reasoning/helpers.py +4 -6
  209. agno/reasoning/ollama.py +4 -4
  210. agno/reasoning/openai.py +4 -4
  211. agno/run/agent.py +633 -0
  212. agno/run/base.py +53 -77
  213. agno/run/cancel.py +81 -0
  214. agno/run/team.py +243 -96
  215. agno/run/workflow.py +550 -12
  216. agno/session/__init__.py +10 -0
  217. agno/session/agent.py +244 -0
  218. agno/session/summary.py +225 -0
  219. agno/session/team.py +262 -0
  220. agno/{storage/session/v2 → session}/workflow.py +47 -24
  221. agno/team/__init__.py +15 -16
  222. agno/team/team.py +3260 -4824
  223. agno/tools/agentql.py +14 -5
  224. agno/tools/airflow.py +9 -4
  225. agno/tools/api.py +7 -3
  226. agno/tools/apify.py +2 -46
  227. agno/tools/arxiv.py +8 -3
  228. agno/tools/aws_lambda.py +7 -5
  229. agno/tools/aws_ses.py +7 -1
  230. agno/tools/baidusearch.py +4 -1
  231. agno/tools/bitbucket.py +4 -4
  232. agno/tools/brandfetch.py +14 -11
  233. agno/tools/bravesearch.py +4 -1
  234. agno/tools/brightdata.py +43 -23
  235. agno/tools/browserbase.py +13 -4
  236. agno/tools/calcom.py +12 -10
  237. agno/tools/calculator.py +10 -27
  238. agno/tools/cartesia.py +20 -17
  239. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  240. agno/tools/confluence.py +8 -8
  241. agno/tools/crawl4ai.py +7 -1
  242. agno/tools/csv_toolkit.py +9 -8
  243. agno/tools/dalle.py +22 -12
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +17 -8
  247. agno/tools/discord.py +11 -8
  248. agno/tools/docker.py +30 -42
  249. agno/tools/duckdb.py +34 -53
  250. agno/tools/duckduckgo.py +8 -7
  251. agno/tools/e2b.py +62 -62
  252. agno/tools/eleven_labs.py +36 -29
  253. agno/tools/email.py +4 -1
  254. agno/tools/evm.py +7 -1
  255. agno/tools/exa.py +19 -14
  256. agno/tools/fal.py +30 -30
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +17 -18
  260. agno/tools/function.py +127 -18
  261. agno/tools/giphy.py +23 -11
  262. agno/tools/github.py +48 -126
  263. agno/tools/gmail.py +45 -61
  264. agno/tools/google_bigquery.py +7 -6
  265. agno/tools/google_maps.py +11 -26
  266. agno/tools/googlesearch.py +7 -2
  267. agno/tools/googlesheets.py +21 -17
  268. agno/tools/hackernews.py +9 -5
  269. agno/tools/jina.py +5 -4
  270. agno/tools/jira.py +18 -9
  271. agno/tools/knowledge.py +31 -32
  272. agno/tools/linear.py +18 -33
  273. agno/tools/linkup.py +5 -1
  274. agno/tools/local_file_system.py +8 -5
  275. agno/tools/lumalab.py +32 -20
  276. agno/tools/mcp.py +1 -2
  277. agno/tools/mem0.py +18 -12
  278. agno/tools/memori.py +14 -10
  279. agno/tools/mlx_transcribe.py +3 -2
  280. agno/tools/models/azure_openai.py +33 -15
  281. agno/tools/models/gemini.py +59 -32
  282. agno/tools/models/groq.py +30 -23
  283. agno/tools/models/nebius.py +28 -12
  284. agno/tools/models_labs.py +40 -16
  285. agno/tools/moviepy_video.py +7 -6
  286. agno/tools/neo4j.py +10 -8
  287. agno/tools/newspaper.py +7 -2
  288. agno/tools/newspaper4k.py +8 -3
  289. agno/tools/openai.py +58 -32
  290. agno/tools/openbb.py +12 -11
  291. agno/tools/opencv.py +63 -47
  292. agno/tools/openweather.py +14 -12
  293. agno/tools/pandas.py +11 -3
  294. agno/tools/postgres.py +4 -12
  295. agno/tools/pubmed.py +4 -1
  296. agno/tools/python.py +9 -22
  297. agno/tools/reasoning.py +35 -27
  298. agno/tools/reddit.py +11 -26
  299. agno/tools/replicate.py +55 -42
  300. agno/tools/resend.py +4 -1
  301. agno/tools/scrapegraph.py +15 -14
  302. agno/tools/searxng.py +10 -23
  303. agno/tools/serpapi.py +6 -3
  304. agno/tools/serper.py +13 -4
  305. agno/tools/shell.py +9 -2
  306. agno/tools/slack.py +12 -11
  307. agno/tools/sleep.py +3 -2
  308. agno/tools/spider.py +24 -4
  309. agno/tools/sql.py +7 -6
  310. agno/tools/tavily.py +6 -4
  311. agno/tools/telegram.py +12 -4
  312. agno/tools/todoist.py +11 -31
  313. agno/tools/toolkit.py +1 -1
  314. agno/tools/trafilatura.py +22 -6
  315. agno/tools/trello.py +9 -22
  316. agno/tools/twilio.py +10 -3
  317. agno/tools/user_control_flow.py +6 -1
  318. agno/tools/valyu.py +34 -5
  319. agno/tools/visualization.py +19 -28
  320. agno/tools/webbrowser.py +4 -3
  321. agno/tools/webex.py +11 -7
  322. agno/tools/website.py +15 -46
  323. agno/tools/webtools.py +12 -4
  324. agno/tools/whatsapp.py +5 -9
  325. agno/tools/wikipedia.py +20 -13
  326. agno/tools/x.py +14 -13
  327. agno/tools/yfinance.py +13 -40
  328. agno/tools/youtube.py +26 -20
  329. agno/tools/zendesk.py +7 -2
  330. agno/tools/zep.py +10 -7
  331. agno/tools/zoom.py +10 -9
  332. agno/utils/common.py +1 -19
  333. agno/utils/events.py +100 -123
  334. agno/utils/gemini.py +1 -1
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/log.py +54 -4
  337. agno/utils/mcp.py +68 -10
  338. agno/utils/media.py +39 -0
  339. agno/utils/message.py +12 -1
  340. agno/utils/models/aws_claude.py +1 -1
  341. agno/utils/models/claude.py +6 -12
  342. agno/utils/models/cohere.py +1 -1
  343. agno/utils/models/mistral.py +8 -7
  344. agno/utils/models/schema_utils.py +3 -3
  345. agno/utils/models/watsonx.py +1 -1
  346. agno/utils/openai.py +1 -1
  347. agno/utils/pprint.py +33 -32
  348. agno/utils/print_response/agent.py +779 -0
  349. agno/utils/print_response/team.py +1669 -0
  350. agno/utils/print_response/workflow.py +1451 -0
  351. agno/utils/prompts.py +14 -14
  352. agno/utils/reasoning.py +87 -0
  353. agno/utils/response.py +42 -42
  354. agno/utils/streamlit.py +481 -0
  355. agno/utils/string.py +8 -22
  356. agno/utils/team.py +50 -0
  357. agno/utils/timer.py +2 -2
  358. agno/vectordb/base.py +33 -21
  359. agno/vectordb/cassandra/cassandra.py +287 -23
  360. agno/vectordb/chroma/chromadb.py +482 -59
  361. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  362. agno/vectordb/couchbase/couchbase.py +309 -29
  363. agno/vectordb/lancedb/lance_db.py +360 -21
  364. agno/vectordb/langchaindb/__init__.py +5 -0
  365. agno/vectordb/langchaindb/langchaindb.py +145 -0
  366. agno/vectordb/lightrag/__init__.py +5 -0
  367. agno/vectordb/lightrag/lightrag.py +374 -0
  368. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  369. agno/vectordb/milvus/milvus.py +242 -32
  370. agno/vectordb/mongodb/mongodb.py +200 -24
  371. agno/vectordb/pgvector/pgvector.py +319 -37
  372. agno/vectordb/pineconedb/pineconedb.py +221 -27
  373. agno/vectordb/qdrant/qdrant.py +334 -14
  374. agno/vectordb/singlestore/singlestore.py +286 -29
  375. agno/vectordb/surrealdb/surrealdb.py +187 -7
  376. agno/vectordb/upstashdb/upstashdb.py +342 -26
  377. agno/vectordb/weaviate/weaviate.py +227 -165
  378. agno/workflow/__init__.py +17 -13
  379. agno/workflow/{v2/condition.py → condition.py} +135 -32
  380. agno/workflow/{v2/loop.py → loop.py} +115 -28
  381. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  382. agno/workflow/{v2/router.py → router.py} +133 -32
  383. agno/workflow/{v2/step.py → step.py} +207 -49
  384. agno/workflow/{v2/steps.py → steps.py} +147 -66
  385. agno/workflow/types.py +482 -0
  386. agno/workflow/workflow.py +2410 -696
  387. agno-2.0.0.dist-info/METADATA +494 -0
  388. agno-2.0.0.dist-info/RECORD +515 -0
  389. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  390. agno/agent/metrics.py +0 -110
  391. agno/api/app.py +0 -35
  392. agno/api/playground.py +0 -92
  393. agno/api/schemas/app.py +0 -12
  394. agno/api/schemas/playground.py +0 -22
  395. agno/api/schemas/user.py +0 -35
  396. agno/api/schemas/workspace.py +0 -46
  397. agno/api/user.py +0 -160
  398. agno/api/workflows.py +0 -33
  399. agno/api/workspace.py +0 -175
  400. agno/app/agui/__init__.py +0 -3
  401. agno/app/agui/app.py +0 -17
  402. agno/app/agui/sync_router.py +0 -120
  403. agno/app/base.py +0 -186
  404. agno/app/discord/__init__.py +0 -3
  405. agno/app/fastapi/__init__.py +0 -3
  406. agno/app/fastapi/app.py +0 -107
  407. agno/app/fastapi/async_router.py +0 -457
  408. agno/app/fastapi/sync_router.py +0 -448
  409. agno/app/playground/app.py +0 -228
  410. agno/app/playground/async_router.py +0 -1053
  411. agno/app/playground/deploy.py +0 -249
  412. agno/app/playground/operator.py +0 -183
  413. agno/app/playground/schemas.py +0 -223
  414. agno/app/playground/serve.py +0 -55
  415. agno/app/playground/sync_router.py +0 -1045
  416. agno/app/playground/utils.py +0 -46
  417. agno/app/settings.py +0 -15
  418. agno/app/slack/__init__.py +0 -3
  419. agno/app/slack/app.py +0 -19
  420. agno/app/slack/sync_router.py +0 -92
  421. agno/app/utils.py +0 -54
  422. agno/app/whatsapp/__init__.py +0 -3
  423. agno/app/whatsapp/app.py +0 -15
  424. agno/app/whatsapp/sync_router.py +0 -197
  425. agno/cli/auth_server.py +0 -249
  426. agno/cli/config.py +0 -274
  427. agno/cli/console.py +0 -88
  428. agno/cli/credentials.py +0 -23
  429. agno/cli/entrypoint.py +0 -571
  430. agno/cli/operator.py +0 -357
  431. agno/cli/settings.py +0 -96
  432. agno/cli/ws/ws_cli.py +0 -817
  433. agno/constants.py +0 -13
  434. agno/document/__init__.py +0 -5
  435. agno/document/chunking/semantic.py +0 -45
  436. agno/document/chunking/strategy.py +0 -31
  437. agno/document/reader/__init__.py +0 -5
  438. agno/document/reader/base.py +0 -47
  439. agno/document/reader/docx_reader.py +0 -60
  440. agno/document/reader/gcs/pdf_reader.py +0 -44
  441. agno/document/reader/s3/pdf_reader.py +0 -59
  442. agno/document/reader/s3/text_reader.py +0 -63
  443. agno/document/reader/url_reader.py +0 -59
  444. agno/document/reader/youtube_reader.py +0 -58
  445. agno/embedder/__init__.py +0 -5
  446. agno/embedder/langdb.py +0 -80
  447. agno/embedder/mistral.py +0 -82
  448. agno/embedder/openai.py +0 -78
  449. agno/file/__init__.py +0 -5
  450. agno/file/file.py +0 -16
  451. agno/file/local/csv.py +0 -32
  452. agno/file/local/txt.py +0 -19
  453. agno/infra/app.py +0 -240
  454. agno/infra/base.py +0 -144
  455. agno/infra/context.py +0 -20
  456. agno/infra/db_app.py +0 -52
  457. agno/infra/resource.py +0 -205
  458. agno/infra/resources.py +0 -55
  459. agno/knowledge/agent.py +0 -702
  460. agno/knowledge/arxiv.py +0 -33
  461. agno/knowledge/combined.py +0 -36
  462. agno/knowledge/csv.py +0 -144
  463. agno/knowledge/csv_url.py +0 -124
  464. agno/knowledge/document.py +0 -223
  465. agno/knowledge/docx.py +0 -137
  466. agno/knowledge/firecrawl.py +0 -34
  467. agno/knowledge/gcs/__init__.py +0 -0
  468. agno/knowledge/gcs/base.py +0 -39
  469. agno/knowledge/gcs/pdf.py +0 -125
  470. agno/knowledge/json.py +0 -137
  471. agno/knowledge/langchain.py +0 -71
  472. agno/knowledge/light_rag.py +0 -273
  473. agno/knowledge/llamaindex.py +0 -66
  474. agno/knowledge/markdown.py +0 -154
  475. agno/knowledge/pdf.py +0 -164
  476. agno/knowledge/pdf_bytes.py +0 -42
  477. agno/knowledge/pdf_url.py +0 -148
  478. agno/knowledge/s3/__init__.py +0 -0
  479. agno/knowledge/s3/base.py +0 -64
  480. agno/knowledge/s3/pdf.py +0 -33
  481. agno/knowledge/s3/text.py +0 -34
  482. agno/knowledge/text.py +0 -141
  483. agno/knowledge/url.py +0 -46
  484. agno/knowledge/website.py +0 -179
  485. agno/knowledge/wikipedia.py +0 -32
  486. agno/knowledge/youtube.py +0 -35
  487. agno/memory/agent.py +0 -423
  488. agno/memory/classifier.py +0 -104
  489. agno/memory/db/__init__.py +0 -5
  490. agno/memory/db/base.py +0 -42
  491. agno/memory/db/mongodb.py +0 -189
  492. agno/memory/db/postgres.py +0 -203
  493. agno/memory/db/sqlite.py +0 -193
  494. agno/memory/memory.py +0 -22
  495. agno/memory/row.py +0 -36
  496. agno/memory/summarizer.py +0 -201
  497. agno/memory/summary.py +0 -19
  498. agno/memory/team.py +0 -415
  499. agno/memory/v2/__init__.py +0 -2
  500. agno/memory/v2/db/__init__.py +0 -1
  501. agno/memory/v2/db/base.py +0 -42
  502. agno/memory/v2/db/firestore.py +0 -339
  503. agno/memory/v2/db/mongodb.py +0 -196
  504. agno/memory/v2/db/postgres.py +0 -214
  505. agno/memory/v2/db/redis.py +0 -187
  506. agno/memory/v2/db/schema.py +0 -54
  507. agno/memory/v2/db/sqlite.py +0 -209
  508. agno/memory/v2/manager.py +0 -437
  509. agno/memory/v2/memory.py +0 -1097
  510. agno/memory/v2/schema.py +0 -55
  511. agno/memory/v2/summarizer.py +0 -215
  512. agno/memory/workflow.py +0 -38
  513. agno/models/ollama/tools.py +0 -430
  514. agno/models/qwen/__init__.py +0 -5
  515. agno/playground/__init__.py +0 -10
  516. agno/playground/deploy.py +0 -3
  517. agno/playground/playground.py +0 -3
  518. agno/playground/serve.py +0 -3
  519. agno/playground/settings.py +0 -3
  520. agno/reranker/__init__.py +0 -0
  521. agno/run/response.py +0 -467
  522. agno/run/v2/__init__.py +0 -0
  523. agno/run/v2/workflow.py +0 -567
  524. agno/storage/__init__.py +0 -0
  525. agno/storage/agent/__init__.py +0 -0
  526. agno/storage/agent/dynamodb.py +0 -1
  527. agno/storage/agent/json.py +0 -1
  528. agno/storage/agent/mongodb.py +0 -1
  529. agno/storage/agent/postgres.py +0 -1
  530. agno/storage/agent/singlestore.py +0 -1
  531. agno/storage/agent/sqlite.py +0 -1
  532. agno/storage/agent/yaml.py +0 -1
  533. agno/storage/base.py +0 -60
  534. agno/storage/dynamodb.py +0 -673
  535. agno/storage/firestore.py +0 -297
  536. agno/storage/gcs_json.py +0 -261
  537. agno/storage/in_memory.py +0 -234
  538. agno/storage/json.py +0 -237
  539. agno/storage/mongodb.py +0 -328
  540. agno/storage/mysql.py +0 -685
  541. agno/storage/postgres.py +0 -682
  542. agno/storage/redis.py +0 -336
  543. agno/storage/session/__init__.py +0 -16
  544. agno/storage/session/agent.py +0 -64
  545. agno/storage/session/team.py +0 -63
  546. agno/storage/session/v2/__init__.py +0 -5
  547. agno/storage/session/workflow.py +0 -61
  548. agno/storage/singlestore.py +0 -606
  549. agno/storage/sqlite.py +0 -646
  550. agno/storage/workflow/__init__.py +0 -0
  551. agno/storage/workflow/mongodb.py +0 -1
  552. agno/storage/workflow/postgres.py +0 -1
  553. agno/storage/workflow/sqlite.py +0 -1
  554. agno/storage/yaml.py +0 -241
  555. agno/tools/thinking.py +0 -73
  556. agno/utils/defaults.py +0 -57
  557. agno/utils/filesystem.py +0 -39
  558. agno/utils/git.py +0 -52
  559. agno/utils/json_io.py +0 -30
  560. agno/utils/load_env.py +0 -19
  561. agno/utils/py_io.py +0 -19
  562. agno/utils/pyproject.py +0 -18
  563. agno/utils/resource_filter.py +0 -31
  564. agno/workflow/v2/__init__.py +0 -21
  565. agno/workflow/v2/types.py +0 -357
  566. agno/workflow/v2/workflow.py +0 -3313
  567. agno/workspace/__init__.py +0 -0
  568. agno/workspace/config.py +0 -325
  569. agno/workspace/enums.py +0 -6
  570. agno/workspace/helpers.py +0 -52
  571. agno/workspace/operator.py +0 -757
  572. agno/workspace/settings.py +0 -158
  573. agno-1.8.2.dist-info/METADATA +0 -982
  574. agno-1.8.2.dist-info/RECORD +0 -566
  575. agno-1.8.2.dist-info/entry_points.txt +0 -3
  576. agno-1.8.2.dist-info/licenses/LICENSE +0 -375
  577. /agno/{app → db/migrations}/__init__.py +0 -0
  578. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  579. /agno/{cli → integrations}/__init__.py +0 -0
  580. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  581. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  582. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  583. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  584. /agno/{app → os/interfaces}/slack/security.py +0 -0
  585. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  586. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  587. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  588. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  589. {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -6,9 +6,11 @@ from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Tuple, Ty
6
6
  from pydantic import BaseModel
7
7
 
8
8
  from agno.exceptions import AgnoError, ModelProviderError
9
- from agno.models.base import MessageData, Model, _add_usage_metrics_to_assistant_message
9
+ from agno.models.base import MessageData, Model
10
10
  from agno.models.message import Message
11
+ from agno.models.metrics import Metrics
11
12
  from agno.models.response import ModelResponse
13
+ from agno.run.agent import RunOutput
12
14
  from agno.utils.log import log_debug, log_error, log_warning
13
15
 
14
16
  try:
@@ -345,10 +347,12 @@ class AwsBedrock(Model):
345
347
  def invoke(
346
348
  self,
347
349
  messages: List[Message],
350
+ assistant_message: Message,
348
351
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
349
352
  tools: Optional[List[Dict[str, Any]]] = None,
350
353
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
351
- ) -> Dict[str, Any]:
354
+ run_response: Optional[RunOutput] = None,
355
+ ) -> ModelResponse:
352
356
  """
353
357
  Invoke the Bedrock API.
354
358
  """
@@ -370,7 +374,17 @@ class AwsBedrock(Model):
370
374
  log_debug(f"Calling {self.provider} with request parameters: {self.request_params}", log_level=2)
371
375
  body.update(**self.request_params)
372
376
 
373
- return self.get_client().converse(modelId=self.id, messages=formatted_messages, **body)
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
+
374
388
  except ClientError as e:
375
389
  log_error(f"Unexpected error calling Bedrock API: {str(e)}")
376
390
  raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
@@ -381,10 +395,12 @@ class AwsBedrock(Model):
381
395
  def invoke_stream(
382
396
  self,
383
397
  messages: List[Message],
398
+ assistant_message: Message,
384
399
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
385
400
  tools: Optional[List[Dict[str, Any]]] = None,
386
401
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
387
- ) -> Iterator[Dict[str, Any]]:
402
+ run_response: Optional[RunOutput] = None,
403
+ ) -> Iterator[ModelResponse]:
388
404
  """
389
405
  Invoke the Bedrock API with streaming.
390
406
  """
@@ -405,7 +421,18 @@ class AwsBedrock(Model):
405
421
  if self.request_params:
406
422
  body.update(**self.request_params)
407
423
 
408
- return self.get_client().converse_stream(modelId=self.id, messages=formatted_messages, **body)["stream"]
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
+ for chunk in self.get_client().converse_stream(modelId=self.id, messages=formatted_messages, **body)[
430
+ "stream"
431
+ ]:
432
+ yield self._parse_provider_response_delta(chunk)
433
+
434
+ assistant_message.metrics.stop_timer()
435
+
409
436
  except ClientError as e:
410
437
  log_error(f"Unexpected error calling Bedrock API: {str(e)}")
411
438
  raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
@@ -416,10 +443,12 @@ class AwsBedrock(Model):
416
443
  async def ainvoke(
417
444
  self,
418
445
  messages: List[Message],
446
+ assistant_message: Message,
419
447
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
420
448
  tools: Optional[List[Dict[str, Any]]] = None,
421
449
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
422
- ) -> Dict[str, Any]:
450
+ run_response: Optional[RunOutput] = None,
451
+ ) -> ModelResponse:
423
452
  """
424
453
  Async invoke the Bedrock API.
425
454
  """
@@ -441,8 +470,20 @@ class AwsBedrock(Model):
441
470
  log_debug(f"Calling {self.provider} with request parameters: {self.request_params}", log_level=2)
442
471
  body.update(**self.request_params)
443
472
 
473
+ if run_response and run_response.metrics:
474
+ run_response.metrics.set_time_to_first_token()
475
+
476
+ assistant_message.metrics.start_timer()
477
+
444
478
  async with self.get_async_client() as client:
445
- return await client.converse(modelId=self.id, messages=formatted_messages, **body)
479
+ response = await client.converse(modelId=self.id, messages=formatted_messages, **body)
480
+
481
+ assistant_message.metrics.stop_timer()
482
+
483
+ model_response = self._parse_provider_response(response, response_format=response_format)
484
+
485
+ return model_response
486
+
446
487
  except ClientError as e:
447
488
  log_error(f"Unexpected error calling Bedrock API: {str(e)}")
448
489
  raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
@@ -453,10 +494,12 @@ class AwsBedrock(Model):
453
494
  async def ainvoke_stream(
454
495
  self,
455
496
  messages: List[Message],
497
+ assistant_message: Message,
456
498
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
457
499
  tools: Optional[List[Dict[str, Any]]] = None,
458
500
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
459
- ):
501
+ run_response: Optional[RunOutput] = None,
502
+ ) -> AsyncIterator[ModelResponse]:
460
503
  """
461
504
  Async invoke the Bedrock API with streaming.
462
505
  """
@@ -477,10 +520,18 @@ class AwsBedrock(Model):
477
520
  if self.request_params:
478
521
  body.update(**self.request_params)
479
522
 
523
+ if run_response and run_response.metrics:
524
+ run_response.metrics.set_time_to_first_token()
525
+
526
+ assistant_message.metrics.start_timer()
527
+
480
528
  async with self.get_async_client() as client:
481
529
  response = await client.converse_stream(modelId=self.id, messages=formatted_messages, **body)
482
530
  async for chunk in response["stream"]:
483
- yield chunk
531
+ yield self._parse_provider_response_delta(chunk)
532
+
533
+ assistant_message.metrics.stop_timer()
534
+
484
535
  except ClientError as e:
485
536
  log_error(f"Unexpected error calling Bedrock API: {str(e)}")
486
537
  raise ModelProviderError(message=str(e.response), model_name=self.name, model_id=self.id) from e
@@ -515,7 +566,7 @@ class AwsBedrock(Model):
515
566
 
516
567
  messages.append(Message(role="user", content=tool_result_content))
517
568
 
518
- def parse_provider_response(self, response: Dict[str, Any], **kwargs) -> ModelResponse:
569
+ def _parse_provider_response(self, response: Dict[str, Any], **kwargs) -> ModelResponse:
519
570
  """
520
571
  Parse the provider response.
521
572
 
@@ -562,11 +613,7 @@ class AwsBedrock(Model):
562
613
  model_response.content = content
563
614
 
564
615
  if "usage" in response:
565
- model_response.response_usage = {
566
- "input_tokens": response["usage"]["inputTokens"],
567
- "output_tokens": response["usage"]["outputTokens"],
568
- "total_tokens": response["usage"]["totalTokens"],
569
- }
616
+ model_response.response_usage = self._get_metrics(response["usage"])
570
617
 
571
618
  return model_response
572
619
 
@@ -578,6 +625,7 @@ class AwsBedrock(Model):
578
625
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
579
626
  tools: Optional[List[Dict[str, Any]]] = None,
580
627
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
628
+ run_response: Optional[RunOutput] = None,
581
629
  ) -> Iterator[ModelResponse]:
582
630
  """
583
631
  Process the synchronous response stream.
@@ -587,94 +635,28 @@ class AwsBedrock(Model):
587
635
  assistant_message (Message): The assistant message.
588
636
  stream_data (MessageData): The stream data.
589
637
  """
590
- tool_use: Dict[str, Any] = {}
591
- content = []
592
- tool_ids = []
593
-
594
638
  for response_delta in self.invoke_stream(
595
- messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
639
+ messages=messages,
640
+ assistant_message=assistant_message,
641
+ response_format=response_format,
642
+ tools=tools,
643
+ tool_choice=tool_choice,
644
+ run_response=run_response,
596
645
  ):
597
- model_response = ModelResponse(role="assistant")
598
646
  should_yield = False
599
- if "contentBlockStart" in response_delta:
600
- # Handle tool use requests
601
- tool = response_delta["contentBlockStart"]["start"].get("toolUse")
602
- if tool:
603
- tool_use["toolUseId"] = tool["toolUseId"]
604
- tool_use["name"] = tool["name"]
605
-
606
- elif "contentBlockDelta" in response_delta:
607
- delta = response_delta["contentBlockDelta"]["delta"]
608
- if "toolUse" in delta:
609
- if "input" not in tool_use:
610
- tool_use["input"] = ""
611
- tool_use["input"] += delta["toolUse"]["input"]
612
- elif "text" in delta:
613
- model_response.content = delta["text"]
614
-
615
- elif "contentBlockStop" in response_delta:
616
- if "input" in tool_use:
617
- # Finish collecting tool use input
618
- try:
619
- tool_use["input"] = json.loads(tool_use["input"])
620
- except json.JSONDecodeError as e:
621
- log_error(f"Failed to parse tool input as JSON: {e}")
622
- tool_use["input"] = {}
623
- content.append({"toolUse": tool_use})
624
- tool_ids.append(tool_use["toolUseId"])
625
- # Prepare the tool call
626
- tool_call = {
627
- "id": tool_use["toolUseId"],
628
- "type": "function",
629
- "function": {
630
- "name": tool_use["name"],
631
- "arguments": json.dumps(tool_use["input"]),
632
- },
633
- }
634
- # Append the tool call to the list of "done" tool calls
635
- model_response.tool_calls.append(tool_call)
636
- # Reset the tool use
637
- tool_use = {}
638
- else:
639
- # Finish collecting text content
640
- content.append({"text": stream_data.response_content})
641
-
642
- elif "messageStop" in response_delta or "metadata" in response_delta:
643
- body = response_delta.get("metadata") or response_delta.get("messageStop") or {}
644
- if "usage" in body:
645
- usage = body["usage"]
646
- model_response.response_usage = {
647
- "input_tokens": usage.get("inputTokens", 0),
648
- "output_tokens": usage.get("outputTokens", 0),
649
- "total_tokens": usage.get("totalTokens", 0),
650
- }
651
647
 
652
- # Update metrics
653
- if not assistant_message.metrics.time_to_first_token:
654
- assistant_message.metrics.set_time_to_first_token()
655
-
656
- if model_response.content:
657
- stream_data.response_content += model_response.content
648
+ if response_delta.content:
649
+ stream_data.response_content += response_delta.content
658
650
  should_yield = True
659
651
 
660
- if model_response.tool_calls:
652
+ if response_delta.tool_calls:
661
653
  if stream_data.response_tool_calls is None:
662
654
  stream_data.response_tool_calls = []
663
- stream_data.response_tool_calls.extend(model_response.tool_calls)
655
+ stream_data.response_tool_calls.extend(response_delta.tool_calls)
664
656
  should_yield = True
665
657
 
666
- if model_response.response_usage is not None:
667
- _add_usage_metrics_to_assistant_message(
668
- assistant_message=assistant_message, response_usage=model_response.response_usage
669
- )
670
-
671
658
  if should_yield:
672
- yield model_response
673
-
674
- if tool_ids:
675
- if stream_data.extra is None:
676
- stream_data.extra = {}
677
- stream_data.extra["tool_ids"] = tool_ids
659
+ yield response_delta
678
660
 
679
661
  async def aprocess_response_stream(
680
662
  self,
@@ -684,6 +666,7 @@ class AwsBedrock(Model):
684
666
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
685
667
  tools: Optional[List[Dict[str, Any]]] = None,
686
668
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
669
+ run_response: Optional[RunOutput] = None,
687
670
  ) -> AsyncIterator[ModelResponse]:
688
671
  """
689
672
  Process the asynchronous response stream.
@@ -693,96 +676,32 @@ class AwsBedrock(Model):
693
676
  assistant_message (Message): The assistant message.
694
677
  stream_data (MessageData): The stream data.
695
678
  """
696
- tool_use: Dict[str, Any] = {}
697
- content = []
698
- tool_ids = []
699
-
700
679
  async for response_delta in self.ainvoke_stream(
701
- messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
680
+ messages=messages,
681
+ assistant_message=assistant_message,
682
+ response_format=response_format,
683
+ tools=tools,
684
+ tool_choice=tool_choice,
685
+ run_response=run_response,
702
686
  ):
703
- model_response = ModelResponse(role="assistant")
704
687
  should_yield = False
705
- if "contentBlockStart" in response_delta:
706
- # Handle tool use requests
707
- tool = response_delta["contentBlockStart"]["start"].get("toolUse")
708
- if tool:
709
- tool_use["toolUseId"] = tool["toolUseId"]
710
- tool_use["name"] = tool["name"]
711
-
712
- elif "contentBlockDelta" in response_delta:
713
- delta = response_delta["contentBlockDelta"]["delta"]
714
- if "toolUse" in delta:
715
- if "input" not in tool_use:
716
- tool_use["input"] = ""
717
- tool_use["input"] += delta["toolUse"]["input"]
718
- elif "text" in delta:
719
- model_response.content = delta["text"]
720
-
721
- elif "contentBlockStop" in response_delta:
722
- if "input" in tool_use:
723
- # Finish collecting tool use input
724
- try:
725
- tool_use["input"] = json.loads(tool_use["input"])
726
- except json.JSONDecodeError as e:
727
- log_error(f"Failed to parse tool input as JSON: {e}")
728
- tool_use["input"] = {}
729
- content.append({"toolUse": tool_use})
730
- tool_ids.append(tool_use["toolUseId"])
731
- # Prepare the tool call
732
- tool_call = {
733
- "id": tool_use["toolUseId"],
734
- "type": "function",
735
- "function": {
736
- "name": tool_use["name"],
737
- "arguments": json.dumps(tool_use["input"]),
738
- },
739
- }
740
- # Append the tool call to the list of "done" tool calls
741
- model_response.tool_calls.append(tool_call)
742
- # Reset the tool use
743
- tool_use = {}
744
- else:
745
- # Finish collecting text content
746
- content.append({"text": stream_data.response_content})
747
-
748
- elif "messageStop" in response_delta or "metadata" in response_delta:
749
- body = response_delta.get("metadata") or response_delta.get("messageStop") or {}
750
- if "usage" in body:
751
- usage = body["usage"]
752
- model_response.response_usage = {
753
- "input_tokens": usage.get("inputTokens", 0),
754
- "output_tokens": usage.get("outputTokens", 0),
755
- "total_tokens": usage.get("totalTokens", 0),
756
- }
757
-
758
- # Update metrics
759
- if not assistant_message.metrics.time_to_first_token:
760
- assistant_message.metrics.set_time_to_first_token()
761
688
 
762
- if model_response.content:
763
- stream_data.response_content += model_response.content
689
+ if response_delta.content:
690
+ stream_data.response_content += response_delta.content
764
691
  should_yield = True
765
692
 
766
- if model_response.tool_calls:
693
+ if response_delta.tool_calls:
767
694
  if stream_data.response_tool_calls is None:
768
695
  stream_data.response_tool_calls = []
769
- stream_data.response_tool_calls.extend(model_response.tool_calls)
696
+ stream_data.response_tool_calls.extend(response_delta.tool_calls)
770
697
  should_yield = True
771
698
 
772
- if model_response.response_usage is not None:
773
- _add_usage_metrics_to_assistant_message(
774
- assistant_message=assistant_message, response_usage=model_response.response_usage
775
- )
776
-
777
699
  if should_yield:
778
- yield model_response
700
+ yield response_delta
779
701
 
780
- if tool_ids:
781
- if stream_data.extra is None:
782
- stream_data.extra = {}
783
- stream_data.extra["tool_ids"] = tool_ids
702
+ self._populate_assistant_message(assistant_message=assistant_message, provider_response=response_delta)
784
703
 
785
- def parse_provider_response_delta(self, response_delta: Dict[str, Any]) -> ModelResponse: # type: ignore
704
+ def _parse_provider_response_delta(self, response_delta: Dict[str, Any]) -> ModelResponse: # type: ignore
786
705
  """Parse the provider response delta for streaming.
787
706
 
788
707
  Args:
@@ -819,11 +738,24 @@ class AwsBedrock(Model):
819
738
  elif "metadata" in response_delta or "messageStop" in response_delta:
820
739
  body = response_delta.get("metadata") or response_delta.get("messageStop") or {}
821
740
  if "usage" in body:
822
- usage = body["usage"]
823
- model_response.response_usage = {
824
- "input_tokens": usage.get("inputTokens", 0),
825
- "output_tokens": usage.get("outputTokens", 0),
826
- "total_tokens": usage.get("totalTokens", 0),
827
- }
741
+ model_response.response_usage = self._get_metrics(body["usage"])
828
742
 
829
743
  return model_response
744
+
745
+ def _get_metrics(self, response_usage: Dict[str, Any]) -> Metrics:
746
+ """
747
+ Parse the given AWS Bedrock usage into an Agno Metrics object.
748
+
749
+ Args:
750
+ response_usage: Usage data from AWS Bedrock
751
+
752
+ Returns:
753
+ Metrics: Parsed metrics data
754
+ """
755
+ metrics = Metrics()
756
+
757
+ metrics.input_tokens = response_usage.get("inputTokens", 0) or 0
758
+ metrics.output_tokens = response_usage.get("outputTokens", 0) or 0
759
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
760
+
761
+ return metrics
agno/models/aws/claude.py CHANGED
@@ -1,18 +1,19 @@
1
1
  from dataclasses import dataclass
2
2
  from os import getenv
3
- from typing import Any, AsyncIterator, Dict, List, Optional, Type, Union
3
+ from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Type, Union
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
7
7
  from agno.exceptions import ModelProviderError, ModelRateLimitError
8
8
  from agno.models.anthropic import Claude as AnthropicClaude
9
9
  from agno.models.message import Message
10
+ from agno.models.response import ModelResponse
11
+ from agno.run.agent import RunOutput
10
12
  from agno.utils.log import log_debug, log_error, log_warning
11
13
  from agno.utils.models.aws_claude import format_messages
12
14
 
13
15
  try:
14
16
  from anthropic import AnthropicBedrock, APIConnectionError, APIStatusError, AsyncAnthropicBedrock, RateLimitError
15
- from anthropic.types import Message as AnthropicMessage
16
17
  except ImportError:
17
18
  raise ImportError("`anthropic[bedrock]` not installed. Please install using `pip install anthropic[bedrock]`")
18
19
 
@@ -167,10 +168,12 @@ class Claude(AnthropicClaude):
167
168
  def invoke(
168
169
  self,
169
170
  messages: List[Message],
171
+ assistant_message: Message,
170
172
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
171
173
  tools: Optional[List[Dict[str, Any]]] = None,
172
174
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
173
- ) -> AnthropicMessage:
175
+ run_response: Optional[RunOutput] = None,
176
+ ) -> ModelResponse:
174
177
  """
175
178
  Send a request to the Anthropic API to generate a response.
176
179
  """
@@ -179,11 +182,21 @@ class Claude(AnthropicClaude):
179
182
  chat_messages, system_message = format_messages(messages)
180
183
  request_kwargs = self._prepare_request_kwargs(system_message, tools)
181
184
 
182
- return self.get_client().messages.create(
185
+ if run_response and run_response.metrics:
186
+ run_response.metrics.set_time_to_first_token()
187
+
188
+ assistant_message.metrics.start_timer()
189
+ response = self.get_client().messages.create(
183
190
  model=self.id,
184
191
  messages=chat_messages, # type: ignore
185
192
  **request_kwargs,
186
193
  )
194
+ assistant_message.metrics.stop_timer()
195
+
196
+ model_response = self._parse_provider_response(response, response_format=response_format)
197
+
198
+ return model_response
199
+
187
200
  except APIConnectionError as e:
188
201
  log_error(f"Connection error while calling Claude API: {str(e)}")
189
202
  raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
@@ -202,10 +215,12 @@ class Claude(AnthropicClaude):
202
215
  def invoke_stream(
203
216
  self,
204
217
  messages: List[Message],
218
+ assistant_message: Message,
205
219
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
206
220
  tools: Optional[List[Dict[str, Any]]] = None,
207
221
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
208
- ) -> Any:
222
+ run_response: Optional[RunOutput] = None,
223
+ ) -> Iterator[ModelResponse]:
209
224
  """
210
225
  Stream a response from the Anthropic API.
211
226
 
@@ -225,15 +240,21 @@ class Claude(AnthropicClaude):
225
240
  request_kwargs = self._prepare_request_kwargs(system_message, tools)
226
241
 
227
242
  try:
228
- return (
229
- self.get_client()
230
- .messages.stream(
231
- model=self.id,
232
- messages=chat_messages, # type: ignore
233
- **request_kwargs,
234
- )
235
- .__enter__()
236
- )
243
+ if run_response and run_response.metrics:
244
+ run_response.metrics.set_time_to_first_token()
245
+
246
+ assistant_message.metrics.start_timer()
247
+
248
+ with self.get_client().messages.stream(
249
+ model=self.id,
250
+ messages=chat_messages, # type: ignore
251
+ **request_kwargs,
252
+ ) as stream:
253
+ for chunk in stream:
254
+ yield self._parse_provider_response_delta(chunk)
255
+
256
+ assistant_message.metrics.stop_timer()
257
+
237
258
  except APIConnectionError as e:
238
259
  log_error(f"Connection error while calling Claude API: {str(e)}")
239
260
  raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
@@ -252,10 +273,12 @@ class Claude(AnthropicClaude):
252
273
  async def ainvoke(
253
274
  self,
254
275
  messages: List[Message],
276
+ assistant_message: Message,
255
277
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
256
278
  tools: Optional[List[Dict[str, Any]]] = None,
257
279
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
258
- ) -> AnthropicMessage:
280
+ run_response: Optional[RunOutput] = None,
281
+ ) -> ModelResponse:
259
282
  """
260
283
  Send an asynchronous request to the Anthropic API to generate a response.
261
284
  """
@@ -264,11 +287,23 @@ class Claude(AnthropicClaude):
264
287
  chat_messages, system_message = format_messages(messages)
265
288
  request_kwargs = self._prepare_request_kwargs(system_message, tools)
266
289
 
267
- return await self.get_async_client().messages.create(
290
+ if run_response and run_response.metrics:
291
+ run_response.metrics.set_time_to_first_token()
292
+
293
+ assistant_message.metrics.start_timer()
294
+
295
+ response = await self.get_async_client().messages.create(
268
296
  model=self.id,
269
297
  messages=chat_messages, # type: ignore
270
298
  **request_kwargs,
271
299
  )
300
+
301
+ assistant_message.metrics.stop_timer()
302
+
303
+ model_response = self._parse_provider_response(response, response_format=response_format)
304
+
305
+ return model_response
306
+
272
307
  except APIConnectionError as e:
273
308
  log_error(f"Connection error while calling Claude API: {str(e)}")
274
309
  raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
@@ -287,10 +322,12 @@ class Claude(AnthropicClaude):
287
322
  async def ainvoke_stream(
288
323
  self,
289
324
  messages: List[Message],
325
+ assistant_message: Message,
290
326
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
291
327
  tools: Optional[List[Dict[str, Any]]] = None,
292
328
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
293
- ) -> AsyncIterator[Any]:
329
+ run_response: Optional[RunOutput] = None,
330
+ ) -> AsyncIterator[ModelResponse]:
294
331
  """
295
332
  Stream an asynchronous response from the Anthropic API.
296
333
 
@@ -309,13 +346,22 @@ class Claude(AnthropicClaude):
309
346
  try:
310
347
  chat_messages, system_message = format_messages(messages)
311
348
  request_kwargs = self._prepare_request_kwargs(system_message, tools)
349
+
350
+ if run_response and run_response.metrics:
351
+ run_response.metrics.set_time_to_first_token()
352
+
353
+ assistant_message.metrics.start_timer()
354
+
312
355
  async with self.get_async_client().messages.stream(
313
356
  model=self.id,
314
357
  messages=chat_messages, # type: ignore
315
358
  **request_kwargs,
316
359
  ) as stream:
317
360
  async for chunk in stream:
318
- yield chunk
361
+ yield self._parse_provider_response_delta(chunk)
362
+
363
+ assistant_message.metrics.stop_timer()
364
+
319
365
  except APIConnectionError as e:
320
366
  log_error(f"Connection error while calling Claude API: {str(e)}")
321
367
  raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e