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.
- agno/agent/agent.py +6015 -2823
- agno/api/api.py +2 -0
- agno/api/os.py +1 -1
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +385 -6
- agno/db/dynamo/dynamo.py +388 -81
- agno/db/dynamo/schemas.py +47 -10
- agno/db/dynamo/utils.py +63 -4
- agno/db/firestore/firestore.py +435 -64
- agno/db/firestore/schemas.py +11 -0
- agno/db/firestore/utils.py +102 -4
- agno/db/gcs_json/gcs_json_db.py +384 -42
- agno/db/gcs_json/utils.py +60 -26
- agno/db/in_memory/in_memory_db.py +351 -66
- agno/db/in_memory/utils.py +60 -2
- agno/db/json/json_db.py +339 -48
- agno/db/json/utils.py +60 -26
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +510 -37
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +15 -1
- agno/db/mongo/async_mongo.py +2036 -0
- agno/db/mongo/mongo.py +653 -76
- agno/db/mongo/schemas.py +13 -0
- agno/db/mongo/utils.py +80 -8
- agno/db/mysql/mysql.py +687 -25
- agno/db/mysql/schemas.py +61 -37
- agno/db/mysql/utils.py +60 -2
- agno/db/postgres/__init__.py +2 -1
- agno/db/postgres/async_postgres.py +2001 -0
- agno/db/postgres/postgres.py +676 -57
- agno/db/postgres/schemas.py +43 -18
- agno/db/postgres/utils.py +164 -2
- agno/db/redis/redis.py +344 -38
- agno/db/redis/schemas.py +18 -0
- agno/db/redis/utils.py +60 -2
- agno/db/schemas/__init__.py +2 -1
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/memory.py +13 -0
- agno/db/singlestore/schemas.py +26 -1
- agno/db/singlestore/singlestore.py +687 -53
- agno/db/singlestore/utils.py +60 -2
- agno/db/sqlite/__init__.py +2 -1
- agno/db/sqlite/async_sqlite.py +2371 -0
- agno/db/sqlite/schemas.py +24 -0
- agno/db/sqlite/sqlite.py +774 -85
- agno/db/sqlite/utils.py +168 -5
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +309 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1361 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +50 -22
- agno/eval/accuracy.py +50 -43
- agno/eval/performance.py +6 -3
- agno/eval/reliability.py +6 -3
- agno/eval/utils.py +33 -16
- agno/exceptions.py +68 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/integrations/discord/client.py +1 -0
- agno/knowledge/chunking/agentic.py +13 -10
- agno/knowledge/chunking/fixed.py +1 -1
- agno/knowledge/chunking/semantic.py +40 -8
- agno/knowledge/chunking/strategy.py +59 -15
- agno/knowledge/embedder/aws_bedrock.py +9 -4
- agno/knowledge/embedder/azure_openai.py +54 -0
- agno/knowledge/embedder/base.py +2 -0
- agno/knowledge/embedder/cohere.py +184 -5
- agno/knowledge/embedder/fastembed.py +1 -1
- agno/knowledge/embedder/google.py +79 -1
- agno/knowledge/embedder/huggingface.py +9 -4
- agno/knowledge/embedder/jina.py +63 -0
- agno/knowledge/embedder/mistral.py +78 -11
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/ollama.py +13 -0
- agno/knowledge/embedder/openai.py +37 -65
- agno/knowledge/embedder/sentence_transformer.py +8 -4
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +69 -16
- agno/knowledge/knowledge.py +594 -186
- agno/knowledge/reader/base.py +9 -2
- agno/knowledge/reader/csv_reader.py +8 -10
- agno/knowledge/reader/docx_reader.py +5 -6
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/json_reader.py +6 -5
- agno/knowledge/reader/markdown_reader.py +13 -13
- agno/knowledge/reader/pdf_reader.py +43 -68
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +51 -6
- agno/knowledge/reader/s3_reader.py +3 -15
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/reader/text_reader.py +13 -13
- agno/knowledge/reader/web_search_reader.py +2 -43
- agno/knowledge/reader/website_reader.py +43 -25
- agno/knowledge/reranker/__init__.py +2 -8
- agno/knowledge/types.py +9 -0
- agno/knowledge/utils.py +20 -0
- agno/media.py +72 -0
- agno/memory/manager.py +336 -82
- agno/models/aimlapi/aimlapi.py +2 -2
- agno/models/anthropic/claude.py +183 -37
- agno/models/aws/bedrock.py +52 -112
- agno/models/aws/claude.py +33 -1
- agno/models/azure/ai_foundry.py +33 -15
- agno/models/azure/openai_chat.py +25 -8
- agno/models/base.py +999 -519
- agno/models/cerebras/cerebras.py +19 -13
- agno/models/cerebras/cerebras_openai.py +8 -5
- agno/models/cohere/chat.py +27 -1
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/dashscope.py +1 -0
- agno/models/deepinfra/deepinfra.py +2 -2
- agno/models/deepseek/deepseek.py +2 -2
- agno/models/fireworks/fireworks.py +2 -2
- agno/models/google/gemini.py +103 -31
- agno/models/groq/groq.py +28 -11
- agno/models/huggingface/huggingface.py +2 -1
- agno/models/internlm/internlm.py +2 -2
- agno/models/langdb/langdb.py +4 -4
- agno/models/litellm/chat.py +18 -1
- agno/models/litellm/litellm_openai.py +2 -2
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/message.py +139 -0
- agno/models/meta/llama.py +27 -10
- agno/models/meta/llama_openai.py +5 -17
- agno/models/nebius/nebius.py +6 -6
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/nvidia.py +2 -2
- agno/models/ollama/chat.py +59 -5
- agno/models/openai/chat.py +69 -29
- agno/models/openai/responses.py +103 -106
- agno/models/openrouter/openrouter.py +41 -3
- agno/models/perplexity/perplexity.py +4 -5
- agno/models/portkey/portkey.py +3 -3
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +77 -1
- agno/models/sambanova/sambanova.py +2 -2
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/together.py +2 -2
- agno/models/utils.py +254 -8
- agno/models/vercel/v0.py +2 -2
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +96 -0
- agno/models/vllm/vllm.py +1 -0
- agno/models/xai/xai.py +3 -2
- agno/os/app.py +543 -178
- agno/os/auth.py +24 -14
- agno/os/config.py +1 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +250 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/agui.py +23 -7
- agno/os/interfaces/agui/router.py +27 -3
- agno/os/interfaces/agui/utils.py +242 -142
- agno/os/interfaces/base.py +6 -2
- agno/os/interfaces/slack/router.py +81 -23
- agno/os/interfaces/slack/slack.py +29 -14
- agno/os/interfaces/whatsapp/router.py +11 -4
- agno/os/interfaces/whatsapp/whatsapp.py +14 -7
- agno/os/mcp.py +111 -54
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +556 -139
- agno/os/routers/evals/evals.py +71 -34
- agno/os/routers/evals/schemas.py +31 -31
- agno/os/routers/evals/utils.py +6 -5
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/knowledge.py +185 -38
- agno/os/routers/knowledge/schemas.py +82 -22
- agno/os/routers/memory/memory.py +158 -53
- agno/os/routers/memory/schemas.py +20 -16
- agno/os/routers/metrics/metrics.py +20 -8
- agno/os/routers/metrics/schemas.py +16 -16
- agno/os/routers/session/session.py +499 -38
- agno/os/schema.py +308 -198
- agno/os/utils.py +401 -41
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +2 -2
- agno/reasoning/deepseek.py +2 -2
- agno/reasoning/default.py +3 -1
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +2 -2
- agno/reasoning/ollama.py +2 -2
- agno/reasoning/openai.py +7 -2
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +248 -94
- agno/run/base.py +44 -5
- agno/run/team.py +238 -97
- agno/run/workflow.py +144 -33
- agno/session/agent.py +105 -89
- agno/session/summary.py +65 -25
- agno/session/team.py +176 -96
- agno/session/workflow.py +406 -40
- agno/team/team.py +3854 -1610
- agno/tools/dalle.py +2 -4
- agno/tools/decorator.py +4 -2
- agno/tools/duckduckgo.py +15 -11
- agno/tools/e2b.py +14 -7
- agno/tools/eleven_labs.py +23 -25
- agno/tools/exa.py +21 -16
- agno/tools/file.py +153 -23
- agno/tools/file_generation.py +350 -0
- agno/tools/firecrawl.py +4 -4
- agno/tools/function.py +250 -30
- agno/tools/gmail.py +238 -14
- agno/tools/google_drive.py +270 -0
- agno/tools/googlecalendar.py +36 -8
- agno/tools/googlesheets.py +20 -5
- agno/tools/jira.py +20 -0
- agno/tools/knowledge.py +3 -3
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +11 -17
- agno/tools/memori.py +1 -53
- agno/tools/memory.py +419 -0
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/notion.py +204 -0
- agno/tools/parallel.py +314 -0
- agno/tools/scrapegraph.py +58 -31
- agno/tools/searxng.py +2 -2
- agno/tools/serper.py +2 -2
- agno/tools/slack.py +18 -3
- agno/tools/spider.py +2 -2
- agno/tools/tavily.py +146 -0
- agno/tools/whatsapp.py +1 -1
- agno/tools/workflow.py +278 -0
- agno/tools/yfinance.py +12 -11
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +27 -0
- agno/utils/common.py +90 -1
- agno/utils/events.py +217 -2
- agno/utils/gemini.py +180 -22
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +111 -0
- agno/utils/knowledge.py +12 -5
- agno/utils/log.py +1 -0
- agno/utils/mcp.py +92 -2
- agno/utils/media.py +188 -10
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +60 -0
- agno/utils/models/claude.py +40 -11
- agno/utils/print_response/agent.py +105 -21
- agno/utils/print_response/team.py +103 -38
- agno/utils/print_response/workflow.py +251 -34
- agno/utils/reasoning.py +22 -1
- agno/utils/serialize.py +32 -0
- agno/utils/streamlit.py +16 -10
- agno/utils/string.py +41 -0
- agno/utils/team.py +98 -9
- agno/utils/tools.py +1 -1
- agno/vectordb/base.py +23 -4
- agno/vectordb/cassandra/cassandra.py +65 -9
- agno/vectordb/chroma/chromadb.py +182 -38
- agno/vectordb/clickhouse/clickhousedb.py +64 -11
- agno/vectordb/couchbase/couchbase.py +105 -10
- agno/vectordb/lancedb/lance_db.py +124 -133
- agno/vectordb/langchaindb/langchaindb.py +25 -7
- agno/vectordb/lightrag/lightrag.py +17 -3
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +46 -7
- agno/vectordb/milvus/milvus.py +126 -9
- agno/vectordb/mongodb/__init__.py +7 -1
- agno/vectordb/mongodb/mongodb.py +112 -7
- agno/vectordb/pgvector/pgvector.py +142 -21
- agno/vectordb/pineconedb/pineconedb.py +80 -8
- agno/vectordb/qdrant/qdrant.py +125 -39
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/singlestore/singlestore.py +111 -25
- agno/vectordb/surrealdb/surrealdb.py +31 -5
- agno/vectordb/upstashdb/upstashdb.py +76 -8
- agno/vectordb/weaviate/weaviate.py +86 -15
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +112 -18
- agno/workflow/loop.py +69 -10
- agno/workflow/parallel.py +266 -118
- agno/workflow/router.py +110 -17
- agno/workflow/step.py +638 -129
- agno/workflow/steps.py +65 -6
- agno/workflow/types.py +61 -23
- agno/workflow/workflow.py +2085 -272
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/METADATA +182 -58
- agno-2.3.0.dist-info/RECORD +577 -0
- agno/knowledge/reader/url_reader.py +0 -128
- agno/tools/googlesearch.py +0 -98
- agno/tools/mcp.py +0 -610
- agno/utils/models/aws_claude.py +0 -170
- agno-2.0.1.dist-info/RECORD +0 -515
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/licenses/LICENSE +0 -0
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
agno/workflow/condition.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
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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 "",
|