agno 2.0.3__py3-none-any.whl → 2.0.4__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 (43) hide show
  1. agno/agent/agent.py +162 -86
  2. agno/db/dynamo/dynamo.py +8 -0
  3. agno/db/firestore/firestore.py +8 -1
  4. agno/db/gcs_json/gcs_json_db.py +9 -0
  5. agno/db/json/json_db.py +8 -0
  6. agno/db/mongo/mongo.py +10 -1
  7. agno/db/mysql/mysql.py +10 -0
  8. agno/db/postgres/postgres.py +16 -8
  9. agno/db/redis/redis.py +6 -0
  10. agno/db/singlestore/schemas.py +1 -1
  11. agno/db/singlestore/singlestore.py +8 -1
  12. agno/db/sqlite/sqlite.py +9 -1
  13. agno/db/utils.py +14 -0
  14. agno/knowledge/knowledge.py +91 -65
  15. agno/models/base.py +2 -2
  16. agno/models/openai/chat.py +3 -0
  17. agno/models/openai/responses.py +6 -0
  18. agno/models/response.py +5 -0
  19. agno/models/siliconflow/__init__.py +5 -0
  20. agno/models/siliconflow/siliconflow.py +25 -0
  21. agno/os/app.py +4 -1
  22. agno/os/auth.py +24 -14
  23. agno/os/router.py +128 -55
  24. agno/os/routers/evals/utils.py +9 -9
  25. agno/os/routers/health.py +26 -0
  26. agno/os/routers/knowledge/knowledge.py +11 -11
  27. agno/os/routers/session/session.py +24 -8
  28. agno/os/schema.py +8 -2
  29. agno/run/workflow.py +64 -10
  30. agno/session/team.py +1 -0
  31. agno/team/team.py +192 -92
  32. agno/tools/mem0.py +11 -17
  33. agno/tools/memory.py +34 -6
  34. agno/utils/common.py +90 -1
  35. agno/utils/streamlit.py +14 -8
  36. agno/vectordb/chroma/chromadb.py +8 -2
  37. agno/workflow/step.py +111 -13
  38. agno/workflow/workflow.py +16 -13
  39. {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/METADATA +1 -1
  40. {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/RECORD +43 -40
  41. {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/WHEEL +0 -0
  42. {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/licenses/LICENSE +0 -0
  43. {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/top_level.txt +0 -0
agno/os/schema.py CHANGED
@@ -826,7 +826,8 @@ class WorkflowSessionDetailSchema(BaseModel):
826
826
 
827
827
  class RunSchema(BaseModel):
828
828
  run_id: str
829
- agent_session_id: Optional[str]
829
+ parent_run_id: Optional[str]
830
+ agent_id: Optional[str]
830
831
  user_id: Optional[str]
831
832
  run_input: Optional[str]
832
833
  content: Optional[Union[str, dict]]
@@ -844,7 +845,8 @@ class RunSchema(BaseModel):
844
845
  run_response_format = "text" if run_dict.get("content_type", "str") == "str" else "json"
845
846
  return cls(
846
847
  run_id=run_dict.get("run_id", ""),
847
- agent_session_id=run_dict.get("session_id", ""),
848
+ parent_run_id=run_dict.get("parent_run_id", ""),
849
+ agent_id=run_dict.get("agent_id", ""),
848
850
  user_id=run_dict.get("user_id", ""),
849
851
  run_input=run_input,
850
852
  content=run_dict.get("content", ""),
@@ -863,6 +865,7 @@ class RunSchema(BaseModel):
863
865
  class TeamRunSchema(BaseModel):
864
866
  run_id: str
865
867
  parent_run_id: Optional[str]
868
+ team_id: Optional[str]
866
869
  content: Optional[Union[str, dict]]
867
870
  reasoning_content: Optional[str]
868
871
  run_input: Optional[str]
@@ -880,6 +883,7 @@ class TeamRunSchema(BaseModel):
880
883
  return cls(
881
884
  run_id=run_dict.get("run_id", ""),
882
885
  parent_run_id=run_dict.get("parent_run_id", ""),
886
+ team_id=run_dict.get("team_id", ""),
883
887
  run_input=run_input,
884
888
  content=run_dict.get("content", ""),
885
889
  run_response_format=run_response_format,
@@ -897,6 +901,7 @@ class TeamRunSchema(BaseModel):
897
901
  class WorkflowRunSchema(BaseModel):
898
902
  run_id: str
899
903
  run_input: Optional[str]
904
+ workflow_id: Optional[str]
900
905
  user_id: Optional[str]
901
906
  content: Optional[Union[str, dict]]
902
907
  content_type: Optional[str]
@@ -912,6 +917,7 @@ class WorkflowRunSchema(BaseModel):
912
917
  return cls(
913
918
  run_id=run_response.get("run_id", ""),
914
919
  run_input=run_input,
920
+ workflow_id=run_response.get("workflow_id", ""),
915
921
  user_id=run_response.get("user_id", ""),
916
922
  content=run_response.get("content", ""),
917
923
  content_type=run_response.get("content_type", ""),
agno/run/workflow.py CHANGED
@@ -7,7 +7,7 @@ from pydantic import BaseModel
7
7
 
8
8
  from agno.media import Audio, Image, Video
9
9
  from agno.run.agent import RunOutput
10
- from agno.run.base import RunStatus
10
+ from agno.run.base import BaseRunOutputEvent, RunStatus
11
11
  from agno.run.team import TeamRunOutput
12
12
  from agno.utils.log import log_error
13
13
 
@@ -53,7 +53,7 @@ class WorkflowRunEvent(str, Enum):
53
53
 
54
54
 
55
55
  @dataclass
56
- class BaseWorkflowRunOutputEvent:
56
+ class BaseWorkflowRunOutputEvent(BaseRunOutputEvent):
57
57
  """Base class for all workflow run response events"""
58
58
 
59
59
  created_at: int = field(default_factory=lambda: int(time()))
@@ -75,19 +75,23 @@ class BaseWorkflowRunOutputEvent:
75
75
 
76
76
  # Handle StepOutput fields that contain Message objects
77
77
  if hasattr(self, "step_results") and self.step_results is not None:
78
- _dict["step_results"] = [step.to_dict() for step in self.step_results]
78
+ _dict["step_results"] = [step.to_dict() if hasattr(step, "to_dict") else step for step in self.step_results]
79
79
 
80
80
  if hasattr(self, "step_response") and self.step_response is not None:
81
- _dict["step_response"] = self.step_response.to_dict()
81
+ _dict["step_response"] = (
82
+ self.step_response.to_dict() if hasattr(self.step_response, "to_dict") else self.step_response
83
+ )
82
84
 
83
85
  if hasattr(self, "iteration_results") and self.iteration_results is not None:
84
- _dict["iteration_results"] = [step.to_dict() for step in self.iteration_results]
86
+ _dict["iteration_results"] = [
87
+ step.to_dict() if hasattr(step, "to_dict") else step for step in self.iteration_results
88
+ ]
85
89
 
86
90
  if hasattr(self, "all_results") and self.all_results is not None:
87
- _dict["all_results"] = [[step.to_dict() for step in iteration] for iteration in self.all_results]
88
-
89
- if hasattr(self, "step_results") and self.step_results is not None:
90
- _dict["step_results"] = [step.to_dict() for step in self.step_results]
91
+ _dict["all_results"] = [
92
+ [step.to_dict() if hasattr(step, "to_dict") else step for step in iteration]
93
+ for iteration in self.all_results
94
+ ]
91
95
 
92
96
  return _dict
93
97
 
@@ -420,6 +424,39 @@ WorkflowRunOutputEvent = Union[
420
424
  CustomEvent,
421
425
  ]
422
426
 
427
+ # Map event string to dataclass for workflow events
428
+ WORKFLOW_RUN_EVENT_TYPE_REGISTRY = {
429
+ WorkflowRunEvent.workflow_started.value: WorkflowStartedEvent,
430
+ WorkflowRunEvent.workflow_completed.value: WorkflowCompletedEvent,
431
+ WorkflowRunEvent.workflow_cancelled.value: WorkflowCancelledEvent,
432
+ WorkflowRunEvent.workflow_error.value: WorkflowErrorEvent,
433
+ WorkflowRunEvent.step_started.value: StepStartedEvent,
434
+ WorkflowRunEvent.step_completed.value: StepCompletedEvent,
435
+ WorkflowRunEvent.step_error.value: StepErrorEvent,
436
+ WorkflowRunEvent.loop_execution_started.value: LoopExecutionStartedEvent,
437
+ WorkflowRunEvent.loop_iteration_started.value: LoopIterationStartedEvent,
438
+ WorkflowRunEvent.loop_iteration_completed.value: LoopIterationCompletedEvent,
439
+ WorkflowRunEvent.loop_execution_completed.value: LoopExecutionCompletedEvent,
440
+ WorkflowRunEvent.parallel_execution_started.value: ParallelExecutionStartedEvent,
441
+ WorkflowRunEvent.parallel_execution_completed.value: ParallelExecutionCompletedEvent,
442
+ WorkflowRunEvent.condition_execution_started.value: ConditionExecutionStartedEvent,
443
+ WorkflowRunEvent.condition_execution_completed.value: ConditionExecutionCompletedEvent,
444
+ WorkflowRunEvent.router_execution_started.value: RouterExecutionStartedEvent,
445
+ WorkflowRunEvent.router_execution_completed.value: RouterExecutionCompletedEvent,
446
+ WorkflowRunEvent.steps_execution_started.value: StepsExecutionStartedEvent,
447
+ WorkflowRunEvent.steps_execution_completed.value: StepsExecutionCompletedEvent,
448
+ WorkflowRunEvent.step_output.value: StepOutputEvent,
449
+ WorkflowRunEvent.custom_event.value: CustomEvent,
450
+ }
451
+
452
+
453
+ def workflow_run_output_event_from_dict(data: dict) -> BaseWorkflowRunOutputEvent:
454
+ event_type = data.get("event", "")
455
+ cls = WORKFLOW_RUN_EVENT_TYPE_REGISTRY.get(event_type)
456
+ if not cls:
457
+ raise ValueError(f"Unknown workflow event type: {event_type}")
458
+ return cls.from_dict(data) # type: ignore
459
+
423
460
 
424
461
  @dataclass
425
462
  class WorkflowRunOutput:
@@ -568,7 +605,24 @@ class WorkflowRunOutput:
568
605
  response_audio = data.pop("response_audio", None)
569
606
  response_audio = Audio.model_validate(response_audio) if response_audio else None
570
607
 
571
- events = data.pop("events", [])
608
+ events_data = data.pop("events", [])
609
+ final_events = []
610
+ for event in events_data or []:
611
+ if "agent_id" in event:
612
+ # Agent event from agent step
613
+ from agno.run.agent import run_output_event_from_dict
614
+
615
+ event = run_output_event_from_dict(event)
616
+ elif "team_id" in event:
617
+ # Team event from team step
618
+ from agno.run.team import team_run_output_event_from_dict
619
+
620
+ event = team_run_output_event_from_dict(event)
621
+ else:
622
+ # Pure workflow event
623
+ event = workflow_run_output_event_from_dict(event)
624
+ final_events.append(event)
625
+ events = final_events
572
626
 
573
627
  return cls(
574
628
  step_results=parsed_step_results,
agno/session/team.py CHANGED
@@ -92,6 +92,7 @@ class TeamSession:
92
92
  if messages is None:
93
93
  return
94
94
 
95
+ # Make message duration None
95
96
  for m in messages or []:
96
97
  if m.metrics is not None:
97
98
  m.metrics.duration = None