agno 2.0.3__py3-none-any.whl → 2.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/agent/agent.py +162 -86
- agno/db/dynamo/dynamo.py +8 -0
- agno/db/firestore/firestore.py +8 -1
- agno/db/gcs_json/gcs_json_db.py +9 -0
- agno/db/json/json_db.py +8 -0
- agno/db/mongo/mongo.py +10 -1
- agno/db/mysql/mysql.py +10 -0
- agno/db/postgres/postgres.py +16 -8
- 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 +9 -1
- agno/db/utils.py +14 -0
- agno/knowledge/knowledge.py +91 -65
- agno/models/base.py +2 -2
- agno/models/openai/chat.py +3 -0
- agno/models/openai/responses.py +6 -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 +4 -1
- agno/os/auth.py +24 -14
- agno/os/router.py +128 -55
- agno/os/routers/evals/utils.py +9 -9
- agno/os/routers/health.py +26 -0
- agno/os/routers/knowledge/knowledge.py +11 -11
- agno/os/routers/session/session.py +24 -8
- agno/os/schema.py +8 -2
- agno/run/workflow.py +64 -10
- agno/session/team.py +1 -0
- agno/team/team.py +192 -92
- 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/vectordb/chroma/chromadb.py +8 -2
- agno/workflow/step.py +111 -13
- agno/workflow/workflow.py +16 -13
- {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/METADATA +1 -1
- {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/RECORD +43 -40
- {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/WHEEL +0 -0
- {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/licenses/LICENSE +0 -0
- {agno-2.0.3.dist-info → agno-2.0.4.dist-info}/top_level.txt +0 -0
agno/agent/agent.py
CHANGED
|
@@ -57,6 +57,7 @@ from agno.run.team import TeamRunOutputEvent
|
|
|
57
57
|
from agno.session import AgentSession, SessionSummaryManager
|
|
58
58
|
from agno.tools import Toolkit
|
|
59
59
|
from agno.tools.function import Function
|
|
60
|
+
from agno.utils.common import is_typed_dict, validate_typed_dict
|
|
60
61
|
from agno.utils.events import (
|
|
61
62
|
create_memory_update_completed_event,
|
|
62
63
|
create_memory_update_started_event,
|
|
@@ -281,7 +282,7 @@ class Agent:
|
|
|
281
282
|
|
|
282
283
|
# --- Agent Response Model Settings ---
|
|
283
284
|
# Provide an input schema to validate the input
|
|
284
|
-
input_schema: Optional[Type[BaseModel]] = None
|
|
285
|
+
input_schema: Optional[Union[Type[BaseModel], type]] = None
|
|
285
286
|
# Provide a response model to get the response as a Pydantic model
|
|
286
287
|
output_schema: Optional[Type[BaseModel]] = None
|
|
287
288
|
# Provide a secondary model to parse the response from the primary model
|
|
@@ -398,13 +399,14 @@ class Agent:
|
|
|
398
399
|
timezone_identifier: Optional[str] = None,
|
|
399
400
|
resolve_in_context: bool = True,
|
|
400
401
|
additional_input: Optional[List[Union[str, Dict, BaseModel, Message]]] = None,
|
|
402
|
+
user_message_role: str = "user",
|
|
401
403
|
build_user_context: bool = True,
|
|
402
404
|
retries: int = 0,
|
|
403
405
|
delay_between_retries: int = 1,
|
|
404
406
|
exponential_backoff: bool = False,
|
|
405
407
|
parser_model: Optional[Model] = None,
|
|
406
408
|
parser_model_prompt: Optional[str] = None,
|
|
407
|
-
input_schema: Optional[Type[BaseModel]] = None,
|
|
409
|
+
input_schema: Optional[Union[Type[BaseModel], type]] = None,
|
|
408
410
|
output_schema: Optional[Type[BaseModel]] = None,
|
|
409
411
|
parse_response: bool = True,
|
|
410
412
|
output_model: Optional[Model] = None,
|
|
@@ -495,7 +497,7 @@ class Agent:
|
|
|
495
497
|
self.timezone_identifier = timezone_identifier
|
|
496
498
|
self.resolve_in_context = resolve_in_context
|
|
497
499
|
self.additional_input = additional_input
|
|
498
|
-
|
|
500
|
+
self.user_message_role = user_message_role
|
|
499
501
|
self.build_user_context = build_user_context
|
|
500
502
|
|
|
501
503
|
self.retries = retries
|
|
@@ -602,8 +604,6 @@ class Agent:
|
|
|
602
604
|
if isinstance(input, BaseModel):
|
|
603
605
|
if isinstance(input, self.input_schema):
|
|
604
606
|
try:
|
|
605
|
-
# Re-validate to catch any field validation errors
|
|
606
|
-
input.model_validate(input.model_dump())
|
|
607
607
|
return input
|
|
608
608
|
except Exception as e:
|
|
609
609
|
raise ValueError(f"BaseModel validation failed: {str(e)}")
|
|
@@ -614,8 +614,13 @@ class Agent:
|
|
|
614
614
|
# Case 2: Message is a dict
|
|
615
615
|
elif isinstance(input, dict):
|
|
616
616
|
try:
|
|
617
|
-
|
|
618
|
-
|
|
617
|
+
# Check if the schema is a TypedDict
|
|
618
|
+
if is_typed_dict(self.input_schema):
|
|
619
|
+
validated_dict = validate_typed_dict(input, self.input_schema)
|
|
620
|
+
return validated_dict
|
|
621
|
+
else:
|
|
622
|
+
validated_model = self.input_schema(**input)
|
|
623
|
+
return validated_model
|
|
619
624
|
except Exception as e:
|
|
620
625
|
raise ValueError(f"Failed to parse dict into {self.input_schema.__name__}: {str(e)}")
|
|
621
626
|
|
|
@@ -1100,7 +1105,6 @@ class Agent:
|
|
|
1100
1105
|
# Resolve dependencies
|
|
1101
1106
|
if run_dependencies is not None:
|
|
1102
1107
|
self._resolve_run_dependencies(dependencies=run_dependencies)
|
|
1103
|
-
|
|
1104
1108
|
add_dependencies = (
|
|
1105
1109
|
add_dependencies_to_context if add_dependencies_to_context is not None else self.add_dependencies_to_context
|
|
1106
1110
|
)
|
|
@@ -1197,7 +1201,7 @@ class Agent:
|
|
|
1197
1201
|
files=files,
|
|
1198
1202
|
knowledge_filters=effective_filters,
|
|
1199
1203
|
add_history_to_context=add_history,
|
|
1200
|
-
dependencies=
|
|
1204
|
+
dependencies=run_dependencies,
|
|
1201
1205
|
add_dependencies_to_context=add_dependencies,
|
|
1202
1206
|
add_session_state_to_context=add_session_state,
|
|
1203
1207
|
**kwargs,
|
|
@@ -1278,41 +1282,75 @@ class Agent:
|
|
|
1278
1282
|
async def _arun(
|
|
1279
1283
|
self,
|
|
1280
1284
|
run_response: RunOutput,
|
|
1281
|
-
|
|
1285
|
+
input: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
|
1282
1286
|
session: AgentSession,
|
|
1287
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
1283
1288
|
user_id: Optional[str] = None,
|
|
1289
|
+
images: Optional[Sequence[Image]] = None,
|
|
1290
|
+
videos: Optional[Sequence[Video]] = None,
|
|
1291
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
1292
|
+
files: Optional[Sequence[File]] = None,
|
|
1293
|
+
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
1294
|
+
add_history_to_context: Optional[bool] = None,
|
|
1295
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
1296
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
1297
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1284
1298
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
1285
1299
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
1300
|
+
**kwargs: Any,
|
|
1286
1301
|
) -> RunOutput:
|
|
1287
1302
|
"""Run the Agent and yield the RunOutput.
|
|
1288
1303
|
|
|
1289
1304
|
Steps:
|
|
1290
|
-
1.
|
|
1291
|
-
2.
|
|
1292
|
-
3.
|
|
1293
|
-
4.
|
|
1294
|
-
5.
|
|
1295
|
-
6.
|
|
1296
|
-
7.
|
|
1297
|
-
8.
|
|
1305
|
+
1. Resolve dependencies
|
|
1306
|
+
2. Prepare run messages
|
|
1307
|
+
3. Reason about the task if reasoning is enabled
|
|
1308
|
+
4. Generate a response from the Model (includes running function calls)
|
|
1309
|
+
5. Update the RunOutput with the model response
|
|
1310
|
+
6. Update Agent Memory
|
|
1311
|
+
7. Calculate session metrics
|
|
1312
|
+
8. Add RunOutput to Agent Session
|
|
1313
|
+
9. Save session to storage
|
|
1298
1314
|
"""
|
|
1299
|
-
# Resolving here for async requirement
|
|
1315
|
+
# 1. Resolving here for async requirement
|
|
1300
1316
|
if dependencies is not None:
|
|
1301
1317
|
await self._aresolve_run_dependencies(dependencies)
|
|
1302
1318
|
|
|
1319
|
+
# 2. Prepare run messages
|
|
1320
|
+
run_messages: RunMessages = self._get_run_messages(
|
|
1321
|
+
run_response=run_response,
|
|
1322
|
+
input=input,
|
|
1323
|
+
session=session,
|
|
1324
|
+
session_state=session_state,
|
|
1325
|
+
user_id=user_id,
|
|
1326
|
+
audio=audio,
|
|
1327
|
+
images=images,
|
|
1328
|
+
videos=videos,
|
|
1329
|
+
files=files,
|
|
1330
|
+
knowledge_filters=knowledge_filters,
|
|
1331
|
+
add_history_to_context=add_history_to_context,
|
|
1332
|
+
dependencies=dependencies,
|
|
1333
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
1334
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
1335
|
+
metadata=metadata,
|
|
1336
|
+
**kwargs,
|
|
1337
|
+
)
|
|
1338
|
+
if len(run_messages.messages) == 0:
|
|
1339
|
+
log_error("No messages to be sent to the model.")
|
|
1340
|
+
|
|
1303
1341
|
log_debug(f"Agent Run Start: {run_response.run_id}", center=True)
|
|
1304
1342
|
|
|
1305
1343
|
# Register run for cancellation tracking
|
|
1306
1344
|
register_run(run_response.run_id) # type: ignore
|
|
1307
1345
|
|
|
1308
1346
|
self.model = cast(Model, self.model)
|
|
1309
|
-
#
|
|
1347
|
+
# 3. Reason about the task if reasoning is enabled
|
|
1310
1348
|
await self._ahandle_reasoning(run_response=run_response, run_messages=run_messages)
|
|
1311
1349
|
|
|
1312
1350
|
# Check for cancellation before model call
|
|
1313
1351
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
1314
1352
|
|
|
1315
|
-
#
|
|
1353
|
+
# 4. Generate a response from the Model (includes running function calls)
|
|
1316
1354
|
model_response: ModelResponse = await self.model.aresponse(
|
|
1317
1355
|
messages=run_messages.messages,
|
|
1318
1356
|
tools=self._tools_for_model,
|
|
@@ -1331,7 +1369,7 @@ class Agent:
|
|
|
1331
1369
|
# If a parser model is provided, structure the response separately
|
|
1332
1370
|
await self._aparse_response_with_parser_model(model_response=model_response, run_messages=run_messages)
|
|
1333
1371
|
|
|
1334
|
-
#
|
|
1372
|
+
# 5. Update the RunOutput with the model response
|
|
1335
1373
|
self._update_run_response(model_response=model_response, run_response=run_response, run_messages=run_messages)
|
|
1336
1374
|
|
|
1337
1375
|
if self.store_media:
|
|
@@ -1345,13 +1383,13 @@ class Agent:
|
|
|
1345
1383
|
run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
|
|
1346
1384
|
)
|
|
1347
1385
|
|
|
1348
|
-
#
|
|
1386
|
+
# 6. Update Agent Memory
|
|
1349
1387
|
async for _ in self._amake_memories_and_summaries(
|
|
1350
1388
|
run_response=run_response, run_messages=run_messages, session=session, user_id=user_id
|
|
1351
1389
|
):
|
|
1352
1390
|
pass
|
|
1353
1391
|
|
|
1354
|
-
#
|
|
1392
|
+
# 7. Calculate session metrics
|
|
1355
1393
|
self._update_session_metrics(session=session, run_response=run_response)
|
|
1356
1394
|
|
|
1357
1395
|
run_response.status = RunStatus.completed
|
|
@@ -1363,15 +1401,15 @@ class Agent:
|
|
|
1363
1401
|
if run_response.metrics:
|
|
1364
1402
|
run_response.metrics.stop_timer()
|
|
1365
1403
|
|
|
1366
|
-
#
|
|
1404
|
+
# Optional: Save output to file if save_response_to_file is set
|
|
1367
1405
|
self.save_run_response_to_file(
|
|
1368
1406
|
run_response=run_response, input=run_messages.user_message, session_id=session.session_id, user_id=user_id
|
|
1369
1407
|
)
|
|
1370
1408
|
|
|
1371
|
-
#
|
|
1409
|
+
# 8. Add RunOutput to Agent Session
|
|
1372
1410
|
session.upsert_run(run=run_response)
|
|
1373
1411
|
|
|
1374
|
-
#
|
|
1412
|
+
# 9. Save session to storage
|
|
1375
1413
|
self.save_session(session=session)
|
|
1376
1414
|
|
|
1377
1415
|
# Log Agent Telemetry
|
|
@@ -1387,30 +1425,61 @@ class Agent:
|
|
|
1387
1425
|
async def _arun_stream(
|
|
1388
1426
|
self,
|
|
1389
1427
|
run_response: RunOutput,
|
|
1390
|
-
run_messages: RunMessages,
|
|
1391
1428
|
session: AgentSession,
|
|
1429
|
+
input: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
|
1430
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
1431
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
1432
|
+
images: Optional[Sequence[Image]] = None,
|
|
1433
|
+
videos: Optional[Sequence[Video]] = None,
|
|
1434
|
+
files: Optional[Sequence[File]] = None,
|
|
1435
|
+
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
1436
|
+
add_history_to_context: Optional[bool] = None,
|
|
1437
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
1438
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
1439
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1440
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
1392
1441
|
user_id: Optional[str] = None,
|
|
1393
1442
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
1394
1443
|
stream_intermediate_steps: bool = False,
|
|
1395
1444
|
workflow_context: Optional[Dict] = None,
|
|
1396
1445
|
yield_run_response: Optional[bool] = None,
|
|
1397
|
-
|
|
1446
|
+
**kwargs: Any,
|
|
1398
1447
|
) -> AsyncIterator[Union[RunOutputEvent, RunOutput]]:
|
|
1399
1448
|
"""Run the Agent and yield the RunOutput.
|
|
1400
1449
|
|
|
1401
1450
|
Steps:
|
|
1402
|
-
1.
|
|
1403
|
-
2.
|
|
1404
|
-
3.
|
|
1405
|
-
4.
|
|
1406
|
-
5.
|
|
1407
|
-
6.
|
|
1408
|
-
7.
|
|
1451
|
+
1. Resolve dependencies
|
|
1452
|
+
2. Prepare run messages
|
|
1453
|
+
3. Reason about the task if reasoning is enabled
|
|
1454
|
+
4. Generate a response from the Model (includes running function calls)
|
|
1455
|
+
5. Update Agent Memory
|
|
1456
|
+
6. Calculate session metrics
|
|
1457
|
+
7. Add RunOutput to Agent Session
|
|
1458
|
+
8. Save session to storage
|
|
1409
1459
|
"""
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1460
|
+
# 1. Resolving here for async requirement
|
|
1461
|
+
if dependencies is not None:
|
|
1462
|
+
await self._aresolve_run_dependencies(dependencies=dependencies)
|
|
1463
|
+
|
|
1464
|
+
# 2. Prepare run messages
|
|
1465
|
+
run_messages: RunMessages = self._get_run_messages(
|
|
1466
|
+
run_response=run_response,
|
|
1467
|
+
input=input,
|
|
1468
|
+
session=session,
|
|
1469
|
+
session_state=session_state,
|
|
1470
|
+
user_id=user_id,
|
|
1471
|
+
audio=audio,
|
|
1472
|
+
images=images,
|
|
1473
|
+
videos=videos,
|
|
1474
|
+
files=files,
|
|
1475
|
+
knowledge_filters=knowledge_filters,
|
|
1476
|
+
add_history_to_context=add_history_to_context,
|
|
1477
|
+
dependencies=dependencies,
|
|
1478
|
+
add_dependencies_to_context=add_dependencies_to_context,
|
|
1479
|
+
add_session_state_to_context=add_session_state_to_context,
|
|
1480
|
+
metadata=metadata,
|
|
1481
|
+
**kwargs,
|
|
1482
|
+
)
|
|
1414
1483
|
|
|
1415
1484
|
log_debug(f"Agent Run Start: {run_response.run_id}", center=True)
|
|
1416
1485
|
|
|
@@ -1422,7 +1491,7 @@ class Agent:
|
|
|
1422
1491
|
if stream_intermediate_steps:
|
|
1423
1492
|
yield self._handle_event(create_run_started_event(run_response), run_response, workflow_context)
|
|
1424
1493
|
|
|
1425
|
-
#
|
|
1494
|
+
# 3. Reason about the task if reasoning is enabled
|
|
1426
1495
|
async for item in self._ahandle_reasoning_stream(run_response=run_response, run_messages=run_messages):
|
|
1427
1496
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
1428
1497
|
yield item
|
|
@@ -1430,7 +1499,7 @@ class Agent:
|
|
|
1430
1499
|
# Check for cancellation before model processing
|
|
1431
1500
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
1432
1501
|
|
|
1433
|
-
#
|
|
1502
|
+
# 4. Generate a response from the Model
|
|
1434
1503
|
if self.output_model is None:
|
|
1435
1504
|
async for event in self._ahandle_model_response_stream(
|
|
1436
1505
|
session=session,
|
|
@@ -1513,7 +1582,7 @@ class Agent:
|
|
|
1513
1582
|
if run_response.metrics:
|
|
1514
1583
|
run_response.metrics.stop_timer()
|
|
1515
1584
|
|
|
1516
|
-
#
|
|
1585
|
+
# Optional: Save output to file if save_response_to_file is set
|
|
1517
1586
|
self.save_run_response_to_file(
|
|
1518
1587
|
run_response=run_response,
|
|
1519
1588
|
input=run_messages.user_message,
|
|
@@ -1521,10 +1590,10 @@ class Agent:
|
|
|
1521
1590
|
user_id=user_id,
|
|
1522
1591
|
)
|
|
1523
1592
|
|
|
1524
|
-
#
|
|
1593
|
+
# 7. Add RunOutput to Agent Session
|
|
1525
1594
|
session.upsert_run(run=run_response)
|
|
1526
1595
|
|
|
1527
|
-
#
|
|
1596
|
+
# 8. Save session to storage
|
|
1528
1597
|
self.save_session(session=session)
|
|
1529
1598
|
|
|
1530
1599
|
if stream_intermediate_steps:
|
|
@@ -1666,10 +1735,6 @@ class Agent:
|
|
|
1666
1735
|
# Determine run dependencies
|
|
1667
1736
|
run_dependencies = dependencies if dependencies is not None else self.dependencies
|
|
1668
1737
|
|
|
1669
|
-
# Resolve callable dependencies if present
|
|
1670
|
-
if run_dependencies is not None:
|
|
1671
|
-
self._resolve_run_dependencies(dependencies=run_dependencies)
|
|
1672
|
-
|
|
1673
1738
|
add_dependencies = (
|
|
1674
1739
|
add_dependencies_to_context if add_dependencies_to_context is not None else self.add_dependencies_to_context
|
|
1675
1740
|
)
|
|
@@ -1750,51 +1815,52 @@ class Agent:
|
|
|
1750
1815
|
|
|
1751
1816
|
for attempt in range(num_attempts):
|
|
1752
1817
|
try:
|
|
1753
|
-
# Prepare run messages
|
|
1754
|
-
run_messages: RunMessages = self._get_run_messages(
|
|
1755
|
-
run_response=run_response,
|
|
1756
|
-
input=validated_input,
|
|
1757
|
-
session=agent_session,
|
|
1758
|
-
session_state=session_state,
|
|
1759
|
-
user_id=user_id,
|
|
1760
|
-
audio=audio,
|
|
1761
|
-
images=images,
|
|
1762
|
-
videos=videos,
|
|
1763
|
-
files=files,
|
|
1764
|
-
knowledge_filters=effective_filters,
|
|
1765
|
-
add_history_to_context=add_history,
|
|
1766
|
-
dependencies=dependencies,
|
|
1767
|
-
add_dependencies_to_context=add_dependencies,
|
|
1768
|
-
add_session_state_to_context=add_session_state,
|
|
1769
|
-
metadata=metadata,
|
|
1770
|
-
**kwargs,
|
|
1771
|
-
)
|
|
1772
|
-
if len(run_messages.messages) == 0:
|
|
1773
|
-
log_error("No messages to be sent to the model.")
|
|
1774
|
-
|
|
1775
|
-
run_messages = run_messages
|
|
1776
|
-
|
|
1777
1818
|
# Pass the new run_response to _arun
|
|
1778
1819
|
if stream:
|
|
1779
1820
|
return self._arun_stream( # type: ignore
|
|
1780
1821
|
run_response=run_response,
|
|
1781
|
-
|
|
1822
|
+
input=validated_input,
|
|
1782
1823
|
user_id=user_id,
|
|
1783
1824
|
session=agent_session,
|
|
1825
|
+
session_state=session_state,
|
|
1826
|
+
audio=audio,
|
|
1827
|
+
images=images,
|
|
1828
|
+
videos=videos,
|
|
1829
|
+
files=files,
|
|
1830
|
+
knowledge_filters=knowledge_filters,
|
|
1831
|
+
add_history_to_context=add_history,
|
|
1832
|
+
add_dependencies_to_context=add_dependencies,
|
|
1833
|
+
add_session_state_to_context=add_session_state,
|
|
1834
|
+
metadata=metadata,
|
|
1784
1835
|
response_format=response_format,
|
|
1785
1836
|
stream_intermediate_steps=stream_intermediate_steps,
|
|
1786
1837
|
workflow_context=workflow_context,
|
|
1787
1838
|
yield_run_response=yield_run_response,
|
|
1788
1839
|
dependencies=run_dependencies,
|
|
1840
|
+
**kwargs,
|
|
1789
1841
|
) # type: ignore[assignment]
|
|
1790
1842
|
else:
|
|
1791
1843
|
return self._arun( # type: ignore
|
|
1792
1844
|
run_response=run_response,
|
|
1793
|
-
|
|
1845
|
+
input=validated_input,
|
|
1794
1846
|
user_id=user_id,
|
|
1795
1847
|
session=agent_session,
|
|
1848
|
+
session_state=session_state,
|
|
1849
|
+
audio=audio,
|
|
1850
|
+
images=images,
|
|
1851
|
+
videos=videos,
|
|
1852
|
+
files=files,
|
|
1853
|
+
knowledge_filters=knowledge_filters,
|
|
1854
|
+
add_history_to_context=add_history,
|
|
1855
|
+
add_dependencies_to_context=add_dependencies,
|
|
1856
|
+
add_session_state_to_context=add_session_state,
|
|
1857
|
+
metadata=metadata,
|
|
1796
1858
|
response_format=response_format,
|
|
1859
|
+
stream_intermediate_steps=stream_intermediate_steps,
|
|
1860
|
+
workflow_context=workflow_context,
|
|
1861
|
+
yield_run_response=yield_run_response,
|
|
1797
1862
|
dependencies=run_dependencies,
|
|
1863
|
+
**kwargs,
|
|
1798
1864
|
)
|
|
1799
1865
|
except ModelProviderError as e:
|
|
1800
1866
|
log_warning(f"Attempt {attempt + 1}/{num_attempts} failed: {str(e)}")
|
|
@@ -4082,7 +4148,7 @@ class Agent:
|
|
|
4082
4148
|
return json_response_format
|
|
4083
4149
|
|
|
4084
4150
|
def _resolve_run_dependencies(self, dependencies: Dict[str, Any]) -> None:
|
|
4085
|
-
from inspect import signature
|
|
4151
|
+
from inspect import iscoroutine, iscoroutinefunction, signature
|
|
4086
4152
|
|
|
4087
4153
|
# Dependencies should already be resolved in run() method
|
|
4088
4154
|
log_debug("Resolving dependencies")
|
|
@@ -4091,7 +4157,10 @@ class Agent:
|
|
|
4091
4157
|
return
|
|
4092
4158
|
|
|
4093
4159
|
for key, value in dependencies.items():
|
|
4094
|
-
if
|
|
4160
|
+
if iscoroutine(value) or iscoroutinefunction(value):
|
|
4161
|
+
log_warning(f"Dependency {key} is a coroutine. Use agent.arun() or agent.aprint_response() instead.")
|
|
4162
|
+
continue
|
|
4163
|
+
elif callable(value):
|
|
4095
4164
|
try:
|
|
4096
4165
|
sig = signature(value)
|
|
4097
4166
|
result = value(agent=self) if "agent" in sig.parameters else value()
|
|
@@ -4103,7 +4172,7 @@ class Agent:
|
|
|
4103
4172
|
dependencies[key] = value
|
|
4104
4173
|
|
|
4105
4174
|
async def _aresolve_run_dependencies(self, dependencies: Dict[str, Any]) -> None:
|
|
4106
|
-
from inspect import iscoroutine, signature
|
|
4175
|
+
from inspect import iscoroutine, iscoroutinefunction, signature
|
|
4107
4176
|
|
|
4108
4177
|
log_debug("Resolving context (async)")
|
|
4109
4178
|
if not isinstance(dependencies, dict):
|
|
@@ -4114,14 +4183,12 @@ class Agent:
|
|
|
4114
4183
|
if not callable(value):
|
|
4115
4184
|
dependencies[key] = value
|
|
4116
4185
|
continue
|
|
4117
|
-
|
|
4118
4186
|
try:
|
|
4119
4187
|
sig = signature(value)
|
|
4120
4188
|
result = value(agent=self) if "agent" in sig.parameters else value()
|
|
4121
4189
|
|
|
4122
|
-
if iscoroutine(result):
|
|
4190
|
+
if iscoroutine(result) or iscoroutinefunction(result):
|
|
4123
4191
|
result = await result
|
|
4124
|
-
|
|
4125
4192
|
dependencies[key] = result
|
|
4126
4193
|
except Exception as e:
|
|
4127
4194
|
log_warning(f"Failed to resolve context for '{key}': {e}")
|
|
@@ -4851,7 +4918,7 @@ class Agent:
|
|
|
4851
4918
|
|
|
4852
4919
|
# 3.3.15 Add the session state to the system message
|
|
4853
4920
|
if self.add_session_state_to_context and session_state is not None:
|
|
4854
|
-
system_message_content +=
|
|
4921
|
+
system_message_content += self._get_formatted_session_state_for_system_message(session_state)
|
|
4855
4922
|
|
|
4856
4923
|
# Return the system message
|
|
4857
4924
|
return (
|
|
@@ -4860,6 +4927,9 @@ class Agent:
|
|
|
4860
4927
|
else None
|
|
4861
4928
|
)
|
|
4862
4929
|
|
|
4930
|
+
def _get_formatted_session_state_for_system_message(self, session_state: Dict[str, Any]) -> str:
|
|
4931
|
+
return f"\n<session_state>\n{session_state}\n</session_state>\n\n"
|
|
4932
|
+
|
|
4863
4933
|
def _get_user_message(
|
|
4864
4934
|
self,
|
|
4865
4935
|
*,
|
|
@@ -5041,7 +5111,7 @@ class Agent:
|
|
|
5041
5111
|
files: Optional[Sequence[File]] = None,
|
|
5042
5112
|
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
5043
5113
|
add_history_to_context: Optional[bool] = None,
|
|
5044
|
-
|
|
5114
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
5045
5115
|
add_dependencies_to_context: Optional[bool] = None,
|
|
5046
5116
|
add_session_state_to_context: Optional[bool] = None,
|
|
5047
5117
|
metadata: Optional[Dict[str, Any]] = None,
|
|
@@ -5079,7 +5149,7 @@ class Agent:
|
|
|
5079
5149
|
session=session,
|
|
5080
5150
|
session_state=session_state,
|
|
5081
5151
|
user_id=user_id,
|
|
5082
|
-
dependencies=
|
|
5152
|
+
dependencies=dependencies,
|
|
5083
5153
|
metadata=metadata,
|
|
5084
5154
|
add_session_state_to_context=add_session_state_to_context,
|
|
5085
5155
|
)
|
|
@@ -5160,7 +5230,7 @@ class Agent:
|
|
|
5160
5230
|
videos=videos,
|
|
5161
5231
|
files=files,
|
|
5162
5232
|
knowledge_filters=knowledge_filters,
|
|
5163
|
-
|
|
5233
|
+
dependencies=dependencies,
|
|
5164
5234
|
add_dependencies_to_context=add_dependencies_to_context,
|
|
5165
5235
|
metadata=metadata,
|
|
5166
5236
|
**kwargs,
|
|
@@ -5173,7 +5243,13 @@ class Agent:
|
|
|
5173
5243
|
# 4.3 If input is provided as a dict, try to validate it as a Message
|
|
5174
5244
|
elif isinstance(input, dict):
|
|
5175
5245
|
try:
|
|
5176
|
-
|
|
5246
|
+
if self.input_schema and is_typed_dict(self.input_schema):
|
|
5247
|
+
import json
|
|
5248
|
+
|
|
5249
|
+
content = json.dumps(input, indent=2, ensure_ascii=False)
|
|
5250
|
+
user_message = Message(role=self.user_message_role, content=content)
|
|
5251
|
+
else:
|
|
5252
|
+
user_message = Message.model_validate(input)
|
|
5177
5253
|
except Exception as e:
|
|
5178
5254
|
log_warning(f"Failed to validate message: {e}")
|
|
5179
5255
|
|
agno/db/dynamo/dynamo.py
CHANGED
|
@@ -30,6 +30,7 @@ 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
|
|
33
34
|
from agno.session import AgentSession, Session, TeamSession, WorkflowSession
|
|
34
35
|
from agno.utils.log import log_debug, log_error
|
|
35
36
|
|
|
@@ -55,6 +56,7 @@ class DynamoDb(BaseDb):
|
|
|
55
56
|
metrics_table: Optional[str] = None,
|
|
56
57
|
eval_table: Optional[str] = None,
|
|
57
58
|
knowledge_table: Optional[str] = None,
|
|
59
|
+
id: Optional[str] = None,
|
|
58
60
|
):
|
|
59
61
|
"""
|
|
60
62
|
Interface for interacting with a DynamoDB database.
|
|
@@ -69,8 +71,14 @@ class DynamoDb(BaseDb):
|
|
|
69
71
|
metrics_table: The name of the metrics table.
|
|
70
72
|
eval_table: The name of the eval table.
|
|
71
73
|
knowledge_table: The name of the knowledge table.
|
|
74
|
+
id: ID of the database.
|
|
72
75
|
"""
|
|
76
|
+
if id is None:
|
|
77
|
+
seed = str(db_client) if db_client else f"{region_name}_{aws_access_key_id}"
|
|
78
|
+
id = generate_deterministic_id(seed)
|
|
79
|
+
|
|
73
80
|
super().__init__(
|
|
81
|
+
id=id,
|
|
74
82
|
session_table=session_table,
|
|
75
83
|
memory_table=memory_table,
|
|
76
84
|
metrics_table=metrics_table,
|
agno/db/firestore/firestore.py
CHANGED
|
@@ -16,7 +16,7 @@ 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, serialize_session_json_fields
|
|
19
|
+
from agno.db.utils import deserialize_session_json_fields, generate_deterministic_id, 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
22
|
|
|
@@ -38,6 +38,7 @@ class FirestoreDb(BaseDb):
|
|
|
38
38
|
metrics_collection: Optional[str] = None,
|
|
39
39
|
eval_collection: Optional[str] = None,
|
|
40
40
|
knowledge_collection: Optional[str] = None,
|
|
41
|
+
id: Optional[str] = None,
|
|
41
42
|
):
|
|
42
43
|
"""
|
|
43
44
|
Interface for interacting with a Firestore database.
|
|
@@ -50,11 +51,17 @@ class FirestoreDb(BaseDb):
|
|
|
50
51
|
metrics_collection (Optional[str]): Name of the collection to store metrics.
|
|
51
52
|
eval_collection (Optional[str]): Name of the collection to store evaluation runs.
|
|
52
53
|
knowledge_collection (Optional[str]): Name of the collection to store knowledge documents.
|
|
54
|
+
id (Optional[str]): ID of the database.
|
|
53
55
|
|
|
54
56
|
Raises:
|
|
55
57
|
ValueError: If neither project_id nor db_client is provided.
|
|
56
58
|
"""
|
|
59
|
+
if id is None:
|
|
60
|
+
seed = project_id or str(db_client)
|
|
61
|
+
id = generate_deterministic_id(seed)
|
|
62
|
+
|
|
57
63
|
super().__init__(
|
|
64
|
+
id=id,
|
|
58
65
|
session_table=session_collection,
|
|
59
66
|
memory_table=memory_collection,
|
|
60
67
|
metrics_table=metrics_collection,
|
agno/db/gcs_json/gcs_json_db.py
CHANGED
|
@@ -14,6 +14,7 @@ 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
|
|
17
18
|
from agno.session import AgentSession, Session, TeamSession, WorkflowSession
|
|
18
19
|
from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
19
20
|
|
|
@@ -35,6 +36,7 @@ class GcsJsonDb(BaseDb):
|
|
|
35
36
|
knowledge_table: Optional[str] = None,
|
|
36
37
|
project: Optional[str] = None,
|
|
37
38
|
credentials: Optional[Any] = None,
|
|
39
|
+
id: Optional[str] = None,
|
|
38
40
|
):
|
|
39
41
|
"""
|
|
40
42
|
Interface for interacting with JSON files stored in Google Cloud Storage as database.
|
|
@@ -50,8 +52,15 @@ class GcsJsonDb(BaseDb):
|
|
|
50
52
|
project (Optional[str]): GCP project ID. If None, uses default project.
|
|
51
53
|
location (Optional[str]): GCS bucket location. If None, uses default location.
|
|
52
54
|
credentials (Optional[Any]): GCP credentials. If None, uses default credentials.
|
|
55
|
+
id (Optional[str]): ID of the database.
|
|
53
56
|
"""
|
|
57
|
+
if id is None:
|
|
58
|
+
prefix_suffix = prefix or "agno/"
|
|
59
|
+
seed = f"{bucket_name}_{project}#{prefix_suffix}"
|
|
60
|
+
id = generate_deterministic_id(seed)
|
|
61
|
+
|
|
54
62
|
super().__init__(
|
|
63
|
+
id=id,
|
|
55
64
|
session_table=session_table,
|
|
56
65
|
memory_table=memory_table,
|
|
57
66
|
metrics_table=metrics_table,
|
agno/db/json/json_db.py
CHANGED
|
@@ -17,6 +17,7 @@ from agno.db.json.utils import (
|
|
|
17
17
|
from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
|
|
18
18
|
from agno.db.schemas.knowledge import KnowledgeRow
|
|
19
19
|
from agno.db.schemas.memory import UserMemory
|
|
20
|
+
from agno.db.utils import generate_deterministic_id
|
|
20
21
|
from agno.session import AgentSession, Session, TeamSession, WorkflowSession
|
|
21
22
|
from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
22
23
|
|
|
@@ -30,6 +31,7 @@ class JsonDb(BaseDb):
|
|
|
30
31
|
metrics_table: Optional[str] = None,
|
|
31
32
|
eval_table: Optional[str] = None,
|
|
32
33
|
knowledge_table: Optional[str] = None,
|
|
34
|
+
id: Optional[str] = None,
|
|
33
35
|
):
|
|
34
36
|
"""
|
|
35
37
|
Interface for interacting with JSON files as database.
|
|
@@ -41,8 +43,14 @@ class JsonDb(BaseDb):
|
|
|
41
43
|
metrics_table (Optional[str]): Name of the JSON file to store metrics.
|
|
42
44
|
eval_table (Optional[str]): Name of the JSON file to store evaluation runs.
|
|
43
45
|
knowledge_table (Optional[str]): Name of the JSON file to store knowledge content.
|
|
46
|
+
id (Optional[str]): ID of the database.
|
|
44
47
|
"""
|
|
48
|
+
if id is None:
|
|
49
|
+
seed = db_path or "agno_json_db"
|
|
50
|
+
id = generate_deterministic_id(seed)
|
|
51
|
+
|
|
45
52
|
super().__init__(
|
|
53
|
+
id=id,
|
|
46
54
|
session_table=session_table,
|
|
47
55
|
memory_table=memory_table,
|
|
48
56
|
metrics_table=metrics_table,
|