agno 1.8.1__py3-none-any.whl → 2.0.0a1__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 (580) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2778 -4123
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +9 -64
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1749 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1438 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +888 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1051 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1417 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +10 -10
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1515 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +129 -82
  141. agno/models/aws/bedrock.py +107 -175
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +347 -287
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +100 -42
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +38 -144
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +84 -46
  158. agno/models/openai/chat.py +121 -23
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +14 -8
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +393 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +65 -28
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +33 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  184. agno/os/router.py +843 -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 +204 -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 +413 -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 +179 -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 +58 -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 +163 -0
  201. agno/os/schema.py +892 -0
  202. agno/{app/playground → os}/settings.py +8 -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/{response.py → agent.py} +144 -72
  212. agno/run/base.py +44 -58
  213. agno/run/cancel.py +83 -0
  214. agno/run/team.py +133 -77
  215. agno/run/workflow.py +537 -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 +2961 -4253
  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 +42 -22
  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 +18 -13
  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 +18 -11
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +16 -7
  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 +61 -61
  252. agno/tools/eleven_labs.py +35 -28
  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 +29 -29
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +22 -22
  260. agno/tools/function.py +68 -17
  261. agno/tools/giphy.py +22 -10
  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 +31 -19
  276. agno/tools/mem0.py +18 -12
  277. agno/tools/memori.py +14 -10
  278. agno/tools/mlx_transcribe.py +3 -2
  279. agno/tools/models/azure_openai.py +32 -14
  280. agno/tools/models/gemini.py +58 -31
  281. agno/tools/models/groq.py +29 -20
  282. agno/tools/models/nebius.py +27 -11
  283. agno/tools/models_labs.py +39 -15
  284. agno/tools/moviepy_video.py +7 -6
  285. agno/tools/neo4j.py +10 -8
  286. agno/tools/newspaper.py +7 -2
  287. agno/tools/newspaper4k.py +8 -3
  288. agno/tools/openai.py +57 -26
  289. agno/tools/openbb.py +12 -11
  290. agno/tools/opencv.py +62 -46
  291. agno/tools/openweather.py +14 -12
  292. agno/tools/pandas.py +11 -3
  293. agno/tools/postgres.py +4 -12
  294. agno/tools/pubmed.py +4 -1
  295. agno/tools/python.py +9 -22
  296. agno/tools/reasoning.py +35 -27
  297. agno/tools/reddit.py +11 -26
  298. agno/tools/replicate.py +54 -41
  299. agno/tools/resend.py +4 -1
  300. agno/tools/scrapegraph.py +15 -14
  301. agno/tools/searxng.py +10 -23
  302. agno/tools/serpapi.py +6 -3
  303. agno/tools/serper.py +13 -4
  304. agno/tools/shell.py +9 -2
  305. agno/tools/slack.py +12 -11
  306. agno/tools/sleep.py +3 -2
  307. agno/tools/spider.py +24 -4
  308. agno/tools/sql.py +7 -6
  309. agno/tools/tavily.py +6 -4
  310. agno/tools/telegram.py +12 -4
  311. agno/tools/todoist.py +11 -31
  312. agno/tools/toolkit.py +1 -1
  313. agno/tools/trafilatura.py +22 -6
  314. agno/tools/trello.py +9 -22
  315. agno/tools/twilio.py +10 -3
  316. agno/tools/user_control_flow.py +6 -1
  317. agno/tools/valyu.py +34 -5
  318. agno/tools/visualization.py +19 -28
  319. agno/tools/webbrowser.py +4 -3
  320. agno/tools/webex.py +11 -7
  321. agno/tools/website.py +15 -46
  322. agno/tools/webtools.py +12 -4
  323. agno/tools/whatsapp.py +5 -9
  324. agno/tools/wikipedia.py +20 -13
  325. agno/tools/x.py +14 -13
  326. agno/tools/yfinance.py +13 -40
  327. agno/tools/youtube.py +26 -20
  328. agno/tools/zendesk.py +7 -2
  329. agno/tools/zep.py +10 -7
  330. agno/tools/zoom.py +10 -9
  331. agno/utils/common.py +1 -19
  332. agno/utils/events.py +95 -118
  333. agno/utils/knowledge.py +29 -0
  334. agno/utils/log.py +2 -2
  335. agno/utils/mcp.py +11 -5
  336. agno/utils/media.py +39 -0
  337. agno/utils/message.py +12 -1
  338. agno/utils/models/claude.py +6 -4
  339. agno/utils/models/mistral.py +8 -7
  340. agno/utils/models/schema_utils.py +3 -3
  341. agno/utils/pprint.py +33 -32
  342. agno/utils/print_response/agent.py +779 -0
  343. agno/utils/print_response/team.py +1565 -0
  344. agno/utils/print_response/workflow.py +1451 -0
  345. agno/utils/prompts.py +14 -14
  346. agno/utils/reasoning.py +87 -0
  347. agno/utils/response.py +42 -42
  348. agno/utils/string.py +8 -22
  349. agno/utils/team.py +50 -0
  350. agno/utils/timer.py +2 -2
  351. agno/vectordb/base.py +33 -21
  352. agno/vectordb/cassandra/cassandra.py +287 -23
  353. agno/vectordb/chroma/chromadb.py +482 -59
  354. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  355. agno/vectordb/couchbase/couchbase.py +309 -29
  356. agno/vectordb/lancedb/lance_db.py +360 -21
  357. agno/vectordb/langchaindb/__init__.py +5 -0
  358. agno/vectordb/langchaindb/langchaindb.py +145 -0
  359. agno/vectordb/lightrag/__init__.py +5 -0
  360. agno/vectordb/lightrag/lightrag.py +374 -0
  361. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  362. agno/vectordb/milvus/milvus.py +242 -32
  363. agno/vectordb/mongodb/mongodb.py +200 -24
  364. agno/vectordb/pgvector/pgvector.py +319 -37
  365. agno/vectordb/pineconedb/pineconedb.py +221 -27
  366. agno/vectordb/qdrant/qdrant.py +334 -14
  367. agno/vectordb/singlestore/singlestore.py +286 -29
  368. agno/vectordb/surrealdb/surrealdb.py +187 -7
  369. agno/vectordb/upstashdb/upstashdb.py +342 -26
  370. agno/vectordb/weaviate/weaviate.py +227 -165
  371. agno/workflow/__init__.py +17 -13
  372. agno/workflow/{v2/condition.py → condition.py} +135 -32
  373. agno/workflow/{v2/loop.py → loop.py} +115 -28
  374. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  375. agno/workflow/{v2/router.py → router.py} +133 -32
  376. agno/workflow/{v2/step.py → step.py} +200 -42
  377. agno/workflow/{v2/steps.py → steps.py} +147 -66
  378. agno/workflow/types.py +482 -0
  379. agno/workflow/workflow.py +2394 -696
  380. agno-2.0.0a1.dist-info/METADATA +355 -0
  381. agno-2.0.0a1.dist-info/RECORD +514 -0
  382. agno/agent/metrics.py +0 -107
  383. agno/api/app.py +0 -35
  384. agno/api/playground.py +0 -92
  385. agno/api/schemas/app.py +0 -12
  386. agno/api/schemas/playground.py +0 -22
  387. agno/api/schemas/user.py +0 -35
  388. agno/api/schemas/workspace.py +0 -46
  389. agno/api/user.py +0 -160
  390. agno/api/workflows.py +0 -33
  391. agno/api/workspace.py +0 -175
  392. agno/app/agui/__init__.py +0 -3
  393. agno/app/agui/app.py +0 -17
  394. agno/app/agui/sync_router.py +0 -120
  395. agno/app/base.py +0 -186
  396. agno/app/discord/__init__.py +0 -3
  397. agno/app/fastapi/__init__.py +0 -3
  398. agno/app/fastapi/app.py +0 -107
  399. agno/app/fastapi/async_router.py +0 -457
  400. agno/app/fastapi/sync_router.py +0 -448
  401. agno/app/playground/app.py +0 -228
  402. agno/app/playground/async_router.py +0 -1050
  403. agno/app/playground/deploy.py +0 -249
  404. agno/app/playground/operator.py +0 -183
  405. agno/app/playground/schemas.py +0 -220
  406. agno/app/playground/serve.py +0 -55
  407. agno/app/playground/sync_router.py +0 -1042
  408. agno/app/playground/utils.py +0 -46
  409. agno/app/settings.py +0 -15
  410. agno/app/slack/__init__.py +0 -3
  411. agno/app/slack/app.py +0 -19
  412. agno/app/slack/sync_router.py +0 -92
  413. agno/app/utils.py +0 -54
  414. agno/app/whatsapp/__init__.py +0 -3
  415. agno/app/whatsapp/app.py +0 -15
  416. agno/app/whatsapp/sync_router.py +0 -197
  417. agno/cli/auth_server.py +0 -249
  418. agno/cli/config.py +0 -274
  419. agno/cli/console.py +0 -88
  420. agno/cli/credentials.py +0 -23
  421. agno/cli/entrypoint.py +0 -571
  422. agno/cli/operator.py +0 -357
  423. agno/cli/settings.py +0 -96
  424. agno/cli/ws/ws_cli.py +0 -817
  425. agno/constants.py +0 -13
  426. agno/document/__init__.py +0 -5
  427. agno/document/chunking/semantic.py +0 -45
  428. agno/document/chunking/strategy.py +0 -31
  429. agno/document/reader/__init__.py +0 -5
  430. agno/document/reader/base.py +0 -47
  431. agno/document/reader/docx_reader.py +0 -60
  432. agno/document/reader/gcs/pdf_reader.py +0 -44
  433. agno/document/reader/s3/pdf_reader.py +0 -59
  434. agno/document/reader/s3/text_reader.py +0 -63
  435. agno/document/reader/url_reader.py +0 -59
  436. agno/document/reader/youtube_reader.py +0 -58
  437. agno/embedder/__init__.py +0 -5
  438. agno/embedder/langdb.py +0 -80
  439. agno/embedder/mistral.py +0 -82
  440. agno/embedder/openai.py +0 -78
  441. agno/file/__init__.py +0 -5
  442. agno/file/file.py +0 -16
  443. agno/file/local/csv.py +0 -32
  444. agno/file/local/txt.py +0 -19
  445. agno/infra/app.py +0 -240
  446. agno/infra/base.py +0 -144
  447. agno/infra/context.py +0 -20
  448. agno/infra/db_app.py +0 -52
  449. agno/infra/resource.py +0 -205
  450. agno/infra/resources.py +0 -55
  451. agno/knowledge/agent.py +0 -702
  452. agno/knowledge/arxiv.py +0 -33
  453. agno/knowledge/combined.py +0 -36
  454. agno/knowledge/csv.py +0 -144
  455. agno/knowledge/csv_url.py +0 -124
  456. agno/knowledge/document.py +0 -223
  457. agno/knowledge/docx.py +0 -137
  458. agno/knowledge/firecrawl.py +0 -34
  459. agno/knowledge/gcs/__init__.py +0 -0
  460. agno/knowledge/gcs/base.py +0 -39
  461. agno/knowledge/gcs/pdf.py +0 -125
  462. agno/knowledge/json.py +0 -137
  463. agno/knowledge/langchain.py +0 -71
  464. agno/knowledge/light_rag.py +0 -273
  465. agno/knowledge/llamaindex.py +0 -66
  466. agno/knowledge/markdown.py +0 -154
  467. agno/knowledge/pdf.py +0 -164
  468. agno/knowledge/pdf_bytes.py +0 -42
  469. agno/knowledge/pdf_url.py +0 -148
  470. agno/knowledge/s3/__init__.py +0 -0
  471. agno/knowledge/s3/base.py +0 -64
  472. agno/knowledge/s3/pdf.py +0 -33
  473. agno/knowledge/s3/text.py +0 -34
  474. agno/knowledge/text.py +0 -141
  475. agno/knowledge/url.py +0 -46
  476. agno/knowledge/website.py +0 -179
  477. agno/knowledge/wikipedia.py +0 -32
  478. agno/knowledge/youtube.py +0 -35
  479. agno/memory/agent.py +0 -423
  480. agno/memory/classifier.py +0 -104
  481. agno/memory/db/__init__.py +0 -5
  482. agno/memory/db/base.py +0 -42
  483. agno/memory/db/mongodb.py +0 -189
  484. agno/memory/db/postgres.py +0 -203
  485. agno/memory/db/sqlite.py +0 -193
  486. agno/memory/memory.py +0 -22
  487. agno/memory/row.py +0 -36
  488. agno/memory/summarizer.py +0 -201
  489. agno/memory/summary.py +0 -19
  490. agno/memory/team.py +0 -415
  491. agno/memory/v2/__init__.py +0 -2
  492. agno/memory/v2/db/__init__.py +0 -1
  493. agno/memory/v2/db/base.py +0 -42
  494. agno/memory/v2/db/firestore.py +0 -339
  495. agno/memory/v2/db/mongodb.py +0 -196
  496. agno/memory/v2/db/postgres.py +0 -214
  497. agno/memory/v2/db/redis.py +0 -187
  498. agno/memory/v2/db/schema.py +0 -54
  499. agno/memory/v2/db/sqlite.py +0 -209
  500. agno/memory/v2/manager.py +0 -437
  501. agno/memory/v2/memory.py +0 -1097
  502. agno/memory/v2/schema.py +0 -55
  503. agno/memory/v2/summarizer.py +0 -215
  504. agno/memory/workflow.py +0 -38
  505. agno/models/ollama/tools.py +0 -430
  506. agno/models/qwen/__init__.py +0 -5
  507. agno/playground/__init__.py +0 -10
  508. agno/playground/deploy.py +0 -3
  509. agno/playground/playground.py +0 -3
  510. agno/playground/serve.py +0 -3
  511. agno/playground/settings.py +0 -3
  512. agno/reranker/__init__.py +0 -0
  513. agno/run/v2/__init__.py +0 -0
  514. agno/run/v2/workflow.py +0 -567
  515. agno/storage/__init__.py +0 -0
  516. agno/storage/agent/__init__.py +0 -0
  517. agno/storage/agent/dynamodb.py +0 -1
  518. agno/storage/agent/json.py +0 -1
  519. agno/storage/agent/mongodb.py +0 -1
  520. agno/storage/agent/postgres.py +0 -1
  521. agno/storage/agent/singlestore.py +0 -1
  522. agno/storage/agent/sqlite.py +0 -1
  523. agno/storage/agent/yaml.py +0 -1
  524. agno/storage/base.py +0 -60
  525. agno/storage/dynamodb.py +0 -673
  526. agno/storage/firestore.py +0 -297
  527. agno/storage/gcs_json.py +0 -261
  528. agno/storage/in_memory.py +0 -234
  529. agno/storage/json.py +0 -237
  530. agno/storage/mongodb.py +0 -328
  531. agno/storage/mysql.py +0 -685
  532. agno/storage/postgres.py +0 -682
  533. agno/storage/redis.py +0 -336
  534. agno/storage/session/__init__.py +0 -16
  535. agno/storage/session/agent.py +0 -64
  536. agno/storage/session/team.py +0 -63
  537. agno/storage/session/v2/__init__.py +0 -5
  538. agno/storage/session/workflow.py +0 -61
  539. agno/storage/singlestore.py +0 -606
  540. agno/storage/sqlite.py +0 -646
  541. agno/storage/workflow/__init__.py +0 -0
  542. agno/storage/workflow/mongodb.py +0 -1
  543. agno/storage/workflow/postgres.py +0 -1
  544. agno/storage/workflow/sqlite.py +0 -1
  545. agno/storage/yaml.py +0 -241
  546. agno/tools/thinking.py +0 -73
  547. agno/utils/defaults.py +0 -57
  548. agno/utils/filesystem.py +0 -39
  549. agno/utils/git.py +0 -52
  550. agno/utils/json_io.py +0 -30
  551. agno/utils/load_env.py +0 -19
  552. agno/utils/py_io.py +0 -19
  553. agno/utils/pyproject.py +0 -18
  554. agno/utils/resource_filter.py +0 -31
  555. agno/workflow/v2/__init__.py +0 -21
  556. agno/workflow/v2/types.py +0 -357
  557. agno/workflow/v2/workflow.py +0 -3312
  558. agno/workspace/__init__.py +0 -0
  559. agno/workspace/config.py +0 -325
  560. agno/workspace/enums.py +0 -6
  561. agno/workspace/helpers.py +0 -52
  562. agno/workspace/operator.py +0 -757
  563. agno/workspace/settings.py +0 -158
  564. agno-1.8.1.dist-info/METADATA +0 -982
  565. agno-1.8.1.dist-info/RECORD +0 -566
  566. agno-1.8.1.dist-info/entry_points.txt +0 -3
  567. /agno/{app → db/migrations}/__init__.py +0 -0
  568. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  569. /agno/{cli → integrations}/__init__.py +0 -0
  570. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  571. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  572. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  573. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  574. /agno/{app → os/interfaces}/slack/security.py +0 -0
  575. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  576. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  577. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  578. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  579. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  580. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
@@ -8,16 +8,20 @@ from typing_extensions import Literal
8
8
 
9
9
  from agno.exceptions import ModelProviderError
10
10
  from agno.media import File
11
- from agno.models.base import MessageData, Model, _add_usage_metrics_to_assistant_message
11
+ from agno.models.base import MessageData, Model
12
12
  from agno.models.message import Citations, Message, UrlCitation
13
+ from agno.models.metrics import Metrics
13
14
  from agno.models.response import ModelResponse
15
+ from agno.run.agent import RunOutput
14
16
  from agno.utils.log import log_debug, log_error, log_warning
15
17
  from agno.utils.models.openai_responses import images_to_message
16
18
  from agno.utils.models.schema_utils import get_response_schema_for_provider
17
19
 
18
20
  try:
19
21
  from openai import APIConnectionError, APIStatusError, AsyncOpenAI, OpenAI, RateLimitError
20
- from openai.resources.responses.responses import Response, ResponseStreamEvent
22
+ from openai.types.responses.response import Response
23
+ from openai.types.responses.response_stream_event import ResponseStreamEvent
24
+ from openai.types.responses.response_usage import ResponseUsage
21
25
  except (ImportError, ModuleNotFoundError) as e:
22
26
  raise ImportError("`openai` not installed. Please install using `pip install openai -U`") from e
23
27
 
@@ -476,10 +480,12 @@ class OpenAIResponses(Model):
476
480
  def invoke(
477
481
  self,
478
482
  messages: List[Message],
483
+ assistant_message: Message,
479
484
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
480
485
  tools: Optional[List[Dict[str, Any]]] = None,
481
486
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
482
- ) -> Response:
487
+ run_response: Optional[RunOutput] = None,
488
+ ) -> ModelResponse:
483
489
  """
484
490
  Send a request to the OpenAI Responses API.
485
491
  """
@@ -487,11 +493,24 @@ class OpenAIResponses(Model):
487
493
  request_params = self.get_request_params(
488
494
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
489
495
  )
490
- return self.get_client().responses.create(
496
+
497
+ if run_response and run_response.metrics:
498
+ run_response.metrics.set_time_to_first_token()
499
+
500
+ assistant_message.metrics.start_timer()
501
+
502
+ provider_response = self.get_client().responses.create(
491
503
  model=self.id,
492
504
  input=self._format_messages(messages), # type: ignore
493
505
  **request_params,
494
506
  )
507
+
508
+ assistant_message.metrics.stop_timer()
509
+
510
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
511
+
512
+ return model_response
513
+
495
514
  except RateLimitError as exc:
496
515
  log_error(f"Rate limit error from OpenAI API: {exc}")
497
516
  error_message = exc.response.json().get("error", {})
@@ -530,10 +549,12 @@ class OpenAIResponses(Model):
530
549
  async def ainvoke(
531
550
  self,
532
551
  messages: List[Message],
552
+ assistant_message: Message,
533
553
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
534
554
  tools: Optional[List[Dict[str, Any]]] = None,
535
555
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
536
- ) -> Response:
556
+ run_response: Optional[RunOutput] = None,
557
+ ) -> ModelResponse:
537
558
  """
538
559
  Sends an asynchronous request to the OpenAI Responses API.
539
560
  """
@@ -542,11 +563,23 @@ class OpenAIResponses(Model):
542
563
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
543
564
  )
544
565
 
545
- return await self.get_async_client().responses.create(
566
+ if run_response and run_response.metrics:
567
+ run_response.metrics.set_time_to_first_token()
568
+
569
+ assistant_message.metrics.start_timer()
570
+
571
+ provider_response = await self.get_async_client().responses.create(
546
572
  model=self.id,
547
573
  input=self._format_messages(messages), # type: ignore
548
574
  **request_params,
549
575
  )
576
+
577
+ assistant_message.metrics.stop_timer()
578
+
579
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
580
+
581
+ return model_response
582
+
550
583
  except RateLimitError as exc:
551
584
  log_error(f"Rate limit error from OpenAI API: {exc}")
552
585
  error_message = exc.response.json().get("error", {})
@@ -585,10 +618,12 @@ class OpenAIResponses(Model):
585
618
  def invoke_stream(
586
619
  self,
587
620
  messages: List[Message],
621
+ assistant_message: Message,
588
622
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
589
623
  tools: Optional[List[Dict[str, Any]]] = None,
590
624
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
591
- ) -> Iterator[ResponseStreamEvent]:
625
+ run_response: Optional[RunOutput] = None,
626
+ ) -> Iterator[ModelResponse]:
592
627
  """
593
628
  Send a streaming request to the OpenAI Responses API.
594
629
  """
@@ -596,13 +631,28 @@ class OpenAIResponses(Model):
596
631
  request_params = self.get_request_params(
597
632
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
598
633
  )
634
+ tool_use: Dict[str, Any] = {}
635
+
636
+ if run_response and run_response.metrics:
637
+ run_response.metrics.set_time_to_first_token()
638
+
639
+ assistant_message.metrics.start_timer()
599
640
 
600
- yield from self.get_client().responses.create(
641
+ for chunk in self.get_client().responses.create(
601
642
  model=self.id,
602
643
  input=self._format_messages(messages), # type: ignore
603
644
  stream=True,
604
645
  **request_params,
605
- ) # type: ignore
646
+ ):
647
+ model_response, tool_use = self._parse_provider_response_delta(
648
+ stream_event=chunk, # type: ignore
649
+ assistant_message=assistant_message,
650
+ tool_use=tool_use, # type: ignore
651
+ )
652
+ yield model_response
653
+
654
+ assistant_message.metrics.stop_timer()
655
+
606
656
  except RateLimitError as exc:
607
657
  log_error(f"Rate limit error from OpenAI API: {exc}")
608
658
  error_message = exc.response.json().get("error", {})
@@ -641,10 +691,12 @@ class OpenAIResponses(Model):
641
691
  async def ainvoke_stream(
642
692
  self,
643
693
  messages: List[Message],
694
+ assistant_message: Message,
644
695
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
645
696
  tools: Optional[List[Dict[str, Any]]] = None,
646
697
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
647
- ) -> AsyncIterator[ResponseStreamEvent]:
698
+ run_response: Optional[RunOutput] = None,
699
+ ) -> AsyncIterator[ModelResponse]:
648
700
  """
649
701
  Sends an asynchronous streaming request to the OpenAI Responses API.
650
702
  """
@@ -652,6 +704,13 @@ class OpenAIResponses(Model):
652
704
  request_params = self.get_request_params(
653
705
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
654
706
  )
707
+ tool_use: Dict[str, Any] = {}
708
+
709
+ if run_response and run_response.metrics:
710
+ run_response.metrics.set_time_to_first_token()
711
+
712
+ assistant_message.metrics.start_timer()
713
+
655
714
  async_stream = await self.get_async_client().responses.create(
656
715
  model=self.id,
657
716
  input=self._format_messages(messages), # type: ignore
@@ -659,7 +718,11 @@ class OpenAIResponses(Model):
659
718
  **request_params,
660
719
  )
661
720
  async for chunk in async_stream: # type: ignore
662
- yield chunk
721
+ model_response, tool_use = self._parse_provider_response_delta(chunk, assistant_message, tool_use) # type: ignore
722
+ yield model_response
723
+
724
+ assistant_message.metrics.stop_timer()
725
+
663
726
  except RateLimitError as exc:
664
727
  log_error(f"Rate limit error from OpenAI API: {exc}")
665
728
  error_message = exc.response.json().get("error", {})
@@ -711,7 +774,64 @@ class OpenAIResponses(Model):
711
774
  _fc_message.tool_call_id = tool_call_ids[_fc_message_index]
712
775
  messages.append(_fc_message)
713
776
 
714
- def parse_provider_response(self, response: Response, **kwargs) -> ModelResponse:
777
+ def process_response_stream(
778
+ self,
779
+ messages: List[Message],
780
+ assistant_message: Message,
781
+ stream_data: MessageData,
782
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
783
+ tools: Optional[List[Dict[str, Any]]] = None,
784
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
785
+ run_response: Optional[RunOutput] = None,
786
+ ) -> Iterator[ModelResponse]:
787
+ """Process the synchronous response stream."""
788
+ for model_response_delta in self.invoke_stream(
789
+ messages=messages,
790
+ assistant_message=assistant_message,
791
+ tools=tools,
792
+ response_format=response_format,
793
+ tool_choice=tool_choice,
794
+ run_response=run_response,
795
+ ):
796
+ yield from self._populate_stream_data_and_assistant_message(
797
+ stream_data=stream_data,
798
+ assistant_message=assistant_message,
799
+ model_response_delta=model_response_delta,
800
+ )
801
+
802
+ # Add final metrics to assistant message
803
+ self._populate_assistant_message(assistant_message=assistant_message, provider_response=model_response_delta)
804
+
805
+ async def aprocess_response_stream(
806
+ self,
807
+ messages: List[Message],
808
+ assistant_message: Message,
809
+ stream_data: MessageData,
810
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
811
+ tools: Optional[List[Dict[str, Any]]] = None,
812
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
813
+ run_response: Optional[RunOutput] = None,
814
+ ) -> AsyncIterator[ModelResponse]:
815
+ """Process the asynchronous response stream."""
816
+ async for model_response_delta in self.ainvoke_stream(
817
+ messages=messages,
818
+ assistant_message=assistant_message,
819
+ tools=tools,
820
+ response_format=response_format,
821
+ tool_choice=tool_choice,
822
+ run_response=run_response,
823
+ ):
824
+ for model_response in self._populate_stream_data_and_assistant_message(
825
+ stream_data=stream_data,
826
+ assistant_message=assistant_message,
827
+ model_response_delta=model_response_delta,
828
+ ):
829
+ yield model_response
830
+
831
+ # Add final metrics to assistant message
832
+ self._populate_assistant_message(assistant_message=assistant_message, provider_response=model_response_delta)
833
+
834
+ def _parse_provider_response(self, response: Response, **kwargs) -> ModelResponse:
715
835
  """
716
836
  Parse the OpenAI response into a ModelResponse.
717
837
 
@@ -797,76 +917,66 @@ class OpenAIResponses(Model):
797
917
 
798
918
  # Add metrics
799
919
  if response.usage is not None:
800
- model_response.response_usage = response.usage
920
+ model_response.response_usage = self._get_metrics(response.usage)
801
921
 
802
922
  return model_response
803
923
 
804
- def _process_stream_response(
805
- self,
806
- stream_event: ResponseStreamEvent,
807
- assistant_message: Message,
808
- stream_data: MessageData,
809
- tool_use: Dict[str, Any],
810
- ) -> Tuple[Optional[ModelResponse], Dict[str, Any]]:
924
+ def _parse_provider_response_delta(
925
+ self, stream_event: ResponseStreamEvent, assistant_message: Message, tool_use: Dict[str, Any]
926
+ ) -> Tuple[ModelResponse, Dict[str, Any]]:
811
927
  """
812
- Common handler for processing stream responses from Cohere.
928
+ Parse the streaming response from the model provider into a ModelResponse object.
813
929
 
814
930
  Args:
815
- stream_event: The streamed response from Cohere
816
- assistant_message: The assistant message being built
817
- stream_data: Data accumulated during streaming
818
- tool_use: Current tool use data being built
931
+ response: Raw response chunk from the model provider
819
932
 
820
933
  Returns:
821
- Tuple containing the ModelResponse to yield and updated tool_use dict
934
+ ModelResponse: Parsed response delta
822
935
  """
823
- model_response = None
936
+ model_response = ModelResponse()
824
937
 
938
+ # 1. Add response ID
825
939
  if stream_event.type == "response.created":
826
- model_response = ModelResponse()
827
- # Store the response ID for continuity
828
940
  if stream_event.response.id:
829
- if stream_data.response_provider_data is None:
830
- stream_data.response_provider_data = {}
831
- stream_data.response_provider_data["response_id"] = stream_event.response.id
832
- # Update metrics
941
+ if model_response.provider_data is None:
942
+ model_response.provider_data = {}
943
+ model_response.provider_data["response_id"] = stream_event.response.id
833
944
  if not assistant_message.metrics.time_to_first_token:
834
945
  assistant_message.metrics.set_time_to_first_token()
946
+
947
+ # 2. Add citations
835
948
  elif stream_event.type == "response.output_text.annotation.added":
836
- model_response = ModelResponse()
837
- if stream_data.response_citations is None:
838
- stream_data.response_citations = Citations(raw=[stream_event.annotation])
949
+ if model_response.citations is None:
950
+ model_response.citations = Citations(raw=[stream_event.annotation])
839
951
  else:
840
- stream_data.response_citations.raw.append(stream_event.annotation) # type: ignore
952
+ model_response.citations.raw.append(stream_event.annotation) # type: ignore
841
953
 
842
954
  if isinstance(stream_event.annotation, dict):
843
955
  if stream_event.annotation.get("type") == "url_citation":
844
- if stream_data.response_citations.urls is None:
845
- stream_data.response_citations.urls = []
846
- stream_data.response_citations.urls.append(
956
+ if model_response.citations.urls is None:
957
+ model_response.citations.urls = []
958
+ model_response.citations.urls.append(
847
959
  UrlCitation(url=stream_event.annotation.get("url"), title=stream_event.annotation.get("title"))
848
960
  )
849
961
  else:
850
962
  if stream_event.annotation.type == "url_citation": # type: ignore
851
- if stream_data.response_citations.urls is None:
852
- stream_data.response_citations.urls = []
853
- stream_data.response_citations.urls.append(
963
+ if model_response.citations.urls is None:
964
+ model_response.citations.urls = []
965
+ model_response.citations.urls.append(
854
966
  UrlCitation(url=stream_event.annotation.url, title=stream_event.annotation.title) # type: ignore
855
967
  )
856
968
 
857
- model_response.citations = stream_data.response_citations
858
-
969
+ # 3. Add content
859
970
  elif stream_event.type == "response.output_text.delta":
860
- model_response = ModelResponse()
861
- # Add content
862
971
  model_response.content = stream_event.delta
863
- stream_data.response_content += stream_event.delta
864
972
 
865
973
  # Treat the output_text deltas as reasoning content if the reasoning summary is not requested.
866
974
  if self.reasoning is not None and self.reasoning_summary is None:
867
975
  model_response.reasoning_content = stream_event.delta
868
- stream_data.response_thinking += stream_event.delta
869
976
 
977
+ # 4. Add tool calls information
978
+
979
+ # 4.1 Add starting tool call
870
980
  elif stream_event.type == "response.output_item.added":
871
981
  item = stream_event.item
872
982
  if item.type == "function_call":
@@ -880,20 +990,22 @@ class OpenAIResponses(Model):
880
990
  },
881
991
  }
882
992
 
993
+ # 4.2 Add tool call arguments
883
994
  elif stream_event.type == "response.function_call_arguments.delta":
884
995
  tool_use["function"]["arguments"] += stream_event.delta
885
996
 
997
+ # 4.3 Add tool call completion data
886
998
  elif stream_event.type == "response.output_item.done" and tool_use:
887
- model_response = ModelResponse()
888
999
  model_response.tool_calls = [tool_use]
889
1000
  if assistant_message.tool_calls is None:
890
1001
  assistant_message.tool_calls = []
891
1002
  assistant_message.tool_calls.append(tool_use)
892
1003
 
893
- stream_data.extra = stream_data.extra or {}
894
- stream_data.extra.setdefault("tool_call_ids", []).append(tool_use["call_id"])
1004
+ model_response.extra = model_response.extra or {}
1005
+ model_response.extra.setdefault("tool_call_ids", []).append(tool_use["call_id"])
895
1006
  tool_use = {}
896
1007
 
1008
+ # 5. Add metrics
897
1009
  elif stream_event.type == "response.completed":
898
1010
  model_response = ModelResponse()
899
1011
 
@@ -915,63 +1027,24 @@ class OpenAIResponses(Model):
915
1027
 
916
1028
  # Add metrics
917
1029
  if stream_event.response.usage is not None:
918
- model_response.response_usage = stream_event.response.usage
919
-
920
- _add_usage_metrics_to_assistant_message(
921
- assistant_message=assistant_message,
922
- response_usage=model_response.response_usage,
923
- )
1030
+ model_response.response_usage = self._get_metrics(stream_event.response.usage)
924
1031
 
925
1032
  return model_response, tool_use
926
1033
 
927
- def process_response_stream(
928
- self,
929
- messages: List[Message],
930
- assistant_message: Message,
931
- stream_data: MessageData,
932
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
933
- tools: Optional[List[Dict[str, Any]]] = None,
934
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
935
- ) -> Iterator[ModelResponse]:
936
- """Process the synchronous response stream."""
937
- tool_use: Dict[str, Any] = {}
938
-
939
- for stream_event in self.invoke_stream(
940
- messages=messages, tools=tools, response_format=response_format, tool_choice=tool_choice
941
- ):
942
- model_response, tool_use = self._process_stream_response(
943
- stream_event=stream_event,
944
- assistant_message=assistant_message,
945
- stream_data=stream_data,
946
- tool_use=tool_use,
947
- )
1034
+ def _get_metrics(self, response_usage: ResponseUsage) -> Metrics:
1035
+ """
1036
+ Parse the given OpenAI-specific usage into an Agno Metrics object.
948
1037
 
949
- if model_response is not None:
950
- yield model_response
1038
+ Args:
1039
+ response: The response from the provider.
951
1040
 
952
- async def aprocess_response_stream(
953
- self,
954
- messages: List[Message],
955
- assistant_message: Message,
956
- stream_data: MessageData,
957
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
958
- tools: Optional[List[Dict[str, Any]]] = None,
959
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
960
- ) -> AsyncIterator[ModelResponse]:
961
- """Process the asynchronous response stream."""
962
- tool_use: Dict[str, Any] = {}
1041
+ Returns:
1042
+ Metrics: Parsed metrics data
1043
+ """
1044
+ metrics = Metrics()
963
1045
 
964
- async for stream_event in self.ainvoke_stream(
965
- messages=messages, tools=tools, response_format=response_format, tool_choice=tool_choice
966
- ):
967
- model_response, tool_use = self._process_stream_response(
968
- stream_event=stream_event,
969
- assistant_message=assistant_message,
970
- stream_data=stream_data,
971
- tool_use=tool_use,
972
- )
973
- if model_response is not None:
974
- yield model_response
1046
+ metrics.input_tokens = response_usage.input_tokens or 0
1047
+ metrics.output_tokens = response_usage.output_tokens or 0
1048
+ metrics.total_tokens = response_usage.total_tokens or 0
975
1049
 
976
- def parse_provider_response_delta(self, response: Any) -> ModelResponse: # type: ignore
977
- pass
1050
+ return metrics
@@ -6,6 +6,7 @@ from pydantic import BaseModel
6
6
 
7
7
  from agno.exceptions import ModelProviderError
8
8
  from agno.models.message import Citations, UrlCitation
9
+ from agno.models.metrics import Metrics
9
10
  from agno.models.response import ModelResponse
10
11
  from agno.utils.log import log_debug, log_warning
11
12
 
@@ -16,6 +17,7 @@ try:
16
17
  ChoiceDelta,
17
18
  )
18
19
  from openai.types.chat.parsed_chat_completion import ParsedChatCompletion
20
+ from openai.types.completion_usage import CompletionUsage
19
21
  except ModuleNotFoundError:
20
22
  raise ImportError("`openai` not installed. Please install using `pip install openai`")
21
23
 
@@ -124,7 +126,7 @@ class Perplexity(OpenAILike):
124
126
  )
125
127
 
126
128
  if response.usage is not None:
127
- model_response.response_usage = response.usage
129
+ model_response.response_usage = self._get_metrics(response.usage)
128
130
 
129
131
  return model_response
130
132
 
@@ -159,6 +161,28 @@ class Perplexity(OpenAILike):
159
161
 
160
162
  # Add usage metrics if present
161
163
  if response_delta.usage is not None:
162
- model_response.response_usage = response_delta.usage
164
+ model_response.response_usage = self._get_metrics(response_delta.usage)
163
165
 
164
166
  return model_response
167
+
168
+ def _get_metrics(self, response_usage: CompletionUsage) -> Metrics:
169
+ """
170
+ Parse the given Perplexity usage into an Agno Metrics object.
171
+ """
172
+ metrics = Metrics()
173
+
174
+ metrics.input_tokens = response_usage.prompt_tokens or 0
175
+ metrics.output_tokens = response_usage.completion_tokens or 0
176
+ metrics.total_tokens = response_usage.total_tokens or 0
177
+
178
+ # Add the prompt_tokens_details field
179
+ if prompt_token_details := response_usage.prompt_tokens_details:
180
+ metrics.audio_input_tokens = prompt_token_details.audio_tokens or 0
181
+ metrics.cache_read_tokens = prompt_token_details.cached_tokens or 0
182
+
183
+ # Add the completion_tokens_details field
184
+ if completion_tokens_details := response_usage.completion_tokens_details:
185
+ metrics.audio_output_tokens = completion_tokens_details.audio_tokens or 0
186
+ metrics.reasoning_tokens = completion_tokens_details.reasoning_tokens or 0
187
+
188
+ return metrics
@@ -44,13 +44,6 @@ class Portkey(OpenAILike):
44
44
  model_id=self.id,
45
45
  )
46
46
 
47
- if not self.virtual_key:
48
- raise ModelProviderError(
49
- message="PORTKEY_VIRTUAL_KEY not set. Please set the PORTKEY_VIRTUAL_KEY environment variable.",
50
- model_name=self.name,
51
- model_id=self.id,
52
- )
53
-
54
47
  # Create headers using Portkey's createHeaders function
55
48
  header_params: Dict[str, Any] = {
56
49
  "api_key": self.portkey_api_key,
agno/models/response.py CHANGED
@@ -3,8 +3,9 @@ from enum import Enum
3
3
  from time import time
4
4
  from typing import Any, Dict, List, Optional
5
5
 
6
- from agno.media import AudioResponse, ImageArtifact
7
- from agno.models.message import Citations, MessageMetrics
6
+ from agno.media import AudioArtifact, AudioResponse, ImageArtifact, VideoArtifact
7
+ from agno.models.message import Citations
8
+ from agno.models.metrics import Metrics
8
9
  from agno.tools.function import UserInputField
9
10
 
10
11
 
@@ -26,7 +27,7 @@ class ToolExecution:
26
27
  tool_args: Optional[Dict[str, Any]] = None
27
28
  tool_call_error: Optional[bool] = None
28
29
  result: Optional[str] = None
29
- metrics: Optional[MessageMetrics] = None
30
+ metrics: Optional[Metrics] = None
30
31
 
31
32
  # If True, the agent will stop executing after this tool call.
32
33
  stop_after_tool_call: bool = False
@@ -74,7 +75,7 @@ class ToolExecution:
74
75
  if "user_input_schema" in data
75
76
  else None,
76
77
  external_execution_required=data.get("external_execution_required"),
77
- metrics=MessageMetrics(**(data.get("metrics", {}) or {})),
78
+ metrics=Metrics(**(data.get("metrics", {}) or {})),
78
79
  )
79
80
 
80
81
 
@@ -87,7 +88,11 @@ class ModelResponse:
87
88
  content: Optional[Any] = None
88
89
  parsed: Optional[Any] = None
89
90
  audio: Optional[AudioResponse] = None
90
- image: Optional[ImageArtifact] = None
91
+
92
+ # Unified media fields for LLM-generated and tool-generated media artifacts
93
+ images: Optional[List[ImageArtifact]] = None
94
+ videos: Optional[List[VideoArtifact]] = None
95
+ audios: Optional[List[AudioArtifact]] = None
91
96
 
92
97
  # Model tool calls
93
98
  tool_calls: List[Dict[str, Any]] = field(default_factory=list)
@@ -99,18 +104,19 @@ class ModelResponse:
99
104
 
100
105
  provider_data: Optional[Dict[str, Any]] = None
101
106
 
102
- thinking: Optional[str] = None
103
- redacted_thinking: Optional[str] = None
107
+ redacted_reasoning_content: Optional[str] = None
104
108
  reasoning_content: Optional[str] = None
105
109
 
106
110
  citations: Optional[Citations] = None
107
111
 
108
- response_usage: Optional[Any] = None
112
+ response_usage: Optional[Metrics] = None
109
113
 
110
114
  created_at: int = int(time())
111
115
 
112
116
  extra: Optional[Dict[str, Any]] = None
113
117
 
118
+ updated_session_state: Optional[Dict[str, Any]] = None
119
+
114
120
 
115
121
  class FileType(str, Enum):
116
122
  MP4 = "mp4"
agno/models/utils.py ADDED
@@ -0,0 +1,20 @@
1
+ from agno.models.base import Model
2
+
3
+
4
+ # TODO: add all supported models
5
+ def get_model(model_id: str, model_provider: str) -> Model:
6
+ """Return the right Agno model instance given a pair of model provider and id"""
7
+ if model_provider == "openai":
8
+ from agno.models.openai import OpenAIChat
9
+
10
+ return OpenAIChat(id=model_id)
11
+ elif model_provider == "anthropic":
12
+ from agno.models.anthropic import Claude
13
+
14
+ return Claude(id=model_id)
15
+ elif model_provider == "gemini":
16
+ from agno.models.google import Gemini
17
+
18
+ return Gemini(id=model_id)
19
+ else:
20
+ raise ValueError(f"Model provider {model_provider} not supported")
@@ -1,3 +1,3 @@
1
- from agno.models.vercel.v0 import v0
1
+ from agno.models.vercel.v0 import V0
2
2
 
3
- __all__ = ["v0"]
3
+ __all__ = ["V0"]
agno/models/vercel/v0.py CHANGED
@@ -6,7 +6,7 @@ from agno.models.openai.like import OpenAILike
6
6
 
7
7
 
8
8
  @dataclass
9
- class v0(OpenAILike):
9
+ class V0(OpenAILike):
10
10
  """
11
11
  Class for interacting with the v0 API.
12
12
 
@@ -1,3 +1,3 @@
1
- from agno.models.vllm.vllm import vLLM
1
+ from agno.models.vllm.vllm import VLLM
2
2
 
3
- __all__ = ["vLLM"]
3
+ __all__ = ["VLLM"]
agno/models/vllm/vllm.py CHANGED
@@ -9,7 +9,7 @@ from agno.utils.log import log_debug
9
9
 
10
10
 
11
11
  @dataclass
12
- class vLLM(OpenAILike):
12
+ class VLLM(OpenAILike):
13
13
  """
14
14
  Class for interacting with vLLM models via OpenAI-compatible API.
15
15
 
@@ -26,8 +26,8 @@ class vLLM(OpenAILike):
26
26
  """
27
27
 
28
28
  id: str = "not-set"
29
- name: str = "vLLM"
30
- provider: str = "vLLM"
29
+ name: str = "VLLM"
30
+ provider: str = "VLLM"
31
31
 
32
32
  api_key: Optional[str] = getenv("VLLM_API_KEY") or "EMPTY"
33
33
  base_url: Optional[str] = getenv("VLLM_BASE_URL", "http://localhost:8000/v1/")