agno 2.2.5__py3-none-any.whl → 2.2.7__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 +500 -423
- agno/api/os.py +1 -1
- agno/culture/manager.py +12 -8
- agno/guardrails/prompt_injection.py +1 -0
- agno/knowledge/chunking/agentic.py +6 -2
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/knowledge.py +37 -5
- agno/memory/manager.py +9 -4
- agno/models/anthropic/claude.py +1 -2
- agno/models/azure/ai_foundry.py +31 -14
- agno/models/azure/openai_chat.py +12 -4
- agno/models/base.py +106 -65
- agno/models/cerebras/cerebras.py +11 -6
- agno/models/groq/groq.py +7 -4
- agno/models/meta/llama.py +12 -6
- agno/models/meta/llama_openai.py +5 -1
- agno/models/openai/chat.py +26 -17
- agno/models/openai/responses.py +11 -63
- agno/models/requesty/requesty.py +5 -2
- agno/models/utils.py +254 -8
- agno/models/vertexai/claude.py +9 -13
- agno/os/app.py +13 -12
- agno/os/routers/evals/evals.py +8 -8
- agno/os/routers/evals/utils.py +1 -0
- agno/os/schema.py +56 -38
- agno/os/utils.py +27 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +5 -0
- agno/run/base.py +18 -1
- agno/run/team.py +13 -9
- agno/run/workflow.py +39 -0
- agno/session/summary.py +8 -2
- agno/session/workflow.py +4 -3
- agno/team/team.py +302 -369
- agno/tools/exa.py +21 -16
- agno/tools/file.py +153 -25
- agno/tools/function.py +98 -17
- agno/tools/mcp/mcp.py +8 -1
- agno/tools/notion.py +204 -0
- agno/utils/agent.py +78 -0
- agno/utils/events.py +2 -0
- agno/utils/hooks.py +1 -1
- agno/utils/models/claude.py +25 -8
- agno/utils/print_response/workflow.py +115 -16
- agno/vectordb/__init__.py +2 -1
- agno/vectordb/milvus/milvus.py +5 -0
- agno/vectordb/redis/__init__.py +5 -0
- agno/vectordb/redis/redisdb.py +687 -0
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/step.py +13 -2
- agno/workflow/workflow.py +969 -72
- {agno-2.2.5.dist-info → agno-2.2.7.dist-info}/METADATA +10 -3
- {agno-2.2.5.dist-info → agno-2.2.7.dist-info}/RECORD +57 -52
- {agno-2.2.5.dist-info → agno-2.2.7.dist-info}/WHEEL +0 -0
- {agno-2.2.5.dist-info → agno-2.2.7.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.5.dist-info → agno-2.2.7.dist-info}/top_level.txt +0 -0
agno/os/schema.py
CHANGED
|
@@ -13,14 +13,18 @@ from agno.os.utils import (
|
|
|
13
13
|
extract_input_media,
|
|
14
14
|
format_team_tools,
|
|
15
15
|
format_tools,
|
|
16
|
+
get_agent_input_schema_dict,
|
|
16
17
|
get_run_input,
|
|
17
18
|
get_session_name,
|
|
19
|
+
get_team_input_schema_dict,
|
|
18
20
|
get_workflow_input_schema_dict,
|
|
19
21
|
)
|
|
22
|
+
from agno.run import RunContext
|
|
20
23
|
from agno.run.agent import RunOutput
|
|
21
24
|
from agno.run.team import TeamRunOutput
|
|
22
25
|
from agno.session import AgentSession, TeamSession, WorkflowSession
|
|
23
26
|
from agno.team.team import Team
|
|
27
|
+
from agno.workflow.agent import WorkflowAgent
|
|
24
28
|
from agno.workflow.workflow import Workflow
|
|
25
29
|
|
|
26
30
|
|
|
@@ -166,21 +170,22 @@ class ModelResponse(BaseModel):
|
|
|
166
170
|
|
|
167
171
|
|
|
168
172
|
class AgentResponse(BaseModel):
|
|
169
|
-
id: Optional[str] =
|
|
170
|
-
name: Optional[str] =
|
|
171
|
-
db_id: Optional[str] =
|
|
172
|
-
model: Optional[ModelResponse] =
|
|
173
|
-
tools: Optional[Dict[str, Any]] =
|
|
174
|
-
sessions: Optional[Dict[str, Any]] =
|
|
175
|
-
knowledge: Optional[Dict[str, Any]] =
|
|
176
|
-
memory: Optional[Dict[str, Any]] =
|
|
177
|
-
reasoning: Optional[Dict[str, Any]] =
|
|
178
|
-
default_tools: Optional[Dict[str, Any]] =
|
|
179
|
-
system_message: Optional[Dict[str, Any]] =
|
|
180
|
-
extra_messages: Optional[Dict[str, Any]] =
|
|
181
|
-
response_settings: Optional[Dict[str, Any]] =
|
|
182
|
-
streaming: Optional[Dict[str, Any]] =
|
|
183
|
-
metadata: Optional[Dict[str, Any]] =
|
|
173
|
+
id: Optional[str] = None
|
|
174
|
+
name: Optional[str] = None
|
|
175
|
+
db_id: Optional[str] = None
|
|
176
|
+
model: Optional[ModelResponse] = None
|
|
177
|
+
tools: Optional[Dict[str, Any]] = None
|
|
178
|
+
sessions: Optional[Dict[str, Any]] = None
|
|
179
|
+
knowledge: Optional[Dict[str, Any]] = None
|
|
180
|
+
memory: Optional[Dict[str, Any]] = None
|
|
181
|
+
reasoning: Optional[Dict[str, Any]] = None
|
|
182
|
+
default_tools: Optional[Dict[str, Any]] = None
|
|
183
|
+
system_message: Optional[Dict[str, Any]] = None
|
|
184
|
+
extra_messages: Optional[Dict[str, Any]] = None
|
|
185
|
+
response_settings: Optional[Dict[str, Any]] = None
|
|
186
|
+
streaming: Optional[Dict[str, Any]] = None
|
|
187
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
188
|
+
input_schema: Optional[Dict[str, Any]] = None
|
|
184
189
|
|
|
185
190
|
@classmethod
|
|
186
191
|
async def from_agent(cls, agent: Agent) -> "AgentResponse":
|
|
@@ -243,9 +248,12 @@ class AgentResponse(BaseModel):
|
|
|
243
248
|
"stream_intermediate_steps": False,
|
|
244
249
|
}
|
|
245
250
|
|
|
251
|
+
session_id = str(uuid4())
|
|
252
|
+
run_id = str(uuid4())
|
|
246
253
|
agent_tools = await agent.aget_tools(
|
|
247
|
-
session=AgentSession(session_id=
|
|
248
|
-
run_response=RunOutput(run_id=
|
|
254
|
+
session=AgentSession(session_id=session_id, session_data={}),
|
|
255
|
+
run_response=RunOutput(run_id=run_id, session_id=session_id),
|
|
256
|
+
run_context=RunContext(run_id=run_id, session_id=session_id, user_id=agent.user_id),
|
|
249
257
|
check_mcp_tools=False,
|
|
250
258
|
)
|
|
251
259
|
formatted_tools = format_tools(agent_tools) if agent_tools else None
|
|
@@ -375,6 +383,7 @@ class AgentResponse(BaseModel):
|
|
|
375
383
|
"stream_events": agent.stream_events,
|
|
376
384
|
"stream_intermediate_steps": agent.stream_intermediate_steps,
|
|
377
385
|
}
|
|
386
|
+
|
|
378
387
|
return AgentResponse(
|
|
379
388
|
id=agent.id,
|
|
380
389
|
name=agent.name,
|
|
@@ -391,28 +400,28 @@ class AgentResponse(BaseModel):
|
|
|
391
400
|
response_settings=filter_meaningful_config(response_settings_info, agent_defaults),
|
|
392
401
|
streaming=filter_meaningful_config(streaming_info, agent_defaults),
|
|
393
402
|
metadata=agent.metadata,
|
|
403
|
+
input_schema=get_agent_input_schema_dict(agent),
|
|
394
404
|
)
|
|
395
405
|
|
|
396
406
|
|
|
397
407
|
class TeamResponse(BaseModel):
|
|
398
|
-
id: Optional[str] =
|
|
399
|
-
name: Optional[str] =
|
|
400
|
-
db_id: Optional[str] =
|
|
401
|
-
description: Optional[str] =
|
|
402
|
-
model: Optional[ModelResponse] =
|
|
403
|
-
tools: Optional[Dict[str, Any]] =
|
|
404
|
-
sessions: Optional[Dict[str, Any]] =
|
|
405
|
-
knowledge: Optional[Dict[str, Any]] =
|
|
406
|
-
memory: Optional[Dict[str, Any]] =
|
|
407
|
-
reasoning: Optional[Dict[str, Any]] =
|
|
408
|
-
default_tools: Optional[Dict[str, Any]] =
|
|
409
|
-
system_message: Optional[Dict[str, Any]] =
|
|
410
|
-
response_settings: Optional[Dict[str, Any]] =
|
|
411
|
-
streaming: Optional[Dict[str, Any]] =
|
|
412
|
-
members: Optional[List[Union[AgentResponse, "TeamResponse"]]] =
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
metadata: Optional[Dict[str, Any]] = Field(None, description="Additional metadata")
|
|
408
|
+
id: Optional[str] = None
|
|
409
|
+
name: Optional[str] = None
|
|
410
|
+
db_id: Optional[str] = None
|
|
411
|
+
description: Optional[str] = None
|
|
412
|
+
model: Optional[ModelResponse] = None
|
|
413
|
+
tools: Optional[Dict[str, Any]] = None
|
|
414
|
+
sessions: Optional[Dict[str, Any]] = None
|
|
415
|
+
knowledge: Optional[Dict[str, Any]] = None
|
|
416
|
+
memory: Optional[Dict[str, Any]] = None
|
|
417
|
+
reasoning: Optional[Dict[str, Any]] = None
|
|
418
|
+
default_tools: Optional[Dict[str, Any]] = None
|
|
419
|
+
system_message: Optional[Dict[str, Any]] = None
|
|
420
|
+
response_settings: Optional[Dict[str, Any]] = None
|
|
421
|
+
streaming: Optional[Dict[str, Any]] = None
|
|
422
|
+
members: Optional[List[Union[AgentResponse, "TeamResponse"]]] = None
|
|
423
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
424
|
+
input_schema: Optional[Dict[str, Any]] = None
|
|
416
425
|
|
|
417
426
|
@classmethod
|
|
418
427
|
async def from_team(cls, team: Team) -> "TeamResponse":
|
|
@@ -466,12 +475,14 @@ class TeamResponse(BaseModel):
|
|
|
466
475
|
"stream_member_events": False,
|
|
467
476
|
}
|
|
468
477
|
|
|
478
|
+
run_id = str(uuid4())
|
|
479
|
+
session_id = str(uuid4())
|
|
469
480
|
_tools = team._determine_tools_for_model(
|
|
470
481
|
model=team.model, # type: ignore
|
|
471
|
-
session=TeamSession(session_id=
|
|
472
|
-
run_response=TeamRunOutput(run_id=
|
|
482
|
+
session=TeamSession(session_id=session_id, session_data={}),
|
|
483
|
+
run_response=TeamRunOutput(run_id=run_id),
|
|
484
|
+
run_context=RunContext(run_id=run_id, session_id=session_id, session_state={}),
|
|
473
485
|
async_mode=True,
|
|
474
|
-
session_state={},
|
|
475
486
|
team_run_context={},
|
|
476
487
|
check_mcp_tools=False,
|
|
477
488
|
)
|
|
@@ -621,6 +632,7 @@ class TeamResponse(BaseModel):
|
|
|
621
632
|
streaming=filter_meaningful_config(streaming_info, team_defaults),
|
|
622
633
|
members=members if members else None,
|
|
623
634
|
metadata=team.metadata,
|
|
635
|
+
input_schema=get_team_input_schema_dict(team),
|
|
624
636
|
)
|
|
625
637
|
|
|
626
638
|
|
|
@@ -634,6 +646,7 @@ class WorkflowResponse(BaseModel):
|
|
|
634
646
|
agent: Optional[AgentResponse] = Field(None, description="Agent configuration if used")
|
|
635
647
|
team: Optional[TeamResponse] = Field(None, description="Team configuration if used")
|
|
636
648
|
metadata: Optional[Dict[str, Any]] = Field(None, description="Additional metadata")
|
|
649
|
+
workflow_agent: bool = Field(False, description="Whether this workflow uses a WorkflowAgent")
|
|
637
650
|
|
|
638
651
|
@classmethod
|
|
639
652
|
async def _resolve_agents_and_teams_recursively(cls, steps: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
@@ -685,6 +698,7 @@ class WorkflowResponse(BaseModel):
|
|
|
685
698
|
steps=steps,
|
|
686
699
|
input_schema=get_workflow_input_schema_dict(workflow),
|
|
687
700
|
metadata=workflow.metadata,
|
|
701
|
+
workflow_agent=isinstance(workflow.agent, WorkflowAgent) if workflow.agent else False,
|
|
688
702
|
)
|
|
689
703
|
|
|
690
704
|
|
|
@@ -870,6 +884,7 @@ class RunSchema(BaseModel):
|
|
|
870
884
|
created_at: Optional[datetime] = Field(None, description="Run creation timestamp")
|
|
871
885
|
references: Optional[List[dict]] = Field(None, description="References cited in the run")
|
|
872
886
|
reasoning_messages: Optional[List[dict]] = Field(None, description="Reasoning process messages")
|
|
887
|
+
session_state: Optional[dict] = Field(None, description="Session state at the end of the run")
|
|
873
888
|
images: Optional[List[dict]] = Field(None, description="Images included in the run")
|
|
874
889
|
videos: Optional[List[dict]] = Field(None, description="Videos included in the run")
|
|
875
890
|
audio: Optional[List[dict]] = Field(None, description="Audio files included in the run")
|
|
@@ -897,6 +912,7 @@ class RunSchema(BaseModel):
|
|
|
897
912
|
events=[event for event in run_dict["events"]] if run_dict.get("events") else None,
|
|
898
913
|
references=run_dict.get("references", []),
|
|
899
914
|
reasoning_messages=run_dict.get("reasoning_messages", []),
|
|
915
|
+
session_state=run_dict.get("session_state"),
|
|
900
916
|
images=run_dict.get("images", []),
|
|
901
917
|
videos=run_dict.get("videos", []),
|
|
902
918
|
audio=run_dict.get("audio", []),
|
|
@@ -925,6 +941,7 @@ class TeamRunSchema(BaseModel):
|
|
|
925
941
|
created_at: Optional[datetime] = Field(None, description="Run creation timestamp")
|
|
926
942
|
references: Optional[List[dict]] = Field(None, description="References cited in the run")
|
|
927
943
|
reasoning_messages: Optional[List[dict]] = Field(None, description="Reasoning process messages")
|
|
944
|
+
session_state: Optional[dict] = Field(None, description="Session state at the end of the run")
|
|
928
945
|
input_media: Optional[Dict[str, Any]] = Field(None, description="Input media attachments")
|
|
929
946
|
images: Optional[List[dict]] = Field(None, description="Images included in the run")
|
|
930
947
|
videos: Optional[List[dict]] = Field(None, description="Videos included in the run")
|
|
@@ -954,6 +971,7 @@ class TeamRunSchema(BaseModel):
|
|
|
954
971
|
else None,
|
|
955
972
|
references=run_dict.get("references", []),
|
|
956
973
|
reasoning_messages=run_dict.get("reasoning_messages", []),
|
|
974
|
+
session_state=run_dict.get("session_state"),
|
|
957
975
|
images=run_dict.get("images", []),
|
|
958
976
|
videos=run_dict.get("videos", []),
|
|
959
977
|
audio=run_dict.get("audio", []),
|
agno/os/utils.py
CHANGED
|
@@ -274,6 +274,33 @@ def get_workflow_by_id(workflow_id: str, workflows: Optional[List[Workflow]] = N
|
|
|
274
274
|
return None
|
|
275
275
|
|
|
276
276
|
|
|
277
|
+
# INPUT SCHEMA VALIDATIONS
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def get_agent_input_schema_dict(agent: Agent) -> Optional[Dict[str, Any]]:
|
|
281
|
+
"""Get input schema as dictionary for API responses"""
|
|
282
|
+
|
|
283
|
+
if agent.input_schema is not None:
|
|
284
|
+
try:
|
|
285
|
+
return agent.input_schema.model_json_schema()
|
|
286
|
+
except Exception:
|
|
287
|
+
return None
|
|
288
|
+
|
|
289
|
+
return None
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def get_team_input_schema_dict(team: Team) -> Optional[Dict[str, Any]]:
|
|
293
|
+
"""Get input schema as dictionary for API responses"""
|
|
294
|
+
|
|
295
|
+
if team.input_schema is not None:
|
|
296
|
+
try:
|
|
297
|
+
return team.input_schema.model_json_schema()
|
|
298
|
+
except Exception:
|
|
299
|
+
return None
|
|
300
|
+
|
|
301
|
+
return None
|
|
302
|
+
|
|
303
|
+
|
|
277
304
|
def get_workflow_input_schema_dict(workflow: Workflow) -> Optional[Dict[str, Any]]:
|
|
278
305
|
"""Get input schema as dictionary for API responses"""
|
|
279
306
|
|
agno/run/__init__.py
CHANGED
agno/run/agent.py
CHANGED
|
@@ -221,6 +221,9 @@ class RunContentEvent(BaseAgentRunEvent):
|
|
|
221
221
|
|
|
222
222
|
event: str = RunEvent.run_content.value
|
|
223
223
|
content: Optional[Any] = None
|
|
224
|
+
workflow_agent: bool = (
|
|
225
|
+
False # Used by consumers of the events to distinguish between workflow agent and regular agent
|
|
226
|
+
)
|
|
224
227
|
content_type: str = "str"
|
|
225
228
|
reasoning_content: Optional[str] = None
|
|
226
229
|
model_provider_data: Optional[Dict[str, Any]] = None
|
|
@@ -263,6 +266,7 @@ class RunCompletedEvent(BaseAgentRunEvent):
|
|
|
263
266
|
reasoning_messages: Optional[List[Message]] = None
|
|
264
267
|
metadata: Optional[Dict[str, Any]] = None
|
|
265
268
|
metrics: Optional[Metrics] = None
|
|
269
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
266
270
|
|
|
267
271
|
|
|
268
272
|
@dataclass
|
|
@@ -527,6 +531,7 @@ class RunOutput:
|
|
|
527
531
|
references: Optional[List[MessageReferences]] = None
|
|
528
532
|
|
|
529
533
|
metadata: Optional[Dict[str, Any]] = None
|
|
534
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
530
535
|
|
|
531
536
|
created_at: int = field(default_factory=lambda: int(time()))
|
|
532
537
|
|
agno/run/base.py
CHANGED
|
@@ -7,11 +7,22 @@ from pydantic import BaseModel
|
|
|
7
7
|
from agno.media import Audio, Image, Video
|
|
8
8
|
from agno.models.message import Citations, Message, MessageReferences
|
|
9
9
|
from agno.models.metrics import Metrics
|
|
10
|
-
from agno.models.response import ToolExecution
|
|
11
10
|
from agno.reasoning.step import ReasoningStep
|
|
12
11
|
from agno.utils.log import log_error
|
|
13
12
|
|
|
14
13
|
|
|
14
|
+
@dataclass
|
|
15
|
+
class RunContext:
|
|
16
|
+
run_id: str
|
|
17
|
+
session_id: str
|
|
18
|
+
user_id: Optional[str] = None
|
|
19
|
+
|
|
20
|
+
dependencies: Optional[Dict[str, Any]] = None
|
|
21
|
+
knowledge_filters: Optional[Dict[str, Any]] = None
|
|
22
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
23
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
24
|
+
|
|
25
|
+
|
|
15
26
|
@dataclass
|
|
16
27
|
class BaseRunOutputEvent:
|
|
17
28
|
def to_dict(self) -> Dict[str, Any]:
|
|
@@ -98,6 +109,8 @@ class BaseRunOutputEvent:
|
|
|
98
109
|
_dict["content"] = self.content.model_dump(exclude_none=True)
|
|
99
110
|
|
|
100
111
|
if hasattr(self, "tools") and self.tools is not None:
|
|
112
|
+
from agno.models.response import ToolExecution
|
|
113
|
+
|
|
101
114
|
_dict["tools"] = []
|
|
102
115
|
for tool in self.tools:
|
|
103
116
|
if isinstance(tool, ToolExecution):
|
|
@@ -106,6 +119,8 @@ class BaseRunOutputEvent:
|
|
|
106
119
|
_dict["tools"].append(tool)
|
|
107
120
|
|
|
108
121
|
if hasattr(self, "tool") and self.tool is not None:
|
|
122
|
+
from agno.models.response import ToolExecution
|
|
123
|
+
|
|
109
124
|
if isinstance(self.tool, ToolExecution):
|
|
110
125
|
_dict["tool"] = self.tool.to_dict()
|
|
111
126
|
else:
|
|
@@ -139,6 +154,8 @@ class BaseRunOutputEvent:
|
|
|
139
154
|
def from_dict(cls, data: Dict[str, Any]):
|
|
140
155
|
tool = data.pop("tool", None)
|
|
141
156
|
if tool:
|
|
157
|
+
from agno.models.response import ToolExecution
|
|
158
|
+
|
|
142
159
|
data["tool"] = ToolExecution.from_dict(tool)
|
|
143
160
|
|
|
144
161
|
images = data.pop("images", None)
|
agno/run/team.py
CHANGED
|
@@ -261,6 +261,7 @@ class RunCompletedEvent(BaseTeamRunEvent):
|
|
|
261
261
|
member_responses: List[Union["TeamRunOutput", RunOutput]] = field(default_factory=list)
|
|
262
262
|
metadata: Optional[Dict[str, Any]] = None
|
|
263
263
|
metrics: Optional[Metrics] = None
|
|
264
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
264
265
|
|
|
265
266
|
|
|
266
267
|
@dataclass
|
|
@@ -468,8 +469,19 @@ def team_run_output_event_from_dict(data: dict) -> BaseTeamRunEvent:
|
|
|
468
469
|
class TeamRunOutput:
|
|
469
470
|
"""Response returned by Team.run() functions"""
|
|
470
471
|
|
|
472
|
+
run_id: Optional[str] = None
|
|
473
|
+
team_id: Optional[str] = None
|
|
474
|
+
team_name: Optional[str] = None
|
|
475
|
+
session_id: Optional[str] = None
|
|
476
|
+
parent_run_id: Optional[str] = None
|
|
477
|
+
user_id: Optional[str] = None
|
|
478
|
+
|
|
479
|
+
# Input media and messages from user
|
|
480
|
+
input: Optional[TeamRunInput] = None
|
|
481
|
+
|
|
471
482
|
content: Optional[Any] = None
|
|
472
483
|
content_type: str = "str"
|
|
484
|
+
|
|
473
485
|
messages: Optional[List[Message]] = None
|
|
474
486
|
metrics: Optional[Metrics] = None
|
|
475
487
|
model: Optional[str] = None
|
|
@@ -477,12 +489,6 @@ class TeamRunOutput:
|
|
|
477
489
|
|
|
478
490
|
member_responses: List[Union["TeamRunOutput", RunOutput]] = field(default_factory=list)
|
|
479
491
|
|
|
480
|
-
run_id: Optional[str] = None
|
|
481
|
-
team_id: Optional[str] = None
|
|
482
|
-
team_name: Optional[str] = None
|
|
483
|
-
session_id: Optional[str] = None
|
|
484
|
-
parent_run_id: Optional[str] = None
|
|
485
|
-
|
|
486
492
|
tools: Optional[List[ToolExecution]] = None
|
|
487
493
|
|
|
488
494
|
images: Optional[List[Image]] = None # Images from member runs
|
|
@@ -492,14 +498,12 @@ class TeamRunOutput:
|
|
|
492
498
|
|
|
493
499
|
response_audio: Optional[Audio] = None # Model audio response
|
|
494
500
|
|
|
495
|
-
# Input media and messages from user
|
|
496
|
-
input: Optional[TeamRunInput] = None
|
|
497
|
-
|
|
498
501
|
reasoning_content: Optional[str] = None
|
|
499
502
|
|
|
500
503
|
citations: Optional[Citations] = None
|
|
501
504
|
model_provider_data: Optional[Dict[str, Any]] = None
|
|
502
505
|
metadata: Optional[Dict[str, Any]] = None
|
|
506
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
503
507
|
|
|
504
508
|
references: Optional[List[MessageReferences]] = None
|
|
505
509
|
additional_input: Optional[List[Message]] = None
|
agno/run/workflow.py
CHANGED
|
@@ -31,6 +31,9 @@ class WorkflowRunEvent(str, Enum):
|
|
|
31
31
|
workflow_cancelled = "WorkflowCancelled"
|
|
32
32
|
workflow_error = "WorkflowError"
|
|
33
33
|
|
|
34
|
+
workflow_agent_started = "WorkflowAgentStarted"
|
|
35
|
+
workflow_agent_completed = "WorkflowAgentCompleted"
|
|
36
|
+
|
|
34
37
|
step_started = "StepStarted"
|
|
35
38
|
step_completed = "StepCompleted"
|
|
36
39
|
step_error = "StepError"
|
|
@@ -126,6 +129,21 @@ class WorkflowStartedEvent(BaseWorkflowRunOutputEvent):
|
|
|
126
129
|
event: str = WorkflowRunEvent.workflow_started.value
|
|
127
130
|
|
|
128
131
|
|
|
132
|
+
@dataclass
|
|
133
|
+
class WorkflowAgentStartedEvent(BaseWorkflowRunOutputEvent):
|
|
134
|
+
"""Event sent when workflow agent starts (before deciding to run workflow or answer directly)"""
|
|
135
|
+
|
|
136
|
+
event: str = WorkflowRunEvent.workflow_agent_started.value
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass
|
|
140
|
+
class WorkflowAgentCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
141
|
+
"""Event sent when workflow agent completes (after running workflow or answering directly)"""
|
|
142
|
+
|
|
143
|
+
event: str = WorkflowRunEvent.workflow_agent_completed.value
|
|
144
|
+
content: Optional[Any] = None
|
|
145
|
+
|
|
146
|
+
|
|
129
147
|
@dataclass
|
|
130
148
|
class WorkflowCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
131
149
|
"""Event sent when workflow execution completes"""
|
|
@@ -403,6 +421,8 @@ class CustomEvent(BaseWorkflowRunOutputEvent):
|
|
|
403
421
|
# Union type for all workflow run response events
|
|
404
422
|
WorkflowRunOutputEvent = Union[
|
|
405
423
|
WorkflowStartedEvent,
|
|
424
|
+
WorkflowAgentStartedEvent,
|
|
425
|
+
WorkflowAgentCompletedEvent,
|
|
406
426
|
WorkflowCompletedEvent,
|
|
407
427
|
WorkflowErrorEvent,
|
|
408
428
|
WorkflowCancelledEvent,
|
|
@@ -428,6 +448,8 @@ WorkflowRunOutputEvent = Union[
|
|
|
428
448
|
# Map event string to dataclass for workflow events
|
|
429
449
|
WORKFLOW_RUN_EVENT_TYPE_REGISTRY = {
|
|
430
450
|
WorkflowRunEvent.workflow_started.value: WorkflowStartedEvent,
|
|
451
|
+
WorkflowRunEvent.workflow_agent_started.value: WorkflowAgentStartedEvent,
|
|
452
|
+
WorkflowRunEvent.workflow_agent_completed.value: WorkflowAgentCompletedEvent,
|
|
431
453
|
WorkflowRunEvent.workflow_completed.value: WorkflowCompletedEvent,
|
|
432
454
|
WorkflowRunEvent.workflow_cancelled.value: WorkflowCancelledEvent,
|
|
433
455
|
WorkflowRunEvent.workflow_error.value: WorkflowErrorEvent,
|
|
@@ -491,6 +513,10 @@ class WorkflowRunOutput:
|
|
|
491
513
|
# Store agent/team responses separately with parent_run_id references
|
|
492
514
|
step_executor_runs: Optional[List[Union[RunOutput, TeamRunOutput]]] = None
|
|
493
515
|
|
|
516
|
+
# Workflow agent run - stores the full agent RunOutput when workflow agent is used
|
|
517
|
+
# The agent's parent_run_id will point to this workflow run's run_id to establish the relationship
|
|
518
|
+
workflow_agent_run: Optional[RunOutput] = None
|
|
519
|
+
|
|
494
520
|
# Store events from workflow execution
|
|
495
521
|
events: Optional[List[WorkflowRunOutputEvent]] = None
|
|
496
522
|
|
|
@@ -522,6 +548,7 @@ class WorkflowRunOutput:
|
|
|
522
548
|
"step_executor_runs",
|
|
523
549
|
"events",
|
|
524
550
|
"metrics",
|
|
551
|
+
"workflow_agent_run",
|
|
525
552
|
]
|
|
526
553
|
}
|
|
527
554
|
|
|
@@ -557,6 +584,9 @@ class WorkflowRunOutput:
|
|
|
557
584
|
if self.step_executor_runs:
|
|
558
585
|
_dict["step_executor_runs"] = [run.to_dict() for run in self.step_executor_runs]
|
|
559
586
|
|
|
587
|
+
if self.workflow_agent_run is not None:
|
|
588
|
+
_dict["workflow_agent_run"] = self.workflow_agent_run.to_dict()
|
|
589
|
+
|
|
560
590
|
if self.metrics is not None:
|
|
561
591
|
_dict["metrics"] = self.metrics.to_dict()
|
|
562
592
|
|
|
@@ -604,6 +634,14 @@ class WorkflowRunOutput:
|
|
|
604
634
|
else:
|
|
605
635
|
step_executor_runs.append(RunOutput.from_dict(run_data))
|
|
606
636
|
|
|
637
|
+
workflow_agent_run_data = data.pop("workflow_agent_run", None)
|
|
638
|
+
workflow_agent_run = None
|
|
639
|
+
if workflow_agent_run_data:
|
|
640
|
+
if isinstance(workflow_agent_run_data, dict):
|
|
641
|
+
workflow_agent_run = RunOutput.from_dict(workflow_agent_run_data)
|
|
642
|
+
elif isinstance(workflow_agent_run_data, RunOutput):
|
|
643
|
+
workflow_agent_run = workflow_agent_run_data
|
|
644
|
+
|
|
607
645
|
metadata = data.pop("metadata", None)
|
|
608
646
|
|
|
609
647
|
images = reconstruct_images(data.pop("images", []))
|
|
@@ -640,6 +678,7 @@ class WorkflowRunOutput:
|
|
|
640
678
|
|
|
641
679
|
return cls(
|
|
642
680
|
step_results=parsed_step_results,
|
|
681
|
+
workflow_agent_run=workflow_agent_run,
|
|
643
682
|
metadata=metadata,
|
|
644
683
|
images=images,
|
|
645
684
|
videos=videos,
|
agno/session/summary.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
from textwrap import dedent
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
8
|
from agno.models.base import Model
|
|
9
|
+
from agno.models.utils import get_model
|
|
9
10
|
from agno.run.agent import Message
|
|
10
11
|
from agno.utils.log import log_debug, log_warning
|
|
11
12
|
|
|
@@ -142,7 +143,10 @@ class SessionSummaryManager:
|
|
|
142
143
|
if not session:
|
|
143
144
|
return None
|
|
144
145
|
|
|
145
|
-
self.model =
|
|
146
|
+
self.model = get_model(self.model)
|
|
147
|
+
if self.model is None:
|
|
148
|
+
return None
|
|
149
|
+
|
|
146
150
|
response_format = self.get_response_format(self.model)
|
|
147
151
|
|
|
148
152
|
system_message = self.get_system_message(
|
|
@@ -210,6 +214,7 @@ class SessionSummaryManager:
|
|
|
210
214
|
) -> Optional[SessionSummary]:
|
|
211
215
|
"""Creates a summary of the session"""
|
|
212
216
|
log_debug("Creating session summary", center=True)
|
|
217
|
+
self.model = get_model(self.model)
|
|
213
218
|
if self.model is None:
|
|
214
219
|
return None
|
|
215
220
|
|
|
@@ -237,6 +242,7 @@ class SessionSummaryManager:
|
|
|
237
242
|
) -> Optional[SessionSummary]:
|
|
238
243
|
"""Creates a summary of the session"""
|
|
239
244
|
log_debug("Creating session summary", center=True)
|
|
245
|
+
self.model = get_model(self.model)
|
|
240
246
|
if self.model is None:
|
|
241
247
|
return None
|
|
242
248
|
|
agno/session/workflow.py
CHANGED
|
@@ -129,12 +129,12 @@ class WorkflowSession:
|
|
|
129
129
|
context_parts = ["<workflow_history_context>"]
|
|
130
130
|
|
|
131
131
|
for i, (input_str, response_str) in enumerate(history_data, 1):
|
|
132
|
-
context_parts.append(f"[
|
|
132
|
+
context_parts.append(f"[Workflow Run-{i}]")
|
|
133
133
|
|
|
134
134
|
if input_str:
|
|
135
|
-
context_parts.append(f"input: {input_str}")
|
|
135
|
+
context_parts.append(f"User input: {input_str}")
|
|
136
136
|
if response_str:
|
|
137
|
-
context_parts.append(f"
|
|
137
|
+
context_parts.append(f"Workflow output: {response_str}")
|
|
138
138
|
|
|
139
139
|
context_parts.append("") # Empty line between runs
|
|
140
140
|
|
|
@@ -154,6 +154,7 @@ class WorkflowSession:
|
|
|
154
154
|
runs_data.append(run.to_dict())
|
|
155
155
|
except Exception as e:
|
|
156
156
|
raise ValueError(f"Serialization failed: {str(e)}")
|
|
157
|
+
|
|
157
158
|
return {
|
|
158
159
|
"session_id": self.session_id,
|
|
159
160
|
"user_id": self.user_id,
|