agno 2.3.4__py3-none-any.whl → 2.3.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 +177 -41
- agno/culture/manager.py +2 -2
- agno/db/base.py +330 -8
- agno/db/dynamo/dynamo.py +722 -2
- agno/db/dynamo/schemas.py +127 -0
- agno/db/firestore/firestore.py +573 -1
- agno/db/firestore/schemas.py +40 -0
- agno/db/gcs_json/gcs_json_db.py +446 -1
- agno/db/in_memory/in_memory_db.py +143 -1
- agno/db/json/json_db.py +438 -1
- agno/db/mongo/async_mongo.py +522 -0
- agno/db/mongo/mongo.py +523 -1
- agno/db/mongo/schemas.py +29 -0
- agno/db/mysql/mysql.py +536 -3
- agno/db/mysql/schemas.py +38 -0
- agno/db/postgres/async_postgres.py +541 -13
- agno/db/postgres/postgres.py +535 -2
- agno/db/postgres/schemas.py +38 -0
- agno/db/redis/redis.py +468 -1
- agno/db/redis/schemas.py +32 -0
- agno/db/singlestore/schemas.py +38 -0
- agno/db/singlestore/singlestore.py +523 -1
- agno/db/sqlite/async_sqlite.py +548 -9
- agno/db/sqlite/schemas.py +38 -0
- agno/db/sqlite/sqlite.py +537 -5
- agno/db/sqlite/utils.py +6 -8
- agno/db/surrealdb/models.py +25 -0
- agno/db/surrealdb/surrealdb.py +548 -1
- agno/eval/accuracy.py +10 -4
- agno/eval/performance.py +10 -4
- agno/eval/reliability.py +22 -13
- agno/exceptions.py +11 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/knowledge/chunking/semantic.py +2 -2
- agno/models/aimlapi/aimlapi.py +2 -3
- agno/models/anthropic/claude.py +18 -13
- agno/models/aws/bedrock.py +3 -4
- agno/models/aws/claude.py +5 -1
- agno/models/azure/ai_foundry.py +2 -2
- agno/models/azure/openai_chat.py +8 -0
- agno/models/cerebras/cerebras.py +63 -11
- agno/models/cerebras/cerebras_openai.py +2 -3
- agno/models/cohere/chat.py +1 -5
- agno/models/cometapi/cometapi.py +2 -3
- agno/models/dashscope/dashscope.py +2 -3
- agno/models/deepinfra/deepinfra.py +2 -3
- agno/models/deepseek/deepseek.py +2 -3
- agno/models/fireworks/fireworks.py +2 -3
- agno/models/google/gemini.py +9 -7
- agno/models/groq/groq.py +2 -3
- agno/models/huggingface/huggingface.py +1 -5
- agno/models/ibm/watsonx.py +1 -5
- agno/models/internlm/internlm.py +2 -3
- agno/models/langdb/langdb.py +6 -4
- agno/models/litellm/chat.py +2 -2
- agno/models/litellm/litellm_openai.py +2 -3
- agno/models/meta/llama.py +1 -5
- agno/models/meta/llama_openai.py +4 -5
- agno/models/mistral/mistral.py +1 -5
- agno/models/nebius/nebius.py +2 -3
- agno/models/nvidia/nvidia.py +4 -5
- agno/models/openai/chat.py +14 -3
- agno/models/openai/responses.py +14 -3
- agno/models/openrouter/openrouter.py +4 -5
- agno/models/perplexity/perplexity.py +2 -3
- agno/models/portkey/portkey.py +7 -6
- agno/models/requesty/requesty.py +4 -5
- agno/models/response.py +2 -1
- agno/models/sambanova/sambanova.py +4 -5
- agno/models/siliconflow/siliconflow.py +3 -4
- agno/models/together/together.py +4 -5
- agno/models/vercel/v0.py +4 -5
- agno/models/vllm/vllm.py +19 -14
- agno/models/xai/xai.py +4 -5
- agno/os/app.py +104 -0
- agno/os/config.py +13 -0
- agno/os/interfaces/whatsapp/router.py +0 -1
- agno/os/mcp.py +1 -0
- agno/os/router.py +31 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/schema.py +10 -1
- agno/os/utils.py +57 -0
- agno/run/agent.py +1 -0
- agno/run/base.py +17 -0
- agno/run/team.py +4 -0
- agno/session/team.py +1 -0
- agno/table.py +10 -0
- agno/team/team.py +214 -65
- agno/tools/function.py +10 -8
- agno/tools/nano_banana.py +1 -1
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +4 -4
- agno/utils/hooks.py +56 -1
- agno/vectordb/qdrant/qdrant.py +22 -22
- agno/workflow/condition.py +8 -0
- agno/workflow/loop.py +8 -0
- agno/workflow/parallel.py +8 -0
- agno/workflow/router.py +8 -0
- agno/workflow/step.py +20 -0
- agno/workflow/steps.py +8 -0
- agno/workflow/workflow.py +83 -17
- {agno-2.3.4.dist-info → agno-2.3.5.dist-info}/METADATA +2 -2
- {agno-2.3.4.dist-info → agno-2.3.5.dist-info}/RECORD +112 -102
- {agno-2.3.4.dist-info → agno-2.3.5.dist-info}/WHEEL +0 -0
- {agno-2.3.4.dist-info → agno-2.3.5.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.4.dist-info → agno-2.3.5.dist-info}/top_level.txt +0 -0
agno/agent/agent.py
CHANGED
|
@@ -83,8 +83,8 @@ from agno.utils.agent import (
|
|
|
83
83
|
aget_session_state_util,
|
|
84
84
|
aset_session_name_util,
|
|
85
85
|
aupdate_session_state_util,
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
await_for_open_threads,
|
|
87
|
+
await_for_thread_tasks_stream,
|
|
88
88
|
collect_joint_audios,
|
|
89
89
|
collect_joint_files,
|
|
90
90
|
collect_joint_images,
|
|
@@ -103,8 +103,8 @@ from agno.utils.agent import (
|
|
|
103
103
|
store_media_util,
|
|
104
104
|
update_session_state_util,
|
|
105
105
|
validate_media_object_id,
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
wait_for_open_threads,
|
|
107
|
+
wait_for_thread_tasks_stream,
|
|
108
108
|
)
|
|
109
109
|
from agno.utils.common import is_typed_dict, validate_typed_dict
|
|
110
110
|
from agno.utils.events import (
|
|
@@ -131,7 +131,7 @@ from agno.utils.events import (
|
|
|
131
131
|
create_tool_call_started_event,
|
|
132
132
|
handle_event,
|
|
133
133
|
)
|
|
134
|
-
from agno.utils.hooks import filter_hook_args, normalize_hooks
|
|
134
|
+
from agno.utils.hooks import copy_args_for_background, filter_hook_args, normalize_hooks, should_run_hook_in_background
|
|
135
135
|
from agno.utils.knowledge import get_agentic_or_user_search_filters
|
|
136
136
|
from agno.utils.log import (
|
|
137
137
|
log_debug,
|
|
@@ -273,6 +273,8 @@ class Agent:
|
|
|
273
273
|
pre_hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail]]] = None
|
|
274
274
|
# Functions called after output is generated but before the response is returned
|
|
275
275
|
post_hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail]]] = None
|
|
276
|
+
# If True, run hooks as FastAPI background tasks (non-blocking). Set by AgentOS.
|
|
277
|
+
_run_hooks_in_background: Optional[bool] = None
|
|
276
278
|
|
|
277
279
|
# --- Agent Reasoning ---
|
|
278
280
|
# Enable reasoning by working through the problem step by step.
|
|
@@ -594,7 +596,6 @@ class Agent:
|
|
|
594
596
|
self.tool_choice = tool_choice
|
|
595
597
|
self.tool_hooks = tool_hooks
|
|
596
598
|
|
|
597
|
-
# Initialize hooks with backward compatibility
|
|
598
599
|
self.pre_hooks = pre_hooks
|
|
599
600
|
self.post_hooks = post_hooks
|
|
600
601
|
|
|
@@ -710,9 +711,13 @@ class Agent:
|
|
|
710
711
|
self.id = generate_id_from_name(self.name)
|
|
711
712
|
|
|
712
713
|
def _set_debug(self, debug_mode: Optional[bool] = None) -> None:
|
|
714
|
+
# Get the debug level from the environment variable or the default debug level
|
|
715
|
+
debug_level: Literal[1, 2] = (
|
|
716
|
+
cast(Literal[1, 2], int(env)) if (env := getenv("AGNO_DEBUG_LEVEL")) in ("1", "2") else self.debug_level
|
|
717
|
+
)
|
|
713
718
|
# If the default debug mode is set, or passed on run, or via environment variable, set the debug mode to True
|
|
714
719
|
if self.debug_mode or debug_mode or getenv("AGNO_DEBUG", "false").lower() == "true":
|
|
715
|
-
set_log_level_to_debug(level=
|
|
720
|
+
set_log_level_to_debug(level=debug_level)
|
|
716
721
|
else:
|
|
717
722
|
set_log_level_to_info()
|
|
718
723
|
|
|
@@ -967,6 +972,7 @@ class Agent:
|
|
|
967
972
|
add_session_state_to_context: Optional[bool] = None,
|
|
968
973
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
969
974
|
debug_mode: Optional[bool] = None,
|
|
975
|
+
background_tasks: Optional[Any] = None,
|
|
970
976
|
**kwargs: Any,
|
|
971
977
|
) -> RunOutput:
|
|
972
978
|
"""Run the Agent and return the RunOutput.
|
|
@@ -987,9 +993,6 @@ class Agent:
|
|
|
987
993
|
13. Cleanup and store the run response and session
|
|
988
994
|
"""
|
|
989
995
|
|
|
990
|
-
# Register run for cancellation tracking
|
|
991
|
-
register_run(run_response.run_id) # type: ignore
|
|
992
|
-
|
|
993
996
|
# 1. Execute pre-hooks
|
|
994
997
|
run_input = cast(RunInput, run_response.input)
|
|
995
998
|
self.model = cast(Model, self.model)
|
|
@@ -1003,6 +1006,7 @@ class Agent:
|
|
|
1003
1006
|
session=session,
|
|
1004
1007
|
user_id=user_id,
|
|
1005
1008
|
debug_mode=debug_mode,
|
|
1009
|
+
background_tasks=background_tasks,
|
|
1006
1010
|
**kwargs,
|
|
1007
1011
|
)
|
|
1008
1012
|
# Consume the generator without yielding
|
|
@@ -1105,9 +1109,7 @@ class Agent:
|
|
|
1105
1109
|
|
|
1106
1110
|
# We should break out of the run function
|
|
1107
1111
|
if any(tool_call.is_paused for tool_call in run_response.tools or []):
|
|
1108
|
-
|
|
1109
|
-
memory_future=memory_future, cultural_knowledge_future=cultural_knowledge_future
|
|
1110
|
-
)
|
|
1112
|
+
wait_for_open_threads(memory_future=memory_future, cultural_knowledge_future=cultural_knowledge_future)
|
|
1111
1113
|
|
|
1112
1114
|
return self._handle_agent_run_paused(run_response=run_response, session=session, user_id=user_id)
|
|
1113
1115
|
|
|
@@ -1127,6 +1129,7 @@ class Agent:
|
|
|
1127
1129
|
session=session,
|
|
1128
1130
|
user_id=user_id,
|
|
1129
1131
|
debug_mode=debug_mode,
|
|
1132
|
+
background_tasks=background_tasks,
|
|
1130
1133
|
**kwargs,
|
|
1131
1134
|
)
|
|
1132
1135
|
deque(post_hook_iterator, maxlen=0)
|
|
@@ -1135,7 +1138,7 @@ class Agent:
|
|
|
1135
1138
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
1136
1139
|
|
|
1137
1140
|
# 11. Wait for background memory creation and cultural knowledge creation
|
|
1138
|
-
|
|
1141
|
+
wait_for_open_threads(memory_future=memory_future, cultural_knowledge_future=cultural_knowledge_future)
|
|
1139
1142
|
|
|
1140
1143
|
# 12. Create session summary
|
|
1141
1144
|
if self.session_summary_manager is not None:
|
|
@@ -1188,6 +1191,7 @@ class Agent:
|
|
|
1188
1191
|
stream_events: bool = False,
|
|
1189
1192
|
yield_run_output: Optional[bool] = None,
|
|
1190
1193
|
debug_mode: Optional[bool] = None,
|
|
1194
|
+
background_tasks: Optional[Any] = None,
|
|
1191
1195
|
**kwargs: Any,
|
|
1192
1196
|
) -> Iterator[Union[RunOutputEvent, RunOutput]]:
|
|
1193
1197
|
"""Run the Agent and yield the RunOutput.
|
|
@@ -1205,9 +1209,6 @@ class Agent:
|
|
|
1205
1209
|
10. Cleanup and store the run response and session
|
|
1206
1210
|
"""
|
|
1207
1211
|
|
|
1208
|
-
# Register run for cancellation tracking
|
|
1209
|
-
register_run(run_response.run_id) # type: ignore
|
|
1210
|
-
|
|
1211
1212
|
# 1. Execute pre-hooks
|
|
1212
1213
|
run_input = cast(RunInput, run_response.input)
|
|
1213
1214
|
self.model = cast(Model, self.model)
|
|
@@ -1222,6 +1223,7 @@ class Agent:
|
|
|
1222
1223
|
user_id=user_id,
|
|
1223
1224
|
debug_mode=debug_mode,
|
|
1224
1225
|
stream_events=stream_events,
|
|
1226
|
+
background_tasks=background_tasks,
|
|
1225
1227
|
**kwargs,
|
|
1226
1228
|
)
|
|
1227
1229
|
for event in pre_hook_iterator:
|
|
@@ -1365,7 +1367,7 @@ class Agent:
|
|
|
1365
1367
|
|
|
1366
1368
|
# We should break out of the run function
|
|
1367
1369
|
if any(tool_call.is_paused for tool_call in run_response.tools or []):
|
|
1368
|
-
yield from
|
|
1370
|
+
yield from wait_for_thread_tasks_stream(
|
|
1369
1371
|
memory_future=memory_future,
|
|
1370
1372
|
cultural_knowledge_future=cultural_knowledge_future,
|
|
1371
1373
|
stream_events=stream_events,
|
|
@@ -1399,11 +1401,12 @@ class Agent:
|
|
|
1399
1401
|
user_id=user_id,
|
|
1400
1402
|
debug_mode=debug_mode,
|
|
1401
1403
|
stream_events=stream_events,
|
|
1404
|
+
background_tasks=background_tasks,
|
|
1402
1405
|
**kwargs,
|
|
1403
1406
|
)
|
|
1404
1407
|
|
|
1405
1408
|
# 8. Wait for background memory creation and cultural knowledge creation
|
|
1406
|
-
yield from
|
|
1409
|
+
yield from wait_for_thread_tasks_stream(
|
|
1407
1410
|
memory_future=memory_future,
|
|
1408
1411
|
cultural_knowledge_future=cultural_knowledge_future,
|
|
1409
1412
|
stream_events=stream_events,
|
|
@@ -1585,6 +1588,10 @@ class Agent:
|
|
|
1585
1588
|
"`run` method is not supported with an async database. Please use `arun` method instead."
|
|
1586
1589
|
)
|
|
1587
1590
|
|
|
1591
|
+
# Create a run_id for this specific run and register immediately for cancellation tracking
|
|
1592
|
+
run_id = str(uuid4())
|
|
1593
|
+
register_run(run_id)
|
|
1594
|
+
|
|
1588
1595
|
if (add_history_to_context or self.add_history_to_context) and not self.db and not self.team_id:
|
|
1589
1596
|
log_warning(
|
|
1590
1597
|
"add_history_to_context is True, but no database has been assigned to the agent. History will not be added to the context."
|
|
@@ -1597,8 +1604,11 @@ class Agent:
|
|
|
1597
1604
|
stacklevel=2,
|
|
1598
1605
|
)
|
|
1599
1606
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1607
|
+
background_tasks = kwargs.pop("background_tasks", None)
|
|
1608
|
+
if background_tasks is not None:
|
|
1609
|
+
from fastapi import BackgroundTasks
|
|
1610
|
+
|
|
1611
|
+
background_tasks: BackgroundTasks = background_tasks # type: ignore
|
|
1602
1612
|
|
|
1603
1613
|
# Validate input against input_schema if provided
|
|
1604
1614
|
validated_input = self._validate_input(input)
|
|
@@ -1750,6 +1760,7 @@ class Agent:
|
|
|
1750
1760
|
stream_events=stream_events,
|
|
1751
1761
|
yield_run_output=yield_run_output,
|
|
1752
1762
|
debug_mode=debug_mode,
|
|
1763
|
+
background_tasks=background_tasks,
|
|
1753
1764
|
**kwargs,
|
|
1754
1765
|
)
|
|
1755
1766
|
return response_iterator
|
|
@@ -1764,6 +1775,7 @@ class Agent:
|
|
|
1764
1775
|
add_session_state_to_context=add_session_state,
|
|
1765
1776
|
response_format=response_format,
|
|
1766
1777
|
debug_mode=debug_mode,
|
|
1778
|
+
background_tasks=background_tasks,
|
|
1767
1779
|
**kwargs,
|
|
1768
1780
|
)
|
|
1769
1781
|
return response
|
|
@@ -1822,6 +1834,7 @@ class Agent:
|
|
|
1822
1834
|
add_session_state_to_context: Optional[bool] = None,
|
|
1823
1835
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
1824
1836
|
debug_mode: Optional[bool] = None,
|
|
1837
|
+
background_tasks: Optional[Any] = None,
|
|
1825
1838
|
**kwargs: Any,
|
|
1826
1839
|
) -> RunOutput:
|
|
1827
1840
|
"""Run the Agent and return the RunOutput.
|
|
@@ -1846,9 +1859,6 @@ class Agent:
|
|
|
1846
1859
|
"""
|
|
1847
1860
|
log_debug(f"Agent Run Start: {run_response.run_id}", center=True)
|
|
1848
1861
|
|
|
1849
|
-
# Register run for cancellation tracking
|
|
1850
|
-
register_run(run_response.run_id) # type: ignore
|
|
1851
|
-
|
|
1852
1862
|
# 1. Read or create session. Reads from the database if provided.
|
|
1853
1863
|
agent_session = await self._aread_or_create_session(session_id=session_id, user_id=user_id)
|
|
1854
1864
|
|
|
@@ -1884,6 +1894,7 @@ class Agent:
|
|
|
1884
1894
|
session=agent_session,
|
|
1885
1895
|
user_id=user_id,
|
|
1886
1896
|
debug_mode=debug_mode,
|
|
1897
|
+
background_tasks=background_tasks,
|
|
1887
1898
|
**kwargs,
|
|
1888
1899
|
)
|
|
1889
1900
|
# Consume the async iterator without yielding
|
|
@@ -1986,9 +1997,7 @@ class Agent:
|
|
|
1986
1997
|
|
|
1987
1998
|
# We should break out of the run function
|
|
1988
1999
|
if any(tool_call.is_paused for tool_call in run_response.tools or []):
|
|
1989
|
-
await
|
|
1990
|
-
memory_task=memory_task, cultural_knowledge_task=cultural_knowledge_task
|
|
1991
|
-
)
|
|
2000
|
+
await await_for_open_threads(memory_task=memory_task, cultural_knowledge_task=cultural_knowledge_task)
|
|
1992
2001
|
return await self._ahandle_agent_run_paused(
|
|
1993
2002
|
run_response=run_response, session=agent_session, user_id=user_id
|
|
1994
2003
|
)
|
|
@@ -2009,6 +2018,7 @@ class Agent:
|
|
|
2009
2018
|
session=agent_session,
|
|
2010
2019
|
user_id=user_id,
|
|
2011
2020
|
debug_mode=debug_mode,
|
|
2021
|
+
background_tasks=background_tasks,
|
|
2012
2022
|
**kwargs,
|
|
2013
2023
|
):
|
|
2014
2024
|
pass
|
|
@@ -2017,7 +2027,7 @@ class Agent:
|
|
|
2017
2027
|
raise_if_cancelled(run_response.run_id) # type: ignore
|
|
2018
2028
|
|
|
2019
2029
|
# 14. Wait for background memory creation
|
|
2020
|
-
await
|
|
2030
|
+
await await_for_open_threads(memory_task=memory_task, cultural_knowledge_task=cultural_knowledge_task)
|
|
2021
2031
|
|
|
2022
2032
|
# 15. Create session summary
|
|
2023
2033
|
if self.session_summary_manager is not None:
|
|
@@ -2096,6 +2106,7 @@ class Agent:
|
|
|
2096
2106
|
stream_events: bool = False,
|
|
2097
2107
|
yield_run_output: Optional[bool] = None,
|
|
2098
2108
|
debug_mode: Optional[bool] = None,
|
|
2109
|
+
background_tasks: Optional[Any] = None,
|
|
2099
2110
|
**kwargs: Any,
|
|
2100
2111
|
) -> AsyncIterator[Union[RunOutputEvent, RunOutput]]:
|
|
2101
2112
|
"""Run the Agent and yield the RunOutput.
|
|
@@ -2162,6 +2173,7 @@ class Agent:
|
|
|
2162
2173
|
user_id=user_id,
|
|
2163
2174
|
debug_mode=debug_mode,
|
|
2164
2175
|
stream_events=stream_events,
|
|
2176
|
+
background_tasks=background_tasks,
|
|
2165
2177
|
**kwargs,
|
|
2166
2178
|
)
|
|
2167
2179
|
async for event in pre_hook_iterator:
|
|
@@ -2220,9 +2232,6 @@ class Agent:
|
|
|
2220
2232
|
log_debug("Starting cultural knowledge creation in background task.")
|
|
2221
2233
|
cultural_knowledge_task = create_task(self._acreate_cultural_knowledge(run_messages=run_messages))
|
|
2222
2234
|
|
|
2223
|
-
# Register run for cancellation tracking
|
|
2224
|
-
register_run(run_response.run_id) # type: ignore
|
|
2225
|
-
|
|
2226
2235
|
try:
|
|
2227
2236
|
# 8. Reason about the task if reasoning is enabled
|
|
2228
2237
|
async for item in self._ahandle_reasoning_stream(
|
|
@@ -2304,7 +2313,7 @@ class Agent:
|
|
|
2304
2313
|
|
|
2305
2314
|
# Break out of the run function if a tool call is paused
|
|
2306
2315
|
if any(tool_call.is_paused for tool_call in run_response.tools or []):
|
|
2307
|
-
async for item in
|
|
2316
|
+
async for item in await_for_thread_tasks_stream(
|
|
2308
2317
|
memory_task=memory_task,
|
|
2309
2318
|
cultural_knowledge_task=cultural_knowledge_task,
|
|
2310
2319
|
stream_events=stream_events,
|
|
@@ -2328,12 +2337,13 @@ class Agent:
|
|
|
2328
2337
|
user_id=user_id,
|
|
2329
2338
|
debug_mode=debug_mode,
|
|
2330
2339
|
stream_events=stream_events,
|
|
2340
|
+
background_tasks=background_tasks,
|
|
2331
2341
|
**kwargs,
|
|
2332
2342
|
):
|
|
2333
2343
|
yield event
|
|
2334
2344
|
|
|
2335
2345
|
# 11. Wait for background memory creation
|
|
2336
|
-
async for item in
|
|
2346
|
+
async for item in await_for_thread_tasks_stream(
|
|
2337
2347
|
memory_task=memory_task,
|
|
2338
2348
|
cultural_knowledge_task=cultural_knowledge_task,
|
|
2339
2349
|
stream_events=stream_events,
|
|
@@ -2537,6 +2547,10 @@ class Agent:
|
|
|
2537
2547
|
) -> Union[RunOutput, AsyncIterator[RunOutputEvent]]:
|
|
2538
2548
|
"""Async Run the Agent and return the response."""
|
|
2539
2549
|
|
|
2550
|
+
# Create a run_id for this specific run and register immediately for cancellation tracking
|
|
2551
|
+
run_id = str(uuid4())
|
|
2552
|
+
register_run(run_id)
|
|
2553
|
+
|
|
2540
2554
|
if (add_history_to_context or self.add_history_to_context) and not self.db and not self.team_id:
|
|
2541
2555
|
log_warning(
|
|
2542
2556
|
"add_history_to_context is True, but no database has been assigned to the agent. History will not be added to the context."
|
|
@@ -2549,8 +2563,11 @@ class Agent:
|
|
|
2549
2563
|
stacklevel=2,
|
|
2550
2564
|
)
|
|
2551
2565
|
|
|
2552
|
-
|
|
2553
|
-
|
|
2566
|
+
background_tasks = kwargs.pop("background_tasks", None)
|
|
2567
|
+
if background_tasks is not None:
|
|
2568
|
+
from fastapi import BackgroundTasks
|
|
2569
|
+
|
|
2570
|
+
background_tasks: BackgroundTasks = background_tasks # type: ignore
|
|
2554
2571
|
|
|
2555
2572
|
# 2. Validate input against input_schema if provided
|
|
2556
2573
|
validated_input = self._validate_input(input)
|
|
@@ -2695,6 +2712,7 @@ class Agent:
|
|
|
2695
2712
|
add_dependencies_to_context=add_dependencies,
|
|
2696
2713
|
add_session_state_to_context=add_session_state,
|
|
2697
2714
|
debug_mode=debug_mode,
|
|
2715
|
+
background_tasks=background_tasks,
|
|
2698
2716
|
**kwargs,
|
|
2699
2717
|
) # type: ignore[assignment]
|
|
2700
2718
|
else:
|
|
@@ -2708,6 +2726,7 @@ class Agent:
|
|
|
2708
2726
|
add_dependencies_to_context=add_dependencies,
|
|
2709
2727
|
add_session_state_to_context=add_session_state,
|
|
2710
2728
|
debug_mode=debug_mode,
|
|
2729
|
+
background_tasks=background_tasks,
|
|
2711
2730
|
**kwargs,
|
|
2712
2731
|
)
|
|
2713
2732
|
|
|
@@ -2839,6 +2858,12 @@ class Agent:
|
|
|
2839
2858
|
if self._has_async_db():
|
|
2840
2859
|
raise Exception("continue_run() is not supported with an async DB. Please use acontinue_arun() instead.")
|
|
2841
2860
|
|
|
2861
|
+
background_tasks = kwargs.pop("background_tasks", None)
|
|
2862
|
+
if background_tasks is not None:
|
|
2863
|
+
from fastapi import BackgroundTasks
|
|
2864
|
+
|
|
2865
|
+
background_tasks: BackgroundTasks = background_tasks # type: ignore
|
|
2866
|
+
|
|
2842
2867
|
session_id = run_response.session_id if run_response else session_id
|
|
2843
2868
|
run_id: str = run_response.run_id if run_response else run_id # type: ignore
|
|
2844
2869
|
|
|
@@ -2982,6 +3007,7 @@ class Agent:
|
|
|
2982
3007
|
response_format=response_format,
|
|
2983
3008
|
stream_events=stream_events,
|
|
2984
3009
|
debug_mode=debug_mode,
|
|
3010
|
+
background_tasks=background_tasks,
|
|
2985
3011
|
**kwargs,
|
|
2986
3012
|
)
|
|
2987
3013
|
return response_iterator
|
|
@@ -2995,6 +3021,7 @@ class Agent:
|
|
|
2995
3021
|
session=agent_session,
|
|
2996
3022
|
response_format=response_format,
|
|
2997
3023
|
debug_mode=debug_mode,
|
|
3024
|
+
background_tasks=background_tasks,
|
|
2998
3025
|
**kwargs,
|
|
2999
3026
|
)
|
|
3000
3027
|
return response
|
|
@@ -3045,6 +3072,7 @@ class Agent:
|
|
|
3045
3072
|
user_id: Optional[str] = None,
|
|
3046
3073
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
3047
3074
|
debug_mode: Optional[bool] = None,
|
|
3075
|
+
background_tasks: Optional[Any] = None,
|
|
3048
3076
|
**kwargs,
|
|
3049
3077
|
) -> RunOutput:
|
|
3050
3078
|
"""Continue a previous run.
|
|
@@ -3109,6 +3137,7 @@ class Agent:
|
|
|
3109
3137
|
session=session,
|
|
3110
3138
|
user_id=user_id,
|
|
3111
3139
|
debug_mode=debug_mode,
|
|
3140
|
+
background_tasks=background_tasks,
|
|
3112
3141
|
**kwargs,
|
|
3113
3142
|
)
|
|
3114
3143
|
deque(post_hook_iterator, maxlen=0)
|
|
@@ -3164,6 +3193,7 @@ class Agent:
|
|
|
3164
3193
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
3165
3194
|
stream_events: bool = False,
|
|
3166
3195
|
debug_mode: Optional[bool] = None,
|
|
3196
|
+
background_tasks: Optional[Any] = None,
|
|
3167
3197
|
**kwargs,
|
|
3168
3198
|
) -> Iterator[RunOutputEvent]:
|
|
3169
3199
|
"""Continue a previous run.
|
|
@@ -3240,6 +3270,7 @@ class Agent:
|
|
|
3240
3270
|
user_id=user_id,
|
|
3241
3271
|
debug_mode=debug_mode,
|
|
3242
3272
|
stream_events=stream_events,
|
|
3273
|
+
background_tasks=background_tasks,
|
|
3243
3274
|
**kwargs,
|
|
3244
3275
|
)
|
|
3245
3276
|
|
|
@@ -3341,6 +3372,7 @@ class Agent:
|
|
|
3341
3372
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
3342
3373
|
metadata: Optional[Dict[str, Any]] = None,
|
|
3343
3374
|
debug_mode: Optional[bool] = None,
|
|
3375
|
+
**kwargs: Any,
|
|
3344
3376
|
) -> RunOutput: ...
|
|
3345
3377
|
|
|
3346
3378
|
@overload
|
|
@@ -3360,6 +3392,7 @@ class Agent:
|
|
|
3360
3392
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
3361
3393
|
metadata: Optional[Dict[str, Any]] = None,
|
|
3362
3394
|
debug_mode: Optional[bool] = None,
|
|
3395
|
+
**kwargs: Any,
|
|
3363
3396
|
) -> AsyncIterator[Union[RunOutputEvent, RunOutput]]: ...
|
|
3364
3397
|
|
|
3365
3398
|
def acontinue_run( # type: ignore
|
|
@@ -3407,6 +3440,12 @@ class Agent:
|
|
|
3407
3440
|
if run_response is None and (run_id is not None and (session_id is None and self.session_id is None)):
|
|
3408
3441
|
raise ValueError("Session ID is required to continue a run from a run_id.")
|
|
3409
3442
|
|
|
3443
|
+
background_tasks = kwargs.pop("background_tasks", None)
|
|
3444
|
+
if background_tasks is not None:
|
|
3445
|
+
from fastapi import BackgroundTasks
|
|
3446
|
+
|
|
3447
|
+
background_tasks: BackgroundTasks = background_tasks # type: ignore
|
|
3448
|
+
|
|
3410
3449
|
session_id, user_id = self._initialize_session(
|
|
3411
3450
|
session_id=session_id,
|
|
3412
3451
|
user_id=user_id,
|
|
@@ -3491,6 +3530,7 @@ class Agent:
|
|
|
3491
3530
|
stream_events=stream_events,
|
|
3492
3531
|
yield_run_output=yield_run_output,
|
|
3493
3532
|
debug_mode=debug_mode,
|
|
3533
|
+
background_tasks=background_tasks,
|
|
3494
3534
|
**kwargs,
|
|
3495
3535
|
)
|
|
3496
3536
|
else:
|
|
@@ -3503,6 +3543,7 @@ class Agent:
|
|
|
3503
3543
|
user_id=user_id,
|
|
3504
3544
|
response_format=response_format,
|
|
3505
3545
|
debug_mode=debug_mode,
|
|
3546
|
+
background_tasks=background_tasks,
|
|
3506
3547
|
**kwargs,
|
|
3507
3548
|
)
|
|
3508
3549
|
except ModelProviderError as e:
|
|
@@ -3552,6 +3593,7 @@ class Agent:
|
|
|
3552
3593
|
user_id: Optional[str] = None,
|
|
3553
3594
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
3554
3595
|
debug_mode: Optional[bool] = None,
|
|
3596
|
+
background_tasks: Optional[Any] = None,
|
|
3555
3597
|
**kwargs,
|
|
3556
3598
|
) -> RunOutput:
|
|
3557
3599
|
"""Continue a previous run.
|
|
@@ -3694,6 +3736,7 @@ class Agent:
|
|
|
3694
3736
|
session=agent_session,
|
|
3695
3737
|
user_id=user_id,
|
|
3696
3738
|
debug_mode=debug_mode,
|
|
3739
|
+
background_tasks=background_tasks,
|
|
3697
3740
|
**kwargs,
|
|
3698
3741
|
):
|
|
3699
3742
|
pass
|
|
@@ -3763,6 +3806,7 @@ class Agent:
|
|
|
3763
3806
|
stream_events: bool = False,
|
|
3764
3807
|
yield_run_output: bool = False,
|
|
3765
3808
|
debug_mode: Optional[bool] = None,
|
|
3809
|
+
background_tasks: Optional[Any] = None,
|
|
3766
3810
|
**kwargs,
|
|
3767
3811
|
) -> AsyncIterator[Union[RunOutputEvent, RunOutput]]:
|
|
3768
3812
|
"""Continue a previous run.
|
|
@@ -3948,6 +3992,7 @@ class Agent:
|
|
|
3948
3992
|
user_id=user_id,
|
|
3949
3993
|
debug_mode=debug_mode,
|
|
3950
3994
|
stream_events=stream_events,
|
|
3995
|
+
background_tasks=background_tasks,
|
|
3951
3996
|
**kwargs,
|
|
3952
3997
|
):
|
|
3953
3998
|
yield event
|
|
@@ -4049,13 +4094,13 @@ class Agent:
|
|
|
4049
4094
|
user_id: Optional[str] = None,
|
|
4050
4095
|
debug_mode: Optional[bool] = None,
|
|
4051
4096
|
stream_events: bool = False,
|
|
4097
|
+
background_tasks: Optional[Any] = None,
|
|
4052
4098
|
**kwargs: Any,
|
|
4053
4099
|
) -> Iterator[RunOutputEvent]:
|
|
4054
4100
|
"""Execute multiple pre-hook functions in succession."""
|
|
4055
4101
|
if hooks is None:
|
|
4056
4102
|
return
|
|
4057
|
-
|
|
4058
|
-
# Prepare all possible arguments once
|
|
4103
|
+
# Prepare arguments for this hook
|
|
4059
4104
|
all_args = {
|
|
4060
4105
|
"run_input": run_input,
|
|
4061
4106
|
"run_context": run_context,
|
|
@@ -4067,9 +4112,32 @@ class Agent:
|
|
|
4067
4112
|
"user_id": user_id,
|
|
4068
4113
|
"debug_mode": debug_mode or self.debug_mode,
|
|
4069
4114
|
}
|
|
4115
|
+
|
|
4116
|
+
# Check if background_tasks is available and ALL hooks should run in background
|
|
4117
|
+
# Note: Pre-hooks running in background may not be able to modify run_input
|
|
4118
|
+
if self._run_hooks_in_background is True and background_tasks is not None:
|
|
4119
|
+
# Schedule ALL pre_hooks as background tasks
|
|
4120
|
+
# Copy args to prevent race conditions
|
|
4121
|
+
bg_args = copy_args_for_background(all_args)
|
|
4122
|
+
for hook in hooks:
|
|
4123
|
+
# Filter arguments to only include those that the hook accepts
|
|
4124
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4125
|
+
|
|
4126
|
+
# Add to background tasks
|
|
4127
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4128
|
+
return
|
|
4129
|
+
|
|
4070
4130
|
all_args.update(kwargs)
|
|
4071
4131
|
|
|
4072
4132
|
for i, hook in enumerate(hooks):
|
|
4133
|
+
# Check if this specific hook should run in background (via @hook decorator)
|
|
4134
|
+
if should_run_hook_in_background(hook) and background_tasks is not None:
|
|
4135
|
+
# Copy args to prevent race conditions
|
|
4136
|
+
bg_args = copy_args_for_background(all_args)
|
|
4137
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4138
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4139
|
+
continue
|
|
4140
|
+
|
|
4073
4141
|
if stream_events:
|
|
4074
4142
|
yield handle_event( # type: ignore
|
|
4075
4143
|
run_response=run_response,
|
|
@@ -4121,13 +4189,13 @@ class Agent:
|
|
|
4121
4189
|
user_id: Optional[str] = None,
|
|
4122
4190
|
debug_mode: Optional[bool] = None,
|
|
4123
4191
|
stream_events: bool = False,
|
|
4192
|
+
background_tasks: Optional[Any] = None,
|
|
4124
4193
|
**kwargs: Any,
|
|
4125
4194
|
) -> AsyncIterator[RunOutputEvent]:
|
|
4126
4195
|
"""Execute multiple pre-hook functions in succession (async version)."""
|
|
4127
4196
|
if hooks is None:
|
|
4128
4197
|
return
|
|
4129
|
-
|
|
4130
|
-
# Prepare all possible arguments once
|
|
4198
|
+
# Prepare arguments for this hook
|
|
4131
4199
|
all_args = {
|
|
4132
4200
|
"run_input": run_input,
|
|
4133
4201
|
"agent": self,
|
|
@@ -4139,9 +4207,32 @@ class Agent:
|
|
|
4139
4207
|
"user_id": user_id,
|
|
4140
4208
|
"debug_mode": debug_mode or self.debug_mode,
|
|
4141
4209
|
}
|
|
4210
|
+
|
|
4211
|
+
# Check if background_tasks is available and ALL hooks should run in background
|
|
4212
|
+
# Note: Pre-hooks running in background may not be able to modify run_input
|
|
4213
|
+
if self._run_hooks_in_background is True and background_tasks is not None:
|
|
4214
|
+
# Schedule ALL pre_hooks as background tasks
|
|
4215
|
+
# Copy args to prevent race conditions
|
|
4216
|
+
bg_args = copy_args_for_background(all_args)
|
|
4217
|
+
for hook in hooks:
|
|
4218
|
+
# Filter arguments to only include those that the hook accepts
|
|
4219
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4220
|
+
|
|
4221
|
+
# Add to background tasks (both sync and async hooks supported)
|
|
4222
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4223
|
+
return
|
|
4224
|
+
|
|
4142
4225
|
all_args.update(kwargs)
|
|
4143
4226
|
|
|
4144
4227
|
for i, hook in enumerate(hooks):
|
|
4228
|
+
# Check if this specific hook should run in background (via @hook decorator)
|
|
4229
|
+
if should_run_hook_in_background(hook) and background_tasks is not None:
|
|
4230
|
+
# Copy args to prevent race conditions
|
|
4231
|
+
bg_args = copy_args_for_background(all_args)
|
|
4232
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4233
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4234
|
+
continue
|
|
4235
|
+
|
|
4145
4236
|
if stream_events:
|
|
4146
4237
|
yield handle_event( # type: ignore
|
|
4147
4238
|
run_response=run_response,
|
|
@@ -4196,13 +4287,14 @@ class Agent:
|
|
|
4196
4287
|
user_id: Optional[str] = None,
|
|
4197
4288
|
debug_mode: Optional[bool] = None,
|
|
4198
4289
|
stream_events: bool = False,
|
|
4290
|
+
background_tasks: Optional[Any] = None,
|
|
4199
4291
|
**kwargs: Any,
|
|
4200
4292
|
) -> Iterator[RunOutputEvent]:
|
|
4201
4293
|
"""Execute multiple post-hook functions in succession."""
|
|
4202
4294
|
if hooks is None:
|
|
4203
4295
|
return
|
|
4204
4296
|
|
|
4205
|
-
# Prepare
|
|
4297
|
+
# Prepare arguments for this hook
|
|
4206
4298
|
all_args = {
|
|
4207
4299
|
"run_output": run_output,
|
|
4208
4300
|
"agent": self,
|
|
@@ -4214,9 +4306,31 @@ class Agent:
|
|
|
4214
4306
|
"run_context": run_context,
|
|
4215
4307
|
"debug_mode": debug_mode or self.debug_mode,
|
|
4216
4308
|
}
|
|
4309
|
+
|
|
4310
|
+
# Check if background_tasks is available and ALL hooks should run in background
|
|
4311
|
+
if self._run_hooks_in_background is True and background_tasks is not None:
|
|
4312
|
+
# Schedule ALL post_hooks as background tasks
|
|
4313
|
+
# Copy args to prevent race conditions
|
|
4314
|
+
bg_args = copy_args_for_background(all_args)
|
|
4315
|
+
for hook in hooks:
|
|
4316
|
+
# Filter arguments to only include those that the hook accepts
|
|
4317
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4318
|
+
|
|
4319
|
+
# Add to background tasks
|
|
4320
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4321
|
+
return
|
|
4322
|
+
|
|
4217
4323
|
all_args.update(kwargs)
|
|
4218
4324
|
|
|
4219
4325
|
for i, hook in enumerate(hooks):
|
|
4326
|
+
# Check if this specific hook should run in background (via @hook decorator)
|
|
4327
|
+
if should_run_hook_in_background(hook) and background_tasks is not None:
|
|
4328
|
+
# Copy args to prevent race conditions
|
|
4329
|
+
bg_args = copy_args_for_background(all_args)
|
|
4330
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4331
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4332
|
+
continue
|
|
4333
|
+
|
|
4220
4334
|
if stream_events:
|
|
4221
4335
|
yield handle_event( # type: ignore
|
|
4222
4336
|
run_response=run_output,
|
|
@@ -4261,13 +4375,14 @@ class Agent:
|
|
|
4261
4375
|
user_id: Optional[str] = None,
|
|
4262
4376
|
debug_mode: Optional[bool] = None,
|
|
4263
4377
|
stream_events: bool = False,
|
|
4378
|
+
background_tasks: Optional[Any] = None,
|
|
4264
4379
|
**kwargs: Any,
|
|
4265
4380
|
) -> AsyncIterator[RunOutputEvent]:
|
|
4266
4381
|
"""Execute multiple post-hook functions in succession (async version)."""
|
|
4267
4382
|
if hooks is None:
|
|
4268
4383
|
return
|
|
4269
4384
|
|
|
4270
|
-
# Prepare
|
|
4385
|
+
# Prepare arguments for this hook
|
|
4271
4386
|
all_args = {
|
|
4272
4387
|
"run_output": run_output,
|
|
4273
4388
|
"agent": self,
|
|
@@ -4279,9 +4394,29 @@ class Agent:
|
|
|
4279
4394
|
"user_id": user_id,
|
|
4280
4395
|
"debug_mode": debug_mode or self.debug_mode,
|
|
4281
4396
|
}
|
|
4397
|
+
# Check if background_tasks is available and ALL hooks should run in background
|
|
4398
|
+
if self._run_hooks_in_background is True and background_tasks is not None:
|
|
4399
|
+
# Copy args to prevent race conditions
|
|
4400
|
+
bg_args = copy_args_for_background(all_args)
|
|
4401
|
+
for hook in hooks:
|
|
4402
|
+
# Filter arguments to only include those that the hook accepts
|
|
4403
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4404
|
+
|
|
4405
|
+
# Add to background tasks (both sync and async hooks supported)
|
|
4406
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4407
|
+
return
|
|
4408
|
+
|
|
4282
4409
|
all_args.update(kwargs)
|
|
4283
4410
|
|
|
4284
4411
|
for i, hook in enumerate(hooks):
|
|
4412
|
+
# Check if this specific hook should run in background (via @hook decorator)
|
|
4413
|
+
if should_run_hook_in_background(hook) and background_tasks is not None:
|
|
4414
|
+
# Copy args to prevent race conditions
|
|
4415
|
+
bg_args = copy_args_for_background(all_args)
|
|
4416
|
+
filtered_args = filter_hook_args(hook, bg_args)
|
|
4417
|
+
background_tasks.add_task(hook, **filtered_args)
|
|
4418
|
+
continue
|
|
4419
|
+
|
|
4285
4420
|
if stream_events:
|
|
4286
4421
|
yield handle_event( # type: ignore
|
|
4287
4422
|
run_response=run_output,
|
|
@@ -8664,6 +8799,7 @@ class Agent:
|
|
|
8664
8799
|
# Update fields if provided
|
|
8665
8800
|
if update:
|
|
8666
8801
|
fields_for_new_agent.update(update)
|
|
8802
|
+
|
|
8667
8803
|
# Create a new Agent
|
|
8668
8804
|
new_agent = self.__class__(**fields_for_new_agent)
|
|
8669
8805
|
log_debug(f"Created new {self.__class__.__name__}")
|
agno/culture/manager.py
CHANGED
|
@@ -118,7 +118,7 @@ class CultureManager:
|
|
|
118
118
|
|
|
119
119
|
self.db = cast(AsyncBaseDb, self.db)
|
|
120
120
|
|
|
121
|
-
return await self.db.get_cultural_knowledge(id=id)
|
|
121
|
+
return await self.db.get_cultural_knowledge(id=id) # type: ignore
|
|
122
122
|
|
|
123
123
|
def get_all_knowledge(self, name: Optional[str] = None) -> Optional[List[CulturalKnowledge]]:
|
|
124
124
|
"""Get all cultural knowledge in the database"""
|
|
@@ -135,7 +135,7 @@ class CultureManager:
|
|
|
135
135
|
return None
|
|
136
136
|
|
|
137
137
|
if isinstance(self.db, AsyncBaseDb):
|
|
138
|
-
return await self.db.get_all_cultural_knowledge(name=name)
|
|
138
|
+
return await self.db.get_all_cultural_knowledge(name=name) # type: ignore
|
|
139
139
|
else:
|
|
140
140
|
return self.db.get_all_cultural_knowledge(name=name)
|
|
141
141
|
|