agno 1.8.0__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 (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2781 -4126
  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/media.py +2 -2
  137. agno/memory/__init__.py +2 -10
  138. agno/memory/manager.py +1003 -148
  139. agno/models/aimlapi/__init__.py +2 -2
  140. agno/models/aimlapi/aimlapi.py +6 -6
  141. agno/models/anthropic/claude.py +129 -82
  142. agno/models/aws/bedrock.py +107 -175
  143. agno/models/aws/claude.py +64 -18
  144. agno/models/azure/ai_foundry.py +73 -23
  145. agno/models/base.py +347 -287
  146. agno/models/cerebras/cerebras.py +84 -27
  147. agno/models/cohere/chat.py +106 -98
  148. agno/models/dashscope/dashscope.py +14 -5
  149. agno/models/google/gemini.py +123 -53
  150. agno/models/groq/groq.py +97 -35
  151. agno/models/huggingface/huggingface.py +92 -27
  152. agno/models/ibm/watsonx.py +72 -13
  153. agno/models/litellm/chat.py +85 -13
  154. agno/models/message.py +38 -144
  155. agno/models/meta/llama.py +85 -49
  156. agno/models/metrics.py +120 -0
  157. agno/models/mistral/mistral.py +90 -21
  158. agno/models/ollama/__init__.py +0 -2
  159. agno/models/ollama/chat.py +84 -46
  160. agno/models/openai/chat.py +135 -27
  161. agno/models/openai/responses.py +233 -115
  162. agno/models/perplexity/perplexity.py +26 -2
  163. agno/models/portkey/portkey.py +0 -7
  164. agno/models/response.py +14 -8
  165. agno/models/utils.py +20 -0
  166. agno/models/vercel/__init__.py +2 -2
  167. agno/models/vercel/v0.py +1 -1
  168. agno/models/vllm/__init__.py +2 -2
  169. agno/models/vllm/vllm.py +3 -3
  170. agno/models/xai/xai.py +10 -10
  171. agno/os/__init__.py +3 -0
  172. agno/os/app.py +393 -0
  173. agno/os/auth.py +47 -0
  174. agno/os/config.py +103 -0
  175. agno/os/interfaces/agui/__init__.py +3 -0
  176. agno/os/interfaces/agui/agui.py +31 -0
  177. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  178. agno/{app → os/interfaces}/agui/utils.py +65 -28
  179. agno/os/interfaces/base.py +21 -0
  180. agno/os/interfaces/slack/__init__.py +3 -0
  181. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  182. agno/os/interfaces/slack/slack.py +33 -0
  183. agno/os/interfaces/whatsapp/__init__.py +3 -0
  184. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  185. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  186. agno/os/router.py +843 -0
  187. agno/os/routers/__init__.py +3 -0
  188. agno/os/routers/evals/__init__.py +3 -0
  189. agno/os/routers/evals/evals.py +204 -0
  190. agno/os/routers/evals/schemas.py +142 -0
  191. agno/os/routers/evals/utils.py +161 -0
  192. agno/os/routers/knowledge/__init__.py +3 -0
  193. agno/os/routers/knowledge/knowledge.py +413 -0
  194. agno/os/routers/knowledge/schemas.py +118 -0
  195. agno/os/routers/memory/__init__.py +3 -0
  196. agno/os/routers/memory/memory.py +179 -0
  197. agno/os/routers/memory/schemas.py +58 -0
  198. agno/os/routers/metrics/__init__.py +3 -0
  199. agno/os/routers/metrics/metrics.py +58 -0
  200. agno/os/routers/metrics/schemas.py +47 -0
  201. agno/os/routers/session/__init__.py +3 -0
  202. agno/os/routers/session/session.py +163 -0
  203. agno/os/schema.py +892 -0
  204. agno/{app/playground → os}/settings.py +8 -15
  205. agno/os/utils.py +270 -0
  206. agno/reasoning/azure_ai_foundry.py +4 -4
  207. agno/reasoning/deepseek.py +4 -4
  208. agno/reasoning/default.py +6 -11
  209. agno/reasoning/groq.py +4 -4
  210. agno/reasoning/helpers.py +4 -6
  211. agno/reasoning/ollama.py +4 -4
  212. agno/reasoning/openai.py +4 -4
  213. agno/run/{response.py → agent.py} +144 -72
  214. agno/run/base.py +44 -58
  215. agno/run/cancel.py +83 -0
  216. agno/run/team.py +133 -77
  217. agno/run/workflow.py +537 -12
  218. agno/session/__init__.py +10 -0
  219. agno/session/agent.py +244 -0
  220. agno/session/summary.py +225 -0
  221. agno/session/team.py +262 -0
  222. agno/{storage/session/v2 → session}/workflow.py +47 -24
  223. agno/team/__init__.py +15 -16
  224. agno/team/team.py +2967 -4243
  225. agno/tools/agentql.py +14 -5
  226. agno/tools/airflow.py +9 -4
  227. agno/tools/api.py +7 -3
  228. agno/tools/apify.py +2 -46
  229. agno/tools/arxiv.py +8 -3
  230. agno/tools/aws_lambda.py +7 -5
  231. agno/tools/aws_ses.py +7 -1
  232. agno/tools/baidusearch.py +4 -1
  233. agno/tools/bitbucket.py +4 -4
  234. agno/tools/brandfetch.py +14 -11
  235. agno/tools/bravesearch.py +4 -1
  236. agno/tools/brightdata.py +42 -22
  237. agno/tools/browserbase.py +13 -4
  238. agno/tools/calcom.py +12 -10
  239. agno/tools/calculator.py +10 -27
  240. agno/tools/cartesia.py +18 -13
  241. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  242. agno/tools/confluence.py +71 -18
  243. agno/tools/crawl4ai.py +7 -1
  244. agno/tools/csv_toolkit.py +9 -8
  245. agno/tools/dalle.py +18 -11
  246. agno/tools/daytona.py +13 -16
  247. agno/tools/decorator.py +6 -3
  248. agno/tools/desi_vocal.py +16 -7
  249. agno/tools/discord.py +11 -8
  250. agno/tools/docker.py +30 -42
  251. agno/tools/duckdb.py +34 -53
  252. agno/tools/duckduckgo.py +8 -7
  253. agno/tools/e2b.py +62 -62
  254. agno/tools/eleven_labs.py +35 -28
  255. agno/tools/email.py +4 -1
  256. agno/tools/evm.py +7 -1
  257. agno/tools/exa.py +19 -14
  258. agno/tools/fal.py +29 -29
  259. agno/tools/file.py +9 -8
  260. agno/tools/financial_datasets.py +25 -44
  261. agno/tools/firecrawl.py +22 -22
  262. agno/tools/function.py +68 -17
  263. agno/tools/giphy.py +22 -10
  264. agno/tools/github.py +48 -126
  265. agno/tools/gmail.py +46 -62
  266. agno/tools/google_bigquery.py +7 -6
  267. agno/tools/google_maps.py +11 -26
  268. agno/tools/googlesearch.py +7 -2
  269. agno/tools/googlesheets.py +21 -17
  270. agno/tools/hackernews.py +9 -5
  271. agno/tools/jina.py +5 -4
  272. agno/tools/jira.py +18 -9
  273. agno/tools/knowledge.py +31 -32
  274. agno/tools/linear.py +18 -33
  275. agno/tools/linkup.py +5 -1
  276. agno/tools/local_file_system.py +8 -5
  277. agno/tools/lumalab.py +31 -19
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +32 -14
  282. agno/tools/models/gemini.py +58 -31
  283. agno/tools/models/groq.py +29 -20
  284. agno/tools/models/nebius.py +27 -11
  285. agno/tools/models_labs.py +39 -15
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +134 -0
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +57 -26
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +62 -46
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +54 -41
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +95 -118
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/location.py +2 -2
  337. agno/utils/log.py +2 -2
  338. agno/utils/mcp.py +11 -5
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/claude.py +6 -4
  342. agno/utils/models/mistral.py +8 -7
  343. agno/utils/models/schema_utils.py +3 -3
  344. agno/utils/pprint.py +33 -32
  345. agno/utils/print_response/agent.py +779 -0
  346. agno/utils/print_response/team.py +1565 -0
  347. agno/utils/print_response/workflow.py +1451 -0
  348. agno/utils/prompts.py +14 -14
  349. agno/utils/reasoning.py +87 -0
  350. agno/utils/response.py +42 -42
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +356 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2394 -696
  383. agno-2.0.0a1.dist-info/METADATA +355 -0
  384. agno-2.0.0a1.dist-info/RECORD +514 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -698
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.0.dist-info/METADATA +0 -979
  568. agno-1.8.0.dist-info/RECORD +0 -565
  569. agno-1.8.0.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.0.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
 
@@ -44,6 +48,7 @@ class OpenAIResponses(Model):
44
48
  reasoning: Optional[Dict[str, Any]] = None
45
49
  verbosity: Optional[Literal["low", "medium", "high"]] = None
46
50
  reasoning_effort: Optional[Literal["minimal", "medium", "high"]] = None
51
+ reasoning_summary: Optional[Literal["auto", "concise", "detailed"]] = None
47
52
  store: Optional[bool] = None
48
53
  temperature: Optional[float] = None
49
54
  top_p: Optional[float] = None
@@ -84,6 +89,18 @@ class OpenAIResponses(Model):
84
89
  """Return True if the contextual used model is a known reasoning model."""
85
90
  return self.id.startswith("o3") or self.id.startswith("o4-mini") or self.id.startswith("gpt-5")
86
91
 
92
+ def _set_reasoning_request_param(self, base_params: Dict[str, Any]) -> Dict[str, Any]:
93
+ """Set the reasoning request parameter."""
94
+ base_params["reasoning"] = self.reasoning or {}
95
+
96
+ if self.reasoning_effort is not None:
97
+ base_params["reasoning"]["effort"] = self.reasoning_effort
98
+
99
+ if self.reasoning_summary is not None:
100
+ base_params["reasoning"]["summary"] = self.reasoning_summary
101
+
102
+ return base_params
103
+
87
104
  def _get_client_params(self) -> Dict[str, Any]:
88
105
  """
89
106
  Get client parameters for API requests.
@@ -185,12 +202,8 @@ class OpenAIResponses(Model):
185
202
  "user": self.user,
186
203
  "service_tier": self.service_tier,
187
204
  }
188
-
189
- # Handle reasoning parameter - convert reasoning_effort to reasoning format
190
- if self.reasoning is not None:
191
- base_params["reasoning"] = self.reasoning
192
- elif self.reasoning_effort is not None:
193
- base_params["reasoning"] = {"effort": self.reasoning_effort}
205
+ # Populate the reasoning parameter
206
+ base_params = self._set_reasoning_request_param(base_params)
194
207
 
195
208
  # Build text parameter
196
209
  text_params: Dict[str, Any] = {}
@@ -467,10 +480,12 @@ class OpenAIResponses(Model):
467
480
  def invoke(
468
481
  self,
469
482
  messages: List[Message],
483
+ assistant_message: Message,
470
484
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
471
485
  tools: Optional[List[Dict[str, Any]]] = None,
472
486
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
473
- ) -> Response:
487
+ run_response: Optional[RunOutput] = None,
488
+ ) -> ModelResponse:
474
489
  """
475
490
  Send a request to the OpenAI Responses API.
476
491
  """
@@ -479,11 +494,23 @@ class OpenAIResponses(Model):
479
494
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
480
495
  )
481
496
 
482
- return self.get_client().responses.create(
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(
483
503
  model=self.id,
484
504
  input=self._format_messages(messages), # type: ignore
485
505
  **request_params,
486
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
+
487
514
  except RateLimitError as exc:
488
515
  log_error(f"Rate limit error from OpenAI API: {exc}")
489
516
  error_message = exc.response.json().get("error", {})
@@ -522,10 +549,12 @@ class OpenAIResponses(Model):
522
549
  async def ainvoke(
523
550
  self,
524
551
  messages: List[Message],
552
+ assistant_message: Message,
525
553
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
526
554
  tools: Optional[List[Dict[str, Any]]] = None,
527
555
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
528
- ) -> Response:
556
+ run_response: Optional[RunOutput] = None,
557
+ ) -> ModelResponse:
529
558
  """
530
559
  Sends an asynchronous request to the OpenAI Responses API.
531
560
  """
@@ -534,11 +563,23 @@ class OpenAIResponses(Model):
534
563
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
535
564
  )
536
565
 
537
- 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(
538
572
  model=self.id,
539
573
  input=self._format_messages(messages), # type: ignore
540
574
  **request_params,
541
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
+
542
583
  except RateLimitError as exc:
543
584
  log_error(f"Rate limit error from OpenAI API: {exc}")
544
585
  error_message = exc.response.json().get("error", {})
@@ -577,10 +618,12 @@ class OpenAIResponses(Model):
577
618
  def invoke_stream(
578
619
  self,
579
620
  messages: List[Message],
621
+ assistant_message: Message,
580
622
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
581
623
  tools: Optional[List[Dict[str, Any]]] = None,
582
624
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
583
- ) -> Iterator[ResponseStreamEvent]:
625
+ run_response: Optional[RunOutput] = None,
626
+ ) -> Iterator[ModelResponse]:
584
627
  """
585
628
  Send a streaming request to the OpenAI Responses API.
586
629
  """
@@ -588,13 +631,28 @@ class OpenAIResponses(Model):
588
631
  request_params = self.get_request_params(
589
632
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
590
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()
591
638
 
592
- yield from self.get_client().responses.create(
639
+ assistant_message.metrics.start_timer()
640
+
641
+ for chunk in self.get_client().responses.create(
593
642
  model=self.id,
594
643
  input=self._format_messages(messages), # type: ignore
595
644
  stream=True,
596
645
  **request_params,
597
- ) # 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
+
598
656
  except RateLimitError as exc:
599
657
  log_error(f"Rate limit error from OpenAI API: {exc}")
600
658
  error_message = exc.response.json().get("error", {})
@@ -633,10 +691,12 @@ class OpenAIResponses(Model):
633
691
  async def ainvoke_stream(
634
692
  self,
635
693
  messages: List[Message],
694
+ assistant_message: Message,
636
695
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
637
696
  tools: Optional[List[Dict[str, Any]]] = None,
638
697
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
639
- ) -> AsyncIterator[ResponseStreamEvent]:
698
+ run_response: Optional[RunOutput] = None,
699
+ ) -> AsyncIterator[ModelResponse]:
640
700
  """
641
701
  Sends an asynchronous streaming request to the OpenAI Responses API.
642
702
  """
@@ -644,6 +704,13 @@ class OpenAIResponses(Model):
644
704
  request_params = self.get_request_params(
645
705
  messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
646
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
+
647
714
  async_stream = await self.get_async_client().responses.create(
648
715
  model=self.id,
649
716
  input=self._format_messages(messages), # type: ignore
@@ -651,7 +718,11 @@ class OpenAIResponses(Model):
651
718
  **request_params,
652
719
  )
653
720
  async for chunk in async_stream: # type: ignore
654
- 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
+
655
726
  except RateLimitError as exc:
656
727
  log_error(f"Rate limit error from OpenAI API: {exc}")
657
728
  error_message = exc.response.json().get("error", {})
@@ -703,7 +774,64 @@ class OpenAIResponses(Model):
703
774
  _fc_message.tool_call_id = tool_call_ids[_fc_message_index]
704
775
  messages.append(_fc_message)
705
776
 
706
- 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:
707
835
  """
708
836
  Parse the OpenAI response into a ModelResponse.
709
837
 
@@ -730,7 +858,10 @@ class OpenAIResponses(Model):
730
858
 
731
859
  # Add role
732
860
  model_response.role = "assistant"
861
+ reasoning_summary: str = ""
862
+
733
863
  for output in response.output:
864
+ # Add content
734
865
  if output.type == "message":
735
866
  model_response.content = response.output_text
736
867
 
@@ -746,6 +877,8 @@ class OpenAIResponses(Model):
746
877
  citations.urls.append(UrlCitation(url=annotation.url, title=annotation.title))
747
878
  if citations.urls or citations.documents:
748
879
  model_response.citations = citations
880
+
881
+ # Add tool calls
749
882
  elif output.type == "function_call":
750
883
  if model_response.tool_calls is None:
751
884
  model_response.tool_calls = []
@@ -765,80 +898,85 @@ class OpenAIResponses(Model):
765
898
  model_response.extra = model_response.extra or {}
766
899
  model_response.extra.setdefault("tool_call_ids", []).append(output.call_id)
767
900
 
768
- # i.e. we asked for reasoning, so we need to add the reasoning content
769
- if self.reasoning is not None:
901
+ # Add reasoning summary
902
+ elif output.type == "reasoning":
903
+ if reasoning_summaries := getattr(output, "summary", None):
904
+ for summary in reasoning_summaries:
905
+ if isinstance(summary, dict):
906
+ summary_text = summary.get("text")
907
+ else:
908
+ summary_text = getattr(summary, "text", None)
909
+ if summary_text:
910
+ reasoning_summary = (reasoning_summary or "") + summary_text
911
+
912
+ # Add reasoning content
913
+ if reasoning_summary is not None:
914
+ model_response.reasoning_content = reasoning_summary
915
+ elif self.reasoning is not None:
770
916
  model_response.reasoning_content = response.output_text
771
917
 
918
+ # Add metrics
772
919
  if response.usage is not None:
773
- model_response.response_usage = response.usage
920
+ model_response.response_usage = self._get_metrics(response.usage)
774
921
 
775
922
  return model_response
776
923
 
777
- def _process_stream_response(
778
- self,
779
- stream_event: ResponseStreamEvent,
780
- assistant_message: Message,
781
- stream_data: MessageData,
782
- tool_use: Dict[str, Any],
783
- ) -> 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]]:
784
927
  """
785
- Common handler for processing stream responses from Cohere.
928
+ Parse the streaming response from the model provider into a ModelResponse object.
786
929
 
787
930
  Args:
788
- stream_event: The streamed response from Cohere
789
- assistant_message: The assistant message being built
790
- stream_data: Data accumulated during streaming
791
- tool_use: Current tool use data being built
931
+ response: Raw response chunk from the model provider
792
932
 
793
933
  Returns:
794
- Tuple containing the ModelResponse to yield and updated tool_use dict
934
+ ModelResponse: Parsed response delta
795
935
  """
796
- model_response = None
936
+ model_response = ModelResponse()
797
937
 
938
+ # 1. Add response ID
798
939
  if stream_event.type == "response.created":
799
- model_response = ModelResponse()
800
- # Store the response ID for continuity
801
940
  if stream_event.response.id:
802
- if stream_data.response_provider_data is None:
803
- stream_data.response_provider_data = {}
804
- stream_data.response_provider_data["response_id"] = stream_event.response.id
805
- # 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
806
944
  if not assistant_message.metrics.time_to_first_token:
807
945
  assistant_message.metrics.set_time_to_first_token()
946
+
947
+ # 2. Add citations
808
948
  elif stream_event.type == "response.output_text.annotation.added":
809
- model_response = ModelResponse()
810
- if stream_data.response_citations is None:
811
- 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])
812
951
  else:
813
- stream_data.response_citations.raw.append(stream_event.annotation) # type: ignore
952
+ model_response.citations.raw.append(stream_event.annotation) # type: ignore
814
953
 
815
954
  if isinstance(stream_event.annotation, dict):
816
955
  if stream_event.annotation.get("type") == "url_citation":
817
- if stream_data.response_citations.urls is None:
818
- stream_data.response_citations.urls = []
819
- 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(
820
959
  UrlCitation(url=stream_event.annotation.get("url"), title=stream_event.annotation.get("title"))
821
960
  )
822
961
  else:
823
962
  if stream_event.annotation.type == "url_citation": # type: ignore
824
- if stream_data.response_citations.urls is None:
825
- stream_data.response_citations.urls = []
826
- 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(
827
966
  UrlCitation(url=stream_event.annotation.url, title=stream_event.annotation.title) # type: ignore
828
967
  )
829
968
 
830
- model_response.citations = stream_data.response_citations
831
-
969
+ # 3. Add content
832
970
  elif stream_event.type == "response.output_text.delta":
833
- model_response = ModelResponse()
834
- # Add content
835
971
  model_response.content = stream_event.delta
836
- stream_data.response_content += stream_event.delta
837
972
 
838
- if self.reasoning is not None:
973
+ # Treat the output_text deltas as reasoning content if the reasoning summary is not requested.
974
+ if self.reasoning is not None and self.reasoning_summary is None:
839
975
  model_response.reasoning_content = stream_event.delta
840
- stream_data.response_thinking += stream_event.delta
841
976
 
977
+ # 4. Add tool calls information
978
+
979
+ # 4.1 Add starting tool call
842
980
  elif stream_event.type == "response.output_item.added":
843
981
  item = stream_event.item
844
982
  if item.type == "function_call":
@@ -852,81 +990,61 @@ class OpenAIResponses(Model):
852
990
  },
853
991
  }
854
992
 
993
+ # 4.2 Add tool call arguments
855
994
  elif stream_event.type == "response.function_call_arguments.delta":
856
995
  tool_use["function"]["arguments"] += stream_event.delta
857
996
 
997
+ # 4.3 Add tool call completion data
858
998
  elif stream_event.type == "response.output_item.done" and tool_use:
859
- model_response = ModelResponse()
860
999
  model_response.tool_calls = [tool_use]
861
1000
  if assistant_message.tool_calls is None:
862
1001
  assistant_message.tool_calls = []
863
1002
  assistant_message.tool_calls.append(tool_use)
864
1003
 
865
- stream_data.extra = stream_data.extra or {}
866
- 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"])
867
1006
  tool_use = {}
868
1007
 
1008
+ # 5. Add metrics
869
1009
  elif stream_event.type == "response.completed":
870
1010
  model_response = ModelResponse()
871
- # Add usage metrics if present
872
- if stream_event.response.usage is not None:
873
- model_response.response_usage = stream_event.response.usage
874
1011
 
875
- _add_usage_metrics_to_assistant_message(
876
- assistant_message=assistant_message,
877
- response_usage=model_response.response_usage,
878
- )
1012
+ # Add reasoning summary
1013
+ if self.reasoning_summary is not None:
1014
+ summary_text: str = ""
1015
+ for out in getattr(stream_event.response, "output", []) or []:
1016
+ if getattr(out, "type", None) == "reasoning":
1017
+ summaries = getattr(out, "summary", None)
1018
+ if summaries:
1019
+ for s in summaries:
1020
+ text_val = s.get("text") if isinstance(s, dict) else getattr(s, "text", None)
1021
+ if text_val:
1022
+ if summary_text:
1023
+ summary_text += "\n\n"
1024
+ summary_text += text_val
1025
+ if summary_text:
1026
+ model_response.reasoning_content = summary_text
1027
+
1028
+ # Add metrics
1029
+ if stream_event.response.usage is not None:
1030
+ model_response.response_usage = self._get_metrics(stream_event.response.usage)
879
1031
 
880
1032
  return model_response, tool_use
881
1033
 
882
- def process_response_stream(
883
- self,
884
- messages: List[Message],
885
- assistant_message: Message,
886
- stream_data: MessageData,
887
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
888
- tools: Optional[List[Dict[str, Any]]] = None,
889
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
890
- ) -> Iterator[ModelResponse]:
891
- """Process the synchronous response stream."""
892
- tool_use: Dict[str, Any] = {}
893
-
894
- for stream_event in self.invoke_stream(
895
- messages=messages, tools=tools, response_format=response_format, tool_choice=tool_choice
896
- ):
897
- model_response, tool_use = self._process_stream_response(
898
- stream_event=stream_event,
899
- assistant_message=assistant_message,
900
- stream_data=stream_data,
901
- tool_use=tool_use,
902
- )
1034
+ def _get_metrics(self, response_usage: ResponseUsage) -> Metrics:
1035
+ """
1036
+ Parse the given OpenAI-specific usage into an Agno Metrics object.
903
1037
 
904
- if model_response is not None:
905
- yield model_response
1038
+ Args:
1039
+ response: The response from the provider.
906
1040
 
907
- async def aprocess_response_stream(
908
- self,
909
- messages: List[Message],
910
- assistant_message: Message,
911
- stream_data: MessageData,
912
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
913
- tools: Optional[List[Dict[str, Any]]] = None,
914
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
915
- ) -> AsyncIterator[ModelResponse]:
916
- """Process the asynchronous response stream."""
917
- tool_use: Dict[str, Any] = {}
1041
+ Returns:
1042
+ Metrics: Parsed metrics data
1043
+ """
1044
+ metrics = Metrics()
918
1045
 
919
- async for stream_event in self.ainvoke_stream(
920
- messages=messages, tools=tools, response_format=response_format, tool_choice=tool_choice
921
- ):
922
- model_response, tool_use = self._process_stream_response(
923
- stream_event=stream_event,
924
- assistant_message=assistant_message,
925
- stream_data=stream_data,
926
- tool_use=tool_use,
927
- )
928
- if model_response is not None:
929
- 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
930
1049
 
931
- def parse_provider_response_delta(self, response: Any) -> ModelResponse: # type: ignore
932
- 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,