agno 2.0.3__py3-none-any.whl → 2.0.5__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 +229 -164
- agno/db/dynamo/dynamo.py +8 -0
- agno/db/firestore/firestore.py +8 -0
- agno/db/gcs_json/gcs_json_db.py +9 -0
- agno/db/json/json_db.py +8 -0
- agno/db/migrations/v1_to_v2.py +191 -23
- agno/db/mongo/mongo.py +68 -0
- agno/db/mysql/mysql.py +13 -3
- agno/db/mysql/schemas.py +27 -27
- agno/db/postgres/postgres.py +19 -11
- agno/db/redis/redis.py +6 -0
- agno/db/singlestore/schemas.py +1 -1
- agno/db/singlestore/singlestore.py +8 -1
- agno/db/sqlite/sqlite.py +12 -3
- agno/integrations/discord/client.py +1 -0
- agno/knowledge/knowledge.py +92 -66
- agno/knowledge/reader/reader_factory.py +7 -3
- agno/knowledge/reader/web_search_reader.py +12 -6
- agno/models/base.py +2 -2
- agno/models/message.py +109 -0
- agno/models/openai/chat.py +3 -0
- agno/models/openai/responses.py +12 -0
- agno/models/response.py +5 -0
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/os/app.py +164 -41
- agno/os/auth.py +24 -14
- agno/os/interfaces/agui/utils.py +98 -134
- agno/os/router.py +128 -55
- agno/os/routers/evals/utils.py +9 -9
- agno/os/routers/health.py +25 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/knowledge.py +11 -11
- agno/os/routers/session/session.py +24 -8
- agno/os/schema.py +29 -2
- agno/os/utils.py +0 -8
- agno/run/agent.py +3 -3
- agno/run/team.py +3 -3
- agno/run/workflow.py +64 -10
- agno/session/team.py +1 -0
- agno/team/team.py +189 -94
- agno/tools/duckduckgo.py +15 -11
- agno/tools/googlesearch.py +1 -1
- agno/tools/mem0.py +11 -17
- agno/tools/memory.py +34 -6
- agno/utils/common.py +90 -1
- agno/utils/streamlit.py +14 -8
- agno/utils/string.py +32 -0
- agno/utils/tools.py +1 -1
- agno/vectordb/chroma/chromadb.py +8 -2
- agno/workflow/step.py +115 -16
- agno/workflow/workflow.py +16 -13
- {agno-2.0.3.dist-info → agno-2.0.5.dist-info}/METADATA +6 -5
- {agno-2.0.3.dist-info → agno-2.0.5.dist-info}/RECORD +57 -54
- agno/knowledge/reader/url_reader.py +0 -128
- {agno-2.0.3.dist-info → agno-2.0.5.dist-info}/WHEEL +0 -0
- {agno-2.0.3.dist-info → agno-2.0.5.dist-info}/licenses/LICENSE +0 -0
- {agno-2.0.3.dist-info → agno-2.0.5.dist-info}/top_level.txt +0 -0
agno/team/team.py
CHANGED
|
@@ -55,6 +55,7 @@ from agno.run.team import TeamRunEvent, TeamRunInput, TeamRunOutput, TeamRunOutp
|
|
|
55
55
|
from agno.session import SessionSummaryManager, TeamSession
|
|
56
56
|
from agno.tools import Toolkit
|
|
57
57
|
from agno.tools.function import Function
|
|
58
|
+
from agno.utils.common import is_typed_dict, validate_typed_dict
|
|
58
59
|
from agno.utils.events import (
|
|
59
60
|
create_team_memory_update_completed_event,
|
|
60
61
|
create_team_memory_update_started_event,
|
|
@@ -103,7 +104,7 @@ from agno.utils.response import (
|
|
|
103
104
|
generator_wrapper,
|
|
104
105
|
)
|
|
105
106
|
from agno.utils.safe_formatter import SafeFormatter
|
|
106
|
-
from agno.utils.string import parse_response_model_str
|
|
107
|
+
from agno.utils.string import generate_id_from_name, parse_response_model_str
|
|
107
108
|
from agno.utils.team import format_member_agent_task, get_member_id
|
|
108
109
|
from agno.utils.timer import Timer
|
|
109
110
|
|
|
@@ -579,10 +580,7 @@ class Team:
|
|
|
579
580
|
If the name is not provided, generate a random UUID.
|
|
580
581
|
"""
|
|
581
582
|
if self.id is None:
|
|
582
|
-
|
|
583
|
-
self.id = self.name.lower().replace(" ", "-")
|
|
584
|
-
else:
|
|
585
|
-
self.id = str(uuid4())
|
|
583
|
+
self.id = generate_id_from_name(self.name)
|
|
586
584
|
|
|
587
585
|
def _set_debug(self, debug_mode: Optional[bool] = None) -> None:
|
|
588
586
|
if self.debug_mode or debug_mode or getenv("AGNO_DEBUG", "false").lower() == "true":
|
|
@@ -621,8 +619,6 @@ class Team:
|
|
|
621
619
|
if isinstance(input, BaseModel):
|
|
622
620
|
if isinstance(input, self.input_schema):
|
|
623
621
|
try:
|
|
624
|
-
# Re-validate to catch any field validation errors
|
|
625
|
-
input.model_validate(input.model_dump())
|
|
626
622
|
return input
|
|
627
623
|
except Exception as e:
|
|
628
624
|
raise ValueError(f"BaseModel validation failed: {str(e)}")
|
|
@@ -633,8 +629,13 @@ class Team:
|
|
|
633
629
|
# Case 2: Message is a dict
|
|
634
630
|
elif isinstance(input, dict):
|
|
635
631
|
try:
|
|
636
|
-
|
|
637
|
-
|
|
632
|
+
# Check if the schema is a TypedDict
|
|
633
|
+
if is_typed_dict(self.input_schema):
|
|
634
|
+
validated_dict = validate_typed_dict(input, self.input_schema)
|
|
635
|
+
return validated_dict
|
|
636
|
+
else:
|
|
637
|
+
validated_model = self.input_schema(**input)
|
|
638
|
+
return validated_model
|
|
638
639
|
except Exception as e:
|
|
639
640
|
raise ValueError(f"Failed to parse dict into {self.input_schema.__name__}: {str(e)}")
|
|
640
641
|
|
|
@@ -655,8 +656,6 @@ class Team:
|
|
|
655
656
|
member.set_id()
|
|
656
657
|
|
|
657
658
|
elif isinstance(member, Team):
|
|
658
|
-
if member.id is None:
|
|
659
|
-
member.id = str(uuid4())
|
|
660
659
|
member.parent_team_id = self.id
|
|
661
660
|
for sub_member in member.members:
|
|
662
661
|
self._initialize_member(sub_member, debug_mode=debug_mode)
|
|
@@ -806,9 +805,9 @@ class Team:
|
|
|
806
805
|
1. Reason about the task(s) if reasoning is enabled
|
|
807
806
|
2. Get a response from the model
|
|
808
807
|
3. Update Team Memory
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
808
|
+
4. Add RunOutput to Team Session
|
|
809
|
+
5. Calculate session metrics
|
|
810
|
+
6. Save session to storage
|
|
812
811
|
"""
|
|
813
812
|
log_debug(f"Team Run Start: {run_response.run_id}", center=True)
|
|
814
813
|
|
|
@@ -849,10 +848,15 @@ class Team:
|
|
|
849
848
|
else:
|
|
850
849
|
self._scrub_media_from_run_output(run_response)
|
|
851
850
|
|
|
852
|
-
|
|
851
|
+
run_response.status = RunStatus.completed
|
|
852
|
+
|
|
853
|
+
# Parse team response model
|
|
854
|
+
self._convert_response_to_structured_format(run_response=run_response)
|
|
855
|
+
|
|
856
|
+
# 3. Add the RunOutput to Team Session
|
|
853
857
|
session.upsert_run(run_response=run_response)
|
|
854
858
|
|
|
855
|
-
#
|
|
859
|
+
# 4. Update Team Memory
|
|
856
860
|
response_iterator = self._make_memories_and_summaries(
|
|
857
861
|
run_response=run_response,
|
|
858
862
|
run_messages=run_messages,
|
|
@@ -864,11 +868,6 @@ class Team:
|
|
|
864
868
|
# 5. Calculate session metrics
|
|
865
869
|
self._update_session_metrics(session=session)
|
|
866
870
|
|
|
867
|
-
run_response.status = RunStatus.completed
|
|
868
|
-
|
|
869
|
-
# 5. Parse team response model
|
|
870
|
-
self._convert_response_to_structured_format(run_response=run_response)
|
|
871
|
-
|
|
872
871
|
# 6. Save session to storage
|
|
873
872
|
self.save_session(session=session)
|
|
874
873
|
|
|
@@ -899,8 +898,9 @@ class Team:
|
|
|
899
898
|
1. Reason about the task(s) if reasoning is enabled
|
|
900
899
|
2. Get a response from the model
|
|
901
900
|
3. Update Team Memory
|
|
902
|
-
4.
|
|
903
|
-
5.
|
|
901
|
+
4. Add RunOutput to Team Session
|
|
902
|
+
5. Calculate session metrics
|
|
903
|
+
6. Save session to storage
|
|
904
904
|
"""
|
|
905
905
|
|
|
906
906
|
log_debug(f"Team Run Start: {run_response.run_id}", center=True)
|
|
@@ -973,10 +973,12 @@ class Team:
|
|
|
973
973
|
session=session, run_response=run_response, stream_intermediate_steps=stream_intermediate_steps
|
|
974
974
|
)
|
|
975
975
|
|
|
976
|
-
|
|
976
|
+
run_response.status = RunStatus.completed
|
|
977
|
+
|
|
978
|
+
# 3. Add the run to Team Session
|
|
977
979
|
session.upsert_run(run_response=run_response)
|
|
978
980
|
|
|
979
|
-
#
|
|
981
|
+
# 4. Update Team Memory
|
|
980
982
|
yield from self._make_memories_and_summaries(
|
|
981
983
|
run_response=run_response,
|
|
982
984
|
run_messages=run_messages,
|
|
@@ -987,8 +989,6 @@ class Team:
|
|
|
987
989
|
# 5. Calculate session metrics
|
|
988
990
|
self._update_session_metrics(session=session)
|
|
989
991
|
|
|
990
|
-
run_response.status = RunStatus.completed
|
|
991
|
-
|
|
992
992
|
completed_event = self._handle_event(
|
|
993
993
|
create_team_run_completed_event(
|
|
994
994
|
from_run_response=run_response,
|
|
@@ -1338,35 +1338,72 @@ class Team:
|
|
|
1338
1338
|
async def _arun(
|
|
1339
1339
|
self,
|
|
1340
1340
|
run_response: TeamRunOutput,
|
|
1341
|
-
|
|
1341
|
+
input_message: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
|
1342
1342
|
session: TeamSession,
|
|
1343
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
1343
1344
|
user_id: Optional[str] = None,
|
|
1345
|
+
images: Optional[Sequence[Image]] = None,
|
|
1346
|
+
videos: Optional[Sequence[Video]] = None,
|
|
1347
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
1348
|
+
files: Optional[Sequence[File]] = None,
|
|
1349
|
+
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
1350
|
+
add_history_to_context: Optional[bool] = None,
|
|
1351
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
1352
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
1353
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1344
1354
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
1355
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
1356
|
+
**kwargs: Any,
|
|
1345
1357
|
) -> TeamRunOutput:
|
|
1346
1358
|
"""Run the Team and return the response.
|
|
1347
1359
|
|
|
1348
1360
|
Steps:
|
|
1349
|
-
1.
|
|
1350
|
-
2.
|
|
1351
|
-
3.
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1361
|
+
1. Resolve dependencies
|
|
1362
|
+
2. Prepare run messages
|
|
1363
|
+
3. Reason about the task(s) if reasoning is enabled
|
|
1364
|
+
4. Get a response from the model
|
|
1365
|
+
5. Update Team Memory
|
|
1366
|
+
6. Add RunOutput to Team Session
|
|
1367
|
+
7. Calculate session metrics
|
|
1368
|
+
8. Save session to storage
|
|
1355
1369
|
"""
|
|
1356
|
-
|
|
1370
|
+
# 1. Resolve callable dependencies if present
|
|
1371
|
+
if dependencies is not None:
|
|
1372
|
+
await self._aresolve_run_dependencies(dependencies=dependencies)
|
|
1373
|
+
|
|
1374
|
+
# 2. Prepare run messages
|
|
1375
|
+
run_messages = self._get_run_messages(
|
|
1376
|
+
run_response=run_response,
|
|
1377
|
+
session=session,
|
|
1378
|
+
session_state=session_state,
|
|
1379
|
+
user_id=user_id,
|
|
1380
|
+
input_message=input_message,
|
|
1381
|
+
audio=audio,
|
|
1382
|
+
images=images,
|
|
1383
|
+
videos=videos,
|
|
1384
|
+
files=files,
|
|
1385
|
+
knowledge_filters=knowledge_filters,
|
|
1386
|
+
add_history_to_context=add_history_to_context,
|
|
1387
|
+
dependencies=dependencies,
|
|
1388
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
1389
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
1390
|
+
metadata=metadata,
|
|
1391
|
+
**kwargs,
|
|
1392
|
+
)
|
|
1357
1393
|
|
|
1394
|
+
self.model = cast(Model, self.model)
|
|
1358
1395
|
log_debug(f"Team Run Start: {run_response.run_id}", center=True)
|
|
1359
1396
|
|
|
1360
1397
|
# Register run for cancellation tracking
|
|
1361
1398
|
register_run(run_response.run_id) # type: ignore
|
|
1362
1399
|
|
|
1363
|
-
#
|
|
1400
|
+
# 3. Reason about the task(s) if reasoning is enabled
|
|
1364
1401
|
await self._ahandle_reasoning(run_response=run_response, run_messages=run_messages)
|
|
1365
1402
|
|
|
1366
1403
|
# Check for cancellation before model call
|
|
1367
1404
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
1368
1405
|
|
|
1369
|
-
#
|
|
1406
|
+
# 4. Get the model response for the team leader
|
|
1370
1407
|
model_response = await self.model.aresponse(
|
|
1371
1408
|
messages=run_messages.messages,
|
|
1372
1409
|
tools=self._tools_for_model,
|
|
@@ -1393,10 +1430,15 @@ class Team:
|
|
|
1393
1430
|
else:
|
|
1394
1431
|
self._scrub_media_from_run_output(run_response)
|
|
1395
1432
|
|
|
1396
|
-
|
|
1433
|
+
run_response.status = RunStatus.completed
|
|
1434
|
+
|
|
1435
|
+
# Parse team response model
|
|
1436
|
+
self._convert_response_to_structured_format(run_response=run_response)
|
|
1437
|
+
|
|
1438
|
+
# 5. Add the run to memory
|
|
1397
1439
|
session.upsert_run(run_response=run_response)
|
|
1398
1440
|
|
|
1399
|
-
#
|
|
1441
|
+
# 6. Update Team Memory
|
|
1400
1442
|
async for _ in self._amake_memories_and_summaries(
|
|
1401
1443
|
run_response=run_response,
|
|
1402
1444
|
session=session,
|
|
@@ -1405,18 +1447,13 @@ class Team:
|
|
|
1405
1447
|
):
|
|
1406
1448
|
pass
|
|
1407
1449
|
|
|
1408
|
-
#
|
|
1450
|
+
# 7. Calculate session metrics
|
|
1409
1451
|
self._update_session_metrics(session=session)
|
|
1410
1452
|
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
# 6. Parse team response model
|
|
1414
|
-
self._convert_response_to_structured_format(run_response=run_response)
|
|
1415
|
-
|
|
1416
|
-
# 7. Save session to storage
|
|
1453
|
+
# 8. Save session to storage
|
|
1417
1454
|
self.save_session(session=session)
|
|
1418
1455
|
|
|
1419
|
-
#
|
|
1456
|
+
# Log Team Telemetry
|
|
1420
1457
|
await self._alog_team_telemetry(session_id=session.session_id, run_id=run_response.run_id)
|
|
1421
1458
|
|
|
1422
1459
|
log_debug(f"Team Run End: {run_response.run_id}", center=True, symbol="*")
|
|
@@ -1429,25 +1466,64 @@ class Team:
|
|
|
1429
1466
|
async def _arun_stream(
|
|
1430
1467
|
self,
|
|
1431
1468
|
run_response: TeamRunOutput,
|
|
1432
|
-
|
|
1469
|
+
input_message: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
|
1433
1470
|
session: TeamSession,
|
|
1471
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
1434
1472
|
user_id: Optional[str] = None,
|
|
1473
|
+
images: Optional[Sequence[Image]] = None,
|
|
1474
|
+
videos: Optional[Sequence[Video]] = None,
|
|
1475
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
1476
|
+
files: Optional[Sequence[File]] = None,
|
|
1477
|
+
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
1478
|
+
add_history_to_context: Optional[bool] = None,
|
|
1479
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
1480
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
1481
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1435
1482
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
1483
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
1436
1484
|
stream_intermediate_steps: bool = False,
|
|
1437
1485
|
workflow_context: Optional[Dict] = None,
|
|
1438
1486
|
yield_run_response: bool = False,
|
|
1487
|
+
**kwargs: Any,
|
|
1439
1488
|
) -> AsyncIterator[Union[TeamRunOutputEvent, RunOutputEvent, TeamRunOutput]]:
|
|
1440
1489
|
"""Run the Team and return the response.
|
|
1441
1490
|
|
|
1442
1491
|
Steps:
|
|
1443
|
-
1.
|
|
1444
|
-
2.
|
|
1445
|
-
3.
|
|
1446
|
-
4.
|
|
1447
|
-
5.
|
|
1492
|
+
1. Resolve dependencies
|
|
1493
|
+
2. Prepare run messages
|
|
1494
|
+
3. Reason about the task(s) if reasoning is enabled
|
|
1495
|
+
4. Get a response from the model
|
|
1496
|
+
5. Update Team Memory
|
|
1497
|
+
6. Add RunOutput to Team Session
|
|
1498
|
+
7. Calculate session metrics
|
|
1499
|
+
8. Save session to storage
|
|
1448
1500
|
"""
|
|
1449
|
-
log_debug(f"Team Run Start: {run_response.run_id}", center=True)
|
|
1450
1501
|
|
|
1502
|
+
# 1. Resolve callable dependencies if present
|
|
1503
|
+
if dependencies is not None:
|
|
1504
|
+
await self._aresolve_run_dependencies(dependencies=dependencies)
|
|
1505
|
+
|
|
1506
|
+
# 2. Prepare run messages
|
|
1507
|
+
run_messages = self._get_run_messages(
|
|
1508
|
+
run_response=run_response,
|
|
1509
|
+
session=session,
|
|
1510
|
+
session_state=session_state,
|
|
1511
|
+
user_id=user_id,
|
|
1512
|
+
input_message=input_message,
|
|
1513
|
+
audio=audio,
|
|
1514
|
+
images=images,
|
|
1515
|
+
videos=videos,
|
|
1516
|
+
files=files,
|
|
1517
|
+
knowledge_filters=knowledge_filters,
|
|
1518
|
+
add_history_to_context=add_history_to_context,
|
|
1519
|
+
dependencies=dependencies,
|
|
1520
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
1521
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
1522
|
+
metadata=metadata,
|
|
1523
|
+
**kwargs,
|
|
1524
|
+
)
|
|
1525
|
+
|
|
1526
|
+
log_debug(f"Team Run Start: {run_response.run_id}", center=True)
|
|
1451
1527
|
# Register run for cancellation tracking
|
|
1452
1528
|
register_run(run_response.run_id) # type: ignore
|
|
1453
1529
|
|
|
@@ -1458,7 +1534,7 @@ class Team:
|
|
|
1458
1534
|
create_team_run_started_event(from_run_response=run_response), run_response, workflow_context
|
|
1459
1535
|
)
|
|
1460
1536
|
|
|
1461
|
-
#
|
|
1537
|
+
# 3. Reason about the task(s) if reasoning is enabled
|
|
1462
1538
|
async for item in self._ahandle_reasoning_stream(run_response=run_response, run_messages=run_messages):
|
|
1463
1539
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
1464
1540
|
yield item
|
|
@@ -1466,7 +1542,7 @@ class Team:
|
|
|
1466
1542
|
# Check for cancellation before model processing
|
|
1467
1543
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
1468
1544
|
|
|
1469
|
-
#
|
|
1545
|
+
# 4. Get a response from the model
|
|
1470
1546
|
if self.output_model is None:
|
|
1471
1547
|
async for event in self._ahandle_model_response_stream(
|
|
1472
1548
|
session=session,
|
|
@@ -1518,10 +1594,12 @@ class Team:
|
|
|
1518
1594
|
):
|
|
1519
1595
|
yield event
|
|
1520
1596
|
|
|
1521
|
-
|
|
1597
|
+
run_response.status = RunStatus.completed
|
|
1598
|
+
|
|
1599
|
+
# 5. Add the run to Team Session
|
|
1522
1600
|
session.upsert_run(run_response=run_response)
|
|
1523
1601
|
|
|
1524
|
-
#
|
|
1602
|
+
# 6. Update Team Memory
|
|
1525
1603
|
async for event in self._amake_memories_and_summaries(
|
|
1526
1604
|
run_response=run_response,
|
|
1527
1605
|
session=session,
|
|
@@ -1530,16 +1608,14 @@ class Team:
|
|
|
1530
1608
|
):
|
|
1531
1609
|
yield event
|
|
1532
1610
|
|
|
1533
|
-
#
|
|
1611
|
+
# 7. Calculate session metrics
|
|
1534
1612
|
self._update_session_metrics(session=session)
|
|
1535
1613
|
|
|
1536
|
-
run_response.status = RunStatus.completed
|
|
1537
|
-
|
|
1538
1614
|
completed_event = self._handle_event(
|
|
1539
1615
|
create_team_run_completed_event(from_run_response=run_response), run_response, workflow_context
|
|
1540
1616
|
)
|
|
1541
1617
|
|
|
1542
|
-
#
|
|
1618
|
+
# 8. Save session to storage
|
|
1543
1619
|
self.save_session(session=session)
|
|
1544
1620
|
|
|
1545
1621
|
if stream_intermediate_steps:
|
|
@@ -1548,7 +1624,7 @@ class Team:
|
|
|
1548
1624
|
if yield_run_response:
|
|
1549
1625
|
yield run_response
|
|
1550
1626
|
|
|
1551
|
-
#
|
|
1627
|
+
# Log Team Telemetry
|
|
1552
1628
|
await self._alog_team_telemetry(session_id=session.session_id, run_id=run_response.run_id)
|
|
1553
1629
|
|
|
1554
1630
|
log_debug(f"Team Run End: {run_response.run_id}", center=True, symbol="*")
|
|
@@ -1681,10 +1757,6 @@ class Team:
|
|
|
1681
1757
|
# Determine run dependencies (runtime override takes priority)
|
|
1682
1758
|
run_dependencies = dependencies if dependencies is not None else self.dependencies
|
|
1683
1759
|
|
|
1684
|
-
# Resolve callable dependencies if present
|
|
1685
|
-
if run_dependencies is not None:
|
|
1686
|
-
self._resolve_run_dependencies(dependencies=run_dependencies)
|
|
1687
|
-
|
|
1688
1760
|
# Determine runtime context parameters
|
|
1689
1761
|
add_dependencies = (
|
|
1690
1762
|
add_dependencies_to_context if add_dependencies_to_context is not None else self.add_dependencies_to_context
|
|
@@ -1781,43 +1853,49 @@ class Team:
|
|
|
1781
1853
|
for attempt in range(num_attempts):
|
|
1782
1854
|
# Run the team
|
|
1783
1855
|
try:
|
|
1784
|
-
run_messages = self._get_run_messages(
|
|
1785
|
-
run_response=run_response,
|
|
1786
|
-
session=team_session, # type: ignore
|
|
1787
|
-
session_state=session_state,
|
|
1788
|
-
user_id=user_id,
|
|
1789
|
-
input_message=validated_input,
|
|
1790
|
-
audio=audio,
|
|
1791
|
-
images=images,
|
|
1792
|
-
videos=videos,
|
|
1793
|
-
files=files,
|
|
1794
|
-
knowledge_filters=effective_filters,
|
|
1795
|
-
add_history_to_context=add_history,
|
|
1796
|
-
dependencies=run_dependencies,
|
|
1797
|
-
add_dependencies_to_context=add_dependencies,
|
|
1798
|
-
add_session_state_to_context=add_session_state,
|
|
1799
|
-
**kwargs,
|
|
1800
|
-
)
|
|
1801
|
-
|
|
1802
1856
|
if stream:
|
|
1803
1857
|
response_iterator = self._arun_stream(
|
|
1804
1858
|
run_response=run_response,
|
|
1805
|
-
|
|
1859
|
+
input_message=validated_input,
|
|
1806
1860
|
session=team_session, # type: ignore
|
|
1861
|
+
session_state=session_state,
|
|
1807
1862
|
user_id=user_id,
|
|
1863
|
+
audio=audio,
|
|
1864
|
+
images=images,
|
|
1865
|
+
videos=videos,
|
|
1866
|
+
files=files,
|
|
1867
|
+
knowledge_filters=effective_filters,
|
|
1868
|
+
add_history_to_context=add_history,
|
|
1869
|
+
add_dependencies_to_context=add_dependencies,
|
|
1870
|
+
add_session_state_to_context=add_session_state,
|
|
1871
|
+
metadata=metadata,
|
|
1808
1872
|
response_format=response_format,
|
|
1873
|
+
dependencies=run_dependencies,
|
|
1809
1874
|
stream_intermediate_steps=stream_intermediate_steps,
|
|
1810
1875
|
workflow_context=workflow_context,
|
|
1811
1876
|
yield_run_response=yield_run_response,
|
|
1877
|
+
**kwargs,
|
|
1812
1878
|
)
|
|
1813
1879
|
return response_iterator # type: ignore
|
|
1814
1880
|
else:
|
|
1815
1881
|
return self._arun( # type: ignore
|
|
1816
1882
|
run_response=run_response,
|
|
1817
|
-
|
|
1883
|
+
input_message=validated_input,
|
|
1818
1884
|
session=team_session, # type: ignore
|
|
1819
1885
|
user_id=user_id,
|
|
1886
|
+
session_state=session_state,
|
|
1887
|
+
audio=audio,
|
|
1888
|
+
images=images,
|
|
1889
|
+
videos=videos,
|
|
1890
|
+
files=files,
|
|
1891
|
+
knowledge_filters=effective_filters,
|
|
1892
|
+
add_history_to_context=add_history,
|
|
1893
|
+
add_dependencies_to_context=add_dependencies,
|
|
1894
|
+
add_session_state_to_context=add_session_state,
|
|
1895
|
+
metadata=metadata,
|
|
1820
1896
|
response_format=response_format,
|
|
1897
|
+
dependencies=run_dependencies,
|
|
1898
|
+
**kwargs,
|
|
1821
1899
|
)
|
|
1822
1900
|
|
|
1823
1901
|
except ModelProviderError as e:
|
|
@@ -2284,11 +2362,13 @@ class Team:
|
|
|
2284
2362
|
tc.tool_call_id: i for i, tc in enumerate(run_response.tools) if tc.tool_call_id is not None
|
|
2285
2363
|
}
|
|
2286
2364
|
# Process tool calls
|
|
2287
|
-
for
|
|
2288
|
-
tool_call_id =
|
|
2365
|
+
for tool_execution in tool_executions_list:
|
|
2366
|
+
tool_call_id = tool_execution.tool_call_id or ""
|
|
2289
2367
|
index = tool_call_index_map.get(tool_call_id)
|
|
2290
2368
|
if index is not None:
|
|
2291
|
-
run_response.tools[index]
|
|
2369
|
+
if run_response.tools[index].child_run_id is not None:
|
|
2370
|
+
tool_execution.child_run_id = run_response.tools[index].child_run_id
|
|
2371
|
+
run_response.tools[index] = tool_execution
|
|
2292
2372
|
else:
|
|
2293
2373
|
run_response.tools = tool_executions_list
|
|
2294
2374
|
|
|
@@ -3731,7 +3811,7 @@ class Team:
|
|
|
3731
3811
|
|
|
3732
3812
|
try:
|
|
3733
3813
|
sig = signature(value)
|
|
3734
|
-
resolved_value = value(
|
|
3814
|
+
resolved_value = value(team=self) if "team" in sig.parameters else value()
|
|
3735
3815
|
|
|
3736
3816
|
if iscoroutine(resolved_value):
|
|
3737
3817
|
resolved_value = await resolved_value
|
|
@@ -4392,8 +4472,8 @@ class Team:
|
|
|
4392
4472
|
f"<additional_context>\n{self.additional_context.strip()}\n</additional_context>\n\n"
|
|
4393
4473
|
)
|
|
4394
4474
|
|
|
4395
|
-
if self.add_session_state_to_context:
|
|
4396
|
-
system_message_content +=
|
|
4475
|
+
if self.add_session_state_to_context and session_state is not None:
|
|
4476
|
+
system_message_content += self._get_formatted_session_state_for_system_message(session_state)
|
|
4397
4477
|
|
|
4398
4478
|
# Add the JSON output prompt if output_schema is provided and structured_outputs is False
|
|
4399
4479
|
if (
|
|
@@ -4406,6 +4486,9 @@ class Team:
|
|
|
4406
4486
|
|
|
4407
4487
|
return Message(role=self.system_message_role, content=system_message_content.strip())
|
|
4408
4488
|
|
|
4489
|
+
def _get_formatted_session_state_for_system_message(self, session_state: Dict[str, Any]) -> str:
|
|
4490
|
+
return f"\n<session_state>\n{session_state}\n</session_state>\n\n"
|
|
4491
|
+
|
|
4409
4492
|
def _get_run_messages(
|
|
4410
4493
|
self,
|
|
4411
4494
|
*,
|
|
@@ -4597,7 +4680,13 @@ class Team:
|
|
|
4597
4680
|
# If message is provided as a dict, try to validate it as a Message
|
|
4598
4681
|
elif isinstance(input_message, dict):
|
|
4599
4682
|
try:
|
|
4600
|
-
|
|
4683
|
+
if self.input_schema and is_typed_dict(self.input_schema):
|
|
4684
|
+
import json
|
|
4685
|
+
|
|
4686
|
+
content = json.dumps(input_message, indent=2, ensure_ascii=False)
|
|
4687
|
+
return Message(role="user", content=content)
|
|
4688
|
+
else:
|
|
4689
|
+
return Message.model_validate(input_message)
|
|
4601
4690
|
except Exception as e:
|
|
4602
4691
|
log_warning(f"Failed to validate input: {e}")
|
|
4603
4692
|
|
|
@@ -5158,6 +5247,12 @@ class Team:
|
|
|
5158
5247
|
if member_agent_run_response is not None:
|
|
5159
5248
|
member_agent_run_response.parent_run_id = run_response.run_id # type: ignore
|
|
5160
5249
|
|
|
5250
|
+
# Update the top-level team run_response tool call to have the run_id of the member run
|
|
5251
|
+
if run_response.tools is not None:
|
|
5252
|
+
for tool in run_response.tools:
|
|
5253
|
+
if tool.tool_name and tool.tool_name.lower() == "delegate_task_to_member":
|
|
5254
|
+
tool.child_run_id = member_agent_run_response.run_id # type: ignore
|
|
5255
|
+
|
|
5161
5256
|
# Update the team run context
|
|
5162
5257
|
member_name = member_agent.name if member_agent.name else member_agent.id if member_agent.id else "Unknown"
|
|
5163
5258
|
if isinstance(member_agent_task, str):
|
agno/tools/duckduckgo.py
CHANGED
|
@@ -12,14 +12,16 @@ except ImportError:
|
|
|
12
12
|
|
|
13
13
|
class DuckDuckGoTools(Toolkit):
|
|
14
14
|
"""
|
|
15
|
-
DuckDuckGo is a toolkit for searching DuckDuckGo easily.
|
|
15
|
+
DuckDuckGo is a toolkit for searching using DuckDuckGo easily.
|
|
16
|
+
It uses the meta-search library DDGS, so it also has access to other backends.
|
|
16
17
|
Args:
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
enable_search (bool): Enable DDGS search function.
|
|
19
|
+
enable_news (bool): Enable DDGS news function.
|
|
19
20
|
modifier (Optional[str]): A modifier to be used in the search request.
|
|
20
21
|
fixed_max_results (Optional[int]): A fixed number of maximum results.
|
|
21
22
|
proxy (Optional[str]): Proxy to be used in the search request.
|
|
22
23
|
timeout (Optional[int]): The maximum number of seconds to wait for a response.
|
|
24
|
+
backend (Optional[str]): The backend to be used in the search request.
|
|
23
25
|
|
|
24
26
|
"""
|
|
25
27
|
|
|
@@ -28,6 +30,7 @@ class DuckDuckGoTools(Toolkit):
|
|
|
28
30
|
enable_search: bool = True,
|
|
29
31
|
enable_news: bool = True,
|
|
30
32
|
all: bool = False,
|
|
33
|
+
backend: str = "duckduckgo",
|
|
31
34
|
modifier: Optional[str] = None,
|
|
32
35
|
fixed_max_results: Optional[int] = None,
|
|
33
36
|
proxy: Optional[str] = None,
|
|
@@ -40,6 +43,7 @@ class DuckDuckGoTools(Toolkit):
|
|
|
40
43
|
self.fixed_max_results: Optional[int] = fixed_max_results
|
|
41
44
|
self.modifier: Optional[str] = modifier
|
|
42
45
|
self.verify_ssl: bool = verify_ssl
|
|
46
|
+
self.backend: str = backend
|
|
43
47
|
|
|
44
48
|
tools: List[Any] = []
|
|
45
49
|
if all or enable_search:
|
|
@@ -50,38 +54,38 @@ class DuckDuckGoTools(Toolkit):
|
|
|
50
54
|
super().__init__(name="duckduckgo", tools=tools, **kwargs)
|
|
51
55
|
|
|
52
56
|
def duckduckgo_search(self, query: str, max_results: int = 5) -> str:
|
|
53
|
-
"""Use this function to search
|
|
57
|
+
"""Use this function to search DDGS for a query.
|
|
54
58
|
|
|
55
59
|
Args:
|
|
56
60
|
query(str): The query to search for.
|
|
57
61
|
max_results (optional, default=5): The maximum number of results to return.
|
|
58
62
|
|
|
59
63
|
Returns:
|
|
60
|
-
The result from
|
|
64
|
+
The result from DDGS.
|
|
61
65
|
"""
|
|
62
66
|
actual_max_results = self.fixed_max_results or max_results
|
|
63
67
|
search_query = f"{self.modifier} {query}" if self.modifier else query
|
|
64
68
|
|
|
65
|
-
log_debug(f"Searching DDG for: {search_query}")
|
|
69
|
+
log_debug(f"Searching DDG for: {search_query} using backend: {self.backend}")
|
|
66
70
|
with DDGS(proxy=self.proxy, timeout=self.timeout, verify=self.verify_ssl) as ddgs:
|
|
67
|
-
results = ddgs.text(query=search_query, max_results=actual_max_results)
|
|
71
|
+
results = ddgs.text(query=search_query, max_results=actual_max_results, backend=self.backend)
|
|
68
72
|
|
|
69
73
|
return json.dumps(results, indent=2)
|
|
70
74
|
|
|
71
75
|
def duckduckgo_news(self, query: str, max_results: int = 5) -> str:
|
|
72
|
-
"""Use this function to get the latest news from
|
|
76
|
+
"""Use this function to get the latest news from DDGS.
|
|
73
77
|
|
|
74
78
|
Args:
|
|
75
79
|
query(str): The query to search for.
|
|
76
80
|
max_results (optional, default=5): The maximum number of results to return.
|
|
77
81
|
|
|
78
82
|
Returns:
|
|
79
|
-
The latest news from
|
|
83
|
+
The latest news from DDGS.
|
|
80
84
|
"""
|
|
81
85
|
actual_max_results = self.fixed_max_results or max_results
|
|
82
86
|
|
|
83
|
-
log_debug(f"Searching DDG news for: {query}")
|
|
87
|
+
log_debug(f"Searching DDG news for: {query} using backend: {self.backend}")
|
|
84
88
|
with DDGS(proxy=self.proxy, timeout=self.timeout, verify=self.verify_ssl) as ddgs:
|
|
85
|
-
results = ddgs.news(query=query, max_results=actual_max_results)
|
|
89
|
+
results = ddgs.news(query=query, max_results=actual_max_results, backend=self.backend)
|
|
86
90
|
|
|
87
91
|
return json.dumps(results, indent=2)
|
agno/tools/googlesearch.py
CHANGED
|
@@ -82,7 +82,7 @@ class GoogleSearchTools(Toolkit):
|
|
|
82
82
|
log_debug(f"Searching Google [{language}] for: {query}")
|
|
83
83
|
|
|
84
84
|
# Perform Google search using the googlesearch-python package
|
|
85
|
-
results = list(search(query,
|
|
85
|
+
results = list(search(query, num_results=max_results, lang=language))
|
|
86
86
|
|
|
87
87
|
# Collect the search results
|
|
88
88
|
res: List[Dict[str, str]] = []
|