agno 2.1.2__py3-none-any.whl → 2.3.13__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.
Files changed (314) hide show
  1. agno/agent/agent.py +5540 -2273
  2. agno/api/api.py +2 -0
  3. agno/api/os.py +1 -1
  4. agno/compression/__init__.py +3 -0
  5. agno/compression/manager.py +247 -0
  6. agno/culture/__init__.py +3 -0
  7. agno/culture/manager.py +956 -0
  8. agno/db/async_postgres/__init__.py +3 -0
  9. agno/db/base.py +689 -6
  10. agno/db/dynamo/dynamo.py +933 -37
  11. agno/db/dynamo/schemas.py +174 -10
  12. agno/db/dynamo/utils.py +63 -4
  13. agno/db/firestore/firestore.py +831 -9
  14. agno/db/firestore/schemas.py +51 -0
  15. agno/db/firestore/utils.py +102 -4
  16. agno/db/gcs_json/gcs_json_db.py +660 -12
  17. agno/db/gcs_json/utils.py +60 -26
  18. agno/db/in_memory/in_memory_db.py +287 -14
  19. agno/db/in_memory/utils.py +60 -2
  20. agno/db/json/json_db.py +590 -14
  21. agno/db/json/utils.py +60 -26
  22. agno/db/migrations/manager.py +199 -0
  23. agno/db/migrations/v1_to_v2.py +43 -13
  24. agno/db/migrations/versions/__init__.py +0 -0
  25. agno/db/migrations/versions/v2_3_0.py +938 -0
  26. agno/db/mongo/__init__.py +15 -1
  27. agno/db/mongo/async_mongo.py +2760 -0
  28. agno/db/mongo/mongo.py +879 -11
  29. agno/db/mongo/schemas.py +42 -0
  30. agno/db/mongo/utils.py +80 -8
  31. agno/db/mysql/__init__.py +2 -1
  32. agno/db/mysql/async_mysql.py +2912 -0
  33. agno/db/mysql/mysql.py +946 -68
  34. agno/db/mysql/schemas.py +72 -10
  35. agno/db/mysql/utils.py +198 -7
  36. agno/db/postgres/__init__.py +2 -1
  37. agno/db/postgres/async_postgres.py +2579 -0
  38. agno/db/postgres/postgres.py +942 -57
  39. agno/db/postgres/schemas.py +81 -18
  40. agno/db/postgres/utils.py +164 -2
  41. agno/db/redis/redis.py +671 -7
  42. agno/db/redis/schemas.py +50 -0
  43. agno/db/redis/utils.py +65 -7
  44. agno/db/schemas/__init__.py +2 -1
  45. agno/db/schemas/culture.py +120 -0
  46. agno/db/schemas/evals.py +1 -0
  47. agno/db/schemas/memory.py +17 -2
  48. agno/db/singlestore/schemas.py +63 -0
  49. agno/db/singlestore/singlestore.py +949 -83
  50. agno/db/singlestore/utils.py +60 -2
  51. agno/db/sqlite/__init__.py +2 -1
  52. agno/db/sqlite/async_sqlite.py +2911 -0
  53. agno/db/sqlite/schemas.py +62 -0
  54. agno/db/sqlite/sqlite.py +965 -46
  55. agno/db/sqlite/utils.py +169 -8
  56. agno/db/surrealdb/__init__.py +3 -0
  57. agno/db/surrealdb/metrics.py +292 -0
  58. agno/db/surrealdb/models.py +334 -0
  59. agno/db/surrealdb/queries.py +71 -0
  60. agno/db/surrealdb/surrealdb.py +1908 -0
  61. agno/db/surrealdb/utils.py +147 -0
  62. agno/db/utils.py +2 -0
  63. agno/eval/__init__.py +10 -0
  64. agno/eval/accuracy.py +75 -55
  65. agno/eval/agent_as_judge.py +861 -0
  66. agno/eval/base.py +29 -0
  67. agno/eval/performance.py +16 -7
  68. agno/eval/reliability.py +28 -16
  69. agno/eval/utils.py +35 -17
  70. agno/exceptions.py +27 -2
  71. agno/filters.py +354 -0
  72. agno/guardrails/prompt_injection.py +1 -0
  73. agno/hooks/__init__.py +3 -0
  74. agno/hooks/decorator.py +164 -0
  75. agno/integrations/discord/client.py +1 -1
  76. agno/knowledge/chunking/agentic.py +13 -10
  77. agno/knowledge/chunking/fixed.py +4 -1
  78. agno/knowledge/chunking/semantic.py +9 -4
  79. agno/knowledge/chunking/strategy.py +59 -15
  80. agno/knowledge/embedder/fastembed.py +1 -1
  81. agno/knowledge/embedder/nebius.py +1 -1
  82. agno/knowledge/embedder/ollama.py +8 -0
  83. agno/knowledge/embedder/openai.py +8 -8
  84. agno/knowledge/embedder/sentence_transformer.py +6 -2
  85. agno/knowledge/embedder/vllm.py +262 -0
  86. agno/knowledge/knowledge.py +1618 -318
  87. agno/knowledge/reader/base.py +6 -2
  88. agno/knowledge/reader/csv_reader.py +8 -10
  89. agno/knowledge/reader/docx_reader.py +5 -6
  90. agno/knowledge/reader/field_labeled_csv_reader.py +16 -20
  91. agno/knowledge/reader/json_reader.py +5 -4
  92. agno/knowledge/reader/markdown_reader.py +8 -8
  93. agno/knowledge/reader/pdf_reader.py +17 -19
  94. agno/knowledge/reader/pptx_reader.py +101 -0
  95. agno/knowledge/reader/reader_factory.py +32 -3
  96. agno/knowledge/reader/s3_reader.py +3 -3
  97. agno/knowledge/reader/tavily_reader.py +193 -0
  98. agno/knowledge/reader/text_reader.py +22 -10
  99. agno/knowledge/reader/web_search_reader.py +1 -48
  100. agno/knowledge/reader/website_reader.py +10 -10
  101. agno/knowledge/reader/wikipedia_reader.py +33 -1
  102. agno/knowledge/types.py +1 -0
  103. agno/knowledge/utils.py +72 -7
  104. agno/media.py +22 -6
  105. agno/memory/__init__.py +14 -1
  106. agno/memory/manager.py +544 -83
  107. agno/memory/strategies/__init__.py +15 -0
  108. agno/memory/strategies/base.py +66 -0
  109. agno/memory/strategies/summarize.py +196 -0
  110. agno/memory/strategies/types.py +37 -0
  111. agno/models/aimlapi/aimlapi.py +17 -0
  112. agno/models/anthropic/claude.py +515 -40
  113. agno/models/aws/bedrock.py +102 -21
  114. agno/models/aws/claude.py +131 -274
  115. agno/models/azure/ai_foundry.py +41 -19
  116. agno/models/azure/openai_chat.py +39 -8
  117. agno/models/base.py +1249 -525
  118. agno/models/cerebras/cerebras.py +91 -21
  119. agno/models/cerebras/cerebras_openai.py +21 -2
  120. agno/models/cohere/chat.py +40 -6
  121. agno/models/cometapi/cometapi.py +18 -1
  122. agno/models/dashscope/dashscope.py +2 -3
  123. agno/models/deepinfra/deepinfra.py +18 -1
  124. agno/models/deepseek/deepseek.py +69 -3
  125. agno/models/fireworks/fireworks.py +18 -1
  126. agno/models/google/gemini.py +877 -80
  127. agno/models/google/utils.py +22 -0
  128. agno/models/groq/groq.py +51 -18
  129. agno/models/huggingface/huggingface.py +17 -6
  130. agno/models/ibm/watsonx.py +16 -6
  131. agno/models/internlm/internlm.py +18 -1
  132. agno/models/langdb/langdb.py +13 -1
  133. agno/models/litellm/chat.py +44 -9
  134. agno/models/litellm/litellm_openai.py +18 -1
  135. agno/models/message.py +28 -5
  136. agno/models/meta/llama.py +47 -14
  137. agno/models/meta/llama_openai.py +22 -17
  138. agno/models/mistral/mistral.py +8 -4
  139. agno/models/nebius/nebius.py +6 -7
  140. agno/models/nvidia/nvidia.py +20 -3
  141. agno/models/ollama/chat.py +24 -8
  142. agno/models/openai/chat.py +104 -29
  143. agno/models/openai/responses.py +101 -81
  144. agno/models/openrouter/openrouter.py +60 -3
  145. agno/models/perplexity/perplexity.py +17 -1
  146. agno/models/portkey/portkey.py +7 -6
  147. agno/models/requesty/requesty.py +24 -4
  148. agno/models/response.py +73 -2
  149. agno/models/sambanova/sambanova.py +20 -3
  150. agno/models/siliconflow/siliconflow.py +19 -2
  151. agno/models/together/together.py +20 -3
  152. agno/models/utils.py +254 -8
  153. agno/models/vercel/v0.py +20 -3
  154. agno/models/vertexai/__init__.py +0 -0
  155. agno/models/vertexai/claude.py +190 -0
  156. agno/models/vllm/vllm.py +19 -14
  157. agno/models/xai/xai.py +19 -2
  158. agno/os/app.py +549 -152
  159. agno/os/auth.py +190 -3
  160. agno/os/config.py +23 -0
  161. agno/os/interfaces/a2a/router.py +8 -11
  162. agno/os/interfaces/a2a/utils.py +1 -1
  163. agno/os/interfaces/agui/router.py +18 -3
  164. agno/os/interfaces/agui/utils.py +152 -39
  165. agno/os/interfaces/slack/router.py +55 -37
  166. agno/os/interfaces/slack/slack.py +9 -1
  167. agno/os/interfaces/whatsapp/router.py +0 -1
  168. agno/os/interfaces/whatsapp/security.py +3 -1
  169. agno/os/mcp.py +110 -52
  170. agno/os/middleware/__init__.py +2 -0
  171. agno/os/middleware/jwt.py +676 -112
  172. agno/os/router.py +40 -1478
  173. agno/os/routers/agents/__init__.py +3 -0
  174. agno/os/routers/agents/router.py +599 -0
  175. agno/os/routers/agents/schema.py +261 -0
  176. agno/os/routers/evals/evals.py +96 -39
  177. agno/os/routers/evals/schemas.py +65 -33
  178. agno/os/routers/evals/utils.py +80 -10
  179. agno/os/routers/health.py +10 -4
  180. agno/os/routers/knowledge/knowledge.py +196 -38
  181. agno/os/routers/knowledge/schemas.py +82 -22
  182. agno/os/routers/memory/memory.py +279 -52
  183. agno/os/routers/memory/schemas.py +46 -17
  184. agno/os/routers/metrics/metrics.py +20 -8
  185. agno/os/routers/metrics/schemas.py +16 -16
  186. agno/os/routers/session/session.py +462 -34
  187. agno/os/routers/teams/__init__.py +3 -0
  188. agno/os/routers/teams/router.py +512 -0
  189. agno/os/routers/teams/schema.py +257 -0
  190. agno/os/routers/traces/__init__.py +3 -0
  191. agno/os/routers/traces/schemas.py +414 -0
  192. agno/os/routers/traces/traces.py +499 -0
  193. agno/os/routers/workflows/__init__.py +3 -0
  194. agno/os/routers/workflows/router.py +624 -0
  195. agno/os/routers/workflows/schema.py +75 -0
  196. agno/os/schema.py +256 -693
  197. agno/os/scopes.py +469 -0
  198. agno/os/utils.py +514 -36
  199. agno/reasoning/anthropic.py +80 -0
  200. agno/reasoning/gemini.py +73 -0
  201. agno/reasoning/openai.py +5 -0
  202. agno/reasoning/vertexai.py +76 -0
  203. agno/run/__init__.py +6 -0
  204. agno/run/agent.py +155 -32
  205. agno/run/base.py +55 -3
  206. agno/run/requirement.py +181 -0
  207. agno/run/team.py +125 -38
  208. agno/run/workflow.py +72 -18
  209. agno/session/agent.py +102 -89
  210. agno/session/summary.py +56 -15
  211. agno/session/team.py +164 -90
  212. agno/session/workflow.py +405 -40
  213. agno/table.py +10 -0
  214. agno/team/team.py +3974 -1903
  215. agno/tools/dalle.py +2 -4
  216. agno/tools/eleven_labs.py +23 -25
  217. agno/tools/exa.py +21 -16
  218. agno/tools/file.py +153 -23
  219. agno/tools/file_generation.py +16 -10
  220. agno/tools/firecrawl.py +15 -7
  221. agno/tools/function.py +193 -38
  222. agno/tools/gmail.py +238 -14
  223. agno/tools/google_drive.py +271 -0
  224. agno/tools/googlecalendar.py +36 -8
  225. agno/tools/googlesheets.py +20 -5
  226. agno/tools/jira.py +20 -0
  227. agno/tools/mcp/__init__.py +10 -0
  228. agno/tools/mcp/mcp.py +331 -0
  229. agno/tools/mcp/multi_mcp.py +347 -0
  230. agno/tools/mcp/params.py +24 -0
  231. agno/tools/mcp_toolbox.py +3 -3
  232. agno/tools/models/nebius.py +5 -5
  233. agno/tools/models_labs.py +20 -10
  234. agno/tools/nano_banana.py +151 -0
  235. agno/tools/notion.py +204 -0
  236. agno/tools/parallel.py +314 -0
  237. agno/tools/postgres.py +76 -36
  238. agno/tools/redshift.py +406 -0
  239. agno/tools/scrapegraph.py +1 -1
  240. agno/tools/shopify.py +1519 -0
  241. agno/tools/slack.py +18 -3
  242. agno/tools/spotify.py +919 -0
  243. agno/tools/tavily.py +146 -0
  244. agno/tools/toolkit.py +25 -0
  245. agno/tools/workflow.py +8 -1
  246. agno/tools/yfinance.py +12 -11
  247. agno/tracing/__init__.py +12 -0
  248. agno/tracing/exporter.py +157 -0
  249. agno/tracing/schemas.py +276 -0
  250. agno/tracing/setup.py +111 -0
  251. agno/utils/agent.py +938 -0
  252. agno/utils/cryptography.py +22 -0
  253. agno/utils/dttm.py +33 -0
  254. agno/utils/events.py +151 -3
  255. agno/utils/gemini.py +15 -5
  256. agno/utils/hooks.py +118 -4
  257. agno/utils/http.py +113 -2
  258. agno/utils/knowledge.py +12 -5
  259. agno/utils/log.py +1 -0
  260. agno/utils/mcp.py +92 -2
  261. agno/utils/media.py +187 -1
  262. agno/utils/merge_dict.py +3 -3
  263. agno/utils/message.py +60 -0
  264. agno/utils/models/ai_foundry.py +9 -2
  265. agno/utils/models/claude.py +49 -14
  266. agno/utils/models/cohere.py +9 -2
  267. agno/utils/models/llama.py +9 -2
  268. agno/utils/models/mistral.py +4 -2
  269. agno/utils/print_response/agent.py +109 -16
  270. agno/utils/print_response/team.py +223 -30
  271. agno/utils/print_response/workflow.py +251 -34
  272. agno/utils/streamlit.py +1 -1
  273. agno/utils/team.py +98 -9
  274. agno/utils/tokens.py +657 -0
  275. agno/vectordb/base.py +39 -7
  276. agno/vectordb/cassandra/cassandra.py +21 -5
  277. agno/vectordb/chroma/chromadb.py +43 -12
  278. agno/vectordb/clickhouse/clickhousedb.py +21 -5
  279. agno/vectordb/couchbase/couchbase.py +29 -5
  280. agno/vectordb/lancedb/lance_db.py +92 -181
  281. agno/vectordb/langchaindb/langchaindb.py +24 -4
  282. agno/vectordb/lightrag/lightrag.py +17 -3
  283. agno/vectordb/llamaindex/llamaindexdb.py +25 -5
  284. agno/vectordb/milvus/milvus.py +50 -37
  285. agno/vectordb/mongodb/__init__.py +7 -1
  286. agno/vectordb/mongodb/mongodb.py +36 -30
  287. agno/vectordb/pgvector/pgvector.py +201 -77
  288. agno/vectordb/pineconedb/pineconedb.py +41 -23
  289. agno/vectordb/qdrant/qdrant.py +67 -54
  290. agno/vectordb/redis/__init__.py +9 -0
  291. agno/vectordb/redis/redisdb.py +682 -0
  292. agno/vectordb/singlestore/singlestore.py +50 -29
  293. agno/vectordb/surrealdb/surrealdb.py +31 -41
  294. agno/vectordb/upstashdb/upstashdb.py +34 -6
  295. agno/vectordb/weaviate/weaviate.py +53 -14
  296. agno/workflow/__init__.py +2 -0
  297. agno/workflow/agent.py +299 -0
  298. agno/workflow/condition.py +120 -18
  299. agno/workflow/loop.py +77 -10
  300. agno/workflow/parallel.py +231 -143
  301. agno/workflow/router.py +118 -17
  302. agno/workflow/step.py +609 -170
  303. agno/workflow/steps.py +73 -6
  304. agno/workflow/types.py +96 -21
  305. agno/workflow/workflow.py +2039 -262
  306. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/METADATA +201 -66
  307. agno-2.3.13.dist-info/RECORD +613 -0
  308. agno/tools/googlesearch.py +0 -98
  309. agno/tools/mcp.py +0 -679
  310. agno/tools/memori.py +0 -339
  311. agno-2.1.2.dist-info/RECORD +0 -543
  312. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +0 -0
  313. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/licenses/LICENSE +0 -0
  314. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/models/response.py CHANGED
@@ -35,9 +35,9 @@ class ToolExecution:
35
35
  # If True, the agent will stop executing after this tool call.
36
36
  stop_after_tool_call: bool = False
37
37
 
38
- created_at: int = int(time())
38
+ created_at: int = field(default_factory=lambda: int(time()))
39
39
 
40
- # User control flow requirements
40
+ # User control flow (HITL) fields
41
41
  requires_confirmation: Optional[bool] = None
42
42
  confirmed: Optional[bool] = None
43
43
  confirmation_note: Optional[str] = None
@@ -81,6 +81,7 @@ class ToolExecution:
81
81
  else None,
82
82
  external_execution_required=data.get("external_execution_required"),
83
83
  metrics=Metrics(**(data.get("metrics", {}) or {})),
84
+ **{"created_at": data["created_at"]} if "created_at" in data else {},
84
85
  )
85
86
 
86
87
 
@@ -123,8 +124,78 @@ class ModelResponse:
123
124
 
124
125
  updated_session_state: Optional[Dict[str, Any]] = None
125
126
 
127
+ def to_dict(self) -> Dict[str, Any]:
128
+ """Serialize ModelResponse to dictionary for caching."""
129
+ _dict = asdict(self)
130
+
131
+ # Handle special serialization for audio
132
+ if self.audio is not None:
133
+ _dict["audio"] = self.audio.to_dict()
134
+
135
+ # Handle lists of media objects
136
+ if self.images is not None:
137
+ _dict["images"] = [img.to_dict() for img in self.images]
138
+ if self.videos is not None:
139
+ _dict["videos"] = [vid.to_dict() for vid in self.videos]
140
+ if self.audios is not None:
141
+ _dict["audios"] = [aud.to_dict() for aud in self.audios]
142
+ if self.files is not None:
143
+ _dict["files"] = [f.to_dict() for f in self.files]
144
+
145
+ # Handle tool executions
146
+ if self.tool_executions is not None:
147
+ _dict["tool_executions"] = [tool_execution.to_dict() for tool_execution in self.tool_executions]
148
+
149
+ # Handle response usage which might be a Pydantic BaseModel
150
+ response_usage = _dict.pop("response_usage", None)
151
+ if response_usage is not None:
152
+ try:
153
+ from pydantic import BaseModel
154
+
155
+ if isinstance(response_usage, BaseModel):
156
+ _dict["response_usage"] = response_usage.model_dump()
157
+ else:
158
+ _dict["response_usage"] = response_usage
159
+ except ImportError:
160
+ _dict["response_usage"] = response_usage
161
+
162
+ return _dict
163
+
164
+ @classmethod
165
+ def from_dict(cls, data: Dict[str, Any]) -> "ModelResponse":
166
+ """Reconstruct ModelResponse from cached dictionary."""
167
+ # Reconstruct media objects
168
+ if data.get("audio"):
169
+ data["audio"] = Audio(**data["audio"])
170
+
171
+ if data.get("images"):
172
+ data["images"] = [Image(**img) for img in data["images"]]
173
+ if data.get("videos"):
174
+ data["videos"] = [Video(**vid) for vid in data["videos"]]
175
+ if data.get("audios"):
176
+ data["audios"] = [Audio(**aud) for aud in data["audios"]]
177
+ if data.get("files"):
178
+ data["files"] = [File(**f) for f in data["files"]]
179
+
180
+ # Reconstruct tool executions
181
+ if data.get("tool_executions"):
182
+ data["tool_executions"] = [ToolExecution.from_dict(te) for te in data["tool_executions"]]
183
+
184
+ # Reconstruct citations
185
+ if data.get("citations") and isinstance(data["citations"], dict):
186
+ data["citations"] = Citations(**data["citations"])
187
+
188
+ # Reconstruct response usage (Metrics)
189
+ if data.get("response_usage") and isinstance(data["response_usage"], dict):
190
+ from agno.models.metrics import Metrics
191
+
192
+ data["response_usage"] = Metrics(**data["response_usage"])
193
+
194
+ return cls(**data)
195
+
126
196
 
127
197
  class FileType(str, Enum):
128
198
  MP4 = "mp4"
129
199
  GIF = "gif"
130
200
  MP3 = "mp3"
201
+ WAV = "wav"
@@ -1,7 +1,8 @@
1
- from dataclasses import dataclass, field
1
+ from dataclasses import dataclass
2
2
  from os import getenv
3
- from typing import Optional
3
+ from typing import Any, Dict, Optional
4
4
 
5
+ from agno.exceptions import ModelAuthenticationError
5
6
  from agno.models.openai.like import OpenAILike
6
7
 
7
8
 
@@ -22,7 +23,23 @@ class Sambanova(OpenAILike):
22
23
  name: str = "Sambanova"
23
24
  provider: str = "Sambanova"
24
25
 
25
- api_key: Optional[str] = field(default_factory=lambda: getenv("SAMBANOVA_API_KEY"))
26
+ api_key: Optional[str] = None
26
27
  base_url: str = "https://api.sambanova.ai/v1"
27
28
 
28
29
  supports_native_structured_outputs: bool = False
30
+
31
+ def _get_client_params(self) -> Dict[str, Any]:
32
+ """
33
+ Returns client parameters for API requests, checking for SAMBANOVA_API_KEY.
34
+
35
+ Returns:
36
+ Dict[str, Any]: A dictionary of client parameters for API requests.
37
+ """
38
+ if not self.api_key:
39
+ self.api_key = getenv("SAMBANOVA_API_KEY")
40
+ if not self.api_key:
41
+ raise ModelAuthenticationError(
42
+ message="SAMBANOVA_API_KEY not set. Please set the SAMBANOVA_API_KEY environment variable.",
43
+ model_name=self.name,
44
+ )
45
+ return super()._get_client_params()
@@ -1,7 +1,8 @@
1
1
  from dataclasses import dataclass
2
2
  from os import getenv
3
- from typing import Optional
3
+ from typing import Any, Dict, Optional
4
4
 
5
+ from agno.exceptions import ModelAuthenticationError
5
6
  from agno.models.openai.like import OpenAILike
6
7
 
7
8
 
@@ -21,5 +22,21 @@ class Siliconflow(OpenAILike):
21
22
  id: str = "Qwen/QwQ-32B"
22
23
  name: str = "Siliconflow"
23
24
  provider: str = "Siliconflow"
24
- api_key: Optional[str] = getenv("SILICONFLOW_API_KEY")
25
+ api_key: Optional[str] = None
25
26
  base_url: str = "https://api.siliconflow.com/v1"
27
+
28
+ def _get_client_params(self) -> Dict[str, Any]:
29
+ """
30
+ Returns client parameters for API requests, checking for SILICONFLOW_API_KEY.
31
+
32
+ Returns:
33
+ Dict[str, Any]: A dictionary of client parameters for API requests.
34
+ """
35
+ if not self.api_key:
36
+ self.api_key = getenv("SILICONFLOW_API_KEY")
37
+ if not self.api_key:
38
+ raise ModelAuthenticationError(
39
+ message="SILICONFLOW_API_KEY not set. Please set the SILICONFLOW_API_KEY environment variable.",
40
+ model_name=self.name,
41
+ )
42
+ return super()._get_client_params()
@@ -1,7 +1,8 @@
1
- from dataclasses import dataclass, field
1
+ from dataclasses import dataclass
2
2
  from os import getenv
3
- from typing import Optional
3
+ from typing import Any, Dict, Optional
4
4
 
5
+ from agno.exceptions import ModelAuthenticationError
5
6
  from agno.models.openai.like import OpenAILike
6
7
 
7
8
 
@@ -21,5 +22,21 @@ class Together(OpenAILike):
21
22
  id: str = "mistralai/Mixtral-8x7B-Instruct-v0.1"
22
23
  name: str = "Together"
23
24
  provider: str = "Together"
24
- api_key: Optional[str] = field(default_factory=lambda: getenv("TOGETHER_API_KEY"))
25
+ api_key: Optional[str] = None
25
26
  base_url: str = "https://api.together.xyz/v1"
27
+
28
+ def _get_client_params(self) -> Dict[str, Any]:
29
+ """
30
+ Returns client parameters for API requests, checking for TOGETHER_API_KEY.
31
+
32
+ Returns:
33
+ Dict[str, Any]: A dictionary of client parameters for API requests.
34
+ """
35
+ if not self.api_key:
36
+ self.api_key = getenv("TOGETHER_API_KEY")
37
+ if not self.api_key:
38
+ raise ModelAuthenticationError(
39
+ message="TOGETHER_API_KEY not set. Please set the TOGETHER_API_KEY environment variable.",
40
+ model_name=self.name,
41
+ )
42
+ return super()._get_client_params()
agno/models/utils.py CHANGED
@@ -1,20 +1,266 @@
1
+ from typing import Optional, Union
2
+
1
3
  from agno.models.base import Model
2
4
 
3
5
 
4
- # TODO: add all supported models
5
- def get_model(model_id: str, model_provider: str) -> Model:
6
- """Return the right Agno model instance given a pair of model provider and id"""
7
- if model_provider == "openai":
8
- from agno.models.openai import OpenAIChat
6
+ def _get_model_class(model_id: str, model_provider: str) -> Model:
7
+ if model_provider == "aimlapi":
8
+ from agno.models.aimlapi import AIMLAPI
9
+
10
+ return AIMLAPI(id=model_id)
9
11
 
10
- return OpenAIChat(id=model_id)
11
12
  elif model_provider == "anthropic":
12
13
  from agno.models.anthropic import Claude
13
14
 
14
15
  return Claude(id=model_id)
15
- elif model_provider == "gemini":
16
+
17
+ elif model_provider == "aws-bedrock":
18
+ from agno.models.aws import AwsBedrock
19
+
20
+ return AwsBedrock(id=model_id)
21
+
22
+ elif model_provider == "aws-claude":
23
+ from agno.models.aws import Claude as AWSClaude
24
+
25
+ return AWSClaude(id=model_id)
26
+
27
+ elif model_provider == "azure-ai-foundry":
28
+ from agno.models.azure import AzureAIFoundry
29
+
30
+ return AzureAIFoundry(id=model_id)
31
+
32
+ elif model_provider == "azure-openai":
33
+ from agno.models.azure import AzureOpenAI
34
+
35
+ return AzureOpenAI(id=model_id)
36
+
37
+ elif model_provider == "cerebras":
38
+ from agno.models.cerebras import Cerebras
39
+
40
+ return Cerebras(id=model_id)
41
+
42
+ elif model_provider == "cerebras-openai":
43
+ from agno.models.cerebras import CerebrasOpenAI
44
+
45
+ return CerebrasOpenAI(id=model_id)
46
+
47
+ elif model_provider == "cohere":
48
+ from agno.models.cohere import Cohere
49
+
50
+ return Cohere(id=model_id)
51
+
52
+ elif model_provider == "cometapi":
53
+ from agno.models.cometapi import CometAPI
54
+
55
+ return CometAPI(id=model_id)
56
+
57
+ elif model_provider == "dashscope":
58
+ from agno.models.dashscope import DashScope
59
+
60
+ return DashScope(id=model_id)
61
+
62
+ elif model_provider == "deepinfra":
63
+ from agno.models.deepinfra import DeepInfra
64
+
65
+ return DeepInfra(id=model_id)
66
+
67
+ elif model_provider == "deepseek":
68
+ from agno.models.deepseek import DeepSeek
69
+
70
+ return DeepSeek(id=model_id)
71
+
72
+ elif model_provider == "fireworks":
73
+ from agno.models.fireworks import Fireworks
74
+
75
+ return Fireworks(id=model_id)
76
+
77
+ elif model_provider == "google":
16
78
  from agno.models.google import Gemini
17
79
 
18
80
  return Gemini(id=model_id)
81
+
82
+ elif model_provider == "groq":
83
+ from agno.models.groq import Groq
84
+
85
+ return Groq(id=model_id)
86
+
87
+ elif model_provider == "huggingface":
88
+ from agno.models.huggingface import HuggingFace
89
+
90
+ return HuggingFace(id=model_id)
91
+
92
+ elif model_provider == "ibm":
93
+ from agno.models.ibm import WatsonX
94
+
95
+ return WatsonX(id=model_id)
96
+
97
+ elif model_provider == "internlm":
98
+ from agno.models.internlm import InternLM
99
+
100
+ return InternLM(id=model_id)
101
+
102
+ elif model_provider == "langdb":
103
+ from agno.models.langdb import LangDB
104
+
105
+ return LangDB(id=model_id)
106
+
107
+ elif model_provider == "litellm":
108
+ from agno.models.litellm import LiteLLM
109
+
110
+ return LiteLLM(id=model_id)
111
+
112
+ elif model_provider == "litellm-openai":
113
+ from agno.models.litellm import LiteLLMOpenAI
114
+
115
+ return LiteLLMOpenAI(id=model_id)
116
+
117
+ elif model_provider == "llama-cpp":
118
+ from agno.models.llama_cpp import LlamaCpp
119
+
120
+ return LlamaCpp(id=model_id)
121
+
122
+ elif model_provider == "llama-openai":
123
+ from agno.models.meta import LlamaOpenAI
124
+
125
+ return LlamaOpenAI(id=model_id)
126
+
127
+ elif model_provider == "lmstudio":
128
+ from agno.models.lmstudio import LMStudio
129
+
130
+ return LMStudio(id=model_id)
131
+
132
+ elif model_provider == "meta":
133
+ from agno.models.meta import Llama
134
+
135
+ return Llama(id=model_id)
136
+
137
+ elif model_provider == "mistral":
138
+ from agno.models.mistral import MistralChat
139
+
140
+ return MistralChat(id=model_id)
141
+
142
+ elif model_provider == "nebius":
143
+ from agno.models.nebius import Nebius
144
+
145
+ return Nebius(id=model_id)
146
+
147
+ elif model_provider == "nexus":
148
+ from agno.models.nexus import Nexus
149
+
150
+ return Nexus(id=model_id)
151
+
152
+ elif model_provider == "nvidia":
153
+ from agno.models.nvidia import Nvidia
154
+
155
+ return Nvidia(id=model_id)
156
+
157
+ elif model_provider == "ollama":
158
+ from agno.models.ollama import Ollama
159
+
160
+ return Ollama(id=model_id)
161
+
162
+ elif model_provider == "openai":
163
+ from agno.models.openai import OpenAIChat
164
+
165
+ return OpenAIChat(id=model_id)
166
+
167
+ elif model_provider == "openai-responses":
168
+ from agno.models.openai import OpenAIResponses
169
+
170
+ return OpenAIResponses(id=model_id)
171
+
172
+ elif model_provider == "openrouter":
173
+ from agno.models.openrouter import OpenRouter
174
+
175
+ return OpenRouter(id=model_id)
176
+
177
+ elif model_provider == "perplexity":
178
+ from agno.models.perplexity import Perplexity
179
+
180
+ return Perplexity(id=model_id)
181
+
182
+ elif model_provider == "portkey":
183
+ from agno.models.portkey import Portkey
184
+
185
+ return Portkey(id=model_id)
186
+
187
+ elif model_provider == "requesty":
188
+ from agno.models.requesty import Requesty
189
+
190
+ return Requesty(id=model_id)
191
+
192
+ elif model_provider == "sambanova":
193
+ from agno.models.sambanova import Sambanova
194
+
195
+ return Sambanova(id=model_id)
196
+
197
+ elif model_provider == "siliconflow":
198
+ from agno.models.siliconflow import Siliconflow
199
+
200
+ return Siliconflow(id=model_id)
201
+
202
+ elif model_provider == "together":
203
+ from agno.models.together import Together
204
+
205
+ return Together(id=model_id)
206
+
207
+ elif model_provider == "vercel":
208
+ from agno.models.vercel import V0
209
+
210
+ return V0(id=model_id)
211
+
212
+ elif model_provider == "vertexai-claude":
213
+ from agno.models.vertexai.claude import Claude as VertexAIClaude
214
+
215
+ return VertexAIClaude(id=model_id)
216
+
217
+ elif model_provider == "vllm":
218
+ from agno.models.vllm import VLLM
219
+
220
+ return VLLM(id=model_id)
221
+
222
+ elif model_provider == "xai":
223
+ from agno.models.xai import xAI
224
+
225
+ return xAI(id=model_id)
226
+
227
+ else:
228
+ raise ValueError(f"Model provider '{model_provider}' is not supported.")
229
+
230
+
231
+ def _parse_model_string(model_string: str) -> Model:
232
+ if not model_string or not isinstance(model_string, str):
233
+ raise ValueError(f"Model string must be a non-empty string, got: {model_string}")
234
+
235
+ if ":" not in model_string:
236
+ raise ValueError(
237
+ f"Invalid model string format: '{model_string}'. Model strings should be in format '<provider>:<model_id>' e.g. 'openai:gpt-4o'"
238
+ )
239
+
240
+ parts = model_string.split(":", 1)
241
+ if len(parts) != 2:
242
+ raise ValueError(
243
+ f"Invalid model string format: '{model_string}'. Model strings should be in format '<provider>:<model_id>' e.g. 'openai:gpt-4o'"
244
+ )
245
+
246
+ model_provider, model_id = parts
247
+ model_provider = model_provider.strip().lower()
248
+ model_id = model_id.strip()
249
+
250
+ if not model_provider or not model_id:
251
+ raise ValueError(
252
+ f"Invalid model string format: '{model_string}'. Model strings should be in format '<provider>:<model_id>' e.g. 'openai:gpt-4o'"
253
+ )
254
+
255
+ return _get_model_class(model_id, model_provider)
256
+
257
+
258
+ def get_model(model: Union[Model, str, None]) -> Optional[Model]:
259
+ if model is None:
260
+ return None
261
+ elif isinstance(model, Model):
262
+ return model
263
+ elif isinstance(model, str):
264
+ return _parse_model_string(model)
19
265
  else:
20
- raise ValueError(f"Model provider {model_provider} not supported")
266
+ raise ValueError("Model must be a Model instance, string, or None")
agno/models/vercel/v0.py CHANGED
@@ -1,7 +1,8 @@
1
- from dataclasses import dataclass, field
1
+ from dataclasses import dataclass
2
2
  from os import getenv
3
- from typing import Optional
3
+ from typing import Any, Dict, Optional
4
4
 
5
+ from agno.exceptions import ModelAuthenticationError
5
6
  from agno.models.openai.like import OpenAILike
6
7
 
7
8
 
@@ -22,5 +23,21 @@ class V0(OpenAILike):
22
23
  name: str = "v0"
23
24
  provider: str = "Vercel"
24
25
 
25
- api_key: Optional[str] = field(default_factory=lambda: getenv("V0_API_KEY"))
26
+ api_key: Optional[str] = None
26
27
  base_url: str = "https://api.v0.dev/v1/"
28
+
29
+ def _get_client_params(self) -> Dict[str, Any]:
30
+ """
31
+ Returns client parameters for API requests, checking for V0_API_KEY.
32
+
33
+ Returns:
34
+ Dict[str, Any]: A dictionary of client parameters for API requests.
35
+ """
36
+ if not self.api_key:
37
+ self.api_key = getenv("V0_API_KEY")
38
+ if not self.api_key:
39
+ raise ModelAuthenticationError(
40
+ message="V0_API_KEY not set. Please set the V0_API_KEY environment variable.",
41
+ model_name=self.name,
42
+ )
43
+ return super()._get_client_params()
File without changes