agno 2.2.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 (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1335 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1160 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
agno/models/message.py ADDED
@@ -0,0 +1,434 @@
1
+ import json
2
+ from time import time
3
+ from typing import Any, Dict, List, Optional, Sequence, Union
4
+ from uuid import uuid4
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field
7
+
8
+ from agno.media import Audio, File, Image, Video
9
+ from agno.models.metrics import Metrics
10
+ from agno.utils.log import log_debug, log_error, log_info, log_warning
11
+
12
+
13
+ class MessageReferences(BaseModel):
14
+ """References added to user message"""
15
+
16
+ # The query used to retrieve the references.
17
+ query: str
18
+ # References (from the vector database or function calls)
19
+ references: Optional[List[Union[Dict[str, Any], str]]] = None
20
+ # Time taken to retrieve the references.
21
+ time: Optional[float] = None
22
+
23
+
24
+ class UrlCitation(BaseModel):
25
+ """URL of the citation"""
26
+
27
+ url: Optional[str] = None
28
+ title: Optional[str] = None
29
+
30
+
31
+ class DocumentCitation(BaseModel):
32
+ """Document of the citation"""
33
+
34
+ document_title: Optional[str] = None
35
+ cited_text: Optional[str] = None
36
+ file_name: Optional[str] = None
37
+
38
+
39
+ class Citations(BaseModel):
40
+ """Citations for the message"""
41
+
42
+ # Raw citations from the model
43
+ raw: Optional[Any] = None
44
+
45
+ # URLs of the citations.
46
+ urls: Optional[List[UrlCitation]] = None
47
+
48
+ # Document Citations
49
+ documents: Optional[List[DocumentCitation]] = None
50
+
51
+
52
+ class Message(BaseModel):
53
+ """Message sent to the Model"""
54
+
55
+ id: str = Field(default_factory=lambda: str(uuid4()))
56
+
57
+ # The role of the message author.
58
+ # One of system, user, assistant, or tool.
59
+ role: str
60
+ # The contents of the message.
61
+ content: Optional[Union[List[Any], str]] = None
62
+ # An optional name for the participant.
63
+ # Provides the model information to differentiate between participants of the same role.
64
+ name: Optional[str] = None
65
+ # Tool call that this message is responding to.
66
+ tool_call_id: Optional[str] = None
67
+ # The tool calls generated by the model, such as function calls.
68
+ tool_calls: Optional[List[Dict[str, Any]]] = None
69
+
70
+ # Additional modalities
71
+ audio: Optional[Sequence[Audio]] = None
72
+ images: Optional[Sequence[Image]] = None
73
+ videos: Optional[Sequence[Video]] = None
74
+ files: Optional[Sequence[File]] = None
75
+
76
+ # Output from the models
77
+ audio_output: Optional[Audio] = None
78
+ image_output: Optional[Image] = None
79
+ video_output: Optional[Video] = None
80
+ file_output: Optional[File] = None
81
+
82
+ # The thinking content from the model
83
+ redacted_reasoning_content: Optional[str] = None
84
+
85
+ # Data from the provider we might need on subsequent messages
86
+ provider_data: Optional[Dict[str, Any]] = None
87
+
88
+ # Citations received from the model
89
+ citations: Optional[Citations] = None
90
+
91
+ # --- Data not sent to the Model API ---
92
+ # The reasoning content from the model
93
+ reasoning_content: Optional[str] = None
94
+ # The name of the tool called
95
+ tool_name: Optional[str] = None
96
+ # Arguments passed to the tool
97
+ tool_args: Optional[Any] = None
98
+ # The error of the tool call
99
+ tool_call_error: Optional[bool] = None
100
+ # If True, the agent will stop executing after this tool call.
101
+ stop_after_tool_call: bool = False
102
+ # When True, the message will be added to the agent's memory.
103
+ add_to_agent_memory: bool = True
104
+ # This flag is enabled when a message is fetched from the agent's memory.
105
+ from_history: bool = False
106
+ # Metrics for the message.
107
+ metrics: Metrics = Field(default_factory=Metrics)
108
+ # The references added to the message for RAG
109
+ references: Optional[MessageReferences] = None
110
+ # The Unix timestamp the message was created.
111
+ created_at: int = Field(default_factory=lambda: int(time()))
112
+
113
+ model_config = ConfigDict(extra="allow", populate_by_name=True, arbitrary_types_allowed=True)
114
+
115
+ def get_content_string(self) -> str:
116
+ """Returns the content as a string."""
117
+ if isinstance(self.content, str):
118
+ return self.content
119
+ if isinstance(self.content, list):
120
+ if len(self.content) > 0 and isinstance(self.content[0], dict) and "text" in self.content[0]:
121
+ return self.content[0].get("text", "")
122
+ else:
123
+ return json.dumps(self.content)
124
+ return ""
125
+
126
+ @classmethod
127
+ def from_dict(cls, data: Dict[str, Any]) -> "Message":
128
+ # Handle image reconstruction properly
129
+ if "images" in data and data["images"]:
130
+ reconstructed_images = []
131
+ for i, img_data in enumerate(data["images"]):
132
+ if isinstance(img_data, dict):
133
+ # If content is base64, decode it back to bytes
134
+ if "content" in img_data and isinstance(img_data["content"], str):
135
+ reconstructed_images.append(
136
+ Image.from_base64(
137
+ img_data["content"],
138
+ id=img_data.get("id"),
139
+ mime_type=img_data.get("mime_type"),
140
+ format=img_data.get("format"),
141
+ )
142
+ )
143
+ else:
144
+ # Regular image (filepath/url)
145
+ reconstructed_images.append(Image(**img_data))
146
+ else:
147
+ reconstructed_images.append(img_data)
148
+ data["images"] = reconstructed_images
149
+
150
+ # Handle audio reconstruction properly
151
+ if "audio" in data and data["audio"]:
152
+ reconstructed_audio = []
153
+ for i, aud_data in enumerate(data["audio"]):
154
+ if isinstance(aud_data, dict):
155
+ # If content is base64, decode it back to bytes
156
+ if "content" in aud_data and isinstance(aud_data["content"], str):
157
+ reconstructed_audio.append(
158
+ Audio.from_base64(
159
+ aud_data["content"],
160
+ id=aud_data.get("id"),
161
+ mime_type=aud_data.get("mime_type"),
162
+ transcript=aud_data.get("transcript"),
163
+ expires_at=aud_data.get("expires_at"),
164
+ sample_rate=aud_data.get("sample_rate", 24000),
165
+ channels=aud_data.get("channels", 1),
166
+ )
167
+ )
168
+ else:
169
+ reconstructed_audio.append(Audio(**aud_data))
170
+ else:
171
+ reconstructed_audio.append(aud_data)
172
+ data["audio"] = reconstructed_audio
173
+
174
+ # Handle video reconstruction properly
175
+ if "videos" in data and data["videos"]:
176
+ reconstructed_videos = []
177
+ for i, vid_data in enumerate(data["videos"]):
178
+ if isinstance(vid_data, dict):
179
+ # If content is base64, decode it back to bytes
180
+ if "content" in vid_data and isinstance(vid_data["content"], str):
181
+ reconstructed_videos.append(
182
+ Video.from_base64(
183
+ vid_data["content"],
184
+ id=vid_data.get("id"),
185
+ mime_type=vid_data.get("mime_type"),
186
+ format=vid_data.get("format"),
187
+ )
188
+ )
189
+ else:
190
+ reconstructed_videos.append(Video(**vid_data))
191
+ else:
192
+ reconstructed_videos.append(vid_data)
193
+ data["videos"] = reconstructed_videos
194
+
195
+ # Handle file reconstruction properly
196
+ if "files" in data and data["files"]:
197
+ reconstructed_files = []
198
+ for i, file_data in enumerate(data["files"]):
199
+ if isinstance(file_data, dict):
200
+ # If content is base64, decode it back to bytes
201
+ if "content" in file_data and isinstance(file_data["content"], str):
202
+ reconstructed_files.append(
203
+ File.from_base64(
204
+ file_data["content"],
205
+ id=file_data.get("id"),
206
+ mime_type=file_data.get("mime_type"),
207
+ filename=file_data.get("filename"),
208
+ name=file_data.get("name"),
209
+ format=file_data.get("format"),
210
+ )
211
+ )
212
+ else:
213
+ reconstructed_files.append(File(**file_data))
214
+ else:
215
+ reconstructed_files.append(file_data)
216
+ data["files"] = reconstructed_files
217
+
218
+ if "audio_output" in data and data["audio_output"]:
219
+ aud_data = data["audio_output"]
220
+ if isinstance(aud_data, dict):
221
+ if "content" in aud_data and isinstance(aud_data["content"], str):
222
+ data["audio_output"] = Audio.from_base64(
223
+ aud_data["content"],
224
+ id=aud_data.get("id"),
225
+ mime_type=aud_data.get("mime_type"),
226
+ transcript=aud_data.get("transcript"),
227
+ expires_at=aud_data.get("expires_at"),
228
+ sample_rate=aud_data.get("sample_rate", 24000),
229
+ channels=aud_data.get("channels", 1),
230
+ )
231
+ else:
232
+ data["audio_output"] = Audio(**aud_data)
233
+
234
+ if "image_output" in data and data["image_output"]:
235
+ img_data = data["image_output"]
236
+ if isinstance(img_data, dict):
237
+ if "content" in img_data and isinstance(img_data["content"], str):
238
+ data["image_output"] = Image.from_base64(
239
+ img_data["content"],
240
+ id=img_data.get("id"),
241
+ mime_type=img_data.get("mime_type"),
242
+ format=img_data.get("format"),
243
+ )
244
+ else:
245
+ data["image_output"] = Image(**img_data)
246
+
247
+ if "video_output" in data and data["video_output"]:
248
+ vid_data = data["video_output"]
249
+ if isinstance(vid_data, dict):
250
+ if "content" in vid_data and isinstance(vid_data["content"], str):
251
+ data["video_output"] = Video.from_base64(
252
+ vid_data["content"],
253
+ id=vid_data.get("id"),
254
+ mime_type=vid_data.get("mime_type"),
255
+ format=vid_data.get("format"),
256
+ )
257
+ else:
258
+ data["video_output"] = Video(**vid_data)
259
+
260
+ return cls(**data)
261
+
262
+ def to_dict(self) -> Dict[str, Any]:
263
+ """Returns the message as a dictionary."""
264
+ message_dict = {
265
+ "id": self.id,
266
+ "content": self.content,
267
+ "reasoning_content": self.reasoning_content,
268
+ "from_history": self.from_history,
269
+ "stop_after_tool_call": self.stop_after_tool_call,
270
+ "role": self.role,
271
+ "name": self.name,
272
+ "tool_call_id": self.tool_call_id,
273
+ "tool_name": self.tool_name,
274
+ "tool_args": self.tool_args,
275
+ "tool_call_error": self.tool_call_error,
276
+ "tool_calls": self.tool_calls,
277
+ "redacted_reasoning_content": self.redacted_reasoning_content,
278
+ "provider_data": self.provider_data,
279
+ }
280
+ # Filter out None and empty collections
281
+ message_dict = {
282
+ k: v for k, v in message_dict.items() if v is not None and not (isinstance(v, (list, dict)) and len(v) == 0)
283
+ }
284
+
285
+ # Convert media objects to dictionaries
286
+ if self.images:
287
+ message_dict["images"] = [img.to_dict() for img in self.images]
288
+ if self.audio:
289
+ message_dict["audio"] = [aud.to_dict() for aud in self.audio]
290
+ if self.videos:
291
+ message_dict["videos"] = [vid.to_dict() for vid in self.videos]
292
+ if self.files:
293
+ message_dict["files"] = [file.to_dict() for file in self.files]
294
+ if self.audio_output:
295
+ message_dict["audio_output"] = self.audio_output.to_dict()
296
+
297
+ if self.references:
298
+ message_dict["references"] = self.references.model_dump()
299
+ if self.metrics:
300
+ message_dict["metrics"] = self.metrics.to_dict()
301
+ if not message_dict["metrics"]:
302
+ message_dict.pop("metrics")
303
+
304
+ message_dict["created_at"] = self.created_at
305
+ return message_dict
306
+
307
+ def to_function_call_dict(self) -> Dict[str, Any]:
308
+ return {
309
+ "content": self.content,
310
+ "tool_call_id": self.tool_call_id,
311
+ "tool_name": self.tool_name,
312
+ "tool_args": self.tool_args,
313
+ "tool_call_error": self.tool_call_error,
314
+ "metrics": self.metrics,
315
+ "created_at": self.created_at,
316
+ }
317
+
318
+ def log(self, metrics: bool = True, level: Optional[str] = None):
319
+ """Log the message to the console
320
+
321
+ Args:
322
+ metrics (bool): Whether to log the metrics.
323
+ level (str): The level to log the message at. One of debug, info, warning, or error.
324
+ Defaults to debug.
325
+ """
326
+ _logger = log_debug
327
+ if level == "info":
328
+ _logger = log_info
329
+ elif level == "warning":
330
+ _logger = log_warning
331
+ elif level == "error":
332
+ _logger = log_error
333
+
334
+ try:
335
+ import shutil
336
+
337
+ terminal_width = shutil.get_terminal_size().columns
338
+ except Exception:
339
+ terminal_width = 80 # fallback width
340
+
341
+ header = f" {self.role} "
342
+ _logger(f"{header.center(terminal_width - 20, '=')}")
343
+
344
+ if self.name:
345
+ _logger(f"Name: {self.name}")
346
+ if self.tool_call_id:
347
+ _logger(f"Tool call Id: {self.tool_call_id}")
348
+ if self.reasoning_content:
349
+ _logger(f"<reasoning>\n{self.reasoning_content}\n</reasoning>")
350
+ if self.content:
351
+ if isinstance(self.content, str) or isinstance(self.content, list):
352
+ _logger(self.content)
353
+ elif isinstance(self.content, dict):
354
+ _logger(json.dumps(self.content, indent=2))
355
+ if self.tool_calls:
356
+ tool_calls_list = ["Tool Calls:"]
357
+ for tool_call in self.tool_calls:
358
+ tool_id = tool_call.get("id")
359
+ function_name = tool_call.get("function", {}).get("name")
360
+ tool_calls_list.append(f" - ID: '{tool_id}'") if tool_id else None
361
+ tool_calls_list.append(f" Name: '{function_name}'") if function_name else None
362
+ tool_call_arguments = tool_call.get("function", {}).get("arguments")
363
+ if tool_call_arguments:
364
+ try:
365
+ tool_call_args: dict = (
366
+ tool_call_arguments
367
+ if isinstance(tool_call_arguments, dict)
368
+ else json.loads(tool_call_arguments)
369
+ )
370
+ if tool_call_args:
371
+ # Ensure tool_call_args is a dictionary before calling .items()
372
+ if isinstance(tool_call_args, dict):
373
+ arguments = ", ".join(f"{k}: {v}" for k, v in tool_call_args.items())
374
+ tool_calls_list.append(f" Arguments: '{arguments}'")
375
+ else:
376
+ tool_calls_list.append(f" Arguments: '{tool_call_args}'")
377
+ except json.JSONDecodeError:
378
+ tool_calls_list.append(" Arguments: 'Invalid JSON format'")
379
+ tool_calls_str = "\n".join(tool_calls_list)
380
+
381
+ _logger(tool_calls_str)
382
+ if self.images:
383
+ _logger(f"Images added: {len(self.images)}")
384
+ if self.videos:
385
+ _logger(f"Videos added: {len(self.videos)}")
386
+ if self.audio:
387
+ _logger(f"Audio Files added: {len(self.audio)}")
388
+ if self.files:
389
+ _logger(f"Files added: {len(self.files)}")
390
+
391
+ metrics_header = " TOOL METRICS " if self.role == "tool" else " METRICS "
392
+ if metrics and self.metrics is not None and self.metrics != Metrics():
393
+ _logger(metrics_header, center=True, symbol="*")
394
+
395
+ # Token metrics
396
+ token_metrics = []
397
+ if self.metrics.input_tokens and self.metrics.input_tokens > 0:
398
+ token_metrics.append(f"input={self.metrics.input_tokens}")
399
+ if self.metrics.output_tokens and self.metrics.output_tokens > 0:
400
+ token_metrics.append(f"output={self.metrics.output_tokens}")
401
+ if self.metrics.total_tokens and self.metrics.total_tokens > 0:
402
+ token_metrics.append(f"total={self.metrics.total_tokens}")
403
+ if self.metrics.cache_read_tokens and self.metrics.cache_read_tokens > 0:
404
+ token_metrics.append(f"cached={self.metrics.cache_read_tokens}")
405
+ if self.metrics.cache_write_tokens and self.metrics.cache_write_tokens > 0:
406
+ token_metrics.append(f"cache_write_tokens={self.metrics.cache_write_tokens}")
407
+ if self.metrics.reasoning_tokens and self.metrics.reasoning_tokens > 0:
408
+ token_metrics.append(f"reasoning={self.metrics.reasoning_tokens}")
409
+ if self.metrics.audio_total_tokens and self.metrics.audio_total_tokens > 0:
410
+ token_metrics.append(f"audio={self.metrics.audio_total_tokens}")
411
+ if token_metrics:
412
+ _logger(f"* Tokens: {', '.join(token_metrics)}")
413
+
414
+ # Time related metrics
415
+ if self.metrics.duration is not None and self.metrics.duration > 0:
416
+ _logger(f"* Duration: {self.metrics.duration:.4f}s")
417
+ if self.metrics.output_tokens and self.metrics.duration and self.metrics.duration > 0:
418
+ _logger(
419
+ f"* Tokens per second: {self.metrics.output_tokens / self.metrics.duration:.4f} tokens/s"
420
+ )
421
+ if self.metrics.time_to_first_token is not None and self.metrics.time_to_first_token > 0:
422
+ _logger(f"* Time to first token: {self.metrics.time_to_first_token:.4f}s")
423
+
424
+ # Non-generic metrics
425
+ if self.metrics.provider_metrics:
426
+ _logger(f"* Provider metrics: {self.metrics.provider_metrics}")
427
+ if self.metrics.additional_metrics:
428
+ _logger(f"* Additional metrics: {self.metrics.additional_metrics}")
429
+
430
+ _logger(metrics_header, center=True, symbol="*")
431
+
432
+ def content_is_valid(self) -> bool:
433
+ """Check if the message content is valid."""
434
+ return self.content is not None and len(self.content) > 0
@@ -0,0 +1,12 @@
1
+ from agno.models.meta.llama import Llama
2
+
3
+ try:
4
+ from agno.models.meta.llama_openai import LlamaOpenAI
5
+ except ImportError:
6
+
7
+ class LlamaOpenAI: # type: ignore
8
+ def __init__(self, *args, **kwargs):
9
+ raise ImportError("`openai` not installed. Please install it via `pip install openai`")
10
+
11
+
12
+ __all__ = ["Llama", "LlamaOpenAI"]