agno 2.0.1__py3-none-any.whl → 2.3.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/agent.py +6015 -2823
- agno/api/api.py +2 -0
- agno/api/os.py +1 -1
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +385 -6
- agno/db/dynamo/dynamo.py +388 -81
- agno/db/dynamo/schemas.py +47 -10
- agno/db/dynamo/utils.py +63 -4
- agno/db/firestore/firestore.py +435 -64
- agno/db/firestore/schemas.py +11 -0
- agno/db/firestore/utils.py +102 -4
- agno/db/gcs_json/gcs_json_db.py +384 -42
- agno/db/gcs_json/utils.py +60 -26
- agno/db/in_memory/in_memory_db.py +351 -66
- agno/db/in_memory/utils.py +60 -2
- agno/db/json/json_db.py +339 -48
- agno/db/json/utils.py +60 -26
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +510 -37
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +15 -1
- agno/db/mongo/async_mongo.py +2036 -0
- agno/db/mongo/mongo.py +653 -76
- agno/db/mongo/schemas.py +13 -0
- agno/db/mongo/utils.py +80 -8
- agno/db/mysql/mysql.py +687 -25
- agno/db/mysql/schemas.py +61 -37
- agno/db/mysql/utils.py +60 -2
- agno/db/postgres/__init__.py +2 -1
- agno/db/postgres/async_postgres.py +2001 -0
- agno/db/postgres/postgres.py +676 -57
- agno/db/postgres/schemas.py +43 -18
- agno/db/postgres/utils.py +164 -2
- agno/db/redis/redis.py +344 -38
- agno/db/redis/schemas.py +18 -0
- agno/db/redis/utils.py +60 -2
- agno/db/schemas/__init__.py +2 -1
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/memory.py +13 -0
- agno/db/singlestore/schemas.py +26 -1
- agno/db/singlestore/singlestore.py +687 -53
- agno/db/singlestore/utils.py +60 -2
- agno/db/sqlite/__init__.py +2 -1
- agno/db/sqlite/async_sqlite.py +2371 -0
- agno/db/sqlite/schemas.py +24 -0
- agno/db/sqlite/sqlite.py +774 -85
- agno/db/sqlite/utils.py +168 -5
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +309 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1361 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +50 -22
- agno/eval/accuracy.py +50 -43
- agno/eval/performance.py +6 -3
- agno/eval/reliability.py +6 -3
- agno/eval/utils.py +33 -16
- agno/exceptions.py +68 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/integrations/discord/client.py +1 -0
- agno/knowledge/chunking/agentic.py +13 -10
- agno/knowledge/chunking/fixed.py +1 -1
- agno/knowledge/chunking/semantic.py +40 -8
- agno/knowledge/chunking/strategy.py +59 -15
- agno/knowledge/embedder/aws_bedrock.py +9 -4
- agno/knowledge/embedder/azure_openai.py +54 -0
- agno/knowledge/embedder/base.py +2 -0
- agno/knowledge/embedder/cohere.py +184 -5
- agno/knowledge/embedder/fastembed.py +1 -1
- agno/knowledge/embedder/google.py +79 -1
- agno/knowledge/embedder/huggingface.py +9 -4
- agno/knowledge/embedder/jina.py +63 -0
- agno/knowledge/embedder/mistral.py +78 -11
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/ollama.py +13 -0
- agno/knowledge/embedder/openai.py +37 -65
- agno/knowledge/embedder/sentence_transformer.py +8 -4
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +69 -16
- agno/knowledge/knowledge.py +594 -186
- agno/knowledge/reader/base.py +9 -2
- agno/knowledge/reader/csv_reader.py +8 -10
- agno/knowledge/reader/docx_reader.py +5 -6
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/json_reader.py +6 -5
- agno/knowledge/reader/markdown_reader.py +13 -13
- agno/knowledge/reader/pdf_reader.py +43 -68
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +51 -6
- agno/knowledge/reader/s3_reader.py +3 -15
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/knowledge/reader/text_reader.py +13 -13
- agno/knowledge/reader/web_search_reader.py +2 -43
- agno/knowledge/reader/website_reader.py +43 -25
- agno/knowledge/reranker/__init__.py +2 -8
- agno/knowledge/types.py +9 -0
- agno/knowledge/utils.py +20 -0
- agno/media.py +72 -0
- agno/memory/manager.py +336 -82
- agno/models/aimlapi/aimlapi.py +2 -2
- agno/models/anthropic/claude.py +183 -37
- agno/models/aws/bedrock.py +52 -112
- agno/models/aws/claude.py +33 -1
- agno/models/azure/ai_foundry.py +33 -15
- agno/models/azure/openai_chat.py +25 -8
- agno/models/base.py +999 -519
- agno/models/cerebras/cerebras.py +19 -13
- agno/models/cerebras/cerebras_openai.py +8 -5
- agno/models/cohere/chat.py +27 -1
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +57 -0
- agno/models/dashscope/dashscope.py +1 -0
- agno/models/deepinfra/deepinfra.py +2 -2
- agno/models/deepseek/deepseek.py +2 -2
- agno/models/fireworks/fireworks.py +2 -2
- agno/models/google/gemini.py +103 -31
- agno/models/groq/groq.py +28 -11
- agno/models/huggingface/huggingface.py +2 -1
- agno/models/internlm/internlm.py +2 -2
- agno/models/langdb/langdb.py +4 -4
- agno/models/litellm/chat.py +18 -1
- agno/models/litellm/litellm_openai.py +2 -2
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/message.py +139 -0
- agno/models/meta/llama.py +27 -10
- agno/models/meta/llama_openai.py +5 -17
- agno/models/nebius/nebius.py +6 -6
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/nvidia.py +2 -2
- agno/models/ollama/chat.py +59 -5
- agno/models/openai/chat.py +69 -29
- agno/models/openai/responses.py +103 -106
- agno/models/openrouter/openrouter.py +41 -3
- agno/models/perplexity/perplexity.py +4 -5
- agno/models/portkey/portkey.py +3 -3
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +52 -0
- agno/models/response.py +77 -1
- agno/models/sambanova/sambanova.py +2 -2
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +25 -0
- agno/models/together/together.py +2 -2
- agno/models/utils.py +254 -8
- agno/models/vercel/v0.py +2 -2
- agno/models/vertexai/__init__.py +0 -0
- agno/models/vertexai/claude.py +96 -0
- agno/models/vllm/vllm.py +1 -0
- agno/models/xai/xai.py +3 -2
- agno/os/app.py +543 -178
- agno/os/auth.py +24 -14
- agno/os/config.py +1 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +250 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/agui.py +23 -7
- agno/os/interfaces/agui/router.py +27 -3
- agno/os/interfaces/agui/utils.py +242 -142
- agno/os/interfaces/base.py +6 -2
- agno/os/interfaces/slack/router.py +81 -23
- agno/os/interfaces/slack/slack.py +29 -14
- agno/os/interfaces/whatsapp/router.py +11 -4
- agno/os/interfaces/whatsapp/whatsapp.py +14 -7
- agno/os/mcp.py +111 -54
- agno/os/middleware/__init__.py +7 -0
- agno/os/middleware/jwt.py +233 -0
- agno/os/router.py +556 -139
- agno/os/routers/evals/evals.py +71 -34
- agno/os/routers/evals/schemas.py +31 -31
- agno/os/routers/evals/utils.py +6 -5
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/knowledge.py +185 -38
- agno/os/routers/knowledge/schemas.py +82 -22
- agno/os/routers/memory/memory.py +158 -53
- agno/os/routers/memory/schemas.py +20 -16
- agno/os/routers/metrics/metrics.py +20 -8
- agno/os/routers/metrics/schemas.py +16 -16
- agno/os/routers/session/session.py +499 -38
- agno/os/schema.py +308 -198
- agno/os/utils.py +401 -41
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +2 -2
- agno/reasoning/deepseek.py +2 -2
- agno/reasoning/default.py +3 -1
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +2 -2
- agno/reasoning/ollama.py +2 -2
- agno/reasoning/openai.py +7 -2
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +248 -94
- agno/run/base.py +44 -5
- agno/run/team.py +238 -97
- agno/run/workflow.py +144 -33
- agno/session/agent.py +105 -89
- agno/session/summary.py +65 -25
- agno/session/team.py +176 -96
- agno/session/workflow.py +406 -40
- agno/team/team.py +3854 -1610
- agno/tools/dalle.py +2 -4
- agno/tools/decorator.py +4 -2
- agno/tools/duckduckgo.py +15 -11
- agno/tools/e2b.py +14 -7
- agno/tools/eleven_labs.py +23 -25
- agno/tools/exa.py +21 -16
- agno/tools/file.py +153 -23
- agno/tools/file_generation.py +350 -0
- agno/tools/firecrawl.py +4 -4
- agno/tools/function.py +250 -30
- agno/tools/gmail.py +238 -14
- agno/tools/google_drive.py +270 -0
- agno/tools/googlecalendar.py +36 -8
- agno/tools/googlesheets.py +20 -5
- agno/tools/jira.py +20 -0
- agno/tools/knowledge.py +3 -3
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +11 -17
- agno/tools/memori.py +1 -53
- agno/tools/memory.py +419 -0
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/notion.py +204 -0
- agno/tools/parallel.py +314 -0
- agno/tools/scrapegraph.py +58 -31
- agno/tools/searxng.py +2 -2
- agno/tools/serper.py +2 -2
- agno/tools/slack.py +18 -3
- agno/tools/spider.py +2 -2
- agno/tools/tavily.py +146 -0
- agno/tools/whatsapp.py +1 -1
- agno/tools/workflow.py +278 -0
- agno/tools/yfinance.py +12 -11
- agno/utils/agent.py +820 -0
- agno/utils/audio.py +27 -0
- agno/utils/common.py +90 -1
- agno/utils/events.py +217 -2
- agno/utils/gemini.py +180 -22
- agno/utils/hooks.py +57 -0
- agno/utils/http.py +111 -0
- agno/utils/knowledge.py +12 -5
- agno/utils/log.py +1 -0
- agno/utils/mcp.py +92 -2
- agno/utils/media.py +188 -10
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +60 -0
- agno/utils/models/claude.py +40 -11
- agno/utils/print_response/agent.py +105 -21
- agno/utils/print_response/team.py +103 -38
- agno/utils/print_response/workflow.py +251 -34
- agno/utils/reasoning.py +22 -1
- agno/utils/serialize.py +32 -0
- agno/utils/streamlit.py +16 -10
- agno/utils/string.py +41 -0
- agno/utils/team.py +98 -9
- agno/utils/tools.py +1 -1
- agno/vectordb/base.py +23 -4
- agno/vectordb/cassandra/cassandra.py +65 -9
- agno/vectordb/chroma/chromadb.py +182 -38
- agno/vectordb/clickhouse/clickhousedb.py +64 -11
- agno/vectordb/couchbase/couchbase.py +105 -10
- agno/vectordb/lancedb/lance_db.py +124 -133
- agno/vectordb/langchaindb/langchaindb.py +25 -7
- agno/vectordb/lightrag/lightrag.py +17 -3
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +46 -7
- agno/vectordb/milvus/milvus.py +126 -9
- agno/vectordb/mongodb/__init__.py +7 -1
- agno/vectordb/mongodb/mongodb.py +112 -7
- agno/vectordb/pgvector/pgvector.py +142 -21
- agno/vectordb/pineconedb/pineconedb.py +80 -8
- agno/vectordb/qdrant/qdrant.py +125 -39
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +694 -0
- agno/vectordb/singlestore/singlestore.py +111 -25
- agno/vectordb/surrealdb/surrealdb.py +31 -5
- agno/vectordb/upstashdb/upstashdb.py +76 -8
- agno/vectordb/weaviate/weaviate.py +86 -15
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +112 -18
- agno/workflow/loop.py +69 -10
- agno/workflow/parallel.py +266 -118
- agno/workflow/router.py +110 -17
- agno/workflow/step.py +638 -129
- agno/workflow/steps.py +65 -6
- agno/workflow/types.py +61 -23
- agno/workflow/workflow.py +2085 -272
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/METADATA +182 -58
- agno-2.3.0.dist-info/RECORD +577 -0
- agno/knowledge/reader/url_reader.py +0 -128
- agno/tools/googlesearch.py +0 -98
- agno/tools/mcp.py +0 -610
- agno/utils/models/aws_claude.py +0 -170
- agno-2.0.1.dist-info/RECORD +0 -515
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/WHEEL +0 -0
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/licenses/LICENSE +0 -0
- {agno-2.0.1.dist-info → agno-2.3.0.dist-info}/top_level.txt +0 -0
agno/run/team.py
CHANGED
|
@@ -12,6 +12,118 @@ from agno.models.response import ToolExecution
|
|
|
12
12
|
from agno.reasoning.step import ReasoningStep
|
|
13
13
|
from agno.run.agent import RunEvent, RunOutput, RunOutputEvent, run_output_event_from_dict
|
|
14
14
|
from agno.run.base import BaseRunOutputEvent, MessageReferences, RunStatus
|
|
15
|
+
from agno.utils.log import log_error
|
|
16
|
+
from agno.utils.media import (
|
|
17
|
+
reconstruct_audio_list,
|
|
18
|
+
reconstruct_files,
|
|
19
|
+
reconstruct_images,
|
|
20
|
+
reconstruct_response_audio,
|
|
21
|
+
reconstruct_videos,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class TeamRunInput:
|
|
27
|
+
"""Container for the raw input data passed to Agent.run().
|
|
28
|
+
This captures the original input exactly as provided by the user,
|
|
29
|
+
separate from the processed messages that go to the model.
|
|
30
|
+
Attributes:
|
|
31
|
+
input_content: The literal input message/content passed to run()
|
|
32
|
+
images: Images directly passed to run()
|
|
33
|
+
videos: Videos directly passed to run()
|
|
34
|
+
audios: Audio files directly passed to run()
|
|
35
|
+
files: Files directly passed to run()
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
input_content: Union[str, List, Dict, Message, BaseModel, List[Message]]
|
|
39
|
+
images: Optional[Sequence[Image]] = None
|
|
40
|
+
videos: Optional[Sequence[Video]] = None
|
|
41
|
+
audios: Optional[Sequence[Audio]] = None
|
|
42
|
+
files: Optional[Sequence[File]] = None
|
|
43
|
+
|
|
44
|
+
def input_content_string(self) -> str:
|
|
45
|
+
import json
|
|
46
|
+
|
|
47
|
+
if isinstance(self.input_content, (str)):
|
|
48
|
+
return self.input_content
|
|
49
|
+
elif isinstance(self.input_content, BaseModel):
|
|
50
|
+
return self.input_content.model_dump_json(exclude_none=True)
|
|
51
|
+
elif isinstance(self.input_content, Message):
|
|
52
|
+
return json.dumps(self.input_content.to_dict())
|
|
53
|
+
elif isinstance(self.input_content, list) and self.input_content and isinstance(self.input_content[0], Message):
|
|
54
|
+
return json.dumps([m.to_dict() for m in self.input_content])
|
|
55
|
+
else:
|
|
56
|
+
return str(self.input_content)
|
|
57
|
+
|
|
58
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
59
|
+
"""Convert to dictionary representation"""
|
|
60
|
+
result: Dict[str, Any] = {}
|
|
61
|
+
|
|
62
|
+
if self.input_content is not None:
|
|
63
|
+
if isinstance(self.input_content, (str)):
|
|
64
|
+
result["input_content"] = self.input_content
|
|
65
|
+
elif isinstance(self.input_content, BaseModel):
|
|
66
|
+
result["input_content"] = self.input_content.model_dump(exclude_none=True)
|
|
67
|
+
elif isinstance(self.input_content, Message):
|
|
68
|
+
result["input_content"] = self.input_content.to_dict()
|
|
69
|
+
|
|
70
|
+
# Handle input_content provided as a list of Message objects
|
|
71
|
+
elif (
|
|
72
|
+
isinstance(self.input_content, list)
|
|
73
|
+
and self.input_content
|
|
74
|
+
and isinstance(self.input_content[0], Message)
|
|
75
|
+
):
|
|
76
|
+
result["input_content"] = [m.to_dict() for m in self.input_content]
|
|
77
|
+
|
|
78
|
+
# Handle input_content provided as a list of dicts
|
|
79
|
+
elif (
|
|
80
|
+
isinstance(self.input_content, list) and self.input_content and isinstance(self.input_content[0], dict)
|
|
81
|
+
):
|
|
82
|
+
for content in self.input_content:
|
|
83
|
+
# Handle media input
|
|
84
|
+
if isinstance(content, dict):
|
|
85
|
+
if content.get("images"):
|
|
86
|
+
content["images"] = [
|
|
87
|
+
img.to_dict() if isinstance(img, Image) else img for img in content["images"]
|
|
88
|
+
]
|
|
89
|
+
if content.get("videos"):
|
|
90
|
+
content["videos"] = [
|
|
91
|
+
vid.to_dict() if isinstance(vid, Video) else vid for vid in content["videos"]
|
|
92
|
+
]
|
|
93
|
+
if content.get("audios"):
|
|
94
|
+
content["audios"] = [
|
|
95
|
+
aud.to_dict() if isinstance(aud, Audio) else aud for aud in content["audios"]
|
|
96
|
+
]
|
|
97
|
+
if content.get("files"):
|
|
98
|
+
content["files"] = [
|
|
99
|
+
file.to_dict() if isinstance(file, File) else file for file in content["files"]
|
|
100
|
+
]
|
|
101
|
+
result["input_content"] = self.input_content
|
|
102
|
+
else:
|
|
103
|
+
result["input_content"] = self.input_content
|
|
104
|
+
|
|
105
|
+
if self.images:
|
|
106
|
+
result["images"] = [img.to_dict() for img in self.images]
|
|
107
|
+
if self.videos:
|
|
108
|
+
result["videos"] = [vid.to_dict() for vid in self.videos]
|
|
109
|
+
if self.audios:
|
|
110
|
+
result["audios"] = [aud.to_dict() for aud in self.audios]
|
|
111
|
+
if self.files:
|
|
112
|
+
result["files"] = [file.to_dict() for file in self.files]
|
|
113
|
+
|
|
114
|
+
return result
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def from_dict(cls, data: Dict[str, Any]) -> "TeamRunInput":
|
|
118
|
+
"""Create TeamRunInput from dictionary"""
|
|
119
|
+
images = reconstruct_images(data.get("images"))
|
|
120
|
+
videos = reconstruct_videos(data.get("videos"))
|
|
121
|
+
audios = reconstruct_audio_list(data.get("audios"))
|
|
122
|
+
files = reconstruct_files(data.get("files"))
|
|
123
|
+
|
|
124
|
+
return cls(
|
|
125
|
+
input_content=data.get("input_content", ""), images=images, videos=videos, audios=audios, files=files
|
|
126
|
+
)
|
|
15
127
|
|
|
16
128
|
|
|
17
129
|
class TeamRunEvent(str, Enum):
|
|
@@ -20,10 +132,17 @@ class TeamRunEvent(str, Enum):
|
|
|
20
132
|
run_started = "TeamRunStarted"
|
|
21
133
|
run_content = "TeamRunContent"
|
|
22
134
|
run_intermediate_content = "TeamRunIntermediateContent"
|
|
135
|
+
run_content_completed = "TeamRunContentCompleted"
|
|
23
136
|
run_completed = "TeamRunCompleted"
|
|
24
137
|
run_error = "TeamRunError"
|
|
25
138
|
run_cancelled = "TeamRunCancelled"
|
|
26
139
|
|
|
140
|
+
pre_hook_started = "TeamPreHookStarted"
|
|
141
|
+
pre_hook_completed = "TeamPreHookCompleted"
|
|
142
|
+
|
|
143
|
+
post_hook_started = "TeamPostHookStarted"
|
|
144
|
+
post_hook_completed = "TeamPostHookCompleted"
|
|
145
|
+
|
|
27
146
|
tool_call_started = "TeamToolCallStarted"
|
|
28
147
|
tool_call_completed = "TeamToolCallCompleted"
|
|
29
148
|
|
|
@@ -34,6 +153,9 @@ class TeamRunEvent(str, Enum):
|
|
|
34
153
|
memory_update_started = "TeamMemoryUpdateStarted"
|
|
35
154
|
memory_update_completed = "TeamMemoryUpdateCompleted"
|
|
36
155
|
|
|
156
|
+
session_summary_started = "TeamSessionSummaryStarted"
|
|
157
|
+
session_summary_completed = "TeamSessionSummaryCompleted"
|
|
158
|
+
|
|
37
159
|
parser_model_response_started = "TeamParserModelResponseStarted"
|
|
38
160
|
parser_model_response_completed = "TeamParserModelResponseCompleted"
|
|
39
161
|
|
|
@@ -50,6 +172,7 @@ class BaseTeamRunEvent(BaseRunOutputEvent):
|
|
|
50
172
|
team_id: str = ""
|
|
51
173
|
team_name: str = ""
|
|
52
174
|
run_id: Optional[str] = None
|
|
175
|
+
parent_run_id: Optional[str] = None
|
|
53
176
|
session_id: Optional[str] = None
|
|
54
177
|
|
|
55
178
|
workflow_id: Optional[str] = None
|
|
@@ -97,6 +220,7 @@ class RunContentEvent(BaseTeamRunEvent):
|
|
|
97
220
|
content: Optional[Any] = None
|
|
98
221
|
content_type: str = "str"
|
|
99
222
|
reasoning_content: Optional[str] = None
|
|
223
|
+
model_provider_data: Optional[Dict[str, Any]] = None
|
|
100
224
|
citations: Optional[Citations] = None
|
|
101
225
|
response_audio: Optional[Audio] = None # Model audio response
|
|
102
226
|
image: Optional[Image] = None # Image attached to the response
|
|
@@ -113,6 +237,11 @@ class IntermediateRunContentEvent(BaseTeamRunEvent):
|
|
|
113
237
|
content_type: str = "str"
|
|
114
238
|
|
|
115
239
|
|
|
240
|
+
@dataclass
|
|
241
|
+
class RunContentCompletedEvent(BaseTeamRunEvent):
|
|
242
|
+
event: str = TeamRunEvent.run_content_completed.value
|
|
243
|
+
|
|
244
|
+
|
|
116
245
|
@dataclass
|
|
117
246
|
class RunCompletedEvent(BaseTeamRunEvent):
|
|
118
247
|
event: str = TeamRunEvent.run_completed.value
|
|
@@ -120,6 +249,7 @@ class RunCompletedEvent(BaseTeamRunEvent):
|
|
|
120
249
|
content_type: str = "str"
|
|
121
250
|
reasoning_content: Optional[str] = None
|
|
122
251
|
citations: Optional[Citations] = None
|
|
252
|
+
model_provider_data: Optional[Dict[str, Any]] = None
|
|
123
253
|
images: Optional[List[Image]] = None # Images attached to the response
|
|
124
254
|
videos: Optional[List[Video]] = None # Videos attached to the response
|
|
125
255
|
audio: Optional[List[Audio]] = None # Audio attached to the response
|
|
@@ -131,6 +261,7 @@ class RunCompletedEvent(BaseTeamRunEvent):
|
|
|
131
261
|
member_responses: List[Union["TeamRunOutput", RunOutput]] = field(default_factory=list)
|
|
132
262
|
metadata: Optional[Dict[str, Any]] = None
|
|
133
263
|
metrics: Optional[Metrics] = None
|
|
264
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
134
265
|
|
|
135
266
|
|
|
136
267
|
@dataclass
|
|
@@ -138,6 +269,11 @@ class RunErrorEvent(BaseTeamRunEvent):
|
|
|
138
269
|
event: str = TeamRunEvent.run_error.value
|
|
139
270
|
content: Optional[str] = None
|
|
140
271
|
|
|
272
|
+
# From exceptions
|
|
273
|
+
error_type: Optional[str] = None
|
|
274
|
+
error_id: Optional[str] = None
|
|
275
|
+
additional_data: Optional[Dict[str, Any]] = None
|
|
276
|
+
|
|
141
277
|
|
|
142
278
|
@dataclass
|
|
143
279
|
class RunCancelledEvent(BaseTeamRunEvent):
|
|
@@ -149,6 +285,32 @@ class RunCancelledEvent(BaseTeamRunEvent):
|
|
|
149
285
|
return True
|
|
150
286
|
|
|
151
287
|
|
|
288
|
+
@dataclass
|
|
289
|
+
class PreHookStartedEvent(BaseTeamRunEvent):
|
|
290
|
+
event: str = TeamRunEvent.pre_hook_started.value
|
|
291
|
+
pre_hook_name: Optional[str] = None
|
|
292
|
+
run_input: Optional[TeamRunInput] = None
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@dataclass
|
|
296
|
+
class PreHookCompletedEvent(BaseTeamRunEvent):
|
|
297
|
+
event: str = TeamRunEvent.pre_hook_completed.value
|
|
298
|
+
pre_hook_name: Optional[str] = None
|
|
299
|
+
run_input: Optional[TeamRunInput] = None
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
@dataclass
|
|
303
|
+
class PostHookStartedEvent(BaseTeamRunEvent):
|
|
304
|
+
event: str = TeamRunEvent.post_hook_started.value
|
|
305
|
+
post_hook_name: Optional[str] = None
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
@dataclass
|
|
309
|
+
class PostHookCompletedEvent(BaseTeamRunEvent):
|
|
310
|
+
event: str = TeamRunEvent.post_hook_completed.value
|
|
311
|
+
post_hook_name: Optional[str] = None
|
|
312
|
+
|
|
313
|
+
|
|
152
314
|
@dataclass
|
|
153
315
|
class MemoryUpdateStartedEvent(BaseTeamRunEvent):
|
|
154
316
|
event: str = TeamRunEvent.memory_update_started.value
|
|
@@ -159,6 +321,17 @@ class MemoryUpdateCompletedEvent(BaseTeamRunEvent):
|
|
|
159
321
|
event: str = TeamRunEvent.memory_update_completed.value
|
|
160
322
|
|
|
161
323
|
|
|
324
|
+
@dataclass
|
|
325
|
+
class SessionSummaryStartedEvent(BaseTeamRunEvent):
|
|
326
|
+
event: str = TeamRunEvent.session_summary_started.value
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@dataclass
|
|
330
|
+
class SessionSummaryCompletedEvent(BaseTeamRunEvent):
|
|
331
|
+
event: str = TeamRunEvent.session_summary_completed.value
|
|
332
|
+
session_summary: Optional[Any] = None
|
|
333
|
+
|
|
334
|
+
|
|
162
335
|
@dataclass
|
|
163
336
|
class ReasoningStartedEvent(BaseTeamRunEvent):
|
|
164
337
|
event: str = TeamRunEvent.reasoning_started.value
|
|
@@ -219,19 +392,29 @@ class OutputModelResponseCompletedEvent(BaseTeamRunEvent):
|
|
|
219
392
|
class CustomEvent(BaseTeamRunEvent):
|
|
220
393
|
event: str = TeamRunEvent.custom_event.value
|
|
221
394
|
|
|
395
|
+
def __init__(self, **kwargs):
|
|
396
|
+
# Store arbitrary attributes directly on the instance
|
|
397
|
+
for key, value in kwargs.items():
|
|
398
|
+
setattr(self, key, value)
|
|
399
|
+
|
|
222
400
|
|
|
223
401
|
TeamRunOutputEvent = Union[
|
|
224
402
|
RunStartedEvent,
|
|
225
403
|
RunContentEvent,
|
|
226
404
|
IntermediateRunContentEvent,
|
|
405
|
+
RunContentCompletedEvent,
|
|
227
406
|
RunCompletedEvent,
|
|
228
407
|
RunErrorEvent,
|
|
229
408
|
RunCancelledEvent,
|
|
409
|
+
PreHookStartedEvent,
|
|
410
|
+
PreHookCompletedEvent,
|
|
230
411
|
ReasoningStartedEvent,
|
|
231
412
|
ReasoningStepEvent,
|
|
232
413
|
ReasoningCompletedEvent,
|
|
233
414
|
MemoryUpdateStartedEvent,
|
|
234
415
|
MemoryUpdateCompletedEvent,
|
|
416
|
+
SessionSummaryStartedEvent,
|
|
417
|
+
SessionSummaryCompletedEvent,
|
|
235
418
|
ToolCallStartedEvent,
|
|
236
419
|
ToolCallCompletedEvent,
|
|
237
420
|
ParserModelResponseStartedEvent,
|
|
@@ -246,14 +429,21 @@ TEAM_RUN_EVENT_TYPE_REGISTRY = {
|
|
|
246
429
|
TeamRunEvent.run_started.value: RunStartedEvent,
|
|
247
430
|
TeamRunEvent.run_content.value: RunContentEvent,
|
|
248
431
|
TeamRunEvent.run_intermediate_content.value: IntermediateRunContentEvent,
|
|
432
|
+
TeamRunEvent.run_content_completed.value: RunContentCompletedEvent,
|
|
249
433
|
TeamRunEvent.run_completed.value: RunCompletedEvent,
|
|
250
434
|
TeamRunEvent.run_error.value: RunErrorEvent,
|
|
251
435
|
TeamRunEvent.run_cancelled.value: RunCancelledEvent,
|
|
436
|
+
TeamRunEvent.pre_hook_started.value: PreHookStartedEvent,
|
|
437
|
+
TeamRunEvent.pre_hook_completed.value: PreHookCompletedEvent,
|
|
438
|
+
TeamRunEvent.post_hook_started.value: PostHookStartedEvent,
|
|
439
|
+
TeamRunEvent.post_hook_completed.value: PostHookCompletedEvent,
|
|
252
440
|
TeamRunEvent.reasoning_started.value: ReasoningStartedEvent,
|
|
253
441
|
TeamRunEvent.reasoning_step.value: ReasoningStepEvent,
|
|
254
442
|
TeamRunEvent.reasoning_completed.value: ReasoningCompletedEvent,
|
|
255
443
|
TeamRunEvent.memory_update_started.value: MemoryUpdateStartedEvent,
|
|
256
444
|
TeamRunEvent.memory_update_completed.value: MemoryUpdateCompletedEvent,
|
|
445
|
+
TeamRunEvent.session_summary_started.value: SessionSummaryStartedEvent,
|
|
446
|
+
TeamRunEvent.session_summary_completed.value: SessionSummaryCompletedEvent,
|
|
257
447
|
TeamRunEvent.tool_call_started.value: ToolCallStartedEvent,
|
|
258
448
|
TeamRunEvent.tool_call_completed.value: ToolCallCompletedEvent,
|
|
259
449
|
TeamRunEvent.parser_model_response_started.value: ParserModelResponseStartedEvent,
|
|
@@ -275,82 +465,23 @@ def team_run_output_event_from_dict(data: dict) -> BaseTeamRunEvent:
|
|
|
275
465
|
return event_class.from_dict(data) # type: ignore
|
|
276
466
|
|
|
277
467
|
|
|
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[Image]] = None
|
|
293
|
-
videos: Optional[Sequence[Video]] = None
|
|
294
|
-
audios: Optional[Sequence[Audio]] = 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 = [Image.model_validate(img_data) for img_data in data["images"]]
|
|
332
|
-
|
|
333
|
-
videos = None
|
|
334
|
-
if data.get("videos"):
|
|
335
|
-
videos = [Video.model_validate(vid_data) for vid_data in data["videos"]]
|
|
336
|
-
|
|
337
|
-
audios = None
|
|
338
|
-
if data.get("audios"):
|
|
339
|
-
audios = [Audio.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
|
-
|
|
348
468
|
@dataclass
|
|
349
469
|
class TeamRunOutput:
|
|
350
470
|
"""Response returned by Team.run() functions"""
|
|
351
471
|
|
|
472
|
+
run_id: Optional[str] = None
|
|
473
|
+
team_id: Optional[str] = None
|
|
474
|
+
team_name: Optional[str] = None
|
|
475
|
+
session_id: Optional[str] = None
|
|
476
|
+
parent_run_id: Optional[str] = None
|
|
477
|
+
user_id: Optional[str] = None
|
|
478
|
+
|
|
479
|
+
# Input media and messages from user
|
|
480
|
+
input: Optional[TeamRunInput] = None
|
|
481
|
+
|
|
352
482
|
content: Optional[Any] = None
|
|
353
483
|
content_type: str = "str"
|
|
484
|
+
|
|
354
485
|
messages: Optional[List[Message]] = None
|
|
355
486
|
metrics: Optional[Metrics] = None
|
|
356
487
|
model: Optional[str] = None
|
|
@@ -358,28 +489,21 @@ class TeamRunOutput:
|
|
|
358
489
|
|
|
359
490
|
member_responses: List[Union["TeamRunOutput", RunOutput]] = field(default_factory=list)
|
|
360
491
|
|
|
361
|
-
run_id: Optional[str] = None
|
|
362
|
-
team_id: Optional[str] = None
|
|
363
|
-
team_name: Optional[str] = None
|
|
364
|
-
session_id: Optional[str] = None
|
|
365
|
-
parent_run_id: Optional[str] = None
|
|
366
|
-
|
|
367
492
|
tools: Optional[List[ToolExecution]] = None
|
|
368
493
|
|
|
369
494
|
images: Optional[List[Image]] = None # Images from member runs
|
|
370
495
|
videos: Optional[List[Video]] = None # Videos from member runs
|
|
371
496
|
audio: Optional[List[Audio]] = None # Audio from member runs
|
|
497
|
+
files: Optional[List[File]] = None # Files from member runs
|
|
372
498
|
|
|
373
499
|
response_audio: Optional[Audio] = None # Model audio response
|
|
374
500
|
|
|
375
|
-
# Input media and messages from user
|
|
376
|
-
input: Optional[TeamRunInput] = None
|
|
377
|
-
|
|
378
501
|
reasoning_content: Optional[str] = None
|
|
379
502
|
|
|
380
503
|
citations: Optional[Citations] = None
|
|
381
|
-
|
|
504
|
+
model_provider_data: Optional[Dict[str, Any]] = None
|
|
382
505
|
metadata: Optional[Dict[str, Any]] = None
|
|
506
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
383
507
|
|
|
384
508
|
references: Optional[List[MessageReferences]] = None
|
|
385
509
|
additional_input: Optional[List[Message]] = None
|
|
@@ -418,6 +542,7 @@ class TeamRunOutput:
|
|
|
418
542
|
"images",
|
|
419
543
|
"videos",
|
|
420
544
|
"audio",
|
|
545
|
+
"files",
|
|
421
546
|
"response_audio",
|
|
422
547
|
"citations",
|
|
423
548
|
"events",
|
|
@@ -460,6 +585,9 @@ class TeamRunOutput:
|
|
|
460
585
|
if self.audio is not None:
|
|
461
586
|
_dict["audio"] = [aud.to_dict() for aud in self.audio]
|
|
462
587
|
|
|
588
|
+
if self.files is not None:
|
|
589
|
+
_dict["files"] = [file.to_dict() for file in self.files]
|
|
590
|
+
|
|
463
591
|
if self.response_audio is not None:
|
|
464
592
|
_dict["response_audio"] = self.response_audio.to_dict()
|
|
465
593
|
|
|
@@ -488,12 +616,19 @@ class TeamRunOutput:
|
|
|
488
616
|
|
|
489
617
|
return _dict
|
|
490
618
|
|
|
491
|
-
def to_json(self) -> str:
|
|
619
|
+
def to_json(self, separators=(", ", ": "), indent: Optional[int] = 2) -> str:
|
|
492
620
|
import json
|
|
493
621
|
|
|
494
|
-
|
|
622
|
+
try:
|
|
623
|
+
_dict = self.to_dict()
|
|
624
|
+
except Exception:
|
|
625
|
+
log_error("Failed to convert response to json", exc_info=True)
|
|
626
|
+
raise
|
|
495
627
|
|
|
496
|
-
|
|
628
|
+
if indent is None:
|
|
629
|
+
return json.dumps(_dict, separators=separators)
|
|
630
|
+
else:
|
|
631
|
+
return json.dumps(_dict, indent=indent, separators=separators)
|
|
497
632
|
|
|
498
633
|
@classmethod
|
|
499
634
|
def from_dict(cls, data: Dict[str, Any]) -> "TeamRunOutput":
|
|
@@ -511,7 +646,7 @@ class TeamRunOutput:
|
|
|
511
646
|
events = final_events
|
|
512
647
|
|
|
513
648
|
messages = data.pop("messages", None)
|
|
514
|
-
messages = [Message.
|
|
649
|
+
messages = [Message.from_dict(message) for message in messages] if messages else None
|
|
515
650
|
|
|
516
651
|
member_responses = data.pop("member_responses", [])
|
|
517
652
|
parsed_member_responses: List[Union["TeamRunOutput", RunOutput]] = []
|
|
@@ -524,7 +659,7 @@ class TeamRunOutput:
|
|
|
524
659
|
|
|
525
660
|
additional_input = data.pop("additional_input", None)
|
|
526
661
|
if additional_input is not None:
|
|
527
|
-
additional_input = [Message.
|
|
662
|
+
additional_input = [Message.from_dict(message) for message in additional_input]
|
|
528
663
|
|
|
529
664
|
reasoning_steps = data.pop("reasoning_steps", None)
|
|
530
665
|
if reasoning_steps is not None:
|
|
@@ -532,26 +667,21 @@ class TeamRunOutput:
|
|
|
532
667
|
|
|
533
668
|
reasoning_messages = data.pop("reasoning_messages", None)
|
|
534
669
|
if reasoning_messages is not None:
|
|
535
|
-
reasoning_messages = [Message.
|
|
670
|
+
reasoning_messages = [Message.from_dict(message) for message in reasoning_messages]
|
|
536
671
|
|
|
537
672
|
references = data.pop("references", None)
|
|
538
673
|
if references is not None:
|
|
539
674
|
references = [MessageReferences.model_validate(reference) for reference in references]
|
|
540
675
|
|
|
541
|
-
images = data.pop("images", [])
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
videos = [Video.model_validate(video) for video in videos] if videos else None
|
|
546
|
-
|
|
547
|
-
audio = data.pop("audio", [])
|
|
548
|
-
audio = [Audio.model_validate(audio) for audio in audio] if audio else None
|
|
676
|
+
images = reconstruct_images(data.pop("images", []))
|
|
677
|
+
videos = reconstruct_videos(data.pop("videos", []))
|
|
678
|
+
audio = reconstruct_audio_list(data.pop("audio", []))
|
|
679
|
+
files = reconstruct_files(data.pop("files", []))
|
|
549
680
|
|
|
550
681
|
tools = data.pop("tools", [])
|
|
551
682
|
tools = [ToolExecution.from_dict(tool) for tool in tools] if tools else None
|
|
552
683
|
|
|
553
|
-
response_audio = data.pop("response_audio", None)
|
|
554
|
-
response_audio = Audio.model_validate(response_audio) if response_audio else None
|
|
684
|
+
response_audio = reconstruct_response_audio(data.pop("response_audio", None))
|
|
555
685
|
|
|
556
686
|
input_data = data.pop("input", None)
|
|
557
687
|
input_obj = None
|
|
@@ -565,6 +695,12 @@ class TeamRunOutput:
|
|
|
565
695
|
citations = data.pop("citations", None)
|
|
566
696
|
citations = Citations.model_validate(citations) if citations else None
|
|
567
697
|
|
|
698
|
+
# Filter data to only include fields that are actually defined in the TeamRunOutput dataclass
|
|
699
|
+
from dataclasses import fields
|
|
700
|
+
|
|
701
|
+
supported_fields = {f.name for f in fields(cls)}
|
|
702
|
+
filtered_data = {k: v for k, v in data.items() if k in supported_fields}
|
|
703
|
+
|
|
568
704
|
return cls(
|
|
569
705
|
messages=messages,
|
|
570
706
|
metrics=metrics,
|
|
@@ -576,12 +712,13 @@ class TeamRunOutput:
|
|
|
576
712
|
images=images,
|
|
577
713
|
videos=videos,
|
|
578
714
|
audio=audio,
|
|
715
|
+
files=files,
|
|
579
716
|
response_audio=response_audio,
|
|
580
717
|
input=input_obj,
|
|
581
718
|
citations=citations,
|
|
582
719
|
tools=tools,
|
|
583
720
|
events=events,
|
|
584
|
-
**
|
|
721
|
+
**filtered_data,
|
|
585
722
|
)
|
|
586
723
|
|
|
587
724
|
def get_content_as_string(self, **kwargs) -> str:
|
|
@@ -610,3 +747,7 @@ class TeamRunOutput:
|
|
|
610
747
|
if self.audio is None:
|
|
611
748
|
self.audio = []
|
|
612
749
|
self.audio.extend(run_response.audio)
|
|
750
|
+
if run_response.files is not None:
|
|
751
|
+
if self.files is None:
|
|
752
|
+
self.files = []
|
|
753
|
+
self.files.extend(run_response.files)
|