agno 2.3.16__py3-none-any.whl → 2.3.17__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/__init__.py +2 -0
- agno/agent/agent.py +4 -53
- agno/agent/remote.py +351 -0
- agno/client/__init__.py +3 -0
- agno/client/os.py +2669 -0
- agno/db/base.py +20 -0
- agno/db/mongo/async_mongo.py +11 -0
- agno/db/mongo/mongo.py +10 -0
- agno/db/mysql/async_mysql.py +9 -0
- agno/db/mysql/mysql.py +9 -0
- agno/db/postgres/async_postgres.py +9 -0
- agno/db/postgres/postgres.py +9 -0
- agno/db/postgres/utils.py +3 -2
- agno/db/sqlite/async_sqlite.py +9 -0
- agno/db/sqlite/sqlite.py +11 -1
- agno/exceptions.py +23 -0
- agno/knowledge/chunking/semantic.py +123 -46
- agno/knowledge/reader/csv_reader.py +1 -1
- agno/knowledge/reader/field_labeled_csv_reader.py +1 -1
- agno/knowledge/reader/json_reader.py +1 -1
- agno/os/app.py +104 -23
- agno/os/auth.py +25 -1
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +13 -13
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +23 -16
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +6 -6
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +29 -6
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +651 -79
- agno/os/router.py +125 -18
- agno/os/routers/agents/router.py +65 -22
- agno/os/routers/agents/schema.py +16 -4
- agno/os/routers/database.py +5 -0
- agno/os/routers/evals/evals.py +93 -11
- agno/os/routers/evals/utils.py +6 -6
- agno/os/routers/knowledge/knowledge.py +104 -16
- agno/os/routers/memory/memory.py +124 -7
- agno/os/routers/metrics/metrics.py +21 -4
- agno/os/routers/session/session.py +141 -12
- agno/os/routers/teams/router.py +40 -14
- agno/os/routers/teams/schema.py +12 -4
- agno/os/routers/traces/traces.py +54 -4
- agno/os/routers/workflows/router.py +223 -117
- agno/os/routers/workflows/schema.py +65 -1
- agno/os/schema.py +38 -12
- agno/os/utils.py +87 -166
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +484 -0
- agno/run/workflow.py +1 -0
- agno/team/__init__.py +2 -0
- agno/team/remote.py +287 -0
- agno/team/team.py +25 -54
- agno/tracing/exporter.py +10 -6
- agno/tracing/setup.py +2 -1
- agno/utils/agent.py +58 -1
- agno/utils/http.py +68 -20
- agno/utils/os.py +0 -0
- agno/utils/remote.py +23 -0
- agno/vectordb/chroma/chromadb.py +452 -16
- agno/vectordb/pgvector/pgvector.py +7 -0
- agno/vectordb/redis/redisdb.py +1 -1
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +2 -2
- agno/workflow/remote.py +222 -0
- agno/workflow/types.py +0 -73
- agno/workflow/workflow.py +119 -68
- {agno-2.3.16.dist-info → agno-2.3.17.dist-info}/METADATA +1 -1
- {agno-2.3.16.dist-info → agno-2.3.17.dist-info}/RECORD +75 -65
- {agno-2.3.16.dist-info → agno-2.3.17.dist-info}/WHEEL +0 -0
- {agno-2.3.16.dist-info → agno-2.3.17.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.16.dist-info → agno-2.3.17.dist-info}/top_level.txt +0 -0
agno/workflow/workflow.py
CHANGED
|
@@ -4,6 +4,7 @@ from dataclasses import dataclass
|
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from os import getenv
|
|
6
6
|
from typing import (
|
|
7
|
+
TYPE_CHECKING,
|
|
7
8
|
Any,
|
|
8
9
|
AsyncIterator,
|
|
9
10
|
Awaitable,
|
|
@@ -24,6 +25,9 @@ from uuid import uuid4
|
|
|
24
25
|
from fastapi import WebSocket
|
|
25
26
|
from pydantic import BaseModel
|
|
26
27
|
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from agno.os.managers import WebSocketHandler
|
|
30
|
+
|
|
27
31
|
from agno.agent.agent import Agent
|
|
28
32
|
from agno.db.base import AsyncBaseDb, BaseDb, SessionType
|
|
29
33
|
from agno.exceptions import InputCheckError, OutputCheckError, RunCancelledException
|
|
@@ -53,7 +57,7 @@ from agno.run.workflow import (
|
|
|
53
57
|
)
|
|
54
58
|
from agno.session.workflow import WorkflowChatInteraction, WorkflowSession
|
|
55
59
|
from agno.team.team import Team
|
|
56
|
-
from agno.utils.
|
|
60
|
+
from agno.utils.agent import validate_input
|
|
57
61
|
from agno.utils.log import (
|
|
58
62
|
log_debug,
|
|
59
63
|
log_error,
|
|
@@ -69,7 +73,7 @@ from agno.utils.print_response.workflow import (
|
|
|
69
73
|
print_response,
|
|
70
74
|
print_response_stream,
|
|
71
75
|
)
|
|
72
|
-
from agno.workflow import WorkflowAgent
|
|
76
|
+
from agno.workflow.agent import WorkflowAgent
|
|
73
77
|
from agno.workflow.condition import Condition
|
|
74
78
|
from agno.workflow.loop import Loop
|
|
75
79
|
from agno.workflow.parallel import Parallel
|
|
@@ -81,7 +85,6 @@ from agno.workflow.types import (
|
|
|
81
85
|
StepMetrics,
|
|
82
86
|
StepOutput,
|
|
83
87
|
StepType,
|
|
84
|
-
WebSocketHandler,
|
|
85
88
|
WorkflowExecutionInput,
|
|
86
89
|
WorkflowMetrics,
|
|
87
90
|
)
|
|
@@ -165,7 +168,7 @@ class Workflow:
|
|
|
165
168
|
# Control whether to store executor responses (agent/team responses) in flattened runs
|
|
166
169
|
store_executor_outputs: bool = True
|
|
167
170
|
|
|
168
|
-
websocket_handler: Optional[WebSocketHandler] = None
|
|
171
|
+
websocket_handler: Optional["WebSocketHandler"] = None
|
|
169
172
|
|
|
170
173
|
# Input schema to validate the input to the workflow
|
|
171
174
|
input_schema: Optional[Type[BaseModel]] = None
|
|
@@ -267,59 +270,6 @@ class Workflow:
|
|
|
267
270
|
def _has_async_db(self) -> bool:
|
|
268
271
|
return self.db is not None and isinstance(self.db, AsyncBaseDb)
|
|
269
272
|
|
|
270
|
-
def _validate_input(
|
|
271
|
-
self, input: Optional[Union[str, Dict[str, Any], List[Any], BaseModel, List[Message]]]
|
|
272
|
-
) -> Optional[Union[str, List, Dict, Message, BaseModel]]:
|
|
273
|
-
"""Parse and validate input against input_schema if provided"""
|
|
274
|
-
if self.input_schema is None:
|
|
275
|
-
return input # Return input unchanged if no schema is set
|
|
276
|
-
|
|
277
|
-
if input is None:
|
|
278
|
-
raise ValueError("Input required when input_schema is set")
|
|
279
|
-
|
|
280
|
-
# Handle Message objects - extract content
|
|
281
|
-
if isinstance(input, Message):
|
|
282
|
-
input = input.content # type: ignore
|
|
283
|
-
|
|
284
|
-
# If input is a string, convert it to a dict
|
|
285
|
-
if isinstance(input, str):
|
|
286
|
-
import json
|
|
287
|
-
|
|
288
|
-
try:
|
|
289
|
-
input = json.loads(input)
|
|
290
|
-
except Exception as e:
|
|
291
|
-
raise ValueError(f"Failed to parse input. Is it a valid JSON string?: {e}")
|
|
292
|
-
|
|
293
|
-
# Case 1: Message is already a BaseModel instance
|
|
294
|
-
if isinstance(input, BaseModel):
|
|
295
|
-
if isinstance(input, self.input_schema):
|
|
296
|
-
try:
|
|
297
|
-
return input
|
|
298
|
-
except Exception as e:
|
|
299
|
-
raise ValueError(f"BaseModel validation failed: {str(e)}")
|
|
300
|
-
else:
|
|
301
|
-
# Different BaseModel types
|
|
302
|
-
raise ValueError(f"Expected {self.input_schema.__name__} but got {type(input).__name__}")
|
|
303
|
-
|
|
304
|
-
# Case 2: Message is a dict
|
|
305
|
-
elif isinstance(input, dict):
|
|
306
|
-
try:
|
|
307
|
-
# Check if the schema is a TypedDict
|
|
308
|
-
if is_typed_dict(self.input_schema):
|
|
309
|
-
validated_dict = validate_typed_dict(input, self.input_schema)
|
|
310
|
-
return validated_dict
|
|
311
|
-
else:
|
|
312
|
-
validated_model = self.input_schema(**input)
|
|
313
|
-
return validated_model
|
|
314
|
-
except Exception as e:
|
|
315
|
-
raise ValueError(f"Failed to parse dict into {self.input_schema.__name__}: {str(e)}")
|
|
316
|
-
|
|
317
|
-
# Case 3: Other types not supported for structured input
|
|
318
|
-
else:
|
|
319
|
-
raise ValueError(
|
|
320
|
-
f"Cannot validate {type(input)} against input_schema. Expected dict or {self.input_schema.__name__} instance."
|
|
321
|
-
)
|
|
322
|
-
|
|
323
273
|
@property
|
|
324
274
|
def run_parameters(self) -> Dict[str, Any]:
|
|
325
275
|
"""Get the run parameters for the workflow"""
|
|
@@ -1016,7 +966,7 @@ class Workflow:
|
|
|
1016
966
|
def _broadcast_to_websocket(
|
|
1017
967
|
self,
|
|
1018
968
|
event: Any,
|
|
1019
|
-
websocket_handler: Optional[WebSocketHandler] = None,
|
|
969
|
+
websocket_handler: Optional["WebSocketHandler"] = None,
|
|
1020
970
|
) -> None:
|
|
1021
971
|
"""Broadcast events to WebSocket if available (async context only)"""
|
|
1022
972
|
if websocket_handler:
|
|
@@ -1031,7 +981,7 @@ class Workflow:
|
|
|
1031
981
|
self,
|
|
1032
982
|
event: "WorkflowRunOutputEvent",
|
|
1033
983
|
workflow_run_response: WorkflowRunOutput,
|
|
1034
|
-
websocket_handler: Optional[WebSocketHandler] = None,
|
|
984
|
+
websocket_handler: Optional["WebSocketHandler"] = None,
|
|
1035
985
|
) -> "WorkflowRunOutputEvent":
|
|
1036
986
|
"""Handle workflow events for storage - similar to Team._handle_event"""
|
|
1037
987
|
from agno.run.agent import RunOutput
|
|
@@ -1059,8 +1009,71 @@ class Workflow:
|
|
|
1059
1009
|
workflow_run_response.events = []
|
|
1060
1010
|
workflow_run_response.events.append(event)
|
|
1061
1011
|
|
|
1012
|
+
# Add to event buffer for reconnection support
|
|
1013
|
+
# Use workflow_run_id for agent/team events, run_id for workflow events
|
|
1014
|
+
buffer_run_id = None
|
|
1015
|
+
event_index = None
|
|
1016
|
+
if hasattr(event, "workflow_run_id") and event.workflow_run_id:
|
|
1017
|
+
# Agent/Team event - use workflow_run_id
|
|
1018
|
+
buffer_run_id = event.workflow_run_id
|
|
1019
|
+
elif hasattr(event, "run_id") and event.run_id:
|
|
1020
|
+
# Workflow event - use run_id
|
|
1021
|
+
buffer_run_id = event.run_id
|
|
1022
|
+
|
|
1023
|
+
if buffer_run_id:
|
|
1024
|
+
try:
|
|
1025
|
+
from agno.os.managers import event_buffer
|
|
1026
|
+
|
|
1027
|
+
# add_event now returns the event_index
|
|
1028
|
+
event_index = event_buffer.add_event(buffer_run_id, event) # type: ignore
|
|
1029
|
+
except Exception as e:
|
|
1030
|
+
# Don't fail workflow execution if buffering fails
|
|
1031
|
+
log_debug(f"Failed to add event to buffer: {e}")
|
|
1032
|
+
|
|
1062
1033
|
# Broadcast to WebSocket if available (async context only)
|
|
1063
|
-
|
|
1034
|
+
# Include event_index for frontend reconnection support
|
|
1035
|
+
if websocket_handler:
|
|
1036
|
+
import asyncio
|
|
1037
|
+
|
|
1038
|
+
try:
|
|
1039
|
+
loop = asyncio.get_running_loop()
|
|
1040
|
+
if loop:
|
|
1041
|
+
# Pass event_index and run_id to websocket handler
|
|
1042
|
+
asyncio.create_task(
|
|
1043
|
+
websocket_handler.handle_event(event, event_index=event_index, run_id=buffer_run_id)
|
|
1044
|
+
)
|
|
1045
|
+
except RuntimeError:
|
|
1046
|
+
pass
|
|
1047
|
+
|
|
1048
|
+
# ALSO broadcast through websocket manager for reconnected clients
|
|
1049
|
+
# This ensures clients who reconnect after workflow started still receive events
|
|
1050
|
+
if buffer_run_id:
|
|
1051
|
+
try:
|
|
1052
|
+
import asyncio
|
|
1053
|
+
|
|
1054
|
+
from agno.os.managers import websocket_manager
|
|
1055
|
+
|
|
1056
|
+
loop = asyncio.get_running_loop()
|
|
1057
|
+
if loop:
|
|
1058
|
+
# Format the event for broadcast
|
|
1059
|
+
event_dict = event.model_dump() if hasattr(event, "model_dump") else event.to_dict()
|
|
1060
|
+
if event_index is not None:
|
|
1061
|
+
event_dict["event_index"] = event_index
|
|
1062
|
+
if "run_id" not in event_dict:
|
|
1063
|
+
event_dict["run_id"] = buffer_run_id
|
|
1064
|
+
|
|
1065
|
+
# Broadcast to registered websocket (if different from original)
|
|
1066
|
+
import json
|
|
1067
|
+
|
|
1068
|
+
from agno.utils.serialize import json_serializer
|
|
1069
|
+
|
|
1070
|
+
asyncio.create_task(
|
|
1071
|
+
websocket_manager.broadcast_to_run(
|
|
1072
|
+
buffer_run_id, json.dumps(event_dict, default=json_serializer)
|
|
1073
|
+
)
|
|
1074
|
+
)
|
|
1075
|
+
except Exception as e:
|
|
1076
|
+
log_debug(f"Failed to broadcast through manager: {e}")
|
|
1064
1077
|
|
|
1065
1078
|
return event
|
|
1066
1079
|
|
|
@@ -1755,6 +1768,17 @@ class Workflow:
|
|
|
1755
1768
|
)
|
|
1756
1769
|
yield self._handle_event(workflow_completed_event, workflow_run_response)
|
|
1757
1770
|
|
|
1771
|
+
# Mark run as completed in event buffer
|
|
1772
|
+
try:
|
|
1773
|
+
from agno.os.managers import event_buffer
|
|
1774
|
+
|
|
1775
|
+
event_buffer.set_run_completed(
|
|
1776
|
+
workflow_run_response.run_id, # type: ignore
|
|
1777
|
+
workflow_run_response.status or RunStatus.completed,
|
|
1778
|
+
)
|
|
1779
|
+
except Exception as e:
|
|
1780
|
+
log_debug(f"Failed to mark run as completed in buffer: {e}")
|
|
1781
|
+
|
|
1758
1782
|
# Stop timer on error
|
|
1759
1783
|
if workflow_run_response.metrics:
|
|
1760
1784
|
workflow_run_response.metrics.stop_timer()
|
|
@@ -2034,7 +2058,7 @@ class Workflow:
|
|
|
2034
2058
|
workflow_run_response: WorkflowRunOutput,
|
|
2035
2059
|
run_context: RunContext,
|
|
2036
2060
|
stream_events: bool = False,
|
|
2037
|
-
websocket_handler: Optional[WebSocketHandler] = None,
|
|
2061
|
+
websocket_handler: Optional["WebSocketHandler"] = None,
|
|
2038
2062
|
background_tasks: Optional[Any] = None,
|
|
2039
2063
|
**kwargs: Any,
|
|
2040
2064
|
) -> AsyncIterator[WorkflowRunOutputEvent]:
|
|
@@ -2347,6 +2371,17 @@ class Workflow:
|
|
|
2347
2371
|
)
|
|
2348
2372
|
yield self._handle_event(workflow_completed_event, workflow_run_response, websocket_handler=websocket_handler)
|
|
2349
2373
|
|
|
2374
|
+
# Mark run as completed in event buffer
|
|
2375
|
+
try:
|
|
2376
|
+
from agno.os.managers import event_buffer
|
|
2377
|
+
|
|
2378
|
+
event_buffer.set_run_completed(
|
|
2379
|
+
workflow_run_response.run_id, # type: ignore
|
|
2380
|
+
workflow_run_response.status or RunStatus.completed,
|
|
2381
|
+
)
|
|
2382
|
+
except Exception as e:
|
|
2383
|
+
log_debug(f"Failed to mark run as completed in buffer: {e}")
|
|
2384
|
+
|
|
2350
2385
|
# Stop timer on error
|
|
2351
2386
|
if workflow_run_response.metrics:
|
|
2352
2387
|
workflow_run_response.metrics.stop_timer()
|
|
@@ -2406,6 +2441,7 @@ class Workflow:
|
|
|
2406
2441
|
run_id=run_id,
|
|
2407
2442
|
input=input,
|
|
2408
2443
|
session_id=session_id,
|
|
2444
|
+
user_id=user_id,
|
|
2409
2445
|
workflow_id=self.id,
|
|
2410
2446
|
workflow_name=self.name,
|
|
2411
2447
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -2494,7 +2530,7 @@ class Workflow:
|
|
|
2494
2530
|
videos: Optional[List[Video]] = None,
|
|
2495
2531
|
files: Optional[List[File]] = None,
|
|
2496
2532
|
stream_events: bool = False,
|
|
2497
|
-
websocket_handler: Optional[WebSocketHandler] = None,
|
|
2533
|
+
websocket_handler: Optional["WebSocketHandler"] = None,
|
|
2498
2534
|
**kwargs: Any,
|
|
2499
2535
|
) -> WorkflowRunOutput:
|
|
2500
2536
|
"""Execute workflow in background with streaming and WebSocket broadcasting"""
|
|
@@ -2524,6 +2560,7 @@ class Workflow:
|
|
|
2524
2560
|
run_id=run_id,
|
|
2525
2561
|
input=input,
|
|
2526
2562
|
session_id=session_id,
|
|
2563
|
+
user_id=user_id,
|
|
2527
2564
|
workflow_id=self.id,
|
|
2528
2565
|
workflow_name=self.name,
|
|
2529
2566
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -2779,6 +2816,7 @@ class Workflow:
|
|
|
2779
2816
|
run_id=run_id,
|
|
2780
2817
|
input=execution_input.input,
|
|
2781
2818
|
session_id=session.session_id,
|
|
2819
|
+
user_id=session.user_id,
|
|
2782
2820
|
workflow_id=self.id,
|
|
2783
2821
|
workflow_name=self.name,
|
|
2784
2822
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -2960,6 +2998,7 @@ class Workflow:
|
|
|
2960
2998
|
run_id=run_id,
|
|
2961
2999
|
input=execution_input.input,
|
|
2962
3000
|
session_id=session.session_id,
|
|
3001
|
+
user_id=session.user_id,
|
|
2963
3002
|
workflow_id=self.id,
|
|
2964
3003
|
workflow_name=self.name,
|
|
2965
3004
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -3008,6 +3047,7 @@ class Workflow:
|
|
|
3008
3047
|
run_id=str(uuid4()),
|
|
3009
3048
|
input=execution_input.input,
|
|
3010
3049
|
session_id=session.session_id,
|
|
3050
|
+
user_id=session.user_id,
|
|
3011
3051
|
workflow_id=self.id,
|
|
3012
3052
|
workflow_name=self.name,
|
|
3013
3053
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -3020,7 +3060,7 @@ class Workflow:
|
|
|
3020
3060
|
session: WorkflowSession,
|
|
3021
3061
|
execution_input: WorkflowExecutionInput,
|
|
3022
3062
|
run_context: RunContext,
|
|
3023
|
-
websocket_handler: Optional[WebSocketHandler] = None,
|
|
3063
|
+
websocket_handler: Optional["WebSocketHandler"] = None,
|
|
3024
3064
|
stream: bool = False,
|
|
3025
3065
|
) -> None:
|
|
3026
3066
|
"""Initialize the workflow agent with async tools (but NOT context - that's passed per-run)"""
|
|
@@ -3056,7 +3096,7 @@ class Workflow:
|
|
|
3056
3096
|
run_context: RunContext,
|
|
3057
3097
|
execution_input: WorkflowExecutionInput,
|
|
3058
3098
|
stream: bool = False,
|
|
3059
|
-
websocket_handler: Optional[WebSocketHandler] = None,
|
|
3099
|
+
websocket_handler: Optional["WebSocketHandler"] = None,
|
|
3060
3100
|
**kwargs: Any,
|
|
3061
3101
|
):
|
|
3062
3102
|
"""
|
|
@@ -3117,7 +3157,7 @@ class Workflow:
|
|
|
3117
3157
|
execution_input: WorkflowExecutionInput,
|
|
3118
3158
|
run_context: RunContext,
|
|
3119
3159
|
stream: bool = False,
|
|
3120
|
-
websocket_handler: Optional[WebSocketHandler] = None,
|
|
3160
|
+
websocket_handler: Optional["WebSocketHandler"] = None,
|
|
3121
3161
|
**kwargs: Any,
|
|
3122
3162
|
) -> AsyncIterator[WorkflowRunOutputEvent]:
|
|
3123
3163
|
"""
|
|
@@ -3162,6 +3202,7 @@ class Workflow:
|
|
|
3162
3202
|
run_id=run_id,
|
|
3163
3203
|
input=execution_input.input,
|
|
3164
3204
|
session_id=session.session_id,
|
|
3205
|
+
user_id=session.user_id,
|
|
3165
3206
|
workflow_id=self.id,
|
|
3166
3207
|
workflow_name=self.name,
|
|
3167
3208
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -3360,6 +3401,7 @@ class Workflow:
|
|
|
3360
3401
|
run_id=run_id,
|
|
3361
3402
|
input=execution_input.input,
|
|
3362
3403
|
session_id=session.session_id,
|
|
3404
|
+
user_id=session.user_id,
|
|
3363
3405
|
workflow_id=self.id,
|
|
3364
3406
|
workflow_name=self.name,
|
|
3365
3407
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -3427,6 +3469,7 @@ class Workflow:
|
|
|
3427
3469
|
run_id=str(uuid4()),
|
|
3428
3470
|
input=execution_input.input,
|
|
3429
3471
|
session_id=session.session_id,
|
|
3472
|
+
user_id=session.user_id,
|
|
3430
3473
|
workflow_id=self.id,
|
|
3431
3474
|
workflow_name=self.name,
|
|
3432
3475
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -3512,7 +3555,10 @@ class Workflow:
|
|
|
3512
3555
|
run_id = run_id or str(uuid4())
|
|
3513
3556
|
register_run(run_id)
|
|
3514
3557
|
|
|
3515
|
-
input
|
|
3558
|
+
if input is None and self.input_schema is not None:
|
|
3559
|
+
raise ValueError("Input is required when input_schema is provided")
|
|
3560
|
+
if input is not None and self.input_schema is not None:
|
|
3561
|
+
input = validate_input(input, self.input_schema)
|
|
3516
3562
|
if background:
|
|
3517
3563
|
raise RuntimeError("Background execution is not supported for sync run()")
|
|
3518
3564
|
|
|
@@ -3591,6 +3637,7 @@ class Workflow:
|
|
|
3591
3637
|
run_id=run_id,
|
|
3592
3638
|
input=input,
|
|
3593
3639
|
session_id=session_id,
|
|
3640
|
+
user_id=user_id,
|
|
3594
3641
|
workflow_id=self.id,
|
|
3595
3642
|
workflow_name=self.name,
|
|
3596
3643
|
created_at=int(datetime.now().timestamp()),
|
|
@@ -3684,11 +3731,14 @@ class Workflow:
|
|
|
3684
3731
|
) -> Union[WorkflowRunOutput, AsyncIterator[WorkflowRunOutputEvent]]:
|
|
3685
3732
|
"""Execute the workflow synchronously with optional streaming"""
|
|
3686
3733
|
|
|
3687
|
-
input
|
|
3734
|
+
if input is None and self.input_schema is not None:
|
|
3735
|
+
raise ValueError("Input is required when input_schema is provided")
|
|
3736
|
+
if input is not None and self.input_schema is not None:
|
|
3737
|
+
input = validate_input(input, self.input_schema)
|
|
3688
3738
|
|
|
3689
3739
|
websocket_handler = None
|
|
3690
3740
|
if websocket:
|
|
3691
|
-
from agno.
|
|
3741
|
+
from agno.os.managers import WebSocketHandler
|
|
3692
3742
|
|
|
3693
3743
|
websocket_handler = WebSocketHandler(websocket=websocket)
|
|
3694
3744
|
|
|
@@ -3798,6 +3848,7 @@ class Workflow:
|
|
|
3798
3848
|
run_id=run_id,
|
|
3799
3849
|
input=input,
|
|
3800
3850
|
session_id=session_id,
|
|
3851
|
+
user_id=user_id,
|
|
3801
3852
|
workflow_id=self.id,
|
|
3802
3853
|
workflow_name=self.name,
|
|
3803
3854
|
created_at=int(datetime.now().timestamp()),
|