agno 2.3.13__py3-none-any.whl → 2.3.14__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 +1131 -1402
- agno/eval/__init__.py +21 -8
- agno/knowledge/embedder/azure_openai.py +0 -1
- agno/knowledge/embedder/google.py +1 -1
- agno/models/anthropic/claude.py +4 -1
- agno/models/base.py +8 -4
- agno/models/openai/responses.py +2 -2
- agno/os/app.py +39 -0
- agno/os/interfaces/a2a/router.py +619 -9
- agno/os/interfaces/a2a/utils.py +31 -32
- agno/os/middleware/jwt.py +5 -5
- agno/os/routers/agents/schema.py +14 -1
- agno/os/routers/teams/schema.py +14 -1
- agno/os/utils.py +61 -53
- agno/reasoning/anthropic.py +85 -1
- agno/reasoning/azure_ai_foundry.py +93 -1
- agno/reasoning/deepseek.py +91 -1
- agno/reasoning/gemini.py +81 -1
- agno/reasoning/groq.py +103 -1
- agno/reasoning/manager.py +1244 -0
- agno/reasoning/ollama.py +93 -1
- agno/reasoning/openai.py +113 -1
- agno/reasoning/vertexai.py +85 -1
- agno/run/agent.py +11 -0
- agno/run/base.py +1 -1
- agno/run/team.py +11 -0
- agno/session/team.py +0 -3
- agno/team/team.py +1201 -1445
- agno/utils/events.py +69 -2
- agno/utils/hooks.py +4 -10
- agno/utils/print_response/agent.py +26 -0
- agno/utils/print_response/team.py +11 -0
- agno/utils/prompts.py +8 -6
- agno/utils/string.py +46 -0
- agno/utils/team.py +1 -1
- agno/vectordb/milvus/milvus.py +32 -3
- {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/METADATA +3 -2
- {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/RECORD +41 -40
- {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/WHEEL +0 -0
- {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.13.dist-info → agno-2.3.14.dist-info}/top_level.txt +0 -0
agno/eval/__init__.py
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
from agno.eval.accuracy import AccuracyAgentResponse, AccuracyEval, AccuracyEvaluation, AccuracyResult
|
|
2
|
-
from agno.eval.agent_as_judge import (
|
|
3
|
-
AgentAsJudgeEval,
|
|
4
|
-
AgentAsJudgeEvaluation,
|
|
5
|
-
AgentAsJudgeResult,
|
|
6
|
-
)
|
|
7
1
|
from agno.eval.base import BaseEval
|
|
8
|
-
from agno.eval.performance import PerformanceEval, PerformanceResult
|
|
9
|
-
from agno.eval.reliability import ReliabilityEval, ReliabilityResult
|
|
10
2
|
|
|
11
3
|
__all__ = [
|
|
12
4
|
"AccuracyAgentResponse",
|
|
@@ -22,3 +14,24 @@ __all__ = [
|
|
|
22
14
|
"ReliabilityEval",
|
|
23
15
|
"ReliabilityResult",
|
|
24
16
|
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(name: str):
|
|
20
|
+
"""Lazy import for eval implementations to avoid circular imports with Agent."""
|
|
21
|
+
if name in ("AccuracyAgentResponse", "AccuracyEval", "AccuracyEvaluation", "AccuracyResult"):
|
|
22
|
+
from agno.eval import accuracy
|
|
23
|
+
|
|
24
|
+
return getattr(accuracy, name)
|
|
25
|
+
elif name in ("AgentAsJudgeEval", "AgentAsJudgeEvaluation", "AgentAsJudgeResult"):
|
|
26
|
+
from agno.eval import agent_as_judge
|
|
27
|
+
|
|
28
|
+
return getattr(agent_as_judge, name)
|
|
29
|
+
elif name in ("PerformanceEval", "PerformanceResult"):
|
|
30
|
+
from agno.eval import performance
|
|
31
|
+
|
|
32
|
+
return getattr(performance, name)
|
|
33
|
+
elif name in ("ReliabilityEval", "ReliabilityResult"):
|
|
34
|
+
from agno.eval import reliability
|
|
35
|
+
|
|
36
|
+
return getattr(reliability, name)
|
|
37
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
@@ -18,7 +18,6 @@ except ImportError:
|
|
|
18
18
|
@dataclass
|
|
19
19
|
class AzureOpenAIEmbedder(Embedder):
|
|
20
20
|
id: str = "text-embedding-3-small" # This has to match the model that you deployed at the provided URL
|
|
21
|
-
|
|
22
21
|
dimensions: int = 1536
|
|
23
22
|
encoding_format: Literal["float", "base64"] = "float"
|
|
24
23
|
user: Optional[str] = None
|
agno/models/anthropic/claude.py
CHANGED
|
@@ -320,8 +320,11 @@ class Claude(Model):
|
|
|
320
320
|
|
|
321
321
|
return {"type": "json_schema", "schema": schema}
|
|
322
322
|
|
|
323
|
-
# Handle dict format
|
|
323
|
+
# Handle dict format
|
|
324
324
|
elif isinstance(response_format, dict):
|
|
325
|
+
# Claude only supports json_schema, not json_object
|
|
326
|
+
if response_format.get("type") == "json_object":
|
|
327
|
+
return None
|
|
325
328
|
return response_format
|
|
326
329
|
|
|
327
330
|
return None
|
agno/models/base.py
CHANGED
|
@@ -196,7 +196,8 @@ class Model(ABC):
|
|
|
196
196
|
)
|
|
197
197
|
sleep(delay)
|
|
198
198
|
else:
|
|
199
|
-
|
|
199
|
+
if self.retries > 0:
|
|
200
|
+
log_error(f"Model provider error after {self.retries + 1} attempts: {e}")
|
|
200
201
|
except RetryableModelProviderError as e:
|
|
201
202
|
current_count = retries_with_guidance_count
|
|
202
203
|
if current_count >= self.retry_with_guidance_limit:
|
|
@@ -238,7 +239,8 @@ class Model(ABC):
|
|
|
238
239
|
)
|
|
239
240
|
await asyncio.sleep(delay)
|
|
240
241
|
else:
|
|
241
|
-
|
|
242
|
+
if self.retries > 0:
|
|
243
|
+
log_error(f"Model provider error after {self.retries + 1} attempts: {e}")
|
|
242
244
|
except RetryableModelProviderError as e:
|
|
243
245
|
current_count = retries_with_guidance_count
|
|
244
246
|
if current_count >= self.retry_with_guidance_limit:
|
|
@@ -283,7 +285,8 @@ class Model(ABC):
|
|
|
283
285
|
)
|
|
284
286
|
sleep(delay)
|
|
285
287
|
else:
|
|
286
|
-
|
|
288
|
+
if self.retries > 0:
|
|
289
|
+
log_error(f"Model provider error after {self.retries + 1} attempts: {e}")
|
|
287
290
|
except RetryableModelProviderError as e:
|
|
288
291
|
current_count = retries_with_guidance_count
|
|
289
292
|
if current_count >= self.retry_with_guidance_limit:
|
|
@@ -330,7 +333,8 @@ class Model(ABC):
|
|
|
330
333
|
)
|
|
331
334
|
await asyncio.sleep(delay)
|
|
332
335
|
else:
|
|
333
|
-
|
|
336
|
+
if self.retries > 0:
|
|
337
|
+
log_error(f"Model provider error after {self.retries + 1} attempts: {e}")
|
|
334
338
|
except RetryableModelProviderError as e:
|
|
335
339
|
current_count = retries_with_guidance_count
|
|
336
340
|
if current_count >= self.retry_with_guidance_limit:
|
agno/models/openai/responses.py
CHANGED
|
@@ -234,8 +234,8 @@ class OpenAIResponses(Model):
|
|
|
234
234
|
"strict": self.strict_output,
|
|
235
235
|
}
|
|
236
236
|
else:
|
|
237
|
-
#
|
|
238
|
-
text_params["format"] =
|
|
237
|
+
# Pass through directly, user handles everything
|
|
238
|
+
text_params["format"] = response_format
|
|
239
239
|
|
|
240
240
|
# Add text parameter if there are any text-level params
|
|
241
241
|
if text_params:
|
agno/os/app.py
CHANGED
|
@@ -225,6 +225,9 @@ class AgentOS:
|
|
|
225
225
|
self._initialize_teams()
|
|
226
226
|
self._initialize_workflows()
|
|
227
227
|
|
|
228
|
+
# Check for duplicate IDs
|
|
229
|
+
self._raise_if_duplicate_ids()
|
|
230
|
+
|
|
228
231
|
if self.tracing:
|
|
229
232
|
self._setup_tracing()
|
|
230
233
|
|
|
@@ -266,6 +269,9 @@ class AgentOS:
|
|
|
266
269
|
self._initialize_agents()
|
|
267
270
|
self._initialize_teams()
|
|
268
271
|
self._initialize_workflows()
|
|
272
|
+
|
|
273
|
+
# Check for duplicate IDs
|
|
274
|
+
self._raise_if_duplicate_ids()
|
|
269
275
|
self._auto_discover_databases()
|
|
270
276
|
self._auto_discover_knowledge_instances()
|
|
271
277
|
|
|
@@ -334,6 +340,31 @@ class AgentOS:
|
|
|
334
340
|
self.interfaces.append(a2a_interface)
|
|
335
341
|
self._add_router(app, a2a_interface.get_router())
|
|
336
342
|
|
|
343
|
+
def _raise_if_duplicate_ids(self) -> None:
|
|
344
|
+
"""Check for duplicate IDs within each entity type.
|
|
345
|
+
|
|
346
|
+
Raises:
|
|
347
|
+
ValueError: If duplicate IDs are found within the same entity type
|
|
348
|
+
"""
|
|
349
|
+
duplicate_ids: List[str] = []
|
|
350
|
+
|
|
351
|
+
for entities in [self.agents, self.teams, self.workflows]:
|
|
352
|
+
if not entities:
|
|
353
|
+
continue
|
|
354
|
+
seen_ids: set[str] = set()
|
|
355
|
+
for entity in entities:
|
|
356
|
+
entity_id = entity.id
|
|
357
|
+
if entity_id is None:
|
|
358
|
+
continue
|
|
359
|
+
if entity_id in seen_ids:
|
|
360
|
+
if entity_id not in duplicate_ids:
|
|
361
|
+
duplicate_ids.append(entity_id)
|
|
362
|
+
else:
|
|
363
|
+
seen_ids.add(entity_id)
|
|
364
|
+
|
|
365
|
+
if duplicate_ids:
|
|
366
|
+
raise ValueError(f"Duplicate IDs found in AgentOS: {', '.join(repr(id_) for id_ in duplicate_ids)}")
|
|
367
|
+
|
|
337
368
|
def _make_app(self, lifespan: Optional[Any] = None) -> FastAPI:
|
|
338
369
|
# Adjust the FastAPI app lifespan to handle MCP connections if relevant
|
|
339
370
|
app_lifespan = lifespan
|
|
@@ -981,6 +1012,8 @@ class AgentOS:
|
|
|
981
1012
|
host: str = "localhost",
|
|
982
1013
|
port: int = 7777,
|
|
983
1014
|
reload: bool = False,
|
|
1015
|
+
reload_includes: Optional[List[str]] = None,
|
|
1016
|
+
reload_excludes: Optional[List[str]] = None,
|
|
984
1017
|
workers: Optional[int] = None,
|
|
985
1018
|
access_log: bool = False,
|
|
986
1019
|
**kwargs,
|
|
@@ -1015,11 +1048,17 @@ class AgentOS:
|
|
|
1015
1048
|
)
|
|
1016
1049
|
)
|
|
1017
1050
|
|
|
1051
|
+
# Adding *.yaml to reload_includes to reload the app when the yaml config file changes.
|
|
1052
|
+
if reload and reload_includes is not None:
|
|
1053
|
+
reload_includes = ["*.yaml", "*.yml"]
|
|
1054
|
+
|
|
1018
1055
|
uvicorn.run(
|
|
1019
1056
|
app=app,
|
|
1020
1057
|
host=host,
|
|
1021
1058
|
port=port,
|
|
1022
1059
|
reload=reload,
|
|
1060
|
+
reload_includes=reload_includes,
|
|
1061
|
+
reload_excludes=reload_excludes,
|
|
1023
1062
|
workers=workers,
|
|
1024
1063
|
access_log=access_log,
|
|
1025
1064
|
lifespan="on",
|