agno 2.2.13__py3-none-any.whl → 2.4.3__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 (383) hide show
  1. agno/agent/__init__.py +6 -0
  2. agno/agent/agent.py +5252 -3145
  3. agno/agent/remote.py +525 -0
  4. agno/api/api.py +2 -0
  5. agno/client/__init__.py +3 -0
  6. agno/client/a2a/__init__.py +10 -0
  7. agno/client/a2a/client.py +554 -0
  8. agno/client/a2a/schemas.py +112 -0
  9. agno/client/a2a/utils.py +369 -0
  10. agno/client/os.py +2669 -0
  11. agno/compression/__init__.py +3 -0
  12. agno/compression/manager.py +247 -0
  13. agno/culture/manager.py +2 -2
  14. agno/db/base.py +927 -6
  15. agno/db/dynamo/dynamo.py +788 -2
  16. agno/db/dynamo/schemas.py +128 -0
  17. agno/db/dynamo/utils.py +26 -3
  18. agno/db/firestore/firestore.py +674 -50
  19. agno/db/firestore/schemas.py +41 -0
  20. agno/db/firestore/utils.py +25 -10
  21. agno/db/gcs_json/gcs_json_db.py +506 -3
  22. agno/db/gcs_json/utils.py +14 -2
  23. agno/db/in_memory/in_memory_db.py +203 -4
  24. agno/db/in_memory/utils.py +14 -2
  25. agno/db/json/json_db.py +498 -2
  26. agno/db/json/utils.py +14 -2
  27. agno/db/migrations/manager.py +199 -0
  28. agno/db/migrations/utils.py +19 -0
  29. agno/db/migrations/v1_to_v2.py +54 -16
  30. agno/db/migrations/versions/__init__.py +0 -0
  31. agno/db/migrations/versions/v2_3_0.py +977 -0
  32. agno/db/mongo/async_mongo.py +1013 -39
  33. agno/db/mongo/mongo.py +684 -4
  34. agno/db/mongo/schemas.py +48 -0
  35. agno/db/mongo/utils.py +17 -0
  36. agno/db/mysql/__init__.py +2 -1
  37. agno/db/mysql/async_mysql.py +2958 -0
  38. agno/db/mysql/mysql.py +722 -53
  39. agno/db/mysql/schemas.py +77 -11
  40. agno/db/mysql/utils.py +151 -8
  41. agno/db/postgres/async_postgres.py +1254 -137
  42. agno/db/postgres/postgres.py +2316 -93
  43. agno/db/postgres/schemas.py +153 -21
  44. agno/db/postgres/utils.py +22 -7
  45. agno/db/redis/redis.py +531 -3
  46. agno/db/redis/schemas.py +36 -0
  47. agno/db/redis/utils.py +31 -15
  48. agno/db/schemas/evals.py +1 -0
  49. agno/db/schemas/memory.py +20 -9
  50. agno/db/singlestore/schemas.py +70 -1
  51. agno/db/singlestore/singlestore.py +737 -74
  52. agno/db/singlestore/utils.py +13 -3
  53. agno/db/sqlite/async_sqlite.py +1069 -89
  54. agno/db/sqlite/schemas.py +133 -1
  55. agno/db/sqlite/sqlite.py +2203 -165
  56. agno/db/sqlite/utils.py +21 -11
  57. agno/db/surrealdb/models.py +25 -0
  58. agno/db/surrealdb/surrealdb.py +603 -1
  59. agno/db/utils.py +60 -0
  60. agno/eval/__init__.py +26 -3
  61. agno/eval/accuracy.py +25 -12
  62. agno/eval/agent_as_judge.py +871 -0
  63. agno/eval/base.py +29 -0
  64. agno/eval/performance.py +10 -4
  65. agno/eval/reliability.py +22 -13
  66. agno/eval/utils.py +2 -1
  67. agno/exceptions.py +42 -0
  68. agno/hooks/__init__.py +3 -0
  69. agno/hooks/decorator.py +164 -0
  70. agno/integrations/discord/client.py +13 -2
  71. agno/knowledge/__init__.py +4 -0
  72. agno/knowledge/chunking/code.py +90 -0
  73. agno/knowledge/chunking/document.py +65 -4
  74. agno/knowledge/chunking/fixed.py +4 -1
  75. agno/knowledge/chunking/markdown.py +102 -11
  76. agno/knowledge/chunking/recursive.py +2 -2
  77. agno/knowledge/chunking/semantic.py +130 -48
  78. agno/knowledge/chunking/strategy.py +18 -0
  79. agno/knowledge/embedder/azure_openai.py +0 -1
  80. agno/knowledge/embedder/google.py +1 -1
  81. agno/knowledge/embedder/mistral.py +1 -1
  82. agno/knowledge/embedder/nebius.py +1 -1
  83. agno/knowledge/embedder/openai.py +16 -12
  84. agno/knowledge/filesystem.py +412 -0
  85. agno/knowledge/knowledge.py +4261 -1199
  86. agno/knowledge/protocol.py +134 -0
  87. agno/knowledge/reader/arxiv_reader.py +3 -2
  88. agno/knowledge/reader/base.py +9 -7
  89. agno/knowledge/reader/csv_reader.py +91 -42
  90. agno/knowledge/reader/docx_reader.py +9 -10
  91. agno/knowledge/reader/excel_reader.py +225 -0
  92. agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
  93. agno/knowledge/reader/firecrawl_reader.py +3 -2
  94. agno/knowledge/reader/json_reader.py +16 -22
  95. agno/knowledge/reader/markdown_reader.py +15 -14
  96. agno/knowledge/reader/pdf_reader.py +33 -28
  97. agno/knowledge/reader/pptx_reader.py +9 -10
  98. agno/knowledge/reader/reader_factory.py +135 -1
  99. agno/knowledge/reader/s3_reader.py +8 -16
  100. agno/knowledge/reader/tavily_reader.py +3 -3
  101. agno/knowledge/reader/text_reader.py +15 -14
  102. agno/knowledge/reader/utils/__init__.py +17 -0
  103. agno/knowledge/reader/utils/spreadsheet.py +114 -0
  104. agno/knowledge/reader/web_search_reader.py +8 -65
  105. agno/knowledge/reader/website_reader.py +16 -13
  106. agno/knowledge/reader/wikipedia_reader.py +36 -3
  107. agno/knowledge/reader/youtube_reader.py +3 -2
  108. agno/knowledge/remote_content/__init__.py +33 -0
  109. agno/knowledge/remote_content/config.py +266 -0
  110. agno/knowledge/remote_content/remote_content.py +105 -17
  111. agno/knowledge/utils.py +76 -22
  112. agno/learn/__init__.py +71 -0
  113. agno/learn/config.py +463 -0
  114. agno/learn/curate.py +185 -0
  115. agno/learn/machine.py +725 -0
  116. agno/learn/schemas.py +1114 -0
  117. agno/learn/stores/__init__.py +38 -0
  118. agno/learn/stores/decision_log.py +1156 -0
  119. agno/learn/stores/entity_memory.py +3275 -0
  120. agno/learn/stores/learned_knowledge.py +1583 -0
  121. agno/learn/stores/protocol.py +117 -0
  122. agno/learn/stores/session_context.py +1217 -0
  123. agno/learn/stores/user_memory.py +1495 -0
  124. agno/learn/stores/user_profile.py +1220 -0
  125. agno/learn/utils.py +209 -0
  126. agno/media.py +22 -6
  127. agno/memory/__init__.py +14 -1
  128. agno/memory/manager.py +223 -8
  129. agno/memory/strategies/__init__.py +15 -0
  130. agno/memory/strategies/base.py +66 -0
  131. agno/memory/strategies/summarize.py +196 -0
  132. agno/memory/strategies/types.py +37 -0
  133. agno/models/aimlapi/aimlapi.py +17 -0
  134. agno/models/anthropic/claude.py +434 -59
  135. agno/models/aws/bedrock.py +121 -20
  136. agno/models/aws/claude.py +131 -274
  137. agno/models/azure/ai_foundry.py +10 -6
  138. agno/models/azure/openai_chat.py +33 -10
  139. agno/models/base.py +1162 -561
  140. agno/models/cerebras/cerebras.py +120 -24
  141. agno/models/cerebras/cerebras_openai.py +21 -2
  142. agno/models/cohere/chat.py +65 -6
  143. agno/models/cometapi/cometapi.py +18 -1
  144. agno/models/dashscope/dashscope.py +2 -3
  145. agno/models/deepinfra/deepinfra.py +18 -1
  146. agno/models/deepseek/deepseek.py +69 -3
  147. agno/models/fireworks/fireworks.py +18 -1
  148. agno/models/google/gemini.py +959 -89
  149. agno/models/google/utils.py +22 -0
  150. agno/models/groq/groq.py +48 -18
  151. agno/models/huggingface/huggingface.py +17 -6
  152. agno/models/ibm/watsonx.py +16 -6
  153. agno/models/internlm/internlm.py +18 -1
  154. agno/models/langdb/langdb.py +13 -1
  155. agno/models/litellm/chat.py +88 -9
  156. agno/models/litellm/litellm_openai.py +18 -1
  157. agno/models/message.py +24 -5
  158. agno/models/meta/llama.py +40 -13
  159. agno/models/meta/llama_openai.py +22 -21
  160. agno/models/metrics.py +12 -0
  161. agno/models/mistral/mistral.py +8 -4
  162. agno/models/n1n/__init__.py +3 -0
  163. agno/models/n1n/n1n.py +57 -0
  164. agno/models/nebius/nebius.py +6 -7
  165. agno/models/nvidia/nvidia.py +20 -3
  166. agno/models/ollama/__init__.py +2 -0
  167. agno/models/ollama/chat.py +17 -6
  168. agno/models/ollama/responses.py +100 -0
  169. agno/models/openai/__init__.py +2 -0
  170. agno/models/openai/chat.py +117 -26
  171. agno/models/openai/open_responses.py +46 -0
  172. agno/models/openai/responses.py +110 -32
  173. agno/models/openrouter/__init__.py +2 -0
  174. agno/models/openrouter/openrouter.py +67 -2
  175. agno/models/openrouter/responses.py +146 -0
  176. agno/models/perplexity/perplexity.py +19 -1
  177. agno/models/portkey/portkey.py +7 -6
  178. agno/models/requesty/requesty.py +19 -2
  179. agno/models/response.py +20 -2
  180. agno/models/sambanova/sambanova.py +20 -3
  181. agno/models/siliconflow/siliconflow.py +19 -2
  182. agno/models/together/together.py +20 -3
  183. agno/models/vercel/v0.py +20 -3
  184. agno/models/vertexai/claude.py +124 -4
  185. agno/models/vllm/vllm.py +19 -14
  186. agno/models/xai/xai.py +19 -2
  187. agno/os/app.py +467 -137
  188. agno/os/auth.py +253 -5
  189. agno/os/config.py +22 -0
  190. agno/os/interfaces/a2a/a2a.py +7 -6
  191. agno/os/interfaces/a2a/router.py +635 -26
  192. agno/os/interfaces/a2a/utils.py +32 -33
  193. agno/os/interfaces/agui/agui.py +5 -3
  194. agno/os/interfaces/agui/router.py +26 -16
  195. agno/os/interfaces/agui/utils.py +97 -57
  196. agno/os/interfaces/base.py +7 -7
  197. agno/os/interfaces/slack/router.py +16 -7
  198. agno/os/interfaces/slack/slack.py +7 -7
  199. agno/os/interfaces/whatsapp/router.py +35 -7
  200. agno/os/interfaces/whatsapp/security.py +3 -1
  201. agno/os/interfaces/whatsapp/whatsapp.py +11 -8
  202. agno/os/managers.py +326 -0
  203. agno/os/mcp.py +652 -79
  204. agno/os/middleware/__init__.py +4 -0
  205. agno/os/middleware/jwt.py +718 -115
  206. agno/os/middleware/trailing_slash.py +27 -0
  207. agno/os/router.py +105 -1558
  208. agno/os/routers/agents/__init__.py +3 -0
  209. agno/os/routers/agents/router.py +655 -0
  210. agno/os/routers/agents/schema.py +288 -0
  211. agno/os/routers/components/__init__.py +3 -0
  212. agno/os/routers/components/components.py +475 -0
  213. agno/os/routers/database.py +155 -0
  214. agno/os/routers/evals/evals.py +111 -18
  215. agno/os/routers/evals/schemas.py +38 -5
  216. agno/os/routers/evals/utils.py +80 -11
  217. agno/os/routers/health.py +3 -3
  218. agno/os/routers/knowledge/knowledge.py +284 -35
  219. agno/os/routers/knowledge/schemas.py +14 -2
  220. agno/os/routers/memory/memory.py +274 -11
  221. agno/os/routers/memory/schemas.py +44 -3
  222. agno/os/routers/metrics/metrics.py +30 -15
  223. agno/os/routers/metrics/schemas.py +10 -6
  224. agno/os/routers/registry/__init__.py +3 -0
  225. agno/os/routers/registry/registry.py +337 -0
  226. agno/os/routers/session/session.py +143 -14
  227. agno/os/routers/teams/__init__.py +3 -0
  228. agno/os/routers/teams/router.py +550 -0
  229. agno/os/routers/teams/schema.py +280 -0
  230. agno/os/routers/traces/__init__.py +3 -0
  231. agno/os/routers/traces/schemas.py +414 -0
  232. agno/os/routers/traces/traces.py +549 -0
  233. agno/os/routers/workflows/__init__.py +3 -0
  234. agno/os/routers/workflows/router.py +757 -0
  235. agno/os/routers/workflows/schema.py +139 -0
  236. agno/os/schema.py +157 -584
  237. agno/os/scopes.py +469 -0
  238. agno/os/settings.py +3 -0
  239. agno/os/utils.py +574 -185
  240. agno/reasoning/anthropic.py +85 -1
  241. agno/reasoning/azure_ai_foundry.py +93 -1
  242. agno/reasoning/deepseek.py +102 -2
  243. agno/reasoning/default.py +6 -7
  244. agno/reasoning/gemini.py +87 -3
  245. agno/reasoning/groq.py +109 -2
  246. agno/reasoning/helpers.py +6 -7
  247. agno/reasoning/manager.py +1238 -0
  248. agno/reasoning/ollama.py +93 -1
  249. agno/reasoning/openai.py +115 -1
  250. agno/reasoning/vertexai.py +85 -1
  251. agno/registry/__init__.py +3 -0
  252. agno/registry/registry.py +68 -0
  253. agno/remote/__init__.py +3 -0
  254. agno/remote/base.py +581 -0
  255. agno/run/__init__.py +2 -4
  256. agno/run/agent.py +134 -19
  257. agno/run/base.py +49 -1
  258. agno/run/cancel.py +65 -52
  259. agno/run/cancellation_management/__init__.py +9 -0
  260. agno/run/cancellation_management/base.py +78 -0
  261. agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
  262. agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
  263. agno/run/requirement.py +181 -0
  264. agno/run/team.py +111 -19
  265. agno/run/workflow.py +2 -1
  266. agno/session/agent.py +57 -92
  267. agno/session/summary.py +1 -1
  268. agno/session/team.py +62 -115
  269. agno/session/workflow.py +353 -57
  270. agno/skills/__init__.py +17 -0
  271. agno/skills/agent_skills.py +377 -0
  272. agno/skills/errors.py +32 -0
  273. agno/skills/loaders/__init__.py +4 -0
  274. agno/skills/loaders/base.py +27 -0
  275. agno/skills/loaders/local.py +216 -0
  276. agno/skills/skill.py +65 -0
  277. agno/skills/utils.py +107 -0
  278. agno/skills/validator.py +277 -0
  279. agno/table.py +10 -0
  280. agno/team/__init__.py +5 -1
  281. agno/team/remote.py +447 -0
  282. agno/team/team.py +3769 -2202
  283. agno/tools/brandfetch.py +27 -18
  284. agno/tools/browserbase.py +225 -16
  285. agno/tools/crawl4ai.py +3 -0
  286. agno/tools/duckduckgo.py +25 -71
  287. agno/tools/exa.py +0 -21
  288. agno/tools/file.py +14 -13
  289. agno/tools/file_generation.py +12 -6
  290. agno/tools/firecrawl.py +15 -7
  291. agno/tools/function.py +94 -113
  292. agno/tools/google_bigquery.py +11 -2
  293. agno/tools/google_drive.py +4 -3
  294. agno/tools/knowledge.py +9 -4
  295. agno/tools/mcp/mcp.py +301 -18
  296. agno/tools/mcp/multi_mcp.py +269 -14
  297. agno/tools/mem0.py +11 -10
  298. agno/tools/memory.py +47 -46
  299. agno/tools/mlx_transcribe.py +10 -7
  300. agno/tools/models/nebius.py +5 -5
  301. agno/tools/models_labs.py +20 -10
  302. agno/tools/nano_banana.py +151 -0
  303. agno/tools/parallel.py +0 -7
  304. agno/tools/postgres.py +76 -36
  305. agno/tools/python.py +14 -6
  306. agno/tools/reasoning.py +30 -23
  307. agno/tools/redshift.py +406 -0
  308. agno/tools/shopify.py +1519 -0
  309. agno/tools/spotify.py +919 -0
  310. agno/tools/tavily.py +4 -1
  311. agno/tools/toolkit.py +253 -18
  312. agno/tools/websearch.py +93 -0
  313. agno/tools/website.py +1 -1
  314. agno/tools/wikipedia.py +1 -1
  315. agno/tools/workflow.py +56 -48
  316. agno/tools/yfinance.py +12 -11
  317. agno/tracing/__init__.py +12 -0
  318. agno/tracing/exporter.py +161 -0
  319. agno/tracing/schemas.py +276 -0
  320. agno/tracing/setup.py +112 -0
  321. agno/utils/agent.py +251 -10
  322. agno/utils/cryptography.py +22 -0
  323. agno/utils/dttm.py +33 -0
  324. agno/utils/events.py +264 -7
  325. agno/utils/hooks.py +111 -3
  326. agno/utils/http.py +161 -2
  327. agno/utils/mcp.py +49 -8
  328. agno/utils/media.py +22 -1
  329. agno/utils/models/ai_foundry.py +9 -2
  330. agno/utils/models/claude.py +20 -5
  331. agno/utils/models/cohere.py +9 -2
  332. agno/utils/models/llama.py +9 -2
  333. agno/utils/models/mistral.py +4 -2
  334. agno/utils/os.py +0 -0
  335. agno/utils/print_response/agent.py +99 -16
  336. agno/utils/print_response/team.py +223 -24
  337. agno/utils/print_response/workflow.py +0 -2
  338. agno/utils/prompts.py +8 -6
  339. agno/utils/remote.py +23 -0
  340. agno/utils/response.py +1 -13
  341. agno/utils/string.py +91 -2
  342. agno/utils/team.py +62 -12
  343. agno/utils/tokens.py +657 -0
  344. agno/vectordb/base.py +15 -2
  345. agno/vectordb/cassandra/cassandra.py +1 -1
  346. agno/vectordb/chroma/__init__.py +2 -1
  347. agno/vectordb/chroma/chromadb.py +468 -23
  348. agno/vectordb/clickhouse/clickhousedb.py +1 -1
  349. agno/vectordb/couchbase/couchbase.py +6 -2
  350. agno/vectordb/lancedb/lance_db.py +7 -38
  351. agno/vectordb/lightrag/lightrag.py +7 -6
  352. agno/vectordb/milvus/milvus.py +118 -84
  353. agno/vectordb/mongodb/__init__.py +2 -1
  354. agno/vectordb/mongodb/mongodb.py +14 -31
  355. agno/vectordb/pgvector/pgvector.py +120 -66
  356. agno/vectordb/pineconedb/pineconedb.py +2 -19
  357. agno/vectordb/qdrant/__init__.py +2 -1
  358. agno/vectordb/qdrant/qdrant.py +33 -56
  359. agno/vectordb/redis/__init__.py +2 -1
  360. agno/vectordb/redis/redisdb.py +19 -31
  361. agno/vectordb/singlestore/singlestore.py +17 -9
  362. agno/vectordb/surrealdb/surrealdb.py +2 -38
  363. agno/vectordb/weaviate/__init__.py +2 -1
  364. agno/vectordb/weaviate/weaviate.py +7 -3
  365. agno/workflow/__init__.py +5 -1
  366. agno/workflow/agent.py +2 -2
  367. agno/workflow/condition.py +12 -10
  368. agno/workflow/loop.py +28 -9
  369. agno/workflow/parallel.py +21 -13
  370. agno/workflow/remote.py +362 -0
  371. agno/workflow/router.py +12 -9
  372. agno/workflow/step.py +261 -36
  373. agno/workflow/steps.py +12 -8
  374. agno/workflow/types.py +40 -77
  375. agno/workflow/workflow.py +939 -213
  376. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
  377. agno-2.4.3.dist-info/RECORD +677 -0
  378. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
  379. agno/tools/googlesearch.py +0 -98
  380. agno/tools/memori.py +0 -339
  381. agno-2.2.13.dist-info/RECORD +0 -575
  382. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
  383. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
agno/reasoning/ollama.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List, Optional
3
+ from typing import AsyncIterator, Iterator, List, Optional, Tuple
4
4
 
5
5
  from agno.models.base import Model
6
6
  from agno.models.message import Message
@@ -65,3 +65,95 @@ async def aget_ollama_reasoning(reasoning_agent: "Agent", messages: List[Message
65
65
  return Message(
66
66
  role="assistant", content=f"<thinking>\n{reasoning_content}\n</thinking>", reasoning_content=reasoning_content
67
67
  )
68
+
69
+
70
+ def get_ollama_reasoning_stream(
71
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
72
+ messages: List[Message],
73
+ ) -> Iterator[Tuple[Optional[str], Optional[Message]]]:
74
+ """
75
+ Stream reasoning content from Ollama model.
76
+
77
+ For reasoning models on Ollama (qwq, deepseek-r1, etc.), we use the main content output as reasoning content.
78
+
79
+ Yields:
80
+ Tuple of (reasoning_content_delta, final_message)
81
+ - During streaming: (reasoning_content_delta, None)
82
+ - At the end: (None, final_message)
83
+ """
84
+ from agno.run.agent import RunEvent
85
+
86
+ reasoning_content: str = ""
87
+
88
+ try:
89
+ for event in reasoning_agent.run(input=messages, stream=True, stream_events=True):
90
+ if hasattr(event, "event"):
91
+ if event.event == RunEvent.run_content:
92
+ # Check for reasoning_content attribute first (native reasoning)
93
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
94
+ reasoning_content += event.reasoning_content
95
+ yield (event.reasoning_content, None)
96
+ # Use the main content as reasoning content
97
+ elif hasattr(event, "content") and event.content:
98
+ reasoning_content += event.content
99
+ yield (event.content, None)
100
+ elif event.event == RunEvent.run_completed:
101
+ pass
102
+ except Exception as e:
103
+ logger.warning(f"Reasoning error: {e}")
104
+ return
105
+
106
+ # Yield final message
107
+ if reasoning_content:
108
+ final_message = Message(
109
+ role="assistant",
110
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
111
+ reasoning_content=reasoning_content,
112
+ )
113
+ yield (None, final_message)
114
+
115
+
116
+ async def aget_ollama_reasoning_stream(
117
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
118
+ messages: List[Message],
119
+ ) -> AsyncIterator[Tuple[Optional[str], Optional[Message]]]:
120
+ """
121
+ Stream reasoning content from Ollama model asynchronously.
122
+
123
+ For reasoning models on Ollama (qwq, deepseek-r1, etc.), we use the main content output as reasoning content.
124
+
125
+ Yields:
126
+ Tuple of (reasoning_content_delta, final_message)
127
+ - During streaming: (reasoning_content_delta, None)
128
+ - At the end: (None, final_message)
129
+ """
130
+ from agno.run.agent import RunEvent
131
+
132
+ reasoning_content: str = ""
133
+
134
+ try:
135
+ async for event in reasoning_agent.arun(input=messages, stream=True, stream_events=True):
136
+ if hasattr(event, "event"):
137
+ if event.event == RunEvent.run_content:
138
+ # Check for reasoning_content attribute first (native reasoning)
139
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
140
+ reasoning_content += event.reasoning_content
141
+ yield (event.reasoning_content, None)
142
+ # Use the main content as reasoning content
143
+ elif hasattr(event, "content") and event.content:
144
+ reasoning_content += event.content
145
+ yield (event.content, None)
146
+ elif event.event == RunEvent.run_completed:
147
+ pass
148
+ except Exception as e:
149
+ logger.warning(f"Reasoning error: {e}")
150
+ return
151
+
152
+ # Yield final message
153
+ if reasoning_content:
154
+ final_message = Message(
155
+ role="assistant",
156
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
157
+ reasoning_content=reasoning_content,
158
+ )
159
+ yield (None, final_message)
agno/reasoning/openai.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List, Optional
3
+ from typing import AsyncIterator, Iterator, List, Optional, Tuple
4
4
 
5
5
  from agno.models.base import Model
6
6
  from agno.models.message import Message
@@ -21,6 +21,8 @@ def is_openai_reasoning_model(reasoning_model: Model) -> bool:
21
21
  or ("o1" in reasoning_model.id)
22
22
  or ("4.1" in reasoning_model.id)
23
23
  or ("4.5" in reasoning_model.id)
24
+ or ("5.1" in reasoning_model.id)
25
+ or ("5.2" in reasoning_model.id)
24
26
  )
25
27
  ) or (isinstance(reasoning_model, OpenAILike) and "deepseek-r1" in reasoning_model.id.lower())
26
28
 
@@ -84,3 +86,115 @@ async def aget_openai_reasoning(reasoning_agent: "Agent", messages: List[Message
84
86
  return Message(
85
87
  role="assistant", content=f"<thinking>\n{reasoning_content}\n</thinking>", reasoning_content=reasoning_content
86
88
  )
89
+
90
+
91
+ def get_openai_reasoning_stream(
92
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
93
+ messages: List[Message],
94
+ ) -> Iterator[Tuple[Optional[str], Optional[Message]]]:
95
+ """
96
+ Stream reasoning content from OpenAI model.
97
+
98
+ For OpenAI reasoning models, we use the main content output as reasoning content.
99
+
100
+ Yields:
101
+ Tuple of (reasoning_content_delta, final_message)
102
+ - During streaming: (reasoning_content_delta, None)
103
+ - At the end: (None, final_message)
104
+ """
105
+ from agno.run.agent import RunEvent
106
+
107
+ # Update system message role to "system"
108
+ for message in messages:
109
+ if message.role == "developer":
110
+ message.role = "system"
111
+
112
+ reasoning_content: str = ""
113
+
114
+ try:
115
+ for event in reasoning_agent.run(input=messages, stream=True, stream_events=True):
116
+ if hasattr(event, "event"):
117
+ if event.event == RunEvent.run_content:
118
+ # Check for reasoning_content attribute first (native reasoning)
119
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
120
+ reasoning_content += event.reasoning_content
121
+ yield (event.reasoning_content, None)
122
+ # Use the main content as reasoning content
123
+ elif hasattr(event, "content") and event.content:
124
+ reasoning_content += event.content
125
+ yield (event.content, None)
126
+ elif event.event == RunEvent.run_completed:
127
+ # Check for reasoning_content at completion (OpenAIResponses with reasoning_summary)
128
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
129
+ # If we haven't accumulated any reasoning content yet, use this
130
+ if not reasoning_content:
131
+ reasoning_content = event.reasoning_content
132
+ yield (event.reasoning_content, None)
133
+ except Exception as e:
134
+ logger.warning(f"Reasoning error: {e}")
135
+ return
136
+
137
+ # Yield final message
138
+ if reasoning_content:
139
+ final_message = Message(
140
+ role="assistant",
141
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
142
+ reasoning_content=reasoning_content,
143
+ )
144
+ yield (None, final_message)
145
+
146
+
147
+ async def aget_openai_reasoning_stream(
148
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
149
+ messages: List[Message],
150
+ ) -> AsyncIterator[Tuple[Optional[str], Optional[Message]]]:
151
+ """
152
+ Stream reasoning content from OpenAI model asynchronously.
153
+
154
+ For OpenAI reasoning models, we use the main content output as reasoning content.
155
+
156
+ Yields:
157
+ Tuple of (reasoning_content_delta, final_message)
158
+ - During streaming: (reasoning_content_delta, None)
159
+ - At the end: (None, final_message)
160
+ """
161
+ from agno.run.agent import RunEvent
162
+
163
+ # Update system message role to "system"
164
+ for message in messages:
165
+ if message.role == "developer":
166
+ message.role = "system"
167
+
168
+ reasoning_content: str = ""
169
+
170
+ try:
171
+ async for event in reasoning_agent.arun(input=messages, stream=True, stream_events=True):
172
+ if hasattr(event, "event"):
173
+ if event.event == RunEvent.run_content:
174
+ # Check for reasoning_content attribute first (native reasoning)
175
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
176
+ reasoning_content += event.reasoning_content
177
+ yield (event.reasoning_content, None)
178
+ # Use the main content as reasoning content
179
+ elif hasattr(event, "content") and event.content:
180
+ reasoning_content += event.content
181
+ yield (event.content, None)
182
+ elif event.event == RunEvent.run_completed:
183
+ # Check for reasoning_content at completion (OpenAIResponses with reasoning_summary)
184
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
185
+ # If we haven't accumulated any reasoning content yet, use this
186
+ if not reasoning_content:
187
+ reasoning_content = event.reasoning_content
188
+ yield (event.reasoning_content, None)
189
+ except Exception as e:
190
+ logger.warning(f"Reasoning error: {e}")
191
+ return
192
+
193
+ # Yield final message
194
+ if reasoning_content:
195
+ final_message = Message(
196
+ role="assistant",
197
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
198
+ reasoning_content=reasoning_content,
199
+ )
200
+ yield (None, final_message)
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List, Optional
3
+ from typing import AsyncIterator, Iterator, List, Optional, Tuple
4
4
 
5
5
  from agno.models.base import Model
6
6
  from agno.models.message import Message
@@ -74,3 +74,87 @@ async def aget_vertexai_reasoning(reasoning_agent: "Agent", messages: List[Messa
74
74
  reasoning_content=reasoning_content,
75
75
  redacted_reasoning_content=redacted_reasoning_content,
76
76
  )
77
+
78
+
79
+ def get_vertexai_reasoning_stream(
80
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
81
+ messages: List[Message],
82
+ ) -> Iterator[Tuple[Optional[str], Optional[Message]]]:
83
+ """
84
+ Stream reasoning content from VertexAI Claude model.
85
+
86
+ Yields:
87
+ Tuple of (reasoning_content_delta, final_message)
88
+ - During streaming: (reasoning_content_delta, None)
89
+ - At the end: (None, final_message)
90
+ """
91
+ from agno.run.agent import RunEvent
92
+
93
+ reasoning_content: str = ""
94
+ redacted_reasoning_content: Optional[str] = None
95
+
96
+ try:
97
+ for event in reasoning_agent.run(input=messages, stream=True, stream_events=True):
98
+ if hasattr(event, "event"):
99
+ if event.event == RunEvent.run_content:
100
+ # Stream reasoning content as it arrives
101
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
102
+ reasoning_content += event.reasoning_content
103
+ yield (event.reasoning_content, None)
104
+ elif event.event == RunEvent.run_completed:
105
+ pass
106
+ except Exception as e:
107
+ logger.warning(f"Reasoning error: {e}")
108
+ return
109
+
110
+ # Yield final message
111
+ if reasoning_content:
112
+ final_message = Message(
113
+ role="assistant",
114
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
115
+ reasoning_content=reasoning_content,
116
+ redacted_reasoning_content=redacted_reasoning_content,
117
+ )
118
+ yield (None, final_message)
119
+
120
+
121
+ async def aget_vertexai_reasoning_stream(
122
+ reasoning_agent: "Agent", # type: ignore # noqa: F821
123
+ messages: List[Message],
124
+ ) -> AsyncIterator[Tuple[Optional[str], Optional[Message]]]:
125
+ """
126
+ Stream reasoning content from VertexAI Claude model asynchronously.
127
+
128
+ Yields:
129
+ Tuple of (reasoning_content_delta, final_message)
130
+ - During streaming: (reasoning_content_delta, None)
131
+ - At the end: (None, final_message)
132
+ """
133
+ from agno.run.agent import RunEvent
134
+
135
+ reasoning_content: str = ""
136
+ redacted_reasoning_content: Optional[str] = None
137
+
138
+ try:
139
+ async for event in reasoning_agent.arun(input=messages, stream=True, stream_events=True):
140
+ if hasattr(event, "event"):
141
+ if event.event == RunEvent.run_content:
142
+ # Stream reasoning content as it arrives
143
+ if hasattr(event, "reasoning_content") and event.reasoning_content:
144
+ reasoning_content += event.reasoning_content
145
+ yield (event.reasoning_content, None)
146
+ elif event.event == RunEvent.run_completed:
147
+ pass
148
+ except Exception as e:
149
+ logger.warning(f"Reasoning error: {e}")
150
+ return
151
+
152
+ # Yield final message
153
+ if reasoning_content:
154
+ final_message = Message(
155
+ role="assistant",
156
+ content=f"<thinking>\n{reasoning_content}\n</thinking>",
157
+ reasoning_content=reasoning_content,
158
+ redacted_reasoning_content=redacted_reasoning_content,
159
+ )
160
+ yield (None, final_message)
@@ -0,0 +1,3 @@
1
+ from agno.registry.registry import Registry
2
+
3
+ __all__ = ["Registry"]
@@ -0,0 +1,68 @@
1
+ from dataclasses import dataclass, field
2
+ from functools import cached_property
3
+ from typing import Any, Callable, Dict, List, Optional, Type
4
+ from uuid import uuid4
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from agno.db.base import BaseDb
9
+ from agno.models.base import Model
10
+ from agno.tools.function import Function
11
+ from agno.tools.toolkit import Toolkit
12
+ from agno.vectordb.base import VectorDb
13
+
14
+
15
+ @dataclass
16
+ class Registry:
17
+ """
18
+ Registry is used to manage non serializable objects like tools, models, databases and vector databases.
19
+ """
20
+
21
+ name: Optional[str] = None
22
+ description: Optional[str] = None
23
+ id: str = field(default_factory=lambda: str(uuid4()))
24
+ tools: List[Any] = field(default_factory=list)
25
+ models: List[Model] = field(default_factory=list)
26
+ dbs: List[BaseDb] = field(default_factory=list)
27
+ vector_dbs: List[VectorDb] = field(default_factory=list)
28
+ schemas: List[Type[BaseModel]] = field(default_factory=list)
29
+
30
+ @cached_property
31
+ def _entrypoint_lookup(self) -> Dict[str, Callable]:
32
+ lookup: Dict[str, Callable] = {}
33
+ for tool in self.tools:
34
+ if isinstance(tool, Toolkit):
35
+ for func in tool.functions.values():
36
+ if func.entrypoint is not None:
37
+ lookup[func.name] = func.entrypoint
38
+ elif isinstance(tool, Function):
39
+ if tool.entrypoint is not None:
40
+ lookup[tool.name] = tool.entrypoint
41
+ elif callable(tool):
42
+ lookup[tool.__name__] = tool
43
+ return lookup
44
+
45
+ def rehydrate_function(self, func_dict: Dict[str, Any]) -> Function:
46
+ """Reconstruct a Function from dict, reattaching its entrypoint."""
47
+ func = Function.from_dict(func_dict)
48
+ func.entrypoint = self._entrypoint_lookup.get(func.name)
49
+ return func
50
+
51
+ def get_schema(self, name: str) -> Optional[Type[BaseModel]]:
52
+ """Get a schema by name."""
53
+ if self.schemas:
54
+ return next((s for s in self.schemas if s.__name__ == name), None)
55
+ return None
56
+
57
+ def get_db(self, db_id: str) -> Optional[BaseDb]:
58
+ """Get a database by id from the registry.
59
+
60
+ Args:
61
+ db_id: The database id to look up
62
+
63
+ Returns:
64
+ The database instance if found, None otherwise
65
+ """
66
+ if self.dbs:
67
+ return next((db for db in self.dbs if db.id == db_id), None)
68
+ return None
@@ -0,0 +1,3 @@
1
+ from agno.remote.base import BaseRemote
2
+
3
+ __all__ = ["BaseRemote"]