agno 2.0.4__py3-none-any.whl → 2.0.6__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 (76) hide show
  1. agno/agent/agent.py +127 -102
  2. agno/db/dynamo/dynamo.py +9 -7
  3. agno/db/firestore/firestore.py +7 -4
  4. agno/db/gcs_json/gcs_json_db.py +6 -4
  5. agno/db/json/json_db.py +10 -6
  6. agno/db/migrations/v1_to_v2.py +191 -23
  7. agno/db/mongo/mongo.py +67 -6
  8. agno/db/mysql/mysql.py +7 -6
  9. agno/db/mysql/schemas.py +27 -27
  10. agno/db/postgres/postgres.py +7 -6
  11. agno/db/redis/redis.py +3 -3
  12. agno/db/singlestore/singlestore.py +4 -4
  13. agno/db/sqlite/sqlite.py +7 -6
  14. agno/db/utils.py +0 -14
  15. agno/integrations/discord/client.py +1 -0
  16. agno/knowledge/embedder/openai.py +19 -11
  17. agno/knowledge/knowledge.py +11 -10
  18. agno/knowledge/reader/reader_factory.py +7 -3
  19. agno/knowledge/reader/web_search_reader.py +12 -6
  20. agno/knowledge/reader/website_reader.py +33 -16
  21. agno/media.py +70 -0
  22. agno/models/aimlapi/aimlapi.py +2 -2
  23. agno/models/base.py +31 -4
  24. agno/models/cerebras/cerebras_openai.py +2 -2
  25. agno/models/deepinfra/deepinfra.py +2 -2
  26. agno/models/deepseek/deepseek.py +2 -2
  27. agno/models/fireworks/fireworks.py +2 -2
  28. agno/models/internlm/internlm.py +2 -2
  29. agno/models/langdb/langdb.py +4 -4
  30. agno/models/litellm/litellm_openai.py +2 -2
  31. agno/models/message.py +135 -0
  32. agno/models/meta/llama_openai.py +2 -2
  33. agno/models/nebius/nebius.py +2 -2
  34. agno/models/nexus/__init__.py +3 -0
  35. agno/models/nexus/nexus.py +25 -0
  36. agno/models/nvidia/nvidia.py +2 -2
  37. agno/models/openai/responses.py +6 -0
  38. agno/models/openrouter/openrouter.py +2 -2
  39. agno/models/perplexity/perplexity.py +2 -2
  40. agno/models/portkey/portkey.py +3 -3
  41. agno/models/response.py +2 -1
  42. agno/models/sambanova/sambanova.py +2 -2
  43. agno/models/together/together.py +2 -2
  44. agno/models/vercel/v0.py +2 -2
  45. agno/models/xai/xai.py +2 -2
  46. agno/os/app.py +162 -42
  47. agno/os/interfaces/agui/utils.py +98 -134
  48. agno/os/router.py +3 -1
  49. agno/os/routers/health.py +0 -1
  50. agno/os/routers/home.py +52 -0
  51. agno/os/routers/knowledge/knowledge.py +2 -2
  52. agno/os/schema.py +21 -0
  53. agno/os/utils.py +1 -9
  54. agno/run/agent.py +19 -3
  55. agno/run/team.py +18 -3
  56. agno/run/workflow.py +10 -0
  57. agno/team/team.py +70 -45
  58. agno/tools/duckduckgo.py +15 -11
  59. agno/tools/e2b.py +14 -7
  60. agno/tools/file_generation.py +350 -0
  61. agno/tools/function.py +2 -0
  62. agno/tools/googlesearch.py +1 -1
  63. agno/utils/gemini.py +24 -4
  64. agno/utils/string.py +32 -0
  65. agno/utils/tools.py +1 -1
  66. agno/vectordb/chroma/chromadb.py +66 -25
  67. agno/vectordb/lancedb/lance_db.py +15 -4
  68. agno/vectordb/milvus/milvus.py +6 -0
  69. agno/workflow/step.py +4 -3
  70. agno/workflow/workflow.py +4 -0
  71. {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/METADATA +9 -5
  72. {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/RECORD +75 -72
  73. agno/knowledge/reader/url_reader.py +0 -128
  74. {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/WHEEL +0 -0
  75. {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/licenses/LICENSE +0 -0
  76. {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/top_level.txt +0 -0
agno/agent/agent.py CHANGED
@@ -107,7 +107,7 @@ from agno.utils.response import (
107
107
  get_paused_content,
108
108
  )
109
109
  from agno.utils.safe_formatter import SafeFormatter
110
- from agno.utils.string import parse_response_model_str
110
+ from agno.utils.string import generate_id_from_name, parse_response_model_str
111
111
  from agno.utils.timer import Timer
112
112
 
113
113
 
@@ -371,7 +371,7 @@ class Agent:
371
371
  knowledge_retriever: Optional[Callable[..., Optional[List[Union[Dict, str]]]]] = None,
372
372
  references_format: Literal["json", "yaml"] = "json",
373
373
  metadata: Optional[Dict[str, Any]] = None,
374
- tools: Optional[List[Union[Toolkit, Callable, Function, Dict]]] = None,
374
+ tools: Optional[Sequence[Union[Toolkit, Callable, Function, Dict]]] = None,
375
375
  tool_call_limit: Optional[int] = None,
376
376
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
377
377
  tool_hooks: Optional[List[Callable]] = None,
@@ -466,7 +466,7 @@ class Agent:
466
466
 
467
467
  self.metadata = metadata
468
468
 
469
- self.tools = tools
469
+ self.tools = list(tools) if tools else []
470
470
  self.tool_call_limit = tool_call_limit
471
471
  self.tool_choice = tool_choice
472
472
  self.tool_hooks = tool_hooks
@@ -545,10 +545,7 @@ class Agent:
545
545
 
546
546
  def set_id(self) -> None:
547
547
  if self.id is None:
548
- if self.name is not None:
549
- self.id = self.name.lower().replace(" ", "-")
550
- else:
551
- self.id = str(uuid4())
548
+ self.id = generate_id_from_name(self.name)
552
549
 
553
550
  def _set_debug(self, debug_mode: Optional[bool] = None) -> None:
554
551
  # If the default debug mode is set, or passed on run, or via environment variable, set the debug mode to True
@@ -684,8 +681,8 @@ class Agent:
684
681
  self.tools.append(tool)
685
682
  self._rebuild_tools = True
686
683
 
687
- def set_tools(self, tools: List[Union[Toolkit, Callable, Function, Dict]]):
688
- self.tools = tools
684
+ def set_tools(self, tools: Sequence[Union[Toolkit, Callable, Function, Dict]]):
685
+ self.tools = list(tools) if tools else []
689
686
  self._rebuild_tools = True
690
687
 
691
688
  def _initialize_session(
@@ -790,14 +787,7 @@ class Agent:
790
787
  run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
791
788
  )
792
789
 
793
- # 4. Update Agent Memory
794
- response_iterator = self._make_memories_and_summaries(
795
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
796
- )
797
- # Consume the response iterator to ensure the memory is updated before the run is completed
798
- deque(response_iterator, maxlen=0)
799
-
800
- # 5. Calculate session metrics
790
+ # 4. Calculate session metrics
801
791
  self._update_session_metrics(session=session, run_response=run_response)
802
792
 
803
793
  run_response.status = RunStatus.completed
@@ -809,14 +799,21 @@ class Agent:
809
799
  if run_response.metrics:
810
800
  run_response.metrics.stop_timer()
811
801
 
812
- # 6. Optional: Save output to file if save_response_to_file is set
802
+ # 5. Optional: Save output to file if save_response_to_file is set
813
803
  self.save_run_response_to_file(
814
804
  run_response=run_response, input=run_messages.user_message, session_id=session.session_id, user_id=user_id
815
805
  )
816
806
 
817
- # 7. Add the RunOutput to Agent Session
807
+ # 6. Add the RunOutput to Agent Session
818
808
  session.upsert_run(run=run_response)
819
809
 
810
+ # 7. Update Agent Memory
811
+ response_iterator = self._make_memories_and_summaries(
812
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
813
+ )
814
+ # Consume the response iterator to ensure the memory is updated before the run is completed
815
+ deque(response_iterator, maxlen=0)
816
+
820
817
  # 8. Save session to memory
821
818
  self.save_session(session=session)
822
819
 
@@ -930,12 +927,7 @@ class Agent:
930
927
  )
931
928
  return
932
929
 
933
- # 3. Update Agent Memory
934
- yield from self._make_memories_and_summaries(
935
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
936
- )
937
-
938
- # 4. Calculate session metrics
930
+ # 3. Calculate session metrics
939
931
  self._update_session_metrics(session=session, run_response=run_response)
940
932
 
941
933
  run_response.status = RunStatus.completed
@@ -948,7 +940,7 @@ class Agent:
948
940
  if run_response.metrics:
949
941
  run_response.metrics.stop_timer()
950
942
 
951
- # 5. Optional: Save output to file if save_response_to_file is set
943
+ # 4. Optional: Save output to file if save_response_to_file is set
952
944
  self.save_run_response_to_file(
953
945
  run_response=run_response,
954
946
  input=run_messages.user_message,
@@ -956,9 +948,14 @@ class Agent:
956
948
  user_id=user_id,
957
949
  )
958
950
 
959
- # 6. Add RunOutput to Agent Session
951
+ # 5. Add RunOutput to Agent Session
960
952
  session.upsert_run(run=run_response)
961
953
 
954
+ # 6. Update Agent Memory
955
+ yield from self._make_memories_and_summaries(
956
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
957
+ )
958
+
962
959
  # 7. Save session to storage
963
960
  self.save_session(session=session)
964
961
 
@@ -1083,13 +1080,17 @@ class Agent:
1083
1080
  # Initialize the Agent
1084
1081
  self.initialize_agent(debug_mode=debug_mode)
1085
1082
 
1086
- image_artifacts, video_artifacts, audio_artifacts = self._validate_media_object_id(
1087
- images=images, videos=videos, audios=audio
1083
+ image_artifacts, video_artifacts, audio_artifacts, file_artifacts = self._validate_media_object_id(
1084
+ images=images, videos=videos, audios=audio, files=files
1088
1085
  )
1089
1086
 
1090
1087
  # Create RunInput to capture the original user input
1091
1088
  run_input = RunInput(
1092
- input_content=input, images=image_artifacts, videos=video_artifacts, audios=audio_artifacts, files=files
1089
+ input_content=input,
1090
+ images=image_artifacts,
1091
+ videos=video_artifacts,
1092
+ audios=audio_artifacts,
1093
+ files=file_artifacts,
1093
1094
  )
1094
1095
 
1095
1096
  # Read existing session from database
@@ -1383,13 +1384,7 @@ class Agent:
1383
1384
  run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
1384
1385
  )
1385
1386
 
1386
- # 6. Update Agent Memory
1387
- async for _ in self._amake_memories_and_summaries(
1388
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
1389
- ):
1390
- pass
1391
-
1392
- # 7. Calculate session metrics
1387
+ # 6. Calculate session metrics
1393
1388
  self._update_session_metrics(session=session, run_response=run_response)
1394
1389
 
1395
1390
  run_response.status = RunStatus.completed
@@ -1406,9 +1401,15 @@ class Agent:
1406
1401
  run_response=run_response, input=run_messages.user_message, session_id=session.session_id, user_id=user_id
1407
1402
  )
1408
1403
 
1409
- # 8. Add RunOutput to Agent Session
1404
+ # 7. Add RunOutput to Agent Session
1410
1405
  session.upsert_run(run=run_response)
1411
1406
 
1407
+ # 8. Update Agent Memory
1408
+ async for _ in self._amake_memories_and_summaries(
1409
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
1410
+ ):
1411
+ pass
1412
+
1412
1413
  # 9. Save session to storage
1413
1414
  self.save_session(session=session)
1414
1415
 
@@ -1563,13 +1564,7 @@ class Agent:
1563
1564
  yield item
1564
1565
  return
1565
1566
 
1566
- # 5. Update Agent Memory
1567
- async for event in self._amake_memories_and_summaries(
1568
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
1569
- ):
1570
- yield event
1571
-
1572
- # 6. Calculate session metrics
1567
+ # 5. Calculate session metrics
1573
1568
  self._update_session_metrics(session=session, run_response=run_response)
1574
1569
 
1575
1570
  run_response.status = RunStatus.completed
@@ -1590,9 +1585,15 @@ class Agent:
1590
1585
  user_id=user_id,
1591
1586
  )
1592
1587
 
1593
- # 7. Add RunOutput to Agent Session
1588
+ # 6. Add RunOutput to Agent Session
1594
1589
  session.upsert_run(run=run_response)
1595
1590
 
1591
+ # 7. Update Agent Memory
1592
+ async for event in self._amake_memories_and_summaries(
1593
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
1594
+ ):
1595
+ yield event
1596
+
1596
1597
  # 8. Save session to storage
1597
1598
  self.save_session(session=session)
1598
1599
 
@@ -1716,13 +1717,17 @@ class Agent:
1716
1717
  # Initialize the Agent
1717
1718
  self.initialize_agent(debug_mode=debug_mode)
1718
1719
 
1719
- image_artifacts, video_artifacts, audio_artifacts = self._validate_media_object_id(
1720
- images=images, videos=videos, audios=audio
1720
+ image_artifacts, video_artifacts, audio_artifacts, file_artifacts = self._validate_media_object_id(
1721
+ images=images, videos=videos, audios=audio, files=files
1721
1722
  )
1722
1723
 
1723
1724
  # Create RunInput to capture the original user input
1724
1725
  run_input = RunInput(
1725
- input_content=input, images=image_artifacts, videos=video_artifacts, audios=audio_artifacts, files=files
1726
+ input_content=input,
1727
+ images=image_artifacts,
1728
+ videos=video_artifacts,
1729
+ audios=audio_artifacts,
1730
+ files=file_artifacts,
1726
1731
  )
1727
1732
 
1728
1733
  # Read existing session from storage
@@ -2177,14 +2182,7 @@ class Agent:
2177
2182
  run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2178
2183
  )
2179
2184
 
2180
- # 4. Update Agent Memory
2181
- response_iterator = self._make_memories_and_summaries(
2182
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2183
- )
2184
- # Consume the response iterator to ensure the memory is updated before the run is completed
2185
- deque(response_iterator, maxlen=0)
2186
-
2187
- # 5. Calculate session metrics
2185
+ # 3. Calculate session metrics
2188
2186
  self._update_session_metrics(session=session, run_response=run_response)
2189
2187
 
2190
2188
  run_response.status = RunStatus.completed
@@ -2196,14 +2194,21 @@ class Agent:
2196
2194
  if run_response.metrics:
2197
2195
  run_response.metrics.stop_timer()
2198
2196
 
2199
- # 5. Save output to file if save_response_to_file is set
2197
+ # 4. Save output to file if save_response_to_file is set
2200
2198
  self.save_run_response_to_file(
2201
2199
  run_response=run_response, input=run_messages.user_message, session_id=session.session_id, user_id=user_id
2202
2200
  )
2203
2201
 
2204
- # 6. Add the run to memory
2202
+ # 5. Add the run to memory
2205
2203
  session.upsert_run(run=run_response)
2206
2204
 
2205
+ # 6. Update Agent Memory
2206
+ response_iterator = self._make_memories_and_summaries(
2207
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2208
+ )
2209
+ # Consume the response iterator to ensure the memory is updated before the run is completed
2210
+ deque(response_iterator, maxlen=0)
2211
+
2207
2212
  # 7. Save session to storage
2208
2213
  self.save_session(session=session)
2209
2214
 
@@ -2261,12 +2266,7 @@ class Agent:
2261
2266
  )
2262
2267
  return
2263
2268
 
2264
- # 4. Update Agent Memory
2265
- yield from self._make_memories_and_summaries(
2266
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2267
- )
2268
-
2269
- # 5. Calculate session metrics
2269
+ # 3. Calculate session metrics
2270
2270
  self._update_session_metrics(session=session, run_response=run_response)
2271
2271
 
2272
2272
  run_response.status = RunStatus.completed
@@ -2277,14 +2277,19 @@ class Agent:
2277
2277
  if run_response.metrics:
2278
2278
  run_response.metrics.stop_timer()
2279
2279
 
2280
- # 5. Save output to file if save_response_to_file is set
2280
+ # 4. Save output to file if save_response_to_file is set
2281
2281
  self.save_run_response_to_file(
2282
2282
  run_response=run_response, input=run_messages.user_message, session_id=session.session_id, user_id=user_id
2283
2283
  )
2284
2284
 
2285
- # 6. Add the run to memory
2285
+ # 5. Add the run to memory
2286
2286
  session.upsert_run(run=run_response)
2287
2287
 
2288
+ # 6. Update Agent Memory
2289
+ yield from self._make_memories_and_summaries(
2290
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2291
+ )
2292
+
2288
2293
  # 7. Save session to storage
2289
2294
  self.save_session(session=session)
2290
2295
 
@@ -2563,13 +2568,7 @@ class Agent:
2563
2568
  run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2564
2569
  )
2565
2570
 
2566
- # 4. Update Agent Memory
2567
- async for _ in self._amake_memories_and_summaries(
2568
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2569
- ):
2570
- pass
2571
-
2572
- # 5. Calculate session metrics
2571
+ # 3. Calculate session metrics
2573
2572
  self._update_session_metrics(session=session, run_response=run_response)
2574
2573
 
2575
2574
  run_response.status = RunStatus.completed
@@ -2581,14 +2580,21 @@ class Agent:
2581
2580
  if run_response.metrics:
2582
2581
  run_response.metrics.stop_timer()
2583
2582
 
2584
- # 7. Save output to file if save_response_to_file is set
2583
+ # 4. Save output to file if save_response_to_file is set
2585
2584
  self.save_run_response_to_file(
2586
2585
  run_response=run_response, input=run_messages.user_message, session_id=session.session_id, user_id=user_id
2587
2586
  )
2588
2587
 
2588
+ # 5. Add the run to memory
2589
2589
  session.upsert_run(run=run_response)
2590
2590
 
2591
- # 6. Save session to storage
2591
+ # 6. Update Agent Memory
2592
+ async for _ in self._amake_memories_and_summaries(
2593
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2594
+ ):
2595
+ pass
2596
+
2597
+ # 7. Save session to storage
2592
2598
  self.save_session(session=session)
2593
2599
 
2594
2600
  # Log Agent Telemetry
@@ -2644,9 +2650,6 @@ class Agent:
2644
2650
  ):
2645
2651
  yield event
2646
2652
 
2647
- # 3. Add the run to memory
2648
- session.upsert_run(run=run_response)
2649
-
2650
2653
  # We should break out of the run function
2651
2654
  if any(tool_call.is_paused for tool_call in run_response.tools or []):
2652
2655
  for item in self._handle_agent_run_paused_stream(
@@ -2655,13 +2658,7 @@ class Agent:
2655
2658
  yield item
2656
2659
  return
2657
2660
 
2658
- # 4. Update Agent Memory
2659
- async for event in self._amake_memories_and_summaries(
2660
- run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2661
- ):
2662
- yield event
2663
-
2664
- # 5. Calculate session metrics
2661
+ # 3. Calculate session metrics
2665
2662
  self._update_session_metrics(session=session, run_response=run_response)
2666
2663
 
2667
2664
  run_response.status = RunStatus.completed
@@ -2672,14 +2669,21 @@ class Agent:
2672
2669
  if run_response.metrics:
2673
2670
  run_response.metrics.stop_timer()
2674
2671
 
2675
- # 6. Save output to file if save_response_to_file is set
2672
+ # 4. Save output to file if save_response_to_file is set
2676
2673
  self.save_run_response_to_file(
2677
2674
  run_response=run_response, input=run_messages.user_message, session_id=session.session_id, user_id=user_id
2678
2675
  )
2679
2676
 
2677
+ # 5. Add the run to memory
2680
2678
  session.upsert_run(run=run_response)
2681
2679
 
2682
- # 6. Save session to storage
2680
+ # 6. Update Agent Memory
2681
+ async for event in self._amake_memories_and_summaries(
2682
+ run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
2683
+ ):
2684
+ yield event
2685
+
2686
+ # 7. Save session to storage
2683
2687
  self.save_session(session=session)
2684
2688
 
2685
2689
  if stream_intermediate_steps:
@@ -3067,6 +3071,10 @@ class Agent:
3067
3071
  for audio in model_response.audios:
3068
3072
  self._add_audio(audio, run_response) # Generated audio go to run_response.audio
3069
3073
 
3074
+ if model_response.files is not None:
3075
+ for file in model_response.files:
3076
+ self._add_file(file, run_response) # Generated files go to run_response.files
3077
+
3070
3078
  def _update_run_response(self, model_response: ModelResponse, run_response: RunOutput, run_messages: RunMessages):
3071
3079
  # Handle structured outputs
3072
3080
  if self.output_schema is not None and model_response.parsed is not None:
@@ -3129,7 +3137,8 @@ class Agent:
3129
3137
  """Calculate session metrics"""
3130
3138
  session_metrics = self._get_session_metrics(session=session)
3131
3139
  # Add the metrics for the current run to the session metrics
3132
- session_metrics += run_response.metrics
3140
+ if run_response.metrics is not None:
3141
+ session_metrics += run_response.metrics
3133
3142
  session_metrics.time_to_first_token = None
3134
3143
  if session.session_data is not None:
3135
3144
  session.session_data["session_metrics"] = session_metrics
@@ -3336,13 +3345,6 @@ class Agent:
3336
3345
  ) + model_response_event.reasoning_content
3337
3346
  run_response.reasoning_content = model_response.reasoning_content
3338
3347
 
3339
- if model_response_event.reasoning_content is not None:
3340
- if not model_response.reasoning_content:
3341
- model_response.reasoning_content = model_response_event.reasoning_content
3342
- else:
3343
- model_response.reasoning_content += model_response_event.reasoning_content
3344
- run_response.reasoning_content = model_response.reasoning_content
3345
-
3346
3348
  if model_response_event.redacted_reasoning_content is not None:
3347
3349
  if not model_response.reasoning_content:
3348
3350
  model_response.reasoning_content = model_response_event.redacted_reasoning_content
@@ -3811,7 +3813,7 @@ class Agent:
3811
3813
  self._rebuild_tools = True
3812
3814
  if self.search_session_history:
3813
3815
  agent_tools.append(
3814
- self._get_previous_sessions_messages_function(num_history_sessions=self.num_history_sessions)
3816
+ self._get_previous_sessions_messages_function(num_history_sessions=self.num_history_sessions, user_id=user_id)
3815
3817
  )
3816
3818
  self._rebuild_tools = True
3817
3819
 
@@ -4959,7 +4961,7 @@ class Agent:
4959
4961
  # 1. If build_user_context is False or message is a list, return the message as is.
4960
4962
  if not self.build_user_context:
4961
4963
  return Message(
4962
- role=self.user_message_role,
4964
+ role=self.user_message_role or "user",
4963
4965
  content=input,
4964
4966
  images=None if not self.send_media_to_model else images,
4965
4967
  audio=None if not self.send_media_to_model else audio,
@@ -4972,7 +4974,7 @@ class Agent:
4972
4974
  # If we have any media, return a message with empty content
4973
4975
  if images is not None or audio is not None or videos is not None or files is not None:
4974
4976
  return Message(
4975
- role=self.user_message_role,
4977
+ role=self.user_message_role or "user",
4976
4978
  content="",
4977
4979
  images=None if not self.send_media_to_model else images,
4978
4980
  audio=None if not self.send_media_to_model else audio,
@@ -5727,6 +5729,13 @@ class Agent:
5727
5729
  run_response.audio = []
5728
5730
  run_response.audio.append(audio)
5729
5731
 
5732
+ def _add_file(self, file: File, run_response: RunOutput) -> None:
5733
+ """Add file to both the agent's stateful storage and the current run response"""
5734
+ # Add to run response
5735
+ if run_response.files is None:
5736
+ run_response.files = []
5737
+ run_response.files.append(file)
5738
+
5730
5739
  ###########################################################################
5731
5740
  # Reasoning
5732
5741
  ###########################################################################
@@ -6790,11 +6799,14 @@ class Agent:
6790
6799
  )
6791
6800
  return "Successfully added to knowledge base"
6792
6801
 
6793
- def _get_previous_sessions_messages_function(self, num_history_sessions: Optional[int] = 2) -> Callable:
6802
+ def _get_previous_sessions_messages_function(
6803
+ self, num_history_sessions: Optional[int] = 2, user_id: Optional[str] = None
6804
+ ) -> Callable:
6794
6805
  """Factory function to create a get_previous_session_messages function.
6795
6806
 
6796
6807
  Args:
6797
6808
  num_history_sessions: The last n sessions to be taken from db
6809
+ user_id: The user ID to filter sessions by
6798
6810
 
6799
6811
  Returns:
6800
6812
  Callable: A function that retrieves messages from previous sessions
@@ -6813,7 +6825,9 @@ class Agent:
6813
6825
  if self.db is None:
6814
6826
  return "Previous session messages not available"
6815
6827
 
6816
- selected_sessions = self.db.get_sessions(session_type=SessionType.AGENT, limit=num_history_sessions)
6828
+ selected_sessions = self.db.get_sessions(
6829
+ session_type=SessionType.AGENT, limit=num_history_sessions, user_id=user_id
6830
+ )
6817
6831
 
6818
6832
  all_messages = []
6819
6833
  seen_message_pairs = set()
@@ -7210,6 +7224,7 @@ class Agent:
7210
7224
  images: Optional[Sequence[Image]] = None,
7211
7225
  videos: Optional[Sequence[Video]] = None,
7212
7226
  audios: Optional[Sequence[Audio]] = None,
7227
+ files: Optional[Sequence[File]] = None,
7213
7228
  ) -> tuple:
7214
7229
  """Convert raw Image/Video/Audio objects - now unified, so just return as-is."""
7215
7230
  # With unified classes, no conversion needed - just ensure IDs are set
@@ -7244,7 +7259,17 @@ class Agent:
7244
7259
  aud.id = str(uuid4())
7245
7260
  audio_list.append(aud)
7246
7261
 
7247
- return image_list, video_list, audio_list
7262
+ file_list = None
7263
+ if files:
7264
+ file_list = []
7265
+ for file in files:
7266
+ if not file.id:
7267
+ from uuid import uuid4
7268
+
7269
+ file.id = str(uuid4())
7270
+ file_list.append(file)
7271
+
7272
+ return image_list, video_list, audio_list, file_list
7248
7273
 
7249
7274
  def cli_app(
7250
7275
  self,
agno/db/dynamo/dynamo.py CHANGED
@@ -30,9 +30,9 @@ from agno.db.dynamo.utils import (
30
30
  from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
31
31
  from agno.db.schemas.knowledge import KnowledgeRow
32
32
  from agno.db.schemas.memory import UserMemory
33
- from agno.db.utils import generate_deterministic_id
34
33
  from agno.session import AgentSession, Session, TeamSession, WorkflowSession
35
34
  from agno.utils.log import log_debug, log_error
35
+ from agno.utils.string import generate_id
36
36
 
37
37
  try:
38
38
  import boto3 # type: ignore[import-untyped]
@@ -75,7 +75,7 @@ class DynamoDb(BaseDb):
75
75
  """
76
76
  if id is None:
77
77
  seed = str(db_client) if db_client else f"{region_name}_{aws_access_key_id}"
78
- id = generate_deterministic_id(seed)
78
+ id = generate_id(seed)
79
79
 
80
80
  super().__init__(
81
81
  id=id,
@@ -181,7 +181,7 @@ class DynamoDb(BaseDb):
181
181
 
182
182
  # --- Sessions ---
183
183
 
184
- def delete_session(self, session_id: Optional[str] = None, session_type: Optional[SessionType] = None) -> bool:
184
+ def delete_session(self, session_id: Optional[str] = None) -> bool:
185
185
  """
186
186
  Delete a session from the database.
187
187
 
@@ -236,7 +236,7 @@ class DynamoDb(BaseDb):
236
236
  def get_session(
237
237
  self,
238
238
  session_id: str,
239
- session_type: Optional[SessionType] = None,
239
+ session_type: SessionType,
240
240
  user_id: Optional[str] = None,
241
241
  deserialize: Optional[bool] = True,
242
242
  ) -> Optional[Union[Session, Dict[str, Any]]]:
@@ -245,7 +245,7 @@ class DynamoDb(BaseDb):
245
245
 
246
246
  Args:
247
247
  session_id (str): The ID of the session to get.
248
- session_type (Optional[SessionType]): The type of session to get.
248
+ session_type (SessionType): The type of session to get.
249
249
  user_id (Optional[str]): The ID of the user to get the session for.
250
250
  deserialize (Optional[bool]): Whether to deserialize the session.
251
251
 
@@ -268,7 +268,7 @@ class DynamoDb(BaseDb):
268
268
 
269
269
  session = deserialize_from_dynamodb_item(item)
270
270
 
271
- if session_type and session.get("session_type") != session_type.value:
271
+ if session.get("session_type") != session_type.value:
272
272
  return None
273
273
  if user_id and session.get("user_id") != user_id:
274
274
  return None
@@ -283,8 +283,10 @@ class DynamoDb(BaseDb):
283
283
  return AgentSession.from_dict(session)
284
284
  elif session_type == SessionType.TEAM:
285
285
  return TeamSession.from_dict(session)
286
- else:
286
+ elif session_type == SessionType.WORKFLOW:
287
287
  return WorkflowSession.from_dict(session)
288
+ else:
289
+ raise ValueError(f"Invalid session type: {session_type}")
288
290
 
289
291
  except Exception as e:
290
292
  log_error(f"Failed to get session {session_id}: {e}")
@@ -16,9 +16,10 @@ from agno.db.firestore.utils import (
16
16
  from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
17
17
  from agno.db.schemas.knowledge import KnowledgeRow
18
18
  from agno.db.schemas.memory import UserMemory
19
- from agno.db.utils import deserialize_session_json_fields, generate_deterministic_id, serialize_session_json_fields
19
+ from agno.db.utils import deserialize_session_json_fields, serialize_session_json_fields
20
20
  from agno.session import AgentSession, Session, TeamSession, WorkflowSession
21
21
  from agno.utils.log import log_debug, log_error, log_info
22
+ from agno.utils.string import generate_id
22
23
 
23
24
  try:
24
25
  from google.cloud.firestore import Client, FieldFilter # type: ignore[import-untyped]
@@ -58,7 +59,7 @@ class FirestoreDb(BaseDb):
58
59
  """
59
60
  if id is None:
60
61
  seed = project_id or str(db_client)
61
- id = generate_deterministic_id(seed)
62
+ id = generate_id(seed)
62
63
 
63
64
  super().__init__(
64
65
  id=id,
@@ -241,8 +242,8 @@ class FirestoreDb(BaseDb):
241
242
 
242
243
  Args:
243
244
  session_id (str): The ID of the session to get.
245
+ session_type (SessionType): The type of session to get.
244
246
  user_id (Optional[str]): The ID of the user to get the session for.
245
- session_type (Optional[SessionType]): The type of session to get.
246
247
  deserialize (Optional[bool]): Whether to serialize the session. Defaults to True.
247
248
 
248
249
  Returns:
@@ -280,8 +281,10 @@ class FirestoreDb(BaseDb):
280
281
  return AgentSession.from_dict(session)
281
282
  elif session_type == SessionType.TEAM:
282
283
  return TeamSession.from_dict(session)
283
- else:
284
+ elif session_type == SessionType.WORKFLOW:
284
285
  return WorkflowSession.from_dict(session)
286
+ else:
287
+ raise ValueError(f"Invalid session type: {session_type}")
285
288
 
286
289
  except Exception as e:
287
290
  log_error(f"Exception reading session: {e}")
@@ -14,9 +14,9 @@ from agno.db.gcs_json.utils import (
14
14
  from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
15
15
  from agno.db.schemas.knowledge import KnowledgeRow
16
16
  from agno.db.schemas.memory import UserMemory
17
- from agno.db.utils import generate_deterministic_id
18
17
  from agno.session import AgentSession, Session, TeamSession, WorkflowSession
19
18
  from agno.utils.log import log_debug, log_error, log_info, log_warning
19
+ from agno.utils.string import generate_id
20
20
 
21
21
  try:
22
22
  from google.cloud import storage as gcs # type: ignore
@@ -57,7 +57,7 @@ class GcsJsonDb(BaseDb):
57
57
  if id is None:
58
58
  prefix_suffix = prefix or "agno/"
59
59
  seed = f"{bucket_name}_{project}#{prefix_suffix}"
60
- id = generate_deterministic_id(seed)
60
+ id = generate_id(seed)
61
61
 
62
62
  super().__init__(
63
63
  id=id,
@@ -185,7 +185,7 @@ class GcsJsonDb(BaseDb):
185
185
  def get_session(
186
186
  self,
187
187
  session_id: str,
188
- session_type: Optional[SessionType] = None,
188
+ session_type: SessionType,
189
189
  user_id: Optional[str] = None,
190
190
  deserialize: Optional[bool] = True,
191
191
  ) -> Optional[Union[AgentSession, TeamSession, WorkflowSession, Dict[str, Any]]]:
@@ -193,7 +193,7 @@ class GcsJsonDb(BaseDb):
193
193
 
194
194
  Args:
195
195
  session_id (str): The ID of the session to read.
196
- session_type (Optional[SessionType]): The type of the session to read.
196
+ session_type (SessionType): The type of the session to read.
197
197
  user_id (Optional[str]): The ID of the user to read the session for.
198
198
  deserialize (Optional[bool]): Whether to deserialize the session.
199
199
 
@@ -226,6 +226,8 @@ class GcsJsonDb(BaseDb):
226
226
  return TeamSession.from_dict(session_data)
227
227
  elif session_type == SessionType.WORKFLOW:
228
228
  return WorkflowSession.from_dict(session_data)
229
+ else:
230
+ raise ValueError(f"Invalid session type: {session_type}")
229
231
 
230
232
  return None
231
233