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.
- agno/agent/agent.py +127 -102
- agno/db/dynamo/dynamo.py +9 -7
- agno/db/firestore/firestore.py +7 -4
- agno/db/gcs_json/gcs_json_db.py +6 -4
- agno/db/json/json_db.py +10 -6
- agno/db/migrations/v1_to_v2.py +191 -23
- agno/db/mongo/mongo.py +67 -6
- agno/db/mysql/mysql.py +7 -6
- agno/db/mysql/schemas.py +27 -27
- agno/db/postgres/postgres.py +7 -6
- agno/db/redis/redis.py +3 -3
- agno/db/singlestore/singlestore.py +4 -4
- agno/db/sqlite/sqlite.py +7 -6
- agno/db/utils.py +0 -14
- agno/integrations/discord/client.py +1 -0
- agno/knowledge/embedder/openai.py +19 -11
- agno/knowledge/knowledge.py +11 -10
- agno/knowledge/reader/reader_factory.py +7 -3
- agno/knowledge/reader/web_search_reader.py +12 -6
- agno/knowledge/reader/website_reader.py +33 -16
- agno/media.py +70 -0
- agno/models/aimlapi/aimlapi.py +2 -2
- agno/models/base.py +31 -4
- agno/models/cerebras/cerebras_openai.py +2 -2
- agno/models/deepinfra/deepinfra.py +2 -2
- agno/models/deepseek/deepseek.py +2 -2
- agno/models/fireworks/fireworks.py +2 -2
- agno/models/internlm/internlm.py +2 -2
- agno/models/langdb/langdb.py +4 -4
- agno/models/litellm/litellm_openai.py +2 -2
- agno/models/message.py +135 -0
- agno/models/meta/llama_openai.py +2 -2
- agno/models/nebius/nebius.py +2 -2
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +25 -0
- agno/models/nvidia/nvidia.py +2 -2
- agno/models/openai/responses.py +6 -0
- agno/models/openrouter/openrouter.py +2 -2
- agno/models/perplexity/perplexity.py +2 -2
- agno/models/portkey/portkey.py +3 -3
- agno/models/response.py +2 -1
- agno/models/sambanova/sambanova.py +2 -2
- agno/models/together/together.py +2 -2
- agno/models/vercel/v0.py +2 -2
- agno/models/xai/xai.py +2 -2
- agno/os/app.py +162 -42
- agno/os/interfaces/agui/utils.py +98 -134
- agno/os/router.py +3 -1
- agno/os/routers/health.py +0 -1
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/knowledge.py +2 -2
- agno/os/schema.py +21 -0
- agno/os/utils.py +1 -9
- agno/run/agent.py +19 -3
- agno/run/team.py +18 -3
- agno/run/workflow.py +10 -0
- agno/team/team.py +70 -45
- agno/tools/duckduckgo.py +15 -11
- agno/tools/e2b.py +14 -7
- agno/tools/file_generation.py +350 -0
- agno/tools/function.py +2 -0
- agno/tools/googlesearch.py +1 -1
- agno/utils/gemini.py +24 -4
- agno/utils/string.py +32 -0
- agno/utils/tools.py +1 -1
- agno/vectordb/chroma/chromadb.py +66 -25
- agno/vectordb/lancedb/lance_db.py +15 -4
- agno/vectordb/milvus/milvus.py +6 -0
- agno/workflow/step.py +4 -3
- agno/workflow/workflow.py +4 -0
- {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/METADATA +9 -5
- {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/RECORD +75 -72
- agno/knowledge/reader/url_reader.py +0 -128
- {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/WHEEL +0 -0
- {agno-2.0.4.dist-info → agno-2.0.6.dist-info}/licenses/LICENSE +0 -0
- {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[
|
|
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
|
-
|
|
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:
|
|
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.
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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.
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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,
|
|
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.
|
|
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
|
-
#
|
|
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.
|
|
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
|
-
#
|
|
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,
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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.
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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.
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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:
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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}")
|
agno/db/firestore/firestore.py
CHANGED
|
@@ -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,
|
|
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 =
|
|
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
|
-
|
|
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}")
|
agno/db/gcs_json/gcs_json_db.py
CHANGED
|
@@ -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 =
|
|
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:
|
|
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 (
|
|
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
|
|