agno 2.0.0rc1__py3-none-any.whl → 2.0.0rc2__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 +32 -14
- agno/db/mongo/mongo.py +8 -3
- agno/eval/accuracy.py +12 -5
- agno/knowledge/chunking/strategy.py +14 -14
- agno/knowledge/knowledge.py +156 -120
- agno/knowledge/reader/arxiv_reader.py +5 -5
- agno/knowledge/reader/csv_reader.py +6 -77
- agno/knowledge/reader/docx_reader.py +5 -5
- agno/knowledge/reader/firecrawl_reader.py +5 -5
- agno/knowledge/reader/json_reader.py +5 -5
- agno/knowledge/reader/markdown_reader.py +31 -9
- agno/knowledge/reader/pdf_reader.py +10 -123
- agno/knowledge/reader/reader_factory.py +65 -72
- agno/knowledge/reader/s3_reader.py +44 -114
- agno/knowledge/reader/text_reader.py +5 -5
- agno/knowledge/reader/url_reader.py +75 -31
- agno/knowledge/reader/web_search_reader.py +6 -29
- agno/knowledge/reader/website_reader.py +5 -5
- agno/knowledge/reader/wikipedia_reader.py +5 -5
- agno/knowledge/reader/youtube_reader.py +6 -6
- agno/knowledge/utils.py +10 -10
- agno/models/aws/bedrock.py +3 -7
- agno/models/base.py +37 -6
- agno/os/app.py +32 -24
- agno/os/mcp.py +39 -59
- agno/os/router.py +547 -16
- agno/os/routers/evals/evals.py +197 -12
- agno/os/routers/knowledge/knowledge.py +428 -14
- agno/os/routers/memory/memory.py +250 -28
- agno/os/routers/metrics/metrics.py +125 -7
- agno/os/routers/session/session.py +393 -25
- agno/os/schema.py +55 -2
- agno/run/agent.py +9 -0
- agno/run/team.py +93 -2
- agno/run/workflow.py +25 -12
- agno/team/team.py +861 -1051
- agno/tools/mcp.py +1 -2
- agno/utils/log.py +52 -2
- agno/utils/mcp.py +55 -3
- agno/utils/models/claude.py +0 -8
- agno/utils/print_response/team.py +177 -73
- agno/utils/streamlit.py +27 -0
- agno/workflow/workflow.py +9 -0
- {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/METADATA +1 -1
- {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/RECORD +48 -49
- agno/knowledge/reader/gcs_reader.py +0 -67
- {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/WHEEL +0 -0
- {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/licenses/LICENSE +0 -0
- {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/top_level.txt +0 -0
agno/run/team.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from dataclasses import asdict, dataclass, field
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from time import time
|
|
4
|
-
from typing import Any, Dict, List, Optional, Union
|
|
4
|
+
from typing import Any, Dict, List, Optional, Sequence, Union
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel
|
|
7
7
|
|
|
8
|
-
from agno.media import AudioArtifact, AudioResponse, ImageArtifact, VideoArtifact
|
|
8
|
+
from agno.media import AudioArtifact, AudioResponse, File, ImageArtifact, VideoArtifact
|
|
9
9
|
from agno.models.message import Citations, Message
|
|
10
10
|
from agno.models.metrics import Metrics
|
|
11
11
|
from agno.models.response import ToolExecution
|
|
@@ -40,6 +40,8 @@ class TeamRunEvent(str, Enum):
|
|
|
40
40
|
output_model_response_started = "TeamOutputModelResponseStarted"
|
|
41
41
|
output_model_response_completed = "TeamOutputModelResponseCompleted"
|
|
42
42
|
|
|
43
|
+
custom_event = "CustomEvent"
|
|
44
|
+
|
|
43
45
|
|
|
44
46
|
@dataclass
|
|
45
47
|
class BaseTeamRunEvent(BaseRunOutputEvent):
|
|
@@ -213,6 +215,11 @@ class OutputModelResponseCompletedEvent(BaseTeamRunEvent):
|
|
|
213
215
|
event: str = TeamRunEvent.output_model_response_completed.value
|
|
214
216
|
|
|
215
217
|
|
|
218
|
+
@dataclass
|
|
219
|
+
class CustomEvent(BaseTeamRunEvent):
|
|
220
|
+
event: str = TeamRunEvent.custom_event.value
|
|
221
|
+
|
|
222
|
+
|
|
216
223
|
TeamRunOutputEvent = Union[
|
|
217
224
|
RunStartedEvent,
|
|
218
225
|
RunContentEvent,
|
|
@@ -231,6 +238,7 @@ TeamRunOutputEvent = Union[
|
|
|
231
238
|
ParserModelResponseCompletedEvent,
|
|
232
239
|
OutputModelResponseStartedEvent,
|
|
233
240
|
OutputModelResponseCompletedEvent,
|
|
241
|
+
CustomEvent,
|
|
234
242
|
]
|
|
235
243
|
|
|
236
244
|
# Map event string to dataclass for team events
|
|
@@ -252,6 +260,7 @@ TEAM_RUN_EVENT_TYPE_REGISTRY = {
|
|
|
252
260
|
TeamRunEvent.parser_model_response_completed.value: ParserModelResponseCompletedEvent,
|
|
253
261
|
TeamRunEvent.output_model_response_started.value: OutputModelResponseStartedEvent,
|
|
254
262
|
TeamRunEvent.output_model_response_completed.value: OutputModelResponseCompletedEvent,
|
|
263
|
+
TeamRunEvent.custom_event.value: CustomEvent,
|
|
255
264
|
}
|
|
256
265
|
|
|
257
266
|
|
|
@@ -266,6 +275,76 @@ def team_run_output_event_from_dict(data: dict) -> BaseTeamRunEvent:
|
|
|
266
275
|
return event_class.from_dict(data) # type: ignore
|
|
267
276
|
|
|
268
277
|
|
|
278
|
+
@dataclass
|
|
279
|
+
class TeamRunInput:
|
|
280
|
+
"""Container for the raw input data passed to Agent.run().
|
|
281
|
+
This captures the original input exactly as provided by the user,
|
|
282
|
+
separate from the processed messages that go to the model.
|
|
283
|
+
Attributes:
|
|
284
|
+
input_content: The literal input message/content passed to run()
|
|
285
|
+
images: Images directly passed to run()
|
|
286
|
+
videos: Videos directly passed to run()
|
|
287
|
+
audios: Audio files directly passed to run()
|
|
288
|
+
files: Files directly passed to run()
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
input_content: Optional[Union[str, List, Dict, Message, BaseModel, List[Message]]] = None
|
|
292
|
+
images: Optional[Sequence[ImageArtifact]] = None
|
|
293
|
+
videos: Optional[Sequence[VideoArtifact]] = None
|
|
294
|
+
audios: Optional[Sequence[AudioArtifact]] = None
|
|
295
|
+
files: Optional[Sequence[File]] = None
|
|
296
|
+
|
|
297
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
298
|
+
"""Convert to dictionary representation"""
|
|
299
|
+
result: Dict[str, Any] = {}
|
|
300
|
+
|
|
301
|
+
if self.input_content is not None:
|
|
302
|
+
if isinstance(self.input_content, (str)):
|
|
303
|
+
result["input_content"] = self.input_content
|
|
304
|
+
elif isinstance(self.input_content, BaseModel):
|
|
305
|
+
result["input_content"] = self.input_content.model_dump(exclude_none=True)
|
|
306
|
+
elif isinstance(self.input_content, Message):
|
|
307
|
+
result["input_content"] = self.input_content.to_dict()
|
|
308
|
+
elif (
|
|
309
|
+
isinstance(self.input_content, list)
|
|
310
|
+
and self.input_content
|
|
311
|
+
and isinstance(self.input_content[0], Message)
|
|
312
|
+
):
|
|
313
|
+
result["input_content"] = [m.to_dict() for m in self.input_content]
|
|
314
|
+
else:
|
|
315
|
+
result["input_content"] = self.input_content
|
|
316
|
+
|
|
317
|
+
if self.images:
|
|
318
|
+
result["images"] = [img.to_dict() for img in self.images]
|
|
319
|
+
if self.videos:
|
|
320
|
+
result["videos"] = [vid.to_dict() for vid in self.videos]
|
|
321
|
+
if self.audios:
|
|
322
|
+
result["audios"] = [aud.to_dict() for aud in self.audios]
|
|
323
|
+
|
|
324
|
+
return result
|
|
325
|
+
|
|
326
|
+
@classmethod
|
|
327
|
+
def from_dict(cls, data: Dict[str, Any]) -> "TeamRunInput":
|
|
328
|
+
"""Create TeamRunInput from dictionary"""
|
|
329
|
+
images = None
|
|
330
|
+
if data.get("images"):
|
|
331
|
+
images = [ImageArtifact.model_validate(img_data) for img_data in data["images"]]
|
|
332
|
+
|
|
333
|
+
videos = None
|
|
334
|
+
if data.get("videos"):
|
|
335
|
+
videos = [VideoArtifact.model_validate(vid_data) for vid_data in data["videos"]]
|
|
336
|
+
|
|
337
|
+
audios = None
|
|
338
|
+
if data.get("audios"):
|
|
339
|
+
audios = [AudioArtifact.model_validate(aud_data) for aud_data in data["audios"]]
|
|
340
|
+
|
|
341
|
+
files = None
|
|
342
|
+
if data.get("files"):
|
|
343
|
+
files = [File.model_validate(file_data) for file_data in data["files"]]
|
|
344
|
+
|
|
345
|
+
return cls(input_content=data.get("input_content"), images=images, videos=videos, audios=audios, files=files)
|
|
346
|
+
|
|
347
|
+
|
|
269
348
|
@dataclass
|
|
270
349
|
class TeamRunOutput:
|
|
271
350
|
"""Response returned by Team.run() functions"""
|
|
@@ -293,6 +372,9 @@ class TeamRunOutput:
|
|
|
293
372
|
|
|
294
373
|
response_audio: Optional[AudioResponse] = None # Model audio response
|
|
295
374
|
|
|
375
|
+
# Input media and messages from user
|
|
376
|
+
input: Optional[TeamRunInput] = None
|
|
377
|
+
|
|
296
378
|
reasoning_content: Optional[str] = None
|
|
297
379
|
|
|
298
380
|
citations: Optional[Citations] = None
|
|
@@ -401,6 +483,9 @@ class TeamRunOutput:
|
|
|
401
483
|
else:
|
|
402
484
|
_dict["tools"].append(tool)
|
|
403
485
|
|
|
486
|
+
if self.input is not None:
|
|
487
|
+
_dict["input"] = self.input.to_dict()
|
|
488
|
+
|
|
404
489
|
return _dict
|
|
405
490
|
|
|
406
491
|
def to_json(self) -> str:
|
|
@@ -468,6 +553,11 @@ class TeamRunOutput:
|
|
|
468
553
|
response_audio = data.pop("response_audio", None)
|
|
469
554
|
response_audio = AudioResponse.model_validate(response_audio) if response_audio else None
|
|
470
555
|
|
|
556
|
+
input_data = data.pop("input", None)
|
|
557
|
+
input_obj = None
|
|
558
|
+
if input_data:
|
|
559
|
+
input_obj = TeamRunInput.from_dict(input_data)
|
|
560
|
+
|
|
471
561
|
metrics = data.pop("metrics", None)
|
|
472
562
|
if metrics:
|
|
473
563
|
metrics = Metrics(**metrics)
|
|
@@ -487,6 +577,7 @@ class TeamRunOutput:
|
|
|
487
577
|
videos=videos,
|
|
488
578
|
audio=audio,
|
|
489
579
|
response_audio=response_audio,
|
|
580
|
+
input=input_obj,
|
|
490
581
|
citations=citations,
|
|
491
582
|
tools=tools,
|
|
492
583
|
events=events,
|
agno/run/workflow.py
CHANGED
|
@@ -13,6 +13,9 @@ from agno.utils.log import log_error
|
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from agno.workflow.types import StepOutput, WorkflowMetrics
|
|
16
|
+
else:
|
|
17
|
+
StepOutput = Any
|
|
18
|
+
WorkflowMetrics = Any
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
class WorkflowRunEvent(str, Enum):
|
|
@@ -46,6 +49,8 @@ class WorkflowRunEvent(str, Enum):
|
|
|
46
49
|
|
|
47
50
|
step_output = "StepOutput"
|
|
48
51
|
|
|
52
|
+
custom_event = "CustomEvent"
|
|
53
|
+
|
|
49
54
|
|
|
50
55
|
@dataclass
|
|
51
56
|
class BaseWorkflowRunOutputEvent:
|
|
@@ -132,7 +137,7 @@ class WorkflowCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
132
137
|
content_type: str = "str"
|
|
133
138
|
|
|
134
139
|
# Store actual step execution results as StepOutput objects
|
|
135
|
-
step_results: List[
|
|
140
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
136
141
|
metadata: Optional[Dict[str, Any]] = None
|
|
137
142
|
|
|
138
143
|
|
|
@@ -183,7 +188,7 @@ class StepCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
183
188
|
response_audio: Optional[AudioResponse] = None
|
|
184
189
|
|
|
185
190
|
# Store actual step execution results as StepOutput objects
|
|
186
|
-
step_response: Optional[
|
|
191
|
+
step_response: Optional[StepOutput] = None
|
|
187
192
|
|
|
188
193
|
|
|
189
194
|
@dataclass
|
|
@@ -226,7 +231,7 @@ class LoopIterationCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
226
231
|
step_index: Optional[Union[int, tuple]] = None
|
|
227
232
|
iteration: int = 0
|
|
228
233
|
max_iterations: Optional[int] = None
|
|
229
|
-
iteration_results: List[
|
|
234
|
+
iteration_results: List[StepOutput] = field(default_factory=list)
|
|
230
235
|
should_continue: bool = True
|
|
231
236
|
|
|
232
237
|
|
|
@@ -239,7 +244,7 @@ class LoopExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
239
244
|
step_index: Optional[Union[int, tuple]] = None
|
|
240
245
|
total_iterations: int = 0
|
|
241
246
|
max_iterations: Optional[int] = None
|
|
242
|
-
all_results: List[List[
|
|
247
|
+
all_results: List[List[StepOutput]] = field(default_factory=list)
|
|
243
248
|
|
|
244
249
|
|
|
245
250
|
@dataclass
|
|
@@ -262,7 +267,7 @@ class ParallelExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
262
267
|
parallel_step_count: Optional[int] = None
|
|
263
268
|
|
|
264
269
|
# Results from all parallel steps
|
|
265
|
-
step_results: List[
|
|
270
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
266
271
|
|
|
267
272
|
|
|
268
273
|
@dataclass
|
|
@@ -286,7 +291,7 @@ class ConditionExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
286
291
|
executed_steps: Optional[int] = None
|
|
287
292
|
|
|
288
293
|
# Results from executed steps
|
|
289
|
-
step_results: List[
|
|
294
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
290
295
|
|
|
291
296
|
|
|
292
297
|
@dataclass
|
|
@@ -312,7 +317,7 @@ class RouterExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
312
317
|
executed_steps: Optional[int] = None
|
|
313
318
|
|
|
314
319
|
# Results from executed steps
|
|
315
|
-
step_results: List[
|
|
320
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
316
321
|
|
|
317
322
|
|
|
318
323
|
@dataclass
|
|
@@ -336,7 +341,7 @@ class StepsExecutionCompletedEvent(BaseWorkflowRunOutputEvent):
|
|
|
336
341
|
executed_steps: Optional[int] = None
|
|
337
342
|
|
|
338
343
|
# Results from executed steps
|
|
339
|
-
step_results: List[
|
|
344
|
+
step_results: List[StepOutput] = field(default_factory=list)
|
|
340
345
|
|
|
341
346
|
|
|
342
347
|
@dataclass
|
|
@@ -348,7 +353,7 @@ class StepOutputEvent(BaseWorkflowRunOutputEvent):
|
|
|
348
353
|
step_index: Optional[Union[int, tuple]] = None
|
|
349
354
|
|
|
350
355
|
# Store actual step execution result as StepOutput object
|
|
351
|
-
step_output: Optional[
|
|
356
|
+
step_output: Optional[StepOutput] = None
|
|
352
357
|
|
|
353
358
|
# Properties for backward compatibility
|
|
354
359
|
@property
|
|
@@ -380,6 +385,13 @@ class StepOutputEvent(BaseWorkflowRunOutputEvent):
|
|
|
380
385
|
return self.step_output.stop if self.step_output else False
|
|
381
386
|
|
|
382
387
|
|
|
388
|
+
@dataclass
|
|
389
|
+
class CustomEvent(BaseWorkflowRunOutputEvent):
|
|
390
|
+
"""Event sent when a custom event is produced"""
|
|
391
|
+
|
|
392
|
+
event: str = WorkflowRunEvent.custom_event.value
|
|
393
|
+
|
|
394
|
+
|
|
383
395
|
# Union type for all workflow run response events
|
|
384
396
|
WorkflowRunOutputEvent = Union[
|
|
385
397
|
WorkflowStartedEvent,
|
|
@@ -402,6 +414,7 @@ WorkflowRunOutputEvent = Union[
|
|
|
402
414
|
StepsExecutionStartedEvent,
|
|
403
415
|
StepsExecutionCompletedEvent,
|
|
404
416
|
StepOutputEvent,
|
|
417
|
+
CustomEvent,
|
|
405
418
|
]
|
|
406
419
|
|
|
407
420
|
|
|
@@ -426,7 +439,7 @@ class WorkflowRunOutput:
|
|
|
426
439
|
response_audio: Optional[AudioResponse] = None
|
|
427
440
|
|
|
428
441
|
# Store actual step execution results as StepOutput objects
|
|
429
|
-
step_results: List[Union[
|
|
442
|
+
step_results: List[Union[StepOutput, List[StepOutput]]] = field(default_factory=list)
|
|
430
443
|
|
|
431
444
|
# Store agent/team responses separately with parent_run_id references
|
|
432
445
|
step_executor_runs: Optional[List[Union[RunOutput, TeamRunOutput]]] = None
|
|
@@ -435,7 +448,7 @@ class WorkflowRunOutput:
|
|
|
435
448
|
events: Optional[List[WorkflowRunOutputEvent]] = None
|
|
436
449
|
|
|
437
450
|
# Workflow metrics aggregated from all steps
|
|
438
|
-
metrics: Optional[
|
|
451
|
+
metrics: Optional[WorkflowMetrics] = None
|
|
439
452
|
|
|
440
453
|
metadata: Optional[Dict[str, Any]] = None
|
|
441
454
|
created_at: int = field(default_factory=lambda: int(time()))
|
|
@@ -521,7 +534,7 @@ class WorkflowRunOutput:
|
|
|
521
534
|
workflow_metrics = WorkflowMetrics.from_dict(workflow_metrics_dict)
|
|
522
535
|
|
|
523
536
|
step_results = data.pop("step_results", [])
|
|
524
|
-
parsed_step_results: List[Union[
|
|
537
|
+
parsed_step_results: List[Union[StepOutput, List[StepOutput]]] = []
|
|
525
538
|
if step_results:
|
|
526
539
|
for step_output_dict in step_results:
|
|
527
540
|
# Reconstruct StepOutput from dict
|