agno 2.3.25__py3-none-any.whl → 2.4.0__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/__init__.py +4 -0
- agno/agent/agent.py +1428 -558
- agno/agent/remote.py +13 -0
- agno/db/base.py +339 -0
- agno/db/postgres/async_postgres.py +116 -12
- agno/db/postgres/postgres.py +1229 -25
- agno/db/postgres/schemas.py +48 -1
- agno/db/sqlite/async_sqlite.py +119 -4
- agno/db/sqlite/schemas.py +51 -0
- agno/db/sqlite/sqlite.py +1173 -13
- agno/db/utils.py +37 -1
- agno/knowledge/__init__.py +4 -0
- agno/knowledge/chunking/code.py +1 -1
- agno/knowledge/chunking/semantic.py +1 -1
- agno/knowledge/chunking/strategy.py +4 -0
- agno/knowledge/filesystem.py +412 -0
- agno/knowledge/knowledge.py +2767 -2254
- agno/knowledge/protocol.py +134 -0
- agno/knowledge/reader/arxiv_reader.py +2 -2
- agno/knowledge/reader/base.py +9 -7
- agno/knowledge/reader/csv_reader.py +5 -5
- agno/knowledge/reader/docx_reader.py +2 -2
- agno/knowledge/reader/field_labeled_csv_reader.py +2 -2
- agno/knowledge/reader/firecrawl_reader.py +2 -2
- agno/knowledge/reader/json_reader.py +2 -2
- agno/knowledge/reader/markdown_reader.py +2 -2
- agno/knowledge/reader/pdf_reader.py +5 -4
- agno/knowledge/reader/pptx_reader.py +2 -2
- agno/knowledge/reader/reader_factory.py +110 -0
- agno/knowledge/reader/s3_reader.py +2 -2
- agno/knowledge/reader/tavily_reader.py +2 -2
- agno/knowledge/reader/text_reader.py +2 -2
- agno/knowledge/reader/web_search_reader.py +2 -2
- agno/knowledge/reader/website_reader.py +5 -3
- agno/knowledge/reader/wikipedia_reader.py +2 -2
- agno/knowledge/reader/youtube_reader.py +2 -2
- agno/knowledge/utils.py +37 -29
- agno/learn/__init__.py +6 -0
- agno/learn/machine.py +35 -0
- agno/learn/schemas.py +82 -11
- agno/learn/stores/__init__.py +3 -0
- agno/learn/stores/decision_log.py +1156 -0
- agno/learn/stores/learned_knowledge.py +6 -6
- agno/models/anthropic/claude.py +24 -0
- agno/models/aws/bedrock.py +20 -0
- agno/models/base.py +48 -4
- agno/models/cohere/chat.py +25 -0
- agno/models/google/gemini.py +50 -5
- agno/models/litellm/chat.py +38 -0
- agno/models/openai/chat.py +7 -0
- agno/models/openrouter/openrouter.py +46 -0
- agno/models/response.py +16 -0
- agno/os/app.py +83 -44
- agno/os/middleware/__init__.py +2 -0
- agno/os/middleware/trailing_slash.py +27 -0
- agno/os/router.py +1 -0
- agno/os/routers/agents/router.py +29 -16
- agno/os/routers/agents/schema.py +6 -4
- agno/os/routers/components/__init__.py +3 -0
- agno/os/routers/components/components.py +466 -0
- agno/os/routers/evals/schemas.py +4 -3
- agno/os/routers/health.py +3 -3
- agno/os/routers/knowledge/knowledge.py +3 -3
- agno/os/routers/memory/schemas.py +4 -2
- agno/os/routers/metrics/metrics.py +9 -11
- agno/os/routers/metrics/schemas.py +10 -6
- agno/os/routers/registry/__init__.py +3 -0
- agno/os/routers/registry/registry.py +337 -0
- agno/os/routers/teams/router.py +20 -8
- agno/os/routers/teams/schema.py +6 -4
- agno/os/routers/traces/traces.py +5 -5
- agno/os/routers/workflows/router.py +38 -11
- agno/os/routers/workflows/schema.py +1 -1
- agno/os/schema.py +92 -26
- agno/os/utils.py +133 -16
- agno/reasoning/anthropic.py +2 -2
- agno/reasoning/azure_ai_foundry.py +2 -2
- agno/reasoning/deepseek.py +2 -2
- agno/reasoning/default.py +6 -7
- agno/reasoning/gemini.py +2 -2
- agno/reasoning/helpers.py +6 -7
- agno/reasoning/manager.py +4 -10
- agno/reasoning/ollama.py +2 -2
- agno/reasoning/openai.py +2 -2
- agno/reasoning/vertexai.py +2 -2
- agno/registry/__init__.py +3 -0
- agno/registry/registry.py +68 -0
- agno/run/agent.py +57 -0
- agno/run/base.py +7 -0
- agno/run/team.py +57 -0
- agno/skills/agent_skills.py +10 -3
- agno/team/__init__.py +3 -1
- agno/team/team.py +1276 -326
- agno/tools/duckduckgo.py +25 -71
- agno/tools/exa.py +0 -21
- agno/tools/function.py +35 -83
- agno/tools/knowledge.py +9 -4
- agno/tools/mem0.py +11 -10
- agno/tools/memory.py +47 -46
- agno/tools/parallel.py +0 -7
- agno/tools/reasoning.py +30 -23
- agno/tools/tavily.py +4 -1
- agno/tools/websearch.py +93 -0
- agno/tools/website.py +1 -1
- agno/tools/wikipedia.py +1 -1
- agno/tools/workflow.py +48 -47
- agno/utils/agent.py +42 -5
- agno/utils/events.py +160 -2
- agno/utils/print_response/agent.py +0 -31
- agno/utils/print_response/team.py +0 -2
- agno/utils/print_response/workflow.py +0 -2
- agno/utils/team.py +61 -11
- agno/vectordb/lancedb/lance_db.py +4 -1
- agno/vectordb/mongodb/mongodb.py +1 -1
- agno/vectordb/qdrant/qdrant.py +4 -4
- agno/workflow/__init__.py +3 -1
- agno/workflow/condition.py +0 -21
- agno/workflow/loop.py +0 -21
- agno/workflow/parallel.py +0 -21
- agno/workflow/router.py +0 -21
- agno/workflow/step.py +117 -24
- agno/workflow/steps.py +0 -21
- agno/workflow/workflow.py +625 -63
- {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/METADATA +46 -76
- {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/RECORD +128 -117
- {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/WHEEL +0 -0
- {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/top_level.txt +0 -0
agno/tools/duckduckgo.py
CHANGED
|
@@ -1,36 +1,26 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Any, List, Optional
|
|
1
|
+
from typing import Optional
|
|
3
2
|
|
|
4
|
-
from agno.tools import
|
|
5
|
-
from agno.utils.log import log_debug
|
|
3
|
+
from agno.tools.websearch import WebSearchTools
|
|
6
4
|
|
|
7
|
-
try:
|
|
8
|
-
from ddgs import DDGS
|
|
9
|
-
except ImportError:
|
|
10
|
-
raise ImportError("`ddgs` not installed. Please install using `pip install ddgs`")
|
|
11
5
|
|
|
12
|
-
|
|
13
|
-
class DuckDuckGoTools(Toolkit):
|
|
6
|
+
class DuckDuckGoTools(WebSearchTools):
|
|
14
7
|
"""
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
DuckDuckGoTools is a convenience wrapper around WebSearchTools with the backend
|
|
9
|
+
defaulting to "duckduckgo".
|
|
17
10
|
Args:
|
|
18
|
-
enable_search (bool): Enable
|
|
19
|
-
enable_news (bool): Enable
|
|
20
|
-
modifier (Optional[str]): A modifier to be
|
|
11
|
+
enable_search (bool): Enable web search function.
|
|
12
|
+
enable_news (bool): Enable news search function.
|
|
13
|
+
modifier (Optional[str]): A modifier to be prepended to search queries.
|
|
21
14
|
fixed_max_results (Optional[int]): A fixed number of maximum results.
|
|
22
|
-
proxy (Optional[str]): Proxy to be used
|
|
15
|
+
proxy (Optional[str]): Proxy to be used for requests.
|
|
23
16
|
timeout (Optional[int]): The maximum number of seconds to wait for a response.
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
verify_ssl (bool): Whether to verify SSL certificates.
|
|
26
18
|
"""
|
|
27
19
|
|
|
28
20
|
def __init__(
|
|
29
21
|
self,
|
|
30
22
|
enable_search: bool = True,
|
|
31
23
|
enable_news: bool = True,
|
|
32
|
-
all: bool = False,
|
|
33
|
-
backend: str = "duckduckgo",
|
|
34
24
|
modifier: Optional[str] = None,
|
|
35
25
|
fixed_max_results: Optional[int] = None,
|
|
36
26
|
proxy: Optional[str] = None,
|
|
@@ -38,54 +28,18 @@ class DuckDuckGoTools(Toolkit):
|
|
|
38
28
|
verify_ssl: bool = True,
|
|
39
29
|
**kwargs,
|
|
40
30
|
):
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def duckduckgo_search(self, query: str, max_results: int = 5) -> str:
|
|
57
|
-
"""Use this function to search DDGS for a query.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
query(str): The query to search for.
|
|
61
|
-
max_results (optional, default=5): The maximum number of results to return.
|
|
62
|
-
|
|
63
|
-
Returns:
|
|
64
|
-
The result from DDGS.
|
|
65
|
-
"""
|
|
66
|
-
actual_max_results = self.fixed_max_results or max_results
|
|
67
|
-
search_query = f"{self.modifier} {query}" if self.modifier else query
|
|
68
|
-
|
|
69
|
-
log_debug(f"Searching DDG for: {search_query} using backend: {self.backend}")
|
|
70
|
-
with DDGS(proxy=self.proxy, timeout=self.timeout, verify=self.verify_ssl) as ddgs:
|
|
71
|
-
results = ddgs.text(query=search_query, max_results=actual_max_results, backend=self.backend)
|
|
72
|
-
|
|
73
|
-
return json.dumps(results, indent=2)
|
|
74
|
-
|
|
75
|
-
def duckduckgo_news(self, query: str, max_results: int = 5) -> str:
|
|
76
|
-
"""Use this function to get the latest news from DDGS.
|
|
77
|
-
|
|
78
|
-
Args:
|
|
79
|
-
query(str): The query to search for.
|
|
80
|
-
max_results (optional, default=5): The maximum number of results to return.
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
The latest news from DDGS.
|
|
84
|
-
"""
|
|
85
|
-
actual_max_results = self.fixed_max_results or max_results
|
|
86
|
-
|
|
87
|
-
log_debug(f"Searching DDG news for: {query} using backend: {self.backend}")
|
|
88
|
-
with DDGS(proxy=self.proxy, timeout=self.timeout, verify=self.verify_ssl) as ddgs:
|
|
89
|
-
results = ddgs.news(query=query, max_results=actual_max_results, backend=self.backend)
|
|
90
|
-
|
|
91
|
-
return json.dumps(results, indent=2)
|
|
31
|
+
super().__init__(
|
|
32
|
+
enable_search=enable_search,
|
|
33
|
+
enable_news=enable_news,
|
|
34
|
+
backend="duckduckgo",
|
|
35
|
+
modifier=modifier,
|
|
36
|
+
fixed_max_results=fixed_max_results,
|
|
37
|
+
proxy=proxy,
|
|
38
|
+
timeout=timeout,
|
|
39
|
+
verify_ssl=verify_ssl,
|
|
40
|
+
**kwargs,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Backward compatibility aliases for old method names
|
|
44
|
+
self.duckduckgo_search = self.web_search
|
|
45
|
+
self.duckduckgo_news = self.search_news
|
agno/tools/exa.py
CHANGED
|
@@ -27,14 +27,12 @@ class ExaTools(Toolkit):
|
|
|
27
27
|
all (bool): Enable all tools. Overrides individual flags when True. Default is False.
|
|
28
28
|
text (bool): Retrieve text content from results. Default is True.
|
|
29
29
|
text_length_limit (int): Max length of text content per result. Default is 1000.
|
|
30
|
-
highlights (bool): Include highlighted snippets. Deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.
|
|
31
30
|
api_key (Optional[str]): Exa API key. Retrieved from `EXA_API_KEY` env variable if not provided.
|
|
32
31
|
num_results (Optional[int]): Default number of search results. Overrides individual searches if set.
|
|
33
32
|
start_crawl_date (Optional[str]): Include results crawled on/after this date (`YYYY-MM-DD`).
|
|
34
33
|
end_crawl_date (Optional[str]): Include results crawled on/before this date (`YYYY-MM-DD`).
|
|
35
34
|
start_published_date (Optional[str]): Include results published on/after this date (`YYYY-MM-DD`).
|
|
36
35
|
end_published_date (Optional[str]): Include results published on/before this date (`YYYY-MM-DD`).
|
|
37
|
-
use_autoprompt (Optional[bool]): Enable autoprompt features in queries. Deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.
|
|
38
36
|
type (Optional[str]): Specify content type (e.g., article, blog, video).
|
|
39
37
|
category (Optional[str]): Filter results by category. Options are "company", "research paper", "news", "pdf", "github", "tweet", "personal site", "linkedin profile", "financial report".
|
|
40
38
|
include_domains (Optional[List[str]]): Restrict results to these domains.
|
|
@@ -54,7 +52,6 @@ class ExaTools(Toolkit):
|
|
|
54
52
|
all: bool = False,
|
|
55
53
|
text: bool = True,
|
|
56
54
|
text_length_limit: int = 1000,
|
|
57
|
-
highlights: Optional[bool] = None, # Deprecated
|
|
58
55
|
summary: bool = False,
|
|
59
56
|
api_key: Optional[str] = None,
|
|
60
57
|
num_results: Optional[int] = None,
|
|
@@ -63,7 +60,6 @@ class ExaTools(Toolkit):
|
|
|
63
60
|
end_crawl_date: Optional[str] = None,
|
|
64
61
|
start_published_date: Optional[str] = None,
|
|
65
62
|
end_published_date: Optional[str] = None,
|
|
66
|
-
use_autoprompt: Optional[bool] = None,
|
|
67
63
|
type: Optional[str] = None,
|
|
68
64
|
category: Optional[str] = None,
|
|
69
65
|
include_domains: Optional[List[str]] = None,
|
|
@@ -85,23 +81,6 @@ class ExaTools(Toolkit):
|
|
|
85
81
|
self.text: bool = text
|
|
86
82
|
self.text_length_limit: int = text_length_limit
|
|
87
83
|
|
|
88
|
-
if highlights:
|
|
89
|
-
import warnings
|
|
90
|
-
|
|
91
|
-
warnings.warn(
|
|
92
|
-
"The 'highlights' parameter is deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.",
|
|
93
|
-
DeprecationWarning,
|
|
94
|
-
stacklevel=2,
|
|
95
|
-
)
|
|
96
|
-
if use_autoprompt:
|
|
97
|
-
import warnings
|
|
98
|
-
|
|
99
|
-
warnings.warn(
|
|
100
|
-
"The 'use_autoprompt' parameter is deprecated since it was removed in the Exa API. It will be removed from Agno in a future release.",
|
|
101
|
-
DeprecationWarning,
|
|
102
|
-
stacklevel=2,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
84
|
self.summary: bool = summary
|
|
106
85
|
self.num_results: Optional[int] = num_results
|
|
107
86
|
self.livecrawl: str = livecrawl
|
agno/tools/function.py
CHANGED
|
@@ -133,10 +133,6 @@ class Function(BaseModel):
|
|
|
133
133
|
_team: Optional[Any] = None
|
|
134
134
|
# The run context that the function is associated with
|
|
135
135
|
_run_context: Optional[RunContext] = None
|
|
136
|
-
# The session state that the function is associated with
|
|
137
|
-
_session_state: Optional[Dict[str, Any]] = None
|
|
138
|
-
# The dependencies that the function is associated with
|
|
139
|
-
_dependencies: Optional[Dict[str, Any]] = None
|
|
140
136
|
|
|
141
137
|
# Media context that the function is associated with
|
|
142
138
|
_images: Optional[Sequence[Image]] = None
|
|
@@ -150,6 +146,19 @@ class Function(BaseModel):
|
|
|
150
146
|
include={"name", "description", "parameters", "strict", "requires_confirmation", "external_execution"},
|
|
151
147
|
)
|
|
152
148
|
|
|
149
|
+
@classmethod
|
|
150
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Function":
|
|
151
|
+
"""Reconstruct a Function from a dictionary."""
|
|
152
|
+
|
|
153
|
+
return cls(
|
|
154
|
+
name=data.get("name"),
|
|
155
|
+
description=data.get("description"),
|
|
156
|
+
parameters=data.get("parameters"),
|
|
157
|
+
strict=data.get("strict"),
|
|
158
|
+
requires_confirmation=data.get("requires_confirmation", False),
|
|
159
|
+
external_execution=data.get("external_execution", False),
|
|
160
|
+
)
|
|
161
|
+
|
|
153
162
|
def model_copy(self, *, deep: bool = False) -> "Function":
|
|
154
163
|
"""
|
|
155
164
|
Override model_copy to handle callable fields that can't be deep copied (pickled).
|
|
@@ -209,10 +218,6 @@ class Function(BaseModel):
|
|
|
209
218
|
del type_hints["team"]
|
|
210
219
|
if "run_context" in sig.parameters and "run_context" in type_hints:
|
|
211
220
|
del type_hints["run_context"]
|
|
212
|
-
if "session_state" in sig.parameters and "session_state" in type_hints:
|
|
213
|
-
del type_hints["session_state"]
|
|
214
|
-
if "dependencies" in sig.parameters and "dependencies" in type_hints:
|
|
215
|
-
del type_hints["dependencies"]
|
|
216
221
|
|
|
217
222
|
# Remove media parameters from type hints as they are injected automatically
|
|
218
223
|
if "images" in sig.parameters and "images" in type_hints:
|
|
@@ -235,8 +240,6 @@ class Function(BaseModel):
|
|
|
235
240
|
"agent",
|
|
236
241
|
"team",
|
|
237
242
|
"run_context",
|
|
238
|
-
"session_state",
|
|
239
|
-
"dependencies",
|
|
240
243
|
"self",
|
|
241
244
|
"images",
|
|
242
245
|
"videos",
|
|
@@ -276,8 +279,6 @@ class Function(BaseModel):
|
|
|
276
279
|
"agent",
|
|
277
280
|
"team",
|
|
278
281
|
"run_context",
|
|
279
|
-
"session_state",
|
|
280
|
-
"dependencies",
|
|
281
282
|
"self",
|
|
282
283
|
"images",
|
|
283
284
|
"videos",
|
|
@@ -296,8 +297,6 @@ class Function(BaseModel):
|
|
|
296
297
|
"agent",
|
|
297
298
|
"team",
|
|
298
299
|
"run_context",
|
|
299
|
-
"session_state",
|
|
300
|
-
"dependencies",
|
|
301
300
|
"self",
|
|
302
301
|
"images",
|
|
303
302
|
"videos",
|
|
@@ -354,10 +353,6 @@ class Function(BaseModel):
|
|
|
354
353
|
del type_hints["team"]
|
|
355
354
|
if "run_context" in sig.parameters and "run_context" in type_hints:
|
|
356
355
|
del type_hints["run_context"]
|
|
357
|
-
if "session_state" in sig.parameters and "session_state" in type_hints:
|
|
358
|
-
del type_hints["session_state"]
|
|
359
|
-
if "dependencies" in sig.parameters and "dependencies" in type_hints:
|
|
360
|
-
del type_hints["dependencies"]
|
|
361
356
|
if "images" in sig.parameters and "images" in type_hints:
|
|
362
357
|
del type_hints["images"]
|
|
363
358
|
if "videos" in sig.parameters and "videos" in type_hints:
|
|
@@ -374,8 +369,6 @@ class Function(BaseModel):
|
|
|
374
369
|
"agent",
|
|
375
370
|
"team",
|
|
376
371
|
"run_context",
|
|
377
|
-
"session_state",
|
|
378
|
-
"dependencies",
|
|
379
372
|
"self",
|
|
380
373
|
"images",
|
|
381
374
|
"videos",
|
|
@@ -488,10 +481,15 @@ class Function(BaseModel):
|
|
|
488
481
|
# Don't wrap callables that are already wrapped with validate_call
|
|
489
482
|
elif getattr(func, "_wrapped_for_validation", False):
|
|
490
483
|
return func
|
|
491
|
-
|
|
492
|
-
#
|
|
493
|
-
|
|
484
|
+
|
|
485
|
+
# Don't wrap functions with framework-injected parameters
|
|
486
|
+
# These parameters (agent, team) are
|
|
487
|
+
# injected by the framework at runtime and shouldn't be validated by Pydantic
|
|
488
|
+
sig = signature(func)
|
|
489
|
+
framework_params = {"agent", "team"}
|
|
490
|
+
if framework_params & set(sig.parameters.keys()):
|
|
494
491
|
return func
|
|
492
|
+
|
|
495
493
|
# Wrap the callable with validate_call
|
|
496
494
|
else:
|
|
497
495
|
wrapped = validate_call(func, config=dict(arbitrary_types_allowed=True)) # type: ignore
|
|
@@ -546,8 +544,6 @@ class Function(BaseModel):
|
|
|
546
544
|
"agent",
|
|
547
545
|
"team",
|
|
548
546
|
"run_context",
|
|
549
|
-
"session_state",
|
|
550
|
-
"dependencies",
|
|
551
547
|
"images",
|
|
552
548
|
"videos",
|
|
553
549
|
"audios",
|
|
@@ -569,10 +565,6 @@ class Function(BaseModel):
|
|
|
569
565
|
del copy_entrypoint_args["team"]
|
|
570
566
|
if "run_context" in copy_entrypoint_args:
|
|
571
567
|
del copy_entrypoint_args["run_context"]
|
|
572
|
-
if "session_state" in copy_entrypoint_args:
|
|
573
|
-
del copy_entrypoint_args["session_state"]
|
|
574
|
-
if "dependencies" in copy_entrypoint_args:
|
|
575
|
-
del copy_entrypoint_args["dependencies"]
|
|
576
568
|
if "images" in copy_entrypoint_args:
|
|
577
569
|
del copy_entrypoint_args["images"]
|
|
578
570
|
if "videos" in copy_entrypoint_args:
|
|
@@ -699,21 +691,15 @@ class FunctionCall(BaseModel):
|
|
|
699
691
|
from inspect import signature
|
|
700
692
|
|
|
701
693
|
pre_hook_args = {}
|
|
702
|
-
# Check if the pre-hook has
|
|
694
|
+
# Check if the pre-hook has an agent argument
|
|
703
695
|
if "agent" in signature(self.function.pre_hook).parameters:
|
|
704
696
|
pre_hook_args["agent"] = self.function._agent
|
|
705
|
-
# Check if the pre-hook has
|
|
697
|
+
# Check if the pre-hook has a team argument
|
|
706
698
|
if "team" in signature(self.function.pre_hook).parameters:
|
|
707
699
|
pre_hook_args["team"] = self.function._team
|
|
708
|
-
# Check if the pre-hook has
|
|
700
|
+
# Check if the pre-hook has a run_context argument
|
|
709
701
|
if "run_context" in signature(self.function.pre_hook).parameters:
|
|
710
702
|
pre_hook_args["run_context"] = self.function._run_context
|
|
711
|
-
# Check if the pre-hook has an session_state argument
|
|
712
|
-
if "session_state" in signature(self.function.pre_hook).parameters:
|
|
713
|
-
pre_hook_args["session_state"] = self.function._session_state
|
|
714
|
-
# Check if the pre-hook has an dependencies argument
|
|
715
|
-
if "dependencies" in signature(self.function.pre_hook).parameters:
|
|
716
|
-
pre_hook_args["dependencies"] = self.function._dependencies
|
|
717
703
|
# Check if the pre-hook has an fc argument
|
|
718
704
|
if "fc" in signature(self.function.pre_hook).parameters:
|
|
719
705
|
pre_hook_args["fc"] = self
|
|
@@ -733,21 +719,15 @@ class FunctionCall(BaseModel):
|
|
|
733
719
|
from inspect import signature
|
|
734
720
|
|
|
735
721
|
post_hook_args = {}
|
|
736
|
-
# Check if the post-hook has
|
|
722
|
+
# Check if the post-hook has an agent argument
|
|
737
723
|
if "agent" in signature(self.function.post_hook).parameters:
|
|
738
724
|
post_hook_args["agent"] = self.function._agent
|
|
739
|
-
# Check if the post-hook has
|
|
725
|
+
# Check if the post-hook has a team argument
|
|
740
726
|
if "team" in signature(self.function.post_hook).parameters:
|
|
741
727
|
post_hook_args["team"] = self.function._team
|
|
742
|
-
# Check if the post-hook has
|
|
728
|
+
# Check if the post-hook has a run_context argument
|
|
743
729
|
if "run_context" in signature(self.function.post_hook).parameters:
|
|
744
730
|
post_hook_args["run_context"] = self.function._run_context
|
|
745
|
-
# Check if the post-hook has an session_state argument
|
|
746
|
-
if "session_state" in signature(self.function.post_hook).parameters:
|
|
747
|
-
post_hook_args["session_state"] = self.function._session_state
|
|
748
|
-
# Check if the post-hook has an dependencies argument
|
|
749
|
-
if "dependencies" in signature(self.function.post_hook).parameters:
|
|
750
|
-
post_hook_args["dependencies"] = self.function._dependencies
|
|
751
731
|
# Check if the post-hook has an fc argument
|
|
752
732
|
if "fc" in signature(self.function.post_hook).parameters:
|
|
753
733
|
post_hook_args["fc"] = self
|
|
@@ -768,18 +748,12 @@ class FunctionCall(BaseModel):
|
|
|
768
748
|
# Check if the entrypoint has an agent argument
|
|
769
749
|
if "agent" in signature(self.function.entrypoint).parameters: # type: ignore
|
|
770
750
|
entrypoint_args["agent"] = self.function._agent
|
|
771
|
-
# Check if the entrypoint has
|
|
751
|
+
# Check if the entrypoint has a team argument
|
|
772
752
|
if "team" in signature(self.function.entrypoint).parameters: # type: ignore
|
|
773
753
|
entrypoint_args["team"] = self.function._team
|
|
774
|
-
# Check if the entrypoint has
|
|
754
|
+
# Check if the entrypoint has a run_context argument
|
|
775
755
|
if "run_context" in signature(self.function.entrypoint).parameters: # type: ignore
|
|
776
756
|
entrypoint_args["run_context"] = self.function._run_context
|
|
777
|
-
# Check if the entrypoint has an session_state argument
|
|
778
|
-
if "session_state" in signature(self.function.entrypoint).parameters: # type: ignore
|
|
779
|
-
entrypoint_args["session_state"] = self.function._session_state
|
|
780
|
-
# Check if the entrypoint has an dependencies argument
|
|
781
|
-
if "dependencies" in signature(self.function.entrypoint).parameters: # type: ignore
|
|
782
|
-
entrypoint_args["dependencies"] = self.function._dependencies
|
|
783
757
|
# Check if the entrypoint has an fc argument
|
|
784
758
|
if "fc" in signature(self.function.entrypoint).parameters: # type: ignore
|
|
785
759
|
entrypoint_args["fc"] = self
|
|
@@ -803,18 +777,12 @@ class FunctionCall(BaseModel):
|
|
|
803
777
|
# Check if the hook has an agent argument
|
|
804
778
|
if "agent" in signature(hook).parameters:
|
|
805
779
|
hook_args["agent"] = self.function._agent
|
|
806
|
-
# Check if the hook has
|
|
780
|
+
# Check if the hook has a team argument
|
|
807
781
|
if "team" in signature(hook).parameters:
|
|
808
782
|
hook_args["team"] = self.function._team
|
|
809
|
-
# Check if the hook has
|
|
783
|
+
# Check if the hook has a run_context argument
|
|
810
784
|
if "run_context" in signature(hook).parameters:
|
|
811
785
|
hook_args["run_context"] = self.function._run_context
|
|
812
|
-
# Check if the hook has an session_state argument
|
|
813
|
-
if "session_state" in signature(hook).parameters:
|
|
814
|
-
hook_args["session_state"] = self.function._session_state
|
|
815
|
-
# Check if the hook has an dependencies argument
|
|
816
|
-
if "dependencies" in signature(hook).parameters:
|
|
817
|
-
hook_args["dependencies"] = self.function._dependencies
|
|
818
786
|
if "name" in signature(hook).parameters:
|
|
819
787
|
hook_args["name"] = name
|
|
820
788
|
if "function_name" in signature(hook).parameters:
|
|
@@ -942,9 +910,6 @@ class FunctionCall(BaseModel):
|
|
|
942
910
|
if run_context is not None and run_context.session_state is not None
|
|
943
911
|
else None
|
|
944
912
|
)
|
|
945
|
-
else:
|
|
946
|
-
if self.function._session_state is not None:
|
|
947
|
-
updated_session_state = self.function._session_state
|
|
948
913
|
|
|
949
914
|
execution_result = FunctionExecutionResult(
|
|
950
915
|
status="success", result=self.result, updated_session_state=updated_session_state
|
|
@@ -979,18 +944,12 @@ class FunctionCall(BaseModel):
|
|
|
979
944
|
# Check if the pre-hook has an agent argument
|
|
980
945
|
if "agent" in signature(self.function.pre_hook).parameters:
|
|
981
946
|
pre_hook_args["agent"] = self.function._agent
|
|
982
|
-
# Check if the pre-hook has
|
|
947
|
+
# Check if the pre-hook has a team argument
|
|
983
948
|
if "team" in signature(self.function.pre_hook).parameters:
|
|
984
949
|
pre_hook_args["team"] = self.function._team
|
|
985
|
-
# Check if the pre-hook has
|
|
950
|
+
# Check if the pre-hook has a run_context argument
|
|
986
951
|
if "run_context" in signature(self.function.pre_hook).parameters:
|
|
987
952
|
pre_hook_args["run_context"] = self.function._run_context
|
|
988
|
-
# Check if the pre-hook has an session_state argument
|
|
989
|
-
if "session_state" in signature(self.function.pre_hook).parameters:
|
|
990
|
-
pre_hook_args["session_state"] = self.function._session_state
|
|
991
|
-
# Check if the pre-hook has an dependencies argument
|
|
992
|
-
if "dependencies" in signature(self.function.pre_hook).parameters:
|
|
993
|
-
pre_hook_args["dependencies"] = self.function._dependencies
|
|
994
953
|
# Check if the pre-hook has an fc argument
|
|
995
954
|
if "fc" in signature(self.function.pre_hook).parameters:
|
|
996
955
|
pre_hook_args["fc"] = self
|
|
@@ -1014,19 +973,12 @@ class FunctionCall(BaseModel):
|
|
|
1014
973
|
# Check if the post-hook has an agent argument
|
|
1015
974
|
if "agent" in signature(self.function.post_hook).parameters:
|
|
1016
975
|
post_hook_args["agent"] = self.function._agent
|
|
1017
|
-
# Check if the post-hook has
|
|
976
|
+
# Check if the post-hook has a team argument
|
|
1018
977
|
if "team" in signature(self.function.post_hook).parameters:
|
|
1019
978
|
post_hook_args["team"] = self.function._team
|
|
1020
|
-
# Check if the post-hook has
|
|
979
|
+
# Check if the post-hook has a run_context argument
|
|
1021
980
|
if "run_context" in signature(self.function.post_hook).parameters:
|
|
1022
981
|
post_hook_args["run_context"] = self.function._run_context
|
|
1023
|
-
# Check if the post-hook has an session_state argument
|
|
1024
|
-
if "session_state" in signature(self.function.post_hook).parameters:
|
|
1025
|
-
post_hook_args["session_state"] = self.function._session_state
|
|
1026
|
-
# Check if the post-hook has an dependencies argument
|
|
1027
|
-
if "dependencies" in signature(self.function.post_hook).parameters:
|
|
1028
|
-
post_hook_args["dependencies"] = self.function._dependencies
|
|
1029
|
-
|
|
1030
982
|
# Check if the post-hook has an fc argument
|
|
1031
983
|
if "fc" in signature(self.function.post_hook).parameters:
|
|
1032
984
|
post_hook_args["fc"] = self
|
agno/tools/knowledge.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from textwrap import dedent
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, List, Optional
|
|
4
4
|
|
|
5
5
|
from agno.knowledge.document import Document
|
|
6
6
|
from agno.knowledge.knowledge import Knowledge
|
|
7
|
+
from agno.run import RunContext
|
|
7
8
|
from agno.tools import Toolkit
|
|
8
9
|
from agno.utils.log import log_debug, log_error
|
|
9
10
|
|
|
@@ -55,7 +56,7 @@ class KnowledgeTools(Toolkit):
|
|
|
55
56
|
**kwargs,
|
|
56
57
|
)
|
|
57
58
|
|
|
58
|
-
def think(self,
|
|
59
|
+
def think(self, run_context: RunContext, thought: str) -> str:
|
|
59
60
|
"""Use this tool as a scratchpad to reason about the question, refine your approach, brainstorm search terms, or revise your plan.
|
|
60
61
|
|
|
61
62
|
Call `Think` whenever you need to figure out what to do next, analyze the user's question, or plan your approach.
|
|
@@ -71,8 +72,10 @@ class KnowledgeTools(Toolkit):
|
|
|
71
72
|
log_debug(f"Thought: {thought}")
|
|
72
73
|
|
|
73
74
|
# Add the thought to the Agent state
|
|
75
|
+
session_state = run_context.session_state
|
|
74
76
|
if session_state is None:
|
|
75
77
|
session_state = {}
|
|
78
|
+
run_context.session_state = session_state
|
|
76
79
|
if "thoughts" not in session_state:
|
|
77
80
|
session_state["thoughts"] = []
|
|
78
81
|
session_state["thoughts"].append(thought)
|
|
@@ -89,7 +92,7 @@ class KnowledgeTools(Toolkit):
|
|
|
89
92
|
log_error(f"Error recording thought: {e}")
|
|
90
93
|
return f"Error recording thought: {e}"
|
|
91
94
|
|
|
92
|
-
def search_knowledge(self,
|
|
95
|
+
def search_knowledge(self, run_context: RunContext, query: str) -> str:
|
|
93
96
|
"""Use this tool to search the knowledge base for relevant information.
|
|
94
97
|
After thinking through the question, use this tool as many times as needed to search for relevant information.
|
|
95
98
|
|
|
@@ -111,7 +114,7 @@ class KnowledgeTools(Toolkit):
|
|
|
111
114
|
log_error(f"Error searching knowledge base: {e}")
|
|
112
115
|
return f"Error searching knowledge base: {e}"
|
|
113
116
|
|
|
114
|
-
def analyze(self,
|
|
117
|
+
def analyze(self, run_context: RunContext, analysis: str) -> str:
|
|
115
118
|
"""Use this tool to evaluate whether the returned documents are correct and sufficient.
|
|
116
119
|
If not, go back to "Think" or "Search" with refined queries.
|
|
117
120
|
|
|
@@ -125,8 +128,10 @@ class KnowledgeTools(Toolkit):
|
|
|
125
128
|
log_debug(f"Analysis: {analysis}")
|
|
126
129
|
|
|
127
130
|
# Add the thought to the Agent state
|
|
131
|
+
session_state = run_context.session_state
|
|
128
132
|
if session_state is None:
|
|
129
133
|
session_state = {}
|
|
134
|
+
run_context.session_state = session_state
|
|
130
135
|
if "analysis" not in session_state:
|
|
131
136
|
session_state["analysis"] = []
|
|
132
137
|
session_state["analysis"].append(analysis)
|
agno/tools/mem0.py
CHANGED
|
@@ -2,6 +2,7 @@ import json
|
|
|
2
2
|
from os import getenv
|
|
3
3
|
from typing import Any, Dict, List, Optional, Union
|
|
4
4
|
|
|
5
|
+
from agno.run import RunContext
|
|
5
6
|
from agno.tools import Toolkit
|
|
6
7
|
from agno.utils.log import log_debug, log_error, log_warning
|
|
7
8
|
|
|
@@ -68,13 +69,13 @@ class Mem0Tools(Toolkit):
|
|
|
68
69
|
def _get_user_id(
|
|
69
70
|
self,
|
|
70
71
|
method_name: str,
|
|
71
|
-
|
|
72
|
+
run_context: RunContext,
|
|
72
73
|
) -> str:
|
|
73
74
|
"""Resolve the user ID"""
|
|
74
75
|
resolved_user_id = self.user_id
|
|
75
76
|
if not resolved_user_id:
|
|
76
77
|
try:
|
|
77
|
-
resolved_user_id =
|
|
78
|
+
resolved_user_id = run_context.user_id
|
|
78
79
|
except Exception:
|
|
79
80
|
pass
|
|
80
81
|
if not resolved_user_id:
|
|
@@ -85,7 +86,7 @@ class Mem0Tools(Toolkit):
|
|
|
85
86
|
|
|
86
87
|
def add_memory(
|
|
87
88
|
self,
|
|
88
|
-
|
|
89
|
+
run_context: RunContext,
|
|
89
90
|
content: Union[str, Dict[str, str]],
|
|
90
91
|
) -> str:
|
|
91
92
|
"""Add facts to the user's memory.
|
|
@@ -98,7 +99,7 @@ class Mem0Tools(Toolkit):
|
|
|
98
99
|
str: JSON-encoded Mem0 response or an error message.
|
|
99
100
|
"""
|
|
100
101
|
|
|
101
|
-
resolved_user_id = self._get_user_id("add_memory",
|
|
102
|
+
resolved_user_id = self._get_user_id("add_memory", run_context=run_context)
|
|
102
103
|
if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in add_memory:"):
|
|
103
104
|
return resolved_user_id
|
|
104
105
|
try:
|
|
@@ -121,12 +122,12 @@ class Mem0Tools(Toolkit):
|
|
|
121
122
|
|
|
122
123
|
def search_memory(
|
|
123
124
|
self,
|
|
124
|
-
|
|
125
|
+
run_context: RunContext,
|
|
125
126
|
query: str,
|
|
126
127
|
) -> str:
|
|
127
128
|
"""Semantic search for *query* across the user's stored memories."""
|
|
128
129
|
|
|
129
|
-
resolved_user_id = self._get_user_id("search_memory",
|
|
130
|
+
resolved_user_id = self._get_user_id("search_memory", run_context=run_context)
|
|
130
131
|
if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in search_memory:"):
|
|
131
132
|
return resolved_user_id
|
|
132
133
|
try:
|
|
@@ -151,10 +152,10 @@ class Mem0Tools(Toolkit):
|
|
|
151
152
|
log_error(f"Error searching memory: {e}")
|
|
152
153
|
return f"Error searching memory: {e}"
|
|
153
154
|
|
|
154
|
-
def get_all_memories(self,
|
|
155
|
+
def get_all_memories(self, run_context: RunContext) -> str:
|
|
155
156
|
"""Return **all** memories for the current user as a JSON string."""
|
|
156
157
|
|
|
157
|
-
resolved_user_id = self._get_user_id("get_all_memories",
|
|
158
|
+
resolved_user_id = self._get_user_id("get_all_memories", run_context=run_context)
|
|
158
159
|
if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in get_all_memories:"):
|
|
159
160
|
return resolved_user_id
|
|
160
161
|
try:
|
|
@@ -177,10 +178,10 @@ class Mem0Tools(Toolkit):
|
|
|
177
178
|
log_error(f"Error getting all memories: {e}")
|
|
178
179
|
return f"Error getting all memories: {e}"
|
|
179
180
|
|
|
180
|
-
def delete_all_memories(self,
|
|
181
|
+
def delete_all_memories(self, run_context: RunContext) -> str:
|
|
181
182
|
"""Delete *all* memories associated with the current user"""
|
|
182
183
|
|
|
183
|
-
resolved_user_id = self._get_user_id("delete_all_memories",
|
|
184
|
+
resolved_user_id = self._get_user_id("delete_all_memories", run_context=run_context)
|
|
184
185
|
if isinstance(resolved_user_id, str) and resolved_user_id.startswith("Error in delete_all_memories:"):
|
|
185
186
|
error_msg = resolved_user_id
|
|
186
187
|
log_error(error_msg)
|