agno 2.3.9__py3-none-any.whl → 2.3.11__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 +0 -12
- agno/db/base.py +5 -5
- agno/db/dynamo/dynamo.py +2 -2
- agno/db/firestore/firestore.py +2 -2
- agno/db/gcs_json/gcs_json_db.py +2 -2
- agno/db/in_memory/in_memory_db.py +2 -2
- agno/db/json/json_db.py +2 -2
- agno/db/mongo/async_mongo.py +171 -69
- agno/db/mongo/mongo.py +171 -77
- agno/db/mysql/async_mysql.py +93 -69
- agno/db/mysql/mysql.py +93 -68
- agno/db/postgres/async_postgres.py +104 -78
- agno/db/postgres/postgres.py +97 -69
- agno/db/redis/redis.py +2 -2
- agno/db/singlestore/singlestore.py +91 -66
- agno/db/sqlite/async_sqlite.py +102 -79
- agno/db/sqlite/sqlite.py +97 -69
- agno/db/surrealdb/surrealdb.py +2 -2
- agno/eval/accuracy.py +11 -8
- agno/eval/agent_as_judge.py +9 -8
- agno/knowledge/chunking/fixed.py +4 -1
- agno/knowledge/embedder/openai.py +1 -1
- agno/knowledge/knowledge.py +22 -4
- agno/knowledge/utils.py +52 -7
- agno/models/base.py +34 -1
- agno/models/google/gemini.py +69 -40
- agno/models/message.py +3 -0
- agno/models/openai/chat.py +21 -0
- agno/os/routers/evals/utils.py +15 -37
- agno/os/routers/knowledge/knowledge.py +21 -9
- agno/team/team.py +14 -8
- agno/tools/function.py +37 -23
- agno/tools/shopify.py +1519 -0
- agno/tools/spotify.py +2 -5
- agno/tracing/exporter.py +2 -2
- agno/vectordb/base.py +15 -2
- agno/vectordb/pgvector/pgvector.py +8 -8
- agno/workflow/parallel.py +2 -0
- {agno-2.3.9.dist-info → agno-2.3.11.dist-info}/METADATA +1 -1
- {agno-2.3.9.dist-info → agno-2.3.11.dist-info}/RECORD +43 -42
- {agno-2.3.9.dist-info → agno-2.3.11.dist-info}/WHEEL +0 -0
- {agno-2.3.9.dist-info → agno-2.3.11.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.9.dist-info → agno-2.3.11.dist-info}/top_level.txt +0 -0
agno/agent/agent.py
CHANGED
|
@@ -1785,9 +1785,6 @@ class Agent:
|
|
|
1785
1785
|
if stream_events is None:
|
|
1786
1786
|
stream_events = False if self.stream_events is None else self.stream_events
|
|
1787
1787
|
|
|
1788
|
-
self.stream = self.stream or stream
|
|
1789
|
-
self.stream_events = self.stream_events or stream_events
|
|
1790
|
-
|
|
1791
1788
|
# Prepare arguments for the model
|
|
1792
1789
|
response_format = (
|
|
1793
1790
|
self._get_response_format(run_context=run_context) if self.parser_model is None else None
|
|
@@ -2711,9 +2708,6 @@ class Agent:
|
|
|
2711
2708
|
if stream_events is None:
|
|
2712
2709
|
stream_events = False if self.stream_events is None else self.stream_events
|
|
2713
2710
|
|
|
2714
|
-
self.stream = self.stream or stream
|
|
2715
|
-
self.stream_events = self.stream_events or stream_events
|
|
2716
|
-
|
|
2717
2711
|
self.model = cast(Model, self.model)
|
|
2718
2712
|
|
|
2719
2713
|
# Get knowledge filters
|
|
@@ -3020,9 +3014,6 @@ class Agent:
|
|
|
3020
3014
|
if stream is False:
|
|
3021
3015
|
stream_events = False
|
|
3022
3016
|
|
|
3023
|
-
self.stream = self.stream or stream
|
|
3024
|
-
self.stream_events = self.stream_events or stream_events
|
|
3025
|
-
|
|
3026
3017
|
# Run can be continued from previous run response or from passed run_response context
|
|
3027
3018
|
if run_response is not None:
|
|
3028
3019
|
# The run is continued from a provided run_response. This contains the updated tools.
|
|
@@ -3589,9 +3580,6 @@ class Agent:
|
|
|
3589
3580
|
if stream is False:
|
|
3590
3581
|
stream_events = False
|
|
3591
3582
|
|
|
3592
|
-
self.stream = self.stream or stream
|
|
3593
|
-
self.stream_events = self.stream_events or stream_events
|
|
3594
|
-
|
|
3595
3583
|
# Get knowledge filters
|
|
3596
3584
|
knowledge_filters = knowledge_filters
|
|
3597
3585
|
if self.knowledge_filters or knowledge_filters:
|
agno/db/base.py
CHANGED
|
@@ -308,8 +308,8 @@ class BaseDb(ABC):
|
|
|
308
308
|
|
|
309
309
|
# --- Traces ---
|
|
310
310
|
@abstractmethod
|
|
311
|
-
def
|
|
312
|
-
"""Create a single trace record in the database.
|
|
311
|
+
def upsert_trace(self, trace: "Trace") -> None:
|
|
312
|
+
"""Create or update a single trace record in the database.
|
|
313
313
|
|
|
314
314
|
Args:
|
|
315
315
|
trace: The Trace object to store (one per trace_id).
|
|
@@ -759,11 +759,11 @@ class AsyncBaseDb(ABC):
|
|
|
759
759
|
|
|
760
760
|
# --- Traces ---
|
|
761
761
|
@abstractmethod
|
|
762
|
-
async def
|
|
763
|
-
"""Create a single trace record in the database.
|
|
762
|
+
async def upsert_trace(self, trace) -> None:
|
|
763
|
+
"""Create or update a single trace record in the database.
|
|
764
764
|
|
|
765
765
|
Args:
|
|
766
|
-
trace: The Trace object to
|
|
766
|
+
trace: The Trace object to update (one per trace_id).
|
|
767
767
|
"""
|
|
768
768
|
raise NotImplementedError
|
|
769
769
|
|
agno/db/dynamo/dynamo.py
CHANGED
|
@@ -2076,8 +2076,8 @@ class DynamoDb(BaseDb):
|
|
|
2076
2076
|
raise e
|
|
2077
2077
|
|
|
2078
2078
|
# --- Traces ---
|
|
2079
|
-
def
|
|
2080
|
-
"""Create a single trace record in the database.
|
|
2079
|
+
def upsert_trace(self, trace: "Trace") -> None:
|
|
2080
|
+
"""Create or update a single trace record in the database.
|
|
2081
2081
|
|
|
2082
2082
|
Args:
|
|
2083
2083
|
trace: The Trace object to store (one per trace_id).
|
agno/db/firestore/firestore.py
CHANGED
|
@@ -1841,8 +1841,8 @@ class FirestoreDb(BaseDb):
|
|
|
1841
1841
|
raise e
|
|
1842
1842
|
|
|
1843
1843
|
# --- Traces ---
|
|
1844
|
-
def
|
|
1845
|
-
"""Create a single trace record in the database.
|
|
1844
|
+
def upsert_trace(self, trace: "Trace") -> None:
|
|
1845
|
+
"""Create or update a single trace record in the database.
|
|
1846
1846
|
|
|
1847
1847
|
Args:
|
|
1848
1848
|
trace: The Trace object to store (one per trace_id).
|
agno/db/gcs_json/gcs_json_db.py
CHANGED
|
@@ -1355,8 +1355,8 @@ class GcsJsonDb(BaseDb):
|
|
|
1355
1355
|
raise e
|
|
1356
1356
|
|
|
1357
1357
|
# --- Traces ---
|
|
1358
|
-
def
|
|
1359
|
-
"""Create a single trace record in the database.
|
|
1358
|
+
def upsert_trace(self, trace: "Trace") -> None:
|
|
1359
|
+
"""Create or update a single trace record in the database.
|
|
1360
1360
|
|
|
1361
1361
|
Args:
|
|
1362
1362
|
trace: The Trace object to store (one per trace_id).
|
|
@@ -1173,8 +1173,8 @@ class InMemoryDb(BaseDb):
|
|
|
1173
1173
|
raise e
|
|
1174
1174
|
|
|
1175
1175
|
# --- Traces ---
|
|
1176
|
-
def
|
|
1177
|
-
"""Create a single trace record in the database.
|
|
1176
|
+
def upsert_trace(self, trace: "Trace") -> None:
|
|
1177
|
+
"""Create or update a single trace record in the database.
|
|
1178
1178
|
|
|
1179
1179
|
Args:
|
|
1180
1180
|
trace: The Trace object to store (one per trace_id).
|
agno/db/json/json_db.py
CHANGED
|
@@ -1349,8 +1349,8 @@ class JsonDb(BaseDb):
|
|
|
1349
1349
|
raise e
|
|
1350
1350
|
|
|
1351
1351
|
# --- Traces ---
|
|
1352
|
-
def
|
|
1353
|
-
"""Create a single trace record in the database.
|
|
1352
|
+
def upsert_trace(self, trace: "Trace") -> None:
|
|
1353
|
+
"""Create or update a single trace record in the database.
|
|
1354
1354
|
|
|
1355
1355
|
Args:
|
|
1356
1356
|
trace: The Trace object to store (one per trace_id).
|
agno/db/mongo/async_mongo.py
CHANGED
|
@@ -2191,8 +2191,45 @@ class AsyncMongoDb(AsyncBaseDb):
|
|
|
2191
2191
|
raise e
|
|
2192
2192
|
|
|
2193
2193
|
# --- Traces ---
|
|
2194
|
-
|
|
2195
|
-
|
|
2194
|
+
def _get_component_level(
|
|
2195
|
+
self, workflow_id: Optional[str], team_id: Optional[str], agent_id: Optional[str], name: str
|
|
2196
|
+
) -> int:
|
|
2197
|
+
"""Get the component level for a trace based on its context.
|
|
2198
|
+
|
|
2199
|
+
Component levels (higher = more important):
|
|
2200
|
+
- 3: Workflow root (.run or .arun with workflow_id)
|
|
2201
|
+
- 2: Team root (.run or .arun with team_id)
|
|
2202
|
+
- 1: Agent root (.run or .arun with agent_id)
|
|
2203
|
+
- 0: Child span (not a root)
|
|
2204
|
+
|
|
2205
|
+
Args:
|
|
2206
|
+
workflow_id: The workflow ID of the trace.
|
|
2207
|
+
team_id: The team ID of the trace.
|
|
2208
|
+
agent_id: The agent ID of the trace.
|
|
2209
|
+
name: The name of the trace.
|
|
2210
|
+
|
|
2211
|
+
Returns:
|
|
2212
|
+
int: The component level (0-3).
|
|
2213
|
+
"""
|
|
2214
|
+
# Check if name indicates a root span
|
|
2215
|
+
is_root_name = ".run" in name or ".arun" in name
|
|
2216
|
+
|
|
2217
|
+
if not is_root_name:
|
|
2218
|
+
return 0 # Child span (not a root)
|
|
2219
|
+
elif workflow_id:
|
|
2220
|
+
return 3 # Workflow root
|
|
2221
|
+
elif team_id:
|
|
2222
|
+
return 2 # Team root
|
|
2223
|
+
elif agent_id:
|
|
2224
|
+
return 1 # Agent root
|
|
2225
|
+
else:
|
|
2226
|
+
return 0 # Unknown
|
|
2227
|
+
|
|
2228
|
+
async def upsert_trace(self, trace: "Trace") -> None:
|
|
2229
|
+
"""Create or update a single trace record in the database.
|
|
2230
|
+
|
|
2231
|
+
Uses MongoDB's update_one with upsert=True and aggregation pipeline
|
|
2232
|
+
to handle concurrent inserts atomically and avoid race conditions.
|
|
2196
2233
|
|
|
2197
2234
|
Args:
|
|
2198
2235
|
trace: The Trace object to store (one per trace_id).
|
|
@@ -2202,75 +2239,140 @@ class AsyncMongoDb(AsyncBaseDb):
|
|
|
2202
2239
|
if collection is None:
|
|
2203
2240
|
return
|
|
2204
2241
|
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
if existing:
|
|
2209
|
-
# workflow (level 3) > team (level 2) > agent (level 1) > child/unknown (level 0)
|
|
2210
|
-
def get_component_level(
|
|
2211
|
-
workflow_id: Optional[str], team_id: Optional[str], agent_id: Optional[str], name: str
|
|
2212
|
-
) -> int:
|
|
2213
|
-
# Check if name indicates a root span
|
|
2214
|
-
is_root_name = ".run" in name or ".arun" in name
|
|
2215
|
-
|
|
2216
|
-
if not is_root_name:
|
|
2217
|
-
return 0 # Child span (not a root)
|
|
2218
|
-
elif workflow_id:
|
|
2219
|
-
return 3 # Workflow root
|
|
2220
|
-
elif team_id:
|
|
2221
|
-
return 2 # Team root
|
|
2222
|
-
elif agent_id:
|
|
2223
|
-
return 1 # Agent root
|
|
2224
|
-
else:
|
|
2225
|
-
return 0 # Unknown
|
|
2242
|
+
trace_dict = trace.to_dict()
|
|
2243
|
+
trace_dict.pop("total_spans", None)
|
|
2244
|
+
trace_dict.pop("error_count", None)
|
|
2226
2245
|
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
existing.get("team_id"),
|
|
2230
|
-
existing.get("agent_id"),
|
|
2231
|
-
existing.get("name", ""),
|
|
2232
|
-
)
|
|
2233
|
-
new_level = get_component_level(trace.workflow_id, trace.team_id, trace.agent_id, trace.name)
|
|
2234
|
-
|
|
2235
|
-
# Only update name if new trace is from a higher or equal level
|
|
2236
|
-
should_update_name = new_level > existing_level
|
|
2237
|
-
|
|
2238
|
-
# Parse existing start_time to calculate correct duration
|
|
2239
|
-
existing_start_time_str = existing.get("start_time")
|
|
2240
|
-
if isinstance(existing_start_time_str, str):
|
|
2241
|
-
existing_start_time = datetime.fromisoformat(existing_start_time_str.replace("Z", "+00:00"))
|
|
2242
|
-
else:
|
|
2243
|
-
existing_start_time = trace.start_time
|
|
2246
|
+
# Calculate the component level for the new trace
|
|
2247
|
+
new_level = self._get_component_level(trace.workflow_id, trace.team_id, trace.agent_id, trace.name)
|
|
2244
2248
|
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
"
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2249
|
+
# Use MongoDB aggregation pipeline update for atomic upsert
|
|
2250
|
+
# This allows conditional logic within a single atomic operation
|
|
2251
|
+
pipeline: List[Dict[str, Any]] = [
|
|
2252
|
+
{
|
|
2253
|
+
"$set": {
|
|
2254
|
+
# Always update these fields
|
|
2255
|
+
"status": trace.status,
|
|
2256
|
+
"created_at": {"$ifNull": ["$created_at", trace_dict.get("created_at")]},
|
|
2257
|
+
# Use $min for start_time (keep earliest)
|
|
2258
|
+
"start_time": {
|
|
2259
|
+
"$cond": {
|
|
2260
|
+
"if": {"$eq": [{"$type": "$start_time"}, "missing"]},
|
|
2261
|
+
"then": trace_dict.get("start_time"),
|
|
2262
|
+
"else": {"$min": ["$start_time", trace_dict.get("start_time")]},
|
|
2263
|
+
}
|
|
2264
|
+
},
|
|
2265
|
+
# Use $max for end_time (keep latest)
|
|
2266
|
+
"end_time": {
|
|
2267
|
+
"$cond": {
|
|
2268
|
+
"if": {"$eq": [{"$type": "$end_time"}, "missing"]},
|
|
2269
|
+
"then": trace_dict.get("end_time"),
|
|
2270
|
+
"else": {"$max": ["$end_time", trace_dict.get("end_time")]},
|
|
2271
|
+
}
|
|
2272
|
+
},
|
|
2273
|
+
# Preserve existing non-null context values using $ifNull
|
|
2274
|
+
"run_id": {"$ifNull": [trace.run_id, "$run_id"]},
|
|
2275
|
+
"session_id": {"$ifNull": [trace.session_id, "$session_id"]},
|
|
2276
|
+
"user_id": {"$ifNull": [trace.user_id, "$user_id"]},
|
|
2277
|
+
"agent_id": {"$ifNull": [trace.agent_id, "$agent_id"]},
|
|
2278
|
+
"team_id": {"$ifNull": [trace.team_id, "$team_id"]},
|
|
2279
|
+
"workflow_id": {"$ifNull": [trace.workflow_id, "$workflow_id"]},
|
|
2280
|
+
}
|
|
2281
|
+
},
|
|
2282
|
+
{
|
|
2283
|
+
"$set": {
|
|
2284
|
+
# Calculate duration_ms from the (potentially updated) start_time and end_time
|
|
2285
|
+
# MongoDB stores dates as strings in ISO format, so we need to parse them
|
|
2286
|
+
"duration_ms": {
|
|
2287
|
+
"$cond": {
|
|
2288
|
+
"if": {
|
|
2289
|
+
"$and": [
|
|
2290
|
+
{"$ne": [{"$type": "$start_time"}, "missing"]},
|
|
2291
|
+
{"$ne": [{"$type": "$end_time"}, "missing"]},
|
|
2292
|
+
]
|
|
2293
|
+
},
|
|
2294
|
+
"then": {
|
|
2295
|
+
"$subtract": [
|
|
2296
|
+
{"$toLong": {"$toDate": "$end_time"}},
|
|
2297
|
+
{"$toLong": {"$toDate": "$start_time"}},
|
|
2298
|
+
]
|
|
2299
|
+
},
|
|
2300
|
+
"else": trace_dict.get("duration_ms", 0),
|
|
2301
|
+
}
|
|
2302
|
+
},
|
|
2303
|
+
# Update name based on component level priority
|
|
2304
|
+
# Only update if new trace is from a higher-level component
|
|
2305
|
+
"name": {
|
|
2306
|
+
"$cond": {
|
|
2307
|
+
"if": {"$eq": [{"$type": "$name"}, "missing"]},
|
|
2308
|
+
"then": trace.name,
|
|
2309
|
+
"else": {
|
|
2310
|
+
"$cond": {
|
|
2311
|
+
"if": {
|
|
2312
|
+
"$gt": [
|
|
2313
|
+
new_level,
|
|
2314
|
+
{
|
|
2315
|
+
"$switch": {
|
|
2316
|
+
"branches": [
|
|
2317
|
+
# Check if existing name is a root span
|
|
2318
|
+
{
|
|
2319
|
+
"case": {
|
|
2320
|
+
"$not": {
|
|
2321
|
+
"$or": [
|
|
2322
|
+
{
|
|
2323
|
+
"$regexMatch": {
|
|
2324
|
+
"input": {"$ifNull": ["$name", ""]},
|
|
2325
|
+
"regex": "\\.run",
|
|
2326
|
+
}
|
|
2327
|
+
},
|
|
2328
|
+
{
|
|
2329
|
+
"$regexMatch": {
|
|
2330
|
+
"input": {"$ifNull": ["$name", ""]},
|
|
2331
|
+
"regex": "\\.arun",
|
|
2332
|
+
}
|
|
2333
|
+
},
|
|
2334
|
+
]
|
|
2335
|
+
}
|
|
2336
|
+
},
|
|
2337
|
+
"then": 0,
|
|
2338
|
+
},
|
|
2339
|
+
# Workflow root (level 3)
|
|
2340
|
+
{
|
|
2341
|
+
"case": {"$ne": ["$workflow_id", None]},
|
|
2342
|
+
"then": 3,
|
|
2343
|
+
},
|
|
2344
|
+
# Team root (level 2)
|
|
2345
|
+
{
|
|
2346
|
+
"case": {"$ne": ["$team_id", None]},
|
|
2347
|
+
"then": 2,
|
|
2348
|
+
},
|
|
2349
|
+
# Agent root (level 1)
|
|
2350
|
+
{
|
|
2351
|
+
"case": {"$ne": ["$agent_id", None]},
|
|
2352
|
+
"then": 1,
|
|
2353
|
+
},
|
|
2354
|
+
],
|
|
2355
|
+
"default": 0,
|
|
2356
|
+
}
|
|
2357
|
+
},
|
|
2358
|
+
]
|
|
2359
|
+
},
|
|
2360
|
+
"then": trace.name,
|
|
2361
|
+
"else": "$name",
|
|
2362
|
+
}
|
|
2363
|
+
},
|
|
2364
|
+
}
|
|
2365
|
+
},
|
|
2366
|
+
}
|
|
2367
|
+
},
|
|
2368
|
+
]
|
|
2253
2369
|
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
update_values["user_id"] = trace.user_id
|
|
2261
|
-
if trace.agent_id is not None:
|
|
2262
|
-
update_values["agent_id"] = trace.agent_id
|
|
2263
|
-
if trace.team_id is not None:
|
|
2264
|
-
update_values["team_id"] = trace.team_id
|
|
2265
|
-
if trace.workflow_id is not None:
|
|
2266
|
-
update_values["workflow_id"] = trace.workflow_id
|
|
2267
|
-
|
|
2268
|
-
await collection.update_one({"trace_id": trace.trace_id}, {"$set": update_values})
|
|
2269
|
-
else:
|
|
2270
|
-
trace_dict = trace.to_dict()
|
|
2271
|
-
trace_dict.pop("total_spans", None)
|
|
2272
|
-
trace_dict.pop("error_count", None)
|
|
2273
|
-
await collection.insert_one(trace_dict)
|
|
2370
|
+
# Perform atomic upsert using aggregation pipeline
|
|
2371
|
+
await collection.update_one(
|
|
2372
|
+
{"trace_id": trace.trace_id},
|
|
2373
|
+
pipeline,
|
|
2374
|
+
upsert=True,
|
|
2375
|
+
)
|
|
2274
2376
|
|
|
2275
2377
|
except Exception as e:
|
|
2276
2378
|
log_error(f"Error creating trace: {e}")
|
|
@@ -2655,4 +2757,4 @@ class AsyncMongoDb(AsyncBaseDb):
|
|
|
2655
2757
|
|
|
2656
2758
|
except Exception as e:
|
|
2657
2759
|
log_error(f"Error getting spans: {e}")
|
|
2658
|
-
return []
|
|
2760
|
+
return []
|