agno 2.0.1__py3-none-any.whl → 2.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. agno/agent/agent.py +6015 -2823
  2. agno/api/api.py +2 -0
  3. agno/api/os.py +1 -1
  4. agno/culture/__init__.py +3 -0
  5. agno/culture/manager.py +956 -0
  6. agno/db/async_postgres/__init__.py +3 -0
  7. agno/db/base.py +385 -6
  8. agno/db/dynamo/dynamo.py +388 -81
  9. agno/db/dynamo/schemas.py +47 -10
  10. agno/db/dynamo/utils.py +63 -4
  11. agno/db/firestore/firestore.py +435 -64
  12. agno/db/firestore/schemas.py +11 -0
  13. agno/db/firestore/utils.py +102 -4
  14. agno/db/gcs_json/gcs_json_db.py +384 -42
  15. agno/db/gcs_json/utils.py +60 -26
  16. agno/db/in_memory/in_memory_db.py +351 -66
  17. agno/db/in_memory/utils.py +60 -2
  18. agno/db/json/json_db.py +339 -48
  19. agno/db/json/utils.py +60 -26
  20. agno/db/migrations/manager.py +199 -0
  21. agno/db/migrations/v1_to_v2.py +510 -37
  22. agno/db/migrations/versions/__init__.py +0 -0
  23. agno/db/migrations/versions/v2_3_0.py +938 -0
  24. agno/db/mongo/__init__.py +15 -1
  25. agno/db/mongo/async_mongo.py +2036 -0
  26. agno/db/mongo/mongo.py +653 -76
  27. agno/db/mongo/schemas.py +13 -0
  28. agno/db/mongo/utils.py +80 -8
  29. agno/db/mysql/mysql.py +687 -25
  30. agno/db/mysql/schemas.py +61 -37
  31. agno/db/mysql/utils.py +60 -2
  32. agno/db/postgres/__init__.py +2 -1
  33. agno/db/postgres/async_postgres.py +2001 -0
  34. agno/db/postgres/postgres.py +676 -57
  35. agno/db/postgres/schemas.py +43 -18
  36. agno/db/postgres/utils.py +164 -2
  37. agno/db/redis/redis.py +344 -38
  38. agno/db/redis/schemas.py +18 -0
  39. agno/db/redis/utils.py +60 -2
  40. agno/db/schemas/__init__.py +2 -1
  41. agno/db/schemas/culture.py +120 -0
  42. agno/db/schemas/memory.py +13 -0
  43. agno/db/singlestore/schemas.py +26 -1
  44. agno/db/singlestore/singlestore.py +687 -53
  45. agno/db/singlestore/utils.py +60 -2
  46. agno/db/sqlite/__init__.py +2 -1
  47. agno/db/sqlite/async_sqlite.py +2371 -0
  48. agno/db/sqlite/schemas.py +24 -0
  49. agno/db/sqlite/sqlite.py +774 -85
  50. agno/db/sqlite/utils.py +168 -5
  51. agno/db/surrealdb/__init__.py +3 -0
  52. agno/db/surrealdb/metrics.py +292 -0
  53. agno/db/surrealdb/models.py +309 -0
  54. agno/db/surrealdb/queries.py +71 -0
  55. agno/db/surrealdb/surrealdb.py +1361 -0
  56. agno/db/surrealdb/utils.py +147 -0
  57. agno/db/utils.py +50 -22
  58. agno/eval/accuracy.py +50 -43
  59. agno/eval/performance.py +6 -3
  60. agno/eval/reliability.py +6 -3
  61. agno/eval/utils.py +33 -16
  62. agno/exceptions.py +68 -1
  63. agno/filters.py +354 -0
  64. agno/guardrails/__init__.py +6 -0
  65. agno/guardrails/base.py +19 -0
  66. agno/guardrails/openai.py +144 -0
  67. agno/guardrails/pii.py +94 -0
  68. agno/guardrails/prompt_injection.py +52 -0
  69. agno/integrations/discord/client.py +1 -0
  70. agno/knowledge/chunking/agentic.py +13 -10
  71. agno/knowledge/chunking/fixed.py +1 -1
  72. agno/knowledge/chunking/semantic.py +40 -8
  73. agno/knowledge/chunking/strategy.py +59 -15
  74. agno/knowledge/embedder/aws_bedrock.py +9 -4
  75. agno/knowledge/embedder/azure_openai.py +54 -0
  76. agno/knowledge/embedder/base.py +2 -0
  77. agno/knowledge/embedder/cohere.py +184 -5
  78. agno/knowledge/embedder/fastembed.py +1 -1
  79. agno/knowledge/embedder/google.py +79 -1
  80. agno/knowledge/embedder/huggingface.py +9 -4
  81. agno/knowledge/embedder/jina.py +63 -0
  82. agno/knowledge/embedder/mistral.py +78 -11
  83. agno/knowledge/embedder/nebius.py +1 -1
  84. agno/knowledge/embedder/ollama.py +13 -0
  85. agno/knowledge/embedder/openai.py +37 -65
  86. agno/knowledge/embedder/sentence_transformer.py +8 -4
  87. agno/knowledge/embedder/vllm.py +262 -0
  88. agno/knowledge/embedder/voyageai.py +69 -16
  89. agno/knowledge/knowledge.py +594 -186
  90. agno/knowledge/reader/base.py +9 -2
  91. agno/knowledge/reader/csv_reader.py +8 -10
  92. agno/knowledge/reader/docx_reader.py +5 -6
  93. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  94. agno/knowledge/reader/json_reader.py +6 -5
  95. agno/knowledge/reader/markdown_reader.py +13 -13
  96. agno/knowledge/reader/pdf_reader.py +43 -68
  97. agno/knowledge/reader/pptx_reader.py +101 -0
  98. agno/knowledge/reader/reader_factory.py +51 -6
  99. agno/knowledge/reader/s3_reader.py +3 -15
  100. agno/knowledge/reader/tavily_reader.py +194 -0
  101. agno/knowledge/reader/text_reader.py +13 -13
  102. agno/knowledge/reader/web_search_reader.py +2 -43
  103. agno/knowledge/reader/website_reader.py +43 -25
  104. agno/knowledge/reranker/__init__.py +2 -8
  105. agno/knowledge/types.py +9 -0
  106. agno/knowledge/utils.py +20 -0
  107. agno/media.py +72 -0
  108. agno/memory/manager.py +336 -82
  109. agno/models/aimlapi/aimlapi.py +2 -2
  110. agno/models/anthropic/claude.py +183 -37
  111. agno/models/aws/bedrock.py +52 -112
  112. agno/models/aws/claude.py +33 -1
  113. agno/models/azure/ai_foundry.py +33 -15
  114. agno/models/azure/openai_chat.py +25 -8
  115. agno/models/base.py +999 -519
  116. agno/models/cerebras/cerebras.py +19 -13
  117. agno/models/cerebras/cerebras_openai.py +8 -5
  118. agno/models/cohere/chat.py +27 -1
  119. agno/models/cometapi/__init__.py +5 -0
  120. agno/models/cometapi/cometapi.py +57 -0
  121. agno/models/dashscope/dashscope.py +1 -0
  122. agno/models/deepinfra/deepinfra.py +2 -2
  123. agno/models/deepseek/deepseek.py +2 -2
  124. agno/models/fireworks/fireworks.py +2 -2
  125. agno/models/google/gemini.py +103 -31
  126. agno/models/groq/groq.py +28 -11
  127. agno/models/huggingface/huggingface.py +2 -1
  128. agno/models/internlm/internlm.py +2 -2
  129. agno/models/langdb/langdb.py +4 -4
  130. agno/models/litellm/chat.py +18 -1
  131. agno/models/litellm/litellm_openai.py +2 -2
  132. agno/models/llama_cpp/__init__.py +5 -0
  133. agno/models/llama_cpp/llama_cpp.py +22 -0
  134. agno/models/message.py +139 -0
  135. agno/models/meta/llama.py +27 -10
  136. agno/models/meta/llama_openai.py +5 -17
  137. agno/models/nebius/nebius.py +6 -6
  138. agno/models/nexus/__init__.py +3 -0
  139. agno/models/nexus/nexus.py +22 -0
  140. agno/models/nvidia/nvidia.py +2 -2
  141. agno/models/ollama/chat.py +59 -5
  142. agno/models/openai/chat.py +69 -29
  143. agno/models/openai/responses.py +103 -106
  144. agno/models/openrouter/openrouter.py +41 -3
  145. agno/models/perplexity/perplexity.py +4 -5
  146. agno/models/portkey/portkey.py +3 -3
  147. agno/models/requesty/__init__.py +5 -0
  148. agno/models/requesty/requesty.py +52 -0
  149. agno/models/response.py +77 -1
  150. agno/models/sambanova/sambanova.py +2 -2
  151. agno/models/siliconflow/__init__.py +5 -0
  152. agno/models/siliconflow/siliconflow.py +25 -0
  153. agno/models/together/together.py +2 -2
  154. agno/models/utils.py +254 -8
  155. agno/models/vercel/v0.py +2 -2
  156. agno/models/vertexai/__init__.py +0 -0
  157. agno/models/vertexai/claude.py +96 -0
  158. agno/models/vllm/vllm.py +1 -0
  159. agno/models/xai/xai.py +3 -2
  160. agno/os/app.py +543 -178
  161. agno/os/auth.py +24 -14
  162. agno/os/config.py +1 -0
  163. agno/os/interfaces/__init__.py +1 -0
  164. agno/os/interfaces/a2a/__init__.py +3 -0
  165. agno/os/interfaces/a2a/a2a.py +42 -0
  166. agno/os/interfaces/a2a/router.py +250 -0
  167. agno/os/interfaces/a2a/utils.py +924 -0
  168. agno/os/interfaces/agui/agui.py +23 -7
  169. agno/os/interfaces/agui/router.py +27 -3
  170. agno/os/interfaces/agui/utils.py +242 -142
  171. agno/os/interfaces/base.py +6 -2
  172. agno/os/interfaces/slack/router.py +81 -23
  173. agno/os/interfaces/slack/slack.py +29 -14
  174. agno/os/interfaces/whatsapp/router.py +11 -4
  175. agno/os/interfaces/whatsapp/whatsapp.py +14 -7
  176. agno/os/mcp.py +111 -54
  177. agno/os/middleware/__init__.py +7 -0
  178. agno/os/middleware/jwt.py +233 -0
  179. agno/os/router.py +556 -139
  180. agno/os/routers/evals/evals.py +71 -34
  181. agno/os/routers/evals/schemas.py +31 -31
  182. agno/os/routers/evals/utils.py +6 -5
  183. agno/os/routers/health.py +31 -0
  184. agno/os/routers/home.py +52 -0
  185. agno/os/routers/knowledge/knowledge.py +185 -38
  186. agno/os/routers/knowledge/schemas.py +82 -22
  187. agno/os/routers/memory/memory.py +158 -53
  188. agno/os/routers/memory/schemas.py +20 -16
  189. agno/os/routers/metrics/metrics.py +20 -8
  190. agno/os/routers/metrics/schemas.py +16 -16
  191. agno/os/routers/session/session.py +499 -38
  192. agno/os/schema.py +308 -198
  193. agno/os/utils.py +401 -41
  194. agno/reasoning/anthropic.py +80 -0
  195. agno/reasoning/azure_ai_foundry.py +2 -2
  196. agno/reasoning/deepseek.py +2 -2
  197. agno/reasoning/default.py +3 -1
  198. agno/reasoning/gemini.py +73 -0
  199. agno/reasoning/groq.py +2 -2
  200. agno/reasoning/ollama.py +2 -2
  201. agno/reasoning/openai.py +7 -2
  202. agno/reasoning/vertexai.py +76 -0
  203. agno/run/__init__.py +6 -0
  204. agno/run/agent.py +248 -94
  205. agno/run/base.py +44 -5
  206. agno/run/team.py +238 -97
  207. agno/run/workflow.py +144 -33
  208. agno/session/agent.py +105 -89
  209. agno/session/summary.py +65 -25
  210. agno/session/team.py +176 -96
  211. agno/session/workflow.py +406 -40
  212. agno/team/team.py +3854 -1610
  213. agno/tools/dalle.py +2 -4
  214. agno/tools/decorator.py +4 -2
  215. agno/tools/duckduckgo.py +15 -11
  216. agno/tools/e2b.py +14 -7
  217. agno/tools/eleven_labs.py +23 -25
  218. agno/tools/exa.py +21 -16
  219. agno/tools/file.py +153 -23
  220. agno/tools/file_generation.py +350 -0
  221. agno/tools/firecrawl.py +4 -4
  222. agno/tools/function.py +250 -30
  223. agno/tools/gmail.py +238 -14
  224. agno/tools/google_drive.py +270 -0
  225. agno/tools/googlecalendar.py +36 -8
  226. agno/tools/googlesheets.py +20 -5
  227. agno/tools/jira.py +20 -0
  228. agno/tools/knowledge.py +3 -3
  229. agno/tools/mcp/__init__.py +10 -0
  230. agno/tools/mcp/mcp.py +331 -0
  231. agno/tools/mcp/multi_mcp.py +347 -0
  232. agno/tools/mcp/params.py +24 -0
  233. agno/tools/mcp_toolbox.py +284 -0
  234. agno/tools/mem0.py +11 -17
  235. agno/tools/memori.py +1 -53
  236. agno/tools/memory.py +419 -0
  237. agno/tools/models/nebius.py +5 -5
  238. agno/tools/models_labs.py +20 -10
  239. agno/tools/notion.py +204 -0
  240. agno/tools/parallel.py +314 -0
  241. agno/tools/scrapegraph.py +58 -31
  242. agno/tools/searxng.py +2 -2
  243. agno/tools/serper.py +2 -2
  244. agno/tools/slack.py +18 -3
  245. agno/tools/spider.py +2 -2
  246. agno/tools/tavily.py +146 -0
  247. agno/tools/whatsapp.py +1 -1
  248. agno/tools/workflow.py +278 -0
  249. agno/tools/yfinance.py +12 -11
  250. agno/utils/agent.py +820 -0
  251. agno/utils/audio.py +27 -0
  252. agno/utils/common.py +90 -1
  253. agno/utils/events.py +217 -2
  254. agno/utils/gemini.py +180 -22
  255. agno/utils/hooks.py +57 -0
  256. agno/utils/http.py +111 -0
  257. agno/utils/knowledge.py +12 -5
  258. agno/utils/log.py +1 -0
  259. agno/utils/mcp.py +92 -2
  260. agno/utils/media.py +188 -10
  261. agno/utils/merge_dict.py +22 -1
  262. agno/utils/message.py +60 -0
  263. agno/utils/models/claude.py +40 -11
  264. agno/utils/print_response/agent.py +105 -21
  265. agno/utils/print_response/team.py +103 -38
  266. agno/utils/print_response/workflow.py +251 -34
  267. agno/utils/reasoning.py +22 -1
  268. agno/utils/serialize.py +32 -0
  269. agno/utils/streamlit.py +16 -10
  270. agno/utils/string.py +41 -0
  271. agno/utils/team.py +98 -9
  272. agno/utils/tools.py +1 -1
  273. agno/vectordb/base.py +23 -4
  274. agno/vectordb/cassandra/cassandra.py +65 -9
  275. agno/vectordb/chroma/chromadb.py +182 -38
  276. agno/vectordb/clickhouse/clickhousedb.py +64 -11
  277. agno/vectordb/couchbase/couchbase.py +105 -10
  278. agno/vectordb/lancedb/lance_db.py +124 -133
  279. agno/vectordb/langchaindb/langchaindb.py +25 -7
  280. agno/vectordb/lightrag/lightrag.py +17 -3
  281. agno/vectordb/llamaindex/__init__.py +3 -0
  282. agno/vectordb/llamaindex/llamaindexdb.py +46 -7
  283. agno/vectordb/milvus/milvus.py +126 -9
  284. agno/vectordb/mongodb/__init__.py +7 -1
  285. agno/vectordb/mongodb/mongodb.py +112 -7
  286. agno/vectordb/pgvector/pgvector.py +142 -21
  287. agno/vectordb/pineconedb/pineconedb.py +80 -8
  288. agno/vectordb/qdrant/qdrant.py +125 -39
  289. agno/vectordb/redis/__init__.py +9 -0
  290. agno/vectordb/redis/redisdb.py +694 -0
  291. agno/vectordb/singlestore/singlestore.py +111 -25
  292. agno/vectordb/surrealdb/surrealdb.py +31 -5
  293. agno/vectordb/upstashdb/upstashdb.py +76 -8
  294. agno/vectordb/weaviate/weaviate.py +86 -15
  295. agno/workflow/__init__.py +2 -0
  296. agno/workflow/agent.py +299 -0
  297. agno/workflow/condition.py +112 -18
  298. agno/workflow/loop.py +69 -10
  299. agno/workflow/parallel.py +266 -118
  300. agno/workflow/router.py +110 -17
  301. agno/workflow/step.py +638 -129
  302. agno/workflow/steps.py +65 -6
  303. agno/workflow/types.py +61 -23
  304. agno/workflow/workflow.py +2085 -272
  305. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/METADATA +182 -58
  306. agno-2.3.0.dist-info/RECORD +577 -0
  307. agno/knowledge/reader/url_reader.py +0 -128
  308. agno/tools/googlesearch.py +0 -98
  309. agno/tools/mcp.py +0 -610
  310. agno/utils/models/aws_claude.py +0 -170
  311. agno-2.0.1.dist-info/RECORD +0 -515
  312. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
  313. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/licenses/LICENSE +0 -0
  314. {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,11 @@
1
1
  import inspect
2
+ import warnings
2
3
  from dataclasses import dataclass
3
4
  from typing import Any, AsyncIterator, Awaitable, Callable, Dict, Iterator, List, Optional, Union
4
5
  from uuid import uuid4
5
6
 
6
7
  from agno.run.agent import RunOutputEvent
8
+ from agno.run.base import RunContext
7
9
  from agno.run.team import TeamRunOutputEvent
8
10
  from agno.run.workflow import (
9
11
  ConditionExecutionCompletedEvent,
@@ -11,6 +13,7 @@ from agno.run.workflow import (
11
13
  WorkflowRunOutput,
12
14
  WorkflowRunOutputEvent,
13
15
  )
16
+ from agno.session.workflow import WorkflowSession
14
17
  from agno.utils.log import log_debug, logger
15
18
  from agno.workflow.step import Step
16
19
  from agno.workflow.types import StepInput, StepOutput, StepType
@@ -110,13 +113,16 @@ class Condition:
110
113
  audio=current_audio + all_audio,
111
114
  )
112
115
 
113
- def _evaluate_condition(self, step_input: StepInput) -> bool:
116
+ def _evaluate_condition(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> bool:
114
117
  """Evaluate the condition and return boolean result"""
115
118
  if isinstance(self.evaluator, bool):
116
119
  return self.evaluator
117
120
 
118
121
  if callable(self.evaluator):
119
- result = self.evaluator(step_input)
122
+ if session_state is not None and self._evaluator_has_session_state_param():
123
+ result = self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
124
+ else:
125
+ result = self.evaluator(step_input)
120
126
 
121
127
  if isinstance(result, bool):
122
128
  return result
@@ -126,16 +132,24 @@ class Condition:
126
132
 
127
133
  return False
128
134
 
129
- async def _aevaluate_condition(self, step_input: StepInput) -> bool:
135
+ async def _aevaluate_condition(self, step_input: StepInput, session_state: Optional[Dict[str, Any]] = None) -> bool:
130
136
  """Async version of condition evaluation"""
131
137
  if isinstance(self.evaluator, bool):
132
138
  return self.evaluator
133
139
 
134
140
  if callable(self.evaluator):
141
+ has_session_state = session_state is not None and self._evaluator_has_session_state_param()
142
+
135
143
  if inspect.iscoroutinefunction(self.evaluator):
136
- result = await self.evaluator(step_input)
144
+ if has_session_state:
145
+ result = await self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
146
+ else:
147
+ result = await self.evaluator(step_input)
137
148
  else:
138
- result = self.evaluator(step_input)
149
+ if has_session_state:
150
+ result = self.evaluator(step_input, session_state=session_state) # type: ignore[call-arg]
151
+ else:
152
+ result = self.evaluator(step_input)
139
153
 
140
154
  if isinstance(result, bool):
141
155
  return result
@@ -145,6 +159,17 @@ class Condition:
145
159
 
146
160
  return False
147
161
 
162
+ def _evaluator_has_session_state_param(self) -> bool:
163
+ """Check if the evaluator function has a session_state parameter"""
164
+ if not callable(self.evaluator):
165
+ return False
166
+
167
+ try:
168
+ sig = inspect.signature(self.evaluator)
169
+ return "session_state" in sig.parameters
170
+ except Exception:
171
+ return False
172
+
148
173
  def execute(
149
174
  self,
150
175
  step_input: StepInput,
@@ -152,7 +177,11 @@ class Condition:
152
177
  user_id: Optional[str] = None,
153
178
  workflow_run_response: Optional[WorkflowRunOutput] = None,
154
179
  store_executor_outputs: bool = True,
180
+ run_context: Optional[RunContext] = None,
155
181
  session_state: Optional[Dict[str, Any]] = None,
182
+ workflow_session: Optional[WorkflowSession] = None,
183
+ add_workflow_history_to_steps: Optional[bool] = False,
184
+ num_history_runs: int = 3,
156
185
  ) -> StepOutput:
157
186
  """Execute the condition and its steps with sequential chaining if condition is true"""
158
187
  log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
@@ -162,7 +191,11 @@ class Condition:
162
191
  self._prepare_steps()
163
192
 
164
193
  # Evaluate the condition
165
- condition_result = self._evaluate_condition(step_input)
194
+ if run_context is not None and run_context.session_state is not None:
195
+ condition_result = self._evaluate_condition(step_input, session_state=run_context.session_state)
196
+ else:
197
+ condition_result = self._evaluate_condition(step_input, session_state=session_state)
198
+
166
199
  log_debug(f"Condition {self.name} evaluated to: {condition_result}")
167
200
 
168
201
  if not condition_result:
@@ -188,7 +221,11 @@ class Condition:
188
221
  user_id=user_id,
189
222
  workflow_run_response=workflow_run_response,
190
223
  store_executor_outputs=store_executor_outputs,
224
+ run_context=run_context,
191
225
  session_state=session_state,
226
+ workflow_session=workflow_session,
227
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
228
+ num_history_runs=num_history_runs,
192
229
  )
193
230
 
194
231
  # Handle both single StepOutput and List[StepOutput] (from Loop/Condition/Router steps)
@@ -249,12 +286,18 @@ class Condition:
249
286
  step_input: StepInput,
250
287
  session_id: Optional[str] = None,
251
288
  user_id: Optional[str] = None,
252
- stream_intermediate_steps: bool = False,
289
+ stream_events: bool = False,
290
+ stream_intermediate_steps: bool = False, # type: ignore
291
+ stream_executor_events: bool = True,
253
292
  workflow_run_response: Optional[WorkflowRunOutput] = None,
254
293
  step_index: Optional[Union[int, tuple]] = None,
255
294
  store_executor_outputs: bool = True,
295
+ run_context: Optional[RunContext] = None,
256
296
  session_state: Optional[Dict[str, Any]] = None,
257
297
  parent_step_id: Optional[str] = None,
298
+ workflow_session: Optional[WorkflowSession] = None,
299
+ add_workflow_history_to_steps: Optional[bool] = False,
300
+ num_history_runs: int = 3,
258
301
  ) -> Iterator[Union[WorkflowRunOutputEvent, StepOutput]]:
259
302
  """Execute the condition with streaming support - mirrors Loop logic"""
260
303
  log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
@@ -264,10 +307,22 @@ class Condition:
264
307
  self._prepare_steps()
265
308
 
266
309
  # Evaluate the condition
267
- condition_result = self._evaluate_condition(step_input)
310
+ if run_context is not None and run_context.session_state is not None:
311
+ condition_result = self._evaluate_condition(step_input, session_state=run_context.session_state)
312
+ else:
313
+ condition_result = self._evaluate_condition(step_input, session_state=session_state)
268
314
  log_debug(f"Condition {self.name} evaluated to: {condition_result}")
269
315
 
270
- if stream_intermediate_steps and workflow_run_response:
316
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
317
+ if stream_intermediate_steps is not None:
318
+ warnings.warn(
319
+ "The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Use 'stream_events' instead.",
320
+ DeprecationWarning,
321
+ stacklevel=2,
322
+ )
323
+ stream_events = stream_events or stream_intermediate_steps
324
+
325
+ if stream_events and workflow_run_response:
271
326
  # Yield condition started event
272
327
  yield ConditionExecutionStartedEvent(
273
328
  run_id=workflow_run_response.run_id or "",
@@ -282,7 +337,7 @@ class Condition:
282
337
  )
283
338
 
284
339
  if not condition_result:
285
- if stream_intermediate_steps and workflow_run_response:
340
+ if stream_events and workflow_run_response:
286
341
  # Yield condition completed event for empty case
287
342
  yield ConditionExecutionCompletedEvent(
288
343
  run_id=workflow_run_response.run_id or "",
@@ -321,12 +376,17 @@ class Condition:
321
376
  current_step_input,
322
377
  session_id=session_id,
323
378
  user_id=user_id,
324
- stream_intermediate_steps=stream_intermediate_steps,
379
+ stream_events=stream_events,
380
+ stream_executor_events=stream_executor_events,
325
381
  workflow_run_response=workflow_run_response,
326
382
  step_index=child_step_index,
327
383
  store_executor_outputs=store_executor_outputs,
384
+ run_context=run_context,
328
385
  session_state=session_state,
329
386
  parent_step_id=conditional_step_id,
387
+ workflow_session=workflow_session,
388
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
389
+ num_history_runs=num_history_runs,
330
390
  ):
331
391
  if isinstance(event, StepOutput):
332
392
  step_outputs_for_step.append(event)
@@ -374,7 +434,7 @@ class Condition:
374
434
  break
375
435
 
376
436
  log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
377
- if stream_intermediate_steps and workflow_run_response:
437
+ if stream_events and workflow_run_response:
378
438
  # Yield condition completed event
379
439
  yield ConditionExecutionCompletedEvent(
380
440
  run_id=workflow_run_response.run_id or "",
@@ -406,7 +466,11 @@ class Condition:
406
466
  user_id: Optional[str] = None,
407
467
  workflow_run_response: Optional[WorkflowRunOutput] = None,
408
468
  store_executor_outputs: bool = True,
469
+ run_context: Optional[RunContext] = None,
409
470
  session_state: Optional[Dict[str, Any]] = None,
471
+ workflow_session: Optional[WorkflowSession] = None,
472
+ add_workflow_history_to_steps: Optional[bool] = False,
473
+ num_history_runs: int = 3,
410
474
  ) -> StepOutput:
411
475
  """Async execute the condition and its steps with sequential chaining"""
412
476
  log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
@@ -416,7 +480,10 @@ class Condition:
416
480
  self._prepare_steps()
417
481
 
418
482
  # Evaluate the condition
419
- condition_result = await self._aevaluate_condition(step_input)
483
+ if run_context is not None and run_context.session_state is not None:
484
+ condition_result = await self._aevaluate_condition(step_input, session_state=run_context.session_state)
485
+ else:
486
+ condition_result = await self._aevaluate_condition(step_input, session_state=session_state)
420
487
  log_debug(f"Condition {self.name} evaluated to: {condition_result}")
421
488
 
422
489
  if not condition_result:
@@ -444,7 +511,11 @@ class Condition:
444
511
  user_id=user_id,
445
512
  workflow_run_response=workflow_run_response,
446
513
  store_executor_outputs=store_executor_outputs,
514
+ run_context=run_context,
447
515
  session_state=session_state,
516
+ workflow_session=workflow_session,
517
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
518
+ num_history_runs=num_history_runs,
448
519
  )
449
520
 
450
521
  # Handle both single StepOutput and List[StepOutput]
@@ -503,12 +574,18 @@ class Condition:
503
574
  step_input: StepInput,
504
575
  session_id: Optional[str] = None,
505
576
  user_id: Optional[str] = None,
577
+ stream_events: bool = False,
506
578
  stream_intermediate_steps: bool = False,
579
+ stream_executor_events: bool = True,
507
580
  workflow_run_response: Optional[WorkflowRunOutput] = None,
508
581
  step_index: Optional[Union[int, tuple]] = None,
509
582
  store_executor_outputs: bool = True,
583
+ run_context: Optional[RunContext] = None,
510
584
  session_state: Optional[Dict[str, Any]] = None,
511
585
  parent_step_id: Optional[str] = None,
586
+ workflow_session: Optional[WorkflowSession] = None,
587
+ add_workflow_history_to_steps: Optional[bool] = False,
588
+ num_history_runs: int = 3,
512
589
  ) -> AsyncIterator[Union[WorkflowRunOutputEvent, TeamRunOutputEvent, RunOutputEvent, StepOutput]]:
513
590
  """Async execute the condition with streaming support - mirrors Loop logic"""
514
591
  log_debug(f"Condition Start: {self.name}", center=True, symbol="-")
@@ -518,10 +595,22 @@ class Condition:
518
595
  self._prepare_steps()
519
596
 
520
597
  # Evaluate the condition
521
- condition_result = await self._aevaluate_condition(step_input)
598
+ if run_context is not None and run_context.session_state is not None:
599
+ condition_result = await self._aevaluate_condition(step_input, session_state=run_context.session_state)
600
+ else:
601
+ condition_result = await self._aevaluate_condition(step_input, session_state=session_state)
522
602
  log_debug(f"Condition {self.name} evaluated to: {condition_result}")
523
603
 
524
- if stream_intermediate_steps and workflow_run_response:
604
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
605
+ if stream_intermediate_steps is not None:
606
+ warnings.warn(
607
+ "The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Use 'stream_events' instead.",
608
+ DeprecationWarning,
609
+ stacklevel=2,
610
+ )
611
+ stream_events = stream_events or stream_intermediate_steps
612
+
613
+ if stream_events and workflow_run_response:
525
614
  # Yield condition started event
526
615
  yield ConditionExecutionStartedEvent(
527
616
  run_id=workflow_run_response.run_id or "",
@@ -536,7 +625,7 @@ class Condition:
536
625
  )
537
626
 
538
627
  if not condition_result:
539
- if stream_intermediate_steps and workflow_run_response:
628
+ if stream_events and workflow_run_response:
540
629
  # Yield condition completed event for empty case
541
630
  yield ConditionExecutionCompletedEvent(
542
631
  run_id=workflow_run_response.run_id or "",
@@ -577,12 +666,17 @@ class Condition:
577
666
  current_step_input,
578
667
  session_id=session_id,
579
668
  user_id=user_id,
580
- stream_intermediate_steps=stream_intermediate_steps,
669
+ stream_events=stream_events,
670
+ stream_executor_events=stream_executor_events,
581
671
  workflow_run_response=workflow_run_response,
582
672
  step_index=child_step_index,
583
673
  store_executor_outputs=store_executor_outputs,
674
+ run_context=run_context,
584
675
  session_state=session_state,
585
676
  parent_step_id=conditional_step_id,
677
+ workflow_session=workflow_session,
678
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
679
+ num_history_runs=num_history_runs,
586
680
  ):
587
681
  if isinstance(event, StepOutput):
588
682
  step_outputs_for_step.append(event)
@@ -631,7 +725,7 @@ class Condition:
631
725
 
632
726
  log_debug(f"Condition End: {self.name} ({len(all_results)} results)", center=True, symbol="-")
633
727
 
634
- if stream_intermediate_steps and workflow_run_response:
728
+ if stream_events and workflow_run_response:
635
729
  # Yield condition completed event
636
730
  yield ConditionExecutionCompletedEvent(
637
731
  run_id=workflow_run_response.run_id or "",
agno/workflow/loop.py CHANGED
@@ -1,9 +1,11 @@
1
1
  import inspect
2
+ import warnings
2
3
  from dataclasses import dataclass
3
4
  from typing import Any, AsyncIterator, Awaitable, Callable, Dict, Iterator, List, Optional, Union
4
5
  from uuid import uuid4
5
6
 
6
7
  from agno.run.agent import RunOutputEvent
8
+ from agno.run.base import RunContext
7
9
  from agno.run.team import TeamRunOutputEvent
8
10
  from agno.run.workflow import (
9
11
  LoopExecutionCompletedEvent,
@@ -13,6 +15,7 @@ from agno.run.workflow import (
13
15
  WorkflowRunOutput,
14
16
  WorkflowRunOutputEvent,
15
17
  )
18
+ from agno.session.workflow import WorkflowSession
16
19
  from agno.utils.log import log_debug, logger
17
20
  from agno.workflow.step import Step
18
21
  from agno.workflow.types import StepInput, StepOutput, StepType
@@ -131,7 +134,11 @@ class Loop:
131
134
  user_id: Optional[str] = None,
132
135
  workflow_run_response: Optional[WorkflowRunOutput] = None,
133
136
  store_executor_outputs: bool = True,
137
+ run_context: Optional[RunContext] = None,
134
138
  session_state: Optional[Dict[str, Any]] = None,
139
+ workflow_session: Optional[WorkflowSession] = None,
140
+ add_workflow_history_to_steps: Optional[bool] = False,
141
+ num_history_runs: int = 3,
135
142
  ) -> StepOutput:
136
143
  """Execute loop steps with iteration control - mirrors workflow execution logic"""
137
144
  # Use workflow logger for loop orchestration
@@ -156,7 +163,11 @@ class Loop:
156
163
  user_id=user_id,
157
164
  workflow_run_response=workflow_run_response,
158
165
  store_executor_outputs=store_executor_outputs,
166
+ run_context=run_context,
159
167
  session_state=session_state,
168
+ workflow_session=workflow_session,
169
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
170
+ num_history_runs=num_history_runs,
160
171
  )
161
172
 
162
173
  # Handle both single StepOutput and List[StepOutput] (from Loop/Condition steps)
@@ -219,12 +230,18 @@ class Loop:
219
230
  step_input: StepInput,
220
231
  session_id: Optional[str] = None,
221
232
  user_id: Optional[str] = None,
233
+ stream_events: bool = False,
222
234
  stream_intermediate_steps: bool = False,
235
+ stream_executor_events: bool = True,
223
236
  workflow_run_response: Optional[WorkflowRunOutput] = None,
224
237
  step_index: Optional[Union[int, tuple]] = None,
225
238
  store_executor_outputs: bool = True,
239
+ run_context: Optional[RunContext] = None,
226
240
  session_state: Optional[Dict[str, Any]] = None,
227
241
  parent_step_id: Optional[str] = None,
242
+ workflow_session: Optional[WorkflowSession] = None,
243
+ add_workflow_history_to_steps: Optional[bool] = False,
244
+ num_history_runs: int = 3,
228
245
  ) -> Iterator[Union[WorkflowRunOutputEvent, StepOutput]]:
229
246
  """Execute loop steps with streaming support - mirrors workflow execution logic"""
230
247
  log_debug(f"Loop Start: {self.name}", center=True, symbol="=")
@@ -234,7 +251,16 @@ class Loop:
234
251
 
235
252
  loop_step_id = str(uuid4())
236
253
 
237
- if stream_intermediate_steps and workflow_run_response:
254
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
255
+ if stream_intermediate_steps is not None:
256
+ warnings.warn(
257
+ "The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Use 'stream_events' instead.",
258
+ DeprecationWarning,
259
+ stacklevel=2,
260
+ )
261
+ stream_events = stream_events or stream_intermediate_steps
262
+
263
+ if stream_events and workflow_run_response:
238
264
  # Yield loop started event
239
265
  yield LoopExecutionStartedEvent(
240
266
  run_id=workflow_run_response.run_id or "",
@@ -255,7 +281,7 @@ class Loop:
255
281
  while iteration < self.max_iterations:
256
282
  log_debug(f"Loop iteration {iteration + 1}/{self.max_iterations}")
257
283
 
258
- if stream_intermediate_steps and workflow_run_response:
284
+ if stream_events and workflow_run_response:
259
285
  # Yield iteration started event
260
286
  yield LoopIterationStartedEvent(
261
287
  run_id=workflow_run_response.run_id or "",
@@ -291,12 +317,17 @@ class Loop:
291
317
  current_step_input,
292
318
  session_id=session_id,
293
319
  user_id=user_id,
294
- stream_intermediate_steps=stream_intermediate_steps,
320
+ stream_events=stream_events,
321
+ stream_executor_events=stream_executor_events,
295
322
  workflow_run_response=workflow_run_response,
296
323
  step_index=composite_step_index,
297
324
  store_executor_outputs=store_executor_outputs,
325
+ run_context=run_context,
298
326
  session_state=session_state,
299
327
  parent_step_id=loop_step_id,
328
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
329
+ workflow_session=workflow_session,
330
+ num_history_runs=num_history_runs,
300
331
  ):
301
332
  if isinstance(event, StepOutput):
302
333
  step_outputs_for_iteration.append(event)
@@ -348,7 +379,7 @@ class Loop:
348
379
  should_continue = False
349
380
  log_debug(f"Loop ending early due to step termination request at iteration {iteration}")
350
381
 
351
- if stream_intermediate_steps and workflow_run_response:
382
+ if stream_events and workflow_run_response:
352
383
  # Yield iteration completed event
353
384
  yield LoopIterationCompletedEvent(
354
385
  run_id=workflow_run_response.run_id or "",
@@ -373,7 +404,7 @@ class Loop:
373
404
 
374
405
  log_debug(f"Loop End: {self.name} ({iteration} iterations)", center=True, symbol="=")
375
406
 
376
- if stream_intermediate_steps and workflow_run_response:
407
+ if stream_events and workflow_run_response:
377
408
  # Yield loop completed event
378
409
  yield LoopExecutionCompletedEvent(
379
410
  run_id=workflow_run_response.run_id or "",
@@ -409,7 +440,11 @@ class Loop:
409
440
  user_id: Optional[str] = None,
410
441
  workflow_run_response: Optional[WorkflowRunOutput] = None,
411
442
  store_executor_outputs: bool = True,
443
+ run_context: Optional[RunContext] = None,
412
444
  session_state: Optional[Dict[str, Any]] = None,
445
+ workflow_session: Optional[WorkflowSession] = None,
446
+ add_workflow_history_to_steps: Optional[bool] = False,
447
+ num_history_runs: int = 3,
413
448
  ) -> StepOutput:
414
449
  """Execute loop steps asynchronously with iteration control - mirrors workflow execution logic"""
415
450
  # Use workflow logger for async loop orchestration
@@ -436,7 +471,11 @@ class Loop:
436
471
  user_id=user_id,
437
472
  workflow_run_response=workflow_run_response,
438
473
  store_executor_outputs=store_executor_outputs,
474
+ run_context=run_context,
439
475
  session_state=session_state,
476
+ workflow_session=workflow_session,
477
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
478
+ num_history_runs=num_history_runs,
440
479
  )
441
480
 
442
481
  # Handle both single StepOutput and List[StepOutput] (from Loop/Condition steps)
@@ -502,12 +541,18 @@ class Loop:
502
541
  step_input: StepInput,
503
542
  session_id: Optional[str] = None,
504
543
  user_id: Optional[str] = None,
544
+ stream_events: bool = False,
505
545
  stream_intermediate_steps: bool = False,
546
+ stream_executor_events: bool = True,
506
547
  workflow_run_response: Optional[WorkflowRunOutput] = None,
507
548
  step_index: Optional[Union[int, tuple]] = None,
508
549
  store_executor_outputs: bool = True,
550
+ run_context: Optional[RunContext] = None,
509
551
  session_state: Optional[Dict[str, Any]] = None,
510
552
  parent_step_id: Optional[str] = None,
553
+ workflow_session: Optional[WorkflowSession] = None,
554
+ add_workflow_history_to_steps: Optional[bool] = False,
555
+ num_history_runs: int = 3,
511
556
  ) -> AsyncIterator[Union[WorkflowRunOutputEvent, TeamRunOutputEvent, RunOutputEvent, StepOutput]]:
512
557
  """Execute loop steps with async streaming support - mirrors workflow execution logic"""
513
558
  log_debug(f"Loop Start: {self.name}", center=True, symbol="=")
@@ -517,7 +562,16 @@ class Loop:
517
562
  # Prepare steps first
518
563
  self._prepare_steps()
519
564
 
520
- if stream_intermediate_steps and workflow_run_response:
565
+ # Considering both stream_events and stream_intermediate_steps (deprecated)
566
+ if stream_intermediate_steps is not None:
567
+ warnings.warn(
568
+ "The 'stream_intermediate_steps' parameter is deprecated and will be removed in future versions. Use 'stream_events' instead.",
569
+ DeprecationWarning,
570
+ stacklevel=2,
571
+ )
572
+ stream_events = stream_events or stream_intermediate_steps
573
+
574
+ if stream_events and workflow_run_response:
521
575
  # Yield loop started event
522
576
  yield LoopExecutionStartedEvent(
523
577
  run_id=workflow_run_response.run_id or "",
@@ -538,7 +592,7 @@ class Loop:
538
592
  while iteration < self.max_iterations:
539
593
  log_debug(f"Async loop iteration {iteration + 1}/{self.max_iterations}")
540
594
 
541
- if stream_intermediate_steps and workflow_run_response:
595
+ if stream_events and workflow_run_response:
542
596
  # Yield iteration started event
543
597
  yield LoopIterationStartedEvent(
544
598
  run_id=workflow_run_response.run_id or "",
@@ -574,12 +628,17 @@ class Loop:
574
628
  current_step_input,
575
629
  session_id=session_id,
576
630
  user_id=user_id,
577
- stream_intermediate_steps=stream_intermediate_steps,
631
+ stream_events=stream_events,
632
+ stream_executor_events=stream_executor_events,
578
633
  workflow_run_response=workflow_run_response,
579
634
  step_index=composite_step_index,
580
635
  store_executor_outputs=store_executor_outputs,
636
+ run_context=run_context,
581
637
  session_state=session_state,
582
638
  parent_step_id=loop_step_id,
639
+ workflow_session=workflow_session,
640
+ add_workflow_history_to_steps=add_workflow_history_to_steps,
641
+ num_history_runs=num_history_runs,
583
642
  ):
584
643
  if isinstance(event, StepOutput):
585
644
  step_outputs_for_iteration.append(event)
@@ -634,7 +693,7 @@ class Loop:
634
693
  should_continue = False
635
694
  log_debug(f"Loop ending early due to step termination request at iteration {iteration}")
636
695
 
637
- if stream_intermediate_steps and workflow_run_response:
696
+ if stream_events and workflow_run_response:
638
697
  # Yield iteration completed event
639
698
  yield LoopIterationCompletedEvent(
640
699
  run_id=workflow_run_response.run_id or "",
@@ -659,7 +718,7 @@ class Loop:
659
718
 
660
719
  log_debug(f"Loop End: {self.name} ({iteration} iterations)", center=True, symbol="=")
661
720
 
662
- if stream_intermediate_steps and workflow_run_response:
721
+ if stream_events and workflow_run_response:
663
722
  # Yield loop completed event
664
723
  yield LoopExecutionCompletedEvent(
665
724
  run_id=workflow_run_response.run_id or "",