agno 0.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 (723) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +44 -5
  3. agno/agent/agent.py +10531 -2975
  4. agno/api/agent.py +14 -53
  5. agno/api/api.py +7 -46
  6. agno/api/evals.py +22 -0
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -25
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +6 -9
  11. agno/api/schemas/evals.py +16 -0
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +10 -10
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +16 -0
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +22 -26
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/compression/__init__.py +3 -0
  25. agno/compression/manager.py +247 -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 +946 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2781 -0
  33. agno/db/dynamo/schemas.py +442 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +2379 -0
  37. agno/db/firestore/schemas.py +181 -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 +1791 -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 +1312 -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 +1777 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/manager.py +199 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/migrations/versions/v2_3_0.py +938 -0
  51. agno/db/mongo/__init__.py +17 -0
  52. agno/db/mongo/async_mongo.py +2760 -0
  53. agno/db/mongo/mongo.py +2597 -0
  54. agno/db/mongo/schemas.py +119 -0
  55. agno/db/mongo/utils.py +276 -0
  56. agno/db/mysql/__init__.py +4 -0
  57. agno/db/mysql/async_mysql.py +2912 -0
  58. agno/db/mysql/mysql.py +2923 -0
  59. agno/db/mysql/schemas.py +186 -0
  60. agno/db/mysql/utils.py +488 -0
  61. agno/db/postgres/__init__.py +4 -0
  62. agno/db/postgres/async_postgres.py +2579 -0
  63. agno/db/postgres/postgres.py +2870 -0
  64. agno/db/postgres/schemas.py +187 -0
  65. agno/db/postgres/utils.py +442 -0
  66. agno/db/redis/__init__.py +3 -0
  67. agno/db/redis/redis.py +2141 -0
  68. agno/db/redis/schemas.py +159 -0
  69. agno/db/redis/utils.py +346 -0
  70. agno/db/schemas/__init__.py +4 -0
  71. agno/db/schemas/culture.py +120 -0
  72. agno/db/schemas/evals.py +34 -0
  73. agno/db/schemas/knowledge.py +40 -0
  74. agno/db/schemas/memory.py +61 -0
  75. agno/db/singlestore/__init__.py +3 -0
  76. agno/db/singlestore/schemas.py +179 -0
  77. agno/db/singlestore/singlestore.py +2877 -0
  78. agno/db/singlestore/utils.py +384 -0
  79. agno/db/sqlite/__init__.py +4 -0
  80. agno/db/sqlite/async_sqlite.py +2911 -0
  81. agno/db/sqlite/schemas.py +181 -0
  82. agno/db/sqlite/sqlite.py +2908 -0
  83. agno/db/sqlite/utils.py +429 -0
  84. agno/db/surrealdb/__init__.py +3 -0
  85. agno/db/surrealdb/metrics.py +292 -0
  86. agno/db/surrealdb/models.py +334 -0
  87. agno/db/surrealdb/queries.py +71 -0
  88. agno/db/surrealdb/surrealdb.py +1908 -0
  89. agno/db/surrealdb/utils.py +147 -0
  90. agno/db/utils.py +118 -0
  91. agno/eval/__init__.py +24 -0
  92. agno/eval/accuracy.py +666 -276
  93. agno/eval/agent_as_judge.py +861 -0
  94. agno/eval/base.py +29 -0
  95. agno/eval/performance.py +779 -0
  96. agno/eval/reliability.py +241 -62
  97. agno/eval/utils.py +120 -0
  98. agno/exceptions.py +143 -1
  99. agno/filters.py +354 -0
  100. agno/guardrails/__init__.py +6 -0
  101. agno/guardrails/base.py +19 -0
  102. agno/guardrails/openai.py +144 -0
  103. agno/guardrails/pii.py +94 -0
  104. agno/guardrails/prompt_injection.py +52 -0
  105. agno/hooks/__init__.py +3 -0
  106. agno/hooks/decorator.py +164 -0
  107. agno/integrations/discord/__init__.py +3 -0
  108. agno/integrations/discord/client.py +203 -0
  109. agno/knowledge/__init__.py +5 -1
  110. agno/{document → knowledge}/chunking/agentic.py +22 -14
  111. agno/{document → knowledge}/chunking/document.py +2 -2
  112. agno/{document → knowledge}/chunking/fixed.py +7 -6
  113. agno/knowledge/chunking/markdown.py +151 -0
  114. agno/{document → knowledge}/chunking/recursive.py +15 -3
  115. agno/knowledge/chunking/row.py +39 -0
  116. agno/knowledge/chunking/semantic.py +91 -0
  117. agno/knowledge/chunking/strategy.py +165 -0
  118. agno/knowledge/content.py +74 -0
  119. agno/knowledge/document/__init__.py +5 -0
  120. agno/{document → knowledge/document}/base.py +12 -2
  121. agno/knowledge/embedder/__init__.py +5 -0
  122. agno/knowledge/embedder/aws_bedrock.py +343 -0
  123. agno/knowledge/embedder/azure_openai.py +210 -0
  124. agno/{embedder → knowledge/embedder}/base.py +8 -0
  125. agno/knowledge/embedder/cohere.py +323 -0
  126. agno/knowledge/embedder/fastembed.py +62 -0
  127. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  128. agno/knowledge/embedder/google.py +258 -0
  129. agno/knowledge/embedder/huggingface.py +94 -0
  130. agno/knowledge/embedder/jina.py +182 -0
  131. agno/knowledge/embedder/langdb.py +22 -0
  132. agno/knowledge/embedder/mistral.py +206 -0
  133. agno/knowledge/embedder/nebius.py +13 -0
  134. agno/knowledge/embedder/ollama.py +154 -0
  135. agno/knowledge/embedder/openai.py +195 -0
  136. agno/knowledge/embedder/sentence_transformer.py +63 -0
  137. agno/{embedder → knowledge/embedder}/together.py +1 -1
  138. agno/knowledge/embedder/vllm.py +262 -0
  139. agno/knowledge/embedder/voyageai.py +165 -0
  140. agno/knowledge/knowledge.py +3006 -0
  141. agno/knowledge/reader/__init__.py +7 -0
  142. agno/knowledge/reader/arxiv_reader.py +81 -0
  143. agno/knowledge/reader/base.py +95 -0
  144. agno/knowledge/reader/csv_reader.py +164 -0
  145. agno/knowledge/reader/docx_reader.py +82 -0
  146. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  147. agno/knowledge/reader/firecrawl_reader.py +201 -0
  148. agno/knowledge/reader/json_reader.py +88 -0
  149. agno/knowledge/reader/markdown_reader.py +137 -0
  150. agno/knowledge/reader/pdf_reader.py +431 -0
  151. agno/knowledge/reader/pptx_reader.py +101 -0
  152. agno/knowledge/reader/reader_factory.py +313 -0
  153. agno/knowledge/reader/s3_reader.py +89 -0
  154. agno/knowledge/reader/tavily_reader.py +193 -0
  155. agno/knowledge/reader/text_reader.py +127 -0
  156. agno/knowledge/reader/web_search_reader.py +325 -0
  157. agno/knowledge/reader/website_reader.py +455 -0
  158. agno/knowledge/reader/wikipedia_reader.py +91 -0
  159. agno/knowledge/reader/youtube_reader.py +78 -0
  160. agno/knowledge/remote_content/remote_content.py +88 -0
  161. agno/knowledge/reranker/__init__.py +3 -0
  162. agno/{reranker → knowledge/reranker}/base.py +1 -1
  163. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  164. agno/knowledge/reranker/infinity.py +195 -0
  165. agno/knowledge/reranker/sentence_transformer.py +54 -0
  166. agno/knowledge/types.py +39 -0
  167. agno/knowledge/utils.py +234 -0
  168. agno/media.py +439 -95
  169. agno/memory/__init__.py +16 -3
  170. agno/memory/manager.py +1474 -123
  171. agno/memory/strategies/__init__.py +15 -0
  172. agno/memory/strategies/base.py +66 -0
  173. agno/memory/strategies/summarize.py +196 -0
  174. agno/memory/strategies/types.py +37 -0
  175. agno/models/aimlapi/__init__.py +5 -0
  176. agno/models/aimlapi/aimlapi.py +62 -0
  177. agno/models/anthropic/__init__.py +4 -0
  178. agno/models/anthropic/claude.py +960 -496
  179. agno/models/aws/__init__.py +15 -0
  180. agno/models/aws/bedrock.py +686 -451
  181. agno/models/aws/claude.py +190 -183
  182. agno/models/azure/__init__.py +18 -1
  183. agno/models/azure/ai_foundry.py +489 -0
  184. agno/models/azure/openai_chat.py +89 -40
  185. agno/models/base.py +2477 -550
  186. agno/models/cerebras/__init__.py +12 -0
  187. agno/models/cerebras/cerebras.py +565 -0
  188. agno/models/cerebras/cerebras_openai.py +131 -0
  189. agno/models/cohere/__init__.py +4 -0
  190. agno/models/cohere/chat.py +306 -492
  191. agno/models/cometapi/__init__.py +5 -0
  192. agno/models/cometapi/cometapi.py +74 -0
  193. agno/models/dashscope/__init__.py +5 -0
  194. agno/models/dashscope/dashscope.py +90 -0
  195. agno/models/deepinfra/__init__.py +5 -0
  196. agno/models/deepinfra/deepinfra.py +45 -0
  197. agno/models/deepseek/__init__.py +4 -0
  198. agno/models/deepseek/deepseek.py +110 -9
  199. agno/models/fireworks/__init__.py +4 -0
  200. agno/models/fireworks/fireworks.py +19 -22
  201. agno/models/google/__init__.py +3 -7
  202. agno/models/google/gemini.py +1717 -662
  203. agno/models/google/utils.py +22 -0
  204. agno/models/groq/__init__.py +4 -0
  205. agno/models/groq/groq.py +391 -666
  206. agno/models/huggingface/__init__.py +4 -0
  207. agno/models/huggingface/huggingface.py +266 -538
  208. agno/models/ibm/__init__.py +5 -0
  209. agno/models/ibm/watsonx.py +432 -0
  210. agno/models/internlm/__init__.py +3 -0
  211. agno/models/internlm/internlm.py +20 -3
  212. agno/models/langdb/__init__.py +1 -0
  213. agno/models/langdb/langdb.py +60 -0
  214. agno/models/litellm/__init__.py +14 -0
  215. agno/models/litellm/chat.py +503 -0
  216. agno/models/litellm/litellm_openai.py +42 -0
  217. agno/models/llama_cpp/__init__.py +5 -0
  218. agno/models/llama_cpp/llama_cpp.py +22 -0
  219. agno/models/lmstudio/__init__.py +5 -0
  220. agno/models/lmstudio/lmstudio.py +25 -0
  221. agno/models/message.py +361 -39
  222. agno/models/meta/__init__.py +12 -0
  223. agno/models/meta/llama.py +502 -0
  224. agno/models/meta/llama_openai.py +79 -0
  225. agno/models/metrics.py +120 -0
  226. agno/models/mistral/__init__.py +4 -0
  227. agno/models/mistral/mistral.py +293 -393
  228. agno/models/nebius/__init__.py +3 -0
  229. agno/models/nebius/nebius.py +53 -0
  230. agno/models/nexus/__init__.py +3 -0
  231. agno/models/nexus/nexus.py +22 -0
  232. agno/models/nvidia/__init__.py +4 -0
  233. agno/models/nvidia/nvidia.py +22 -3
  234. agno/models/ollama/__init__.py +4 -2
  235. agno/models/ollama/chat.py +257 -492
  236. agno/models/openai/__init__.py +7 -0
  237. agno/models/openai/chat.py +725 -770
  238. agno/models/openai/like.py +16 -2
  239. agno/models/openai/responses.py +1121 -0
  240. agno/models/openrouter/__init__.py +4 -0
  241. agno/models/openrouter/openrouter.py +62 -5
  242. agno/models/perplexity/__init__.py +5 -0
  243. agno/models/perplexity/perplexity.py +203 -0
  244. agno/models/portkey/__init__.py +3 -0
  245. agno/models/portkey/portkey.py +82 -0
  246. agno/models/requesty/__init__.py +5 -0
  247. agno/models/requesty/requesty.py +69 -0
  248. agno/models/response.py +177 -7
  249. agno/models/sambanova/__init__.py +4 -0
  250. agno/models/sambanova/sambanova.py +23 -4
  251. agno/models/siliconflow/__init__.py +5 -0
  252. agno/models/siliconflow/siliconflow.py +42 -0
  253. agno/models/together/__init__.py +4 -0
  254. agno/models/together/together.py +21 -164
  255. agno/models/utils.py +266 -0
  256. agno/models/vercel/__init__.py +3 -0
  257. agno/models/vercel/v0.py +43 -0
  258. agno/models/vertexai/__init__.py +0 -1
  259. agno/models/vertexai/claude.py +190 -0
  260. agno/models/vllm/__init__.py +3 -0
  261. agno/models/vllm/vllm.py +83 -0
  262. agno/models/xai/__init__.py +2 -0
  263. agno/models/xai/xai.py +111 -7
  264. agno/os/__init__.py +3 -0
  265. agno/os/app.py +1027 -0
  266. agno/os/auth.py +244 -0
  267. agno/os/config.py +126 -0
  268. agno/os/interfaces/__init__.py +1 -0
  269. agno/os/interfaces/a2a/__init__.py +3 -0
  270. agno/os/interfaces/a2a/a2a.py +42 -0
  271. agno/os/interfaces/a2a/router.py +249 -0
  272. agno/os/interfaces/a2a/utils.py +924 -0
  273. agno/os/interfaces/agui/__init__.py +3 -0
  274. agno/os/interfaces/agui/agui.py +47 -0
  275. agno/os/interfaces/agui/router.py +147 -0
  276. agno/os/interfaces/agui/utils.py +574 -0
  277. agno/os/interfaces/base.py +25 -0
  278. agno/os/interfaces/slack/__init__.py +3 -0
  279. agno/os/interfaces/slack/router.py +148 -0
  280. agno/os/interfaces/slack/security.py +30 -0
  281. agno/os/interfaces/slack/slack.py +47 -0
  282. agno/os/interfaces/whatsapp/__init__.py +3 -0
  283. agno/os/interfaces/whatsapp/router.py +210 -0
  284. agno/os/interfaces/whatsapp/security.py +55 -0
  285. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  286. agno/os/mcp.py +293 -0
  287. agno/os/middleware/__init__.py +9 -0
  288. agno/os/middleware/jwt.py +797 -0
  289. agno/os/router.py +258 -0
  290. agno/os/routers/__init__.py +3 -0
  291. agno/os/routers/agents/__init__.py +3 -0
  292. agno/os/routers/agents/router.py +599 -0
  293. agno/os/routers/agents/schema.py +261 -0
  294. agno/os/routers/evals/__init__.py +3 -0
  295. agno/os/routers/evals/evals.py +450 -0
  296. agno/os/routers/evals/schemas.py +174 -0
  297. agno/os/routers/evals/utils.py +231 -0
  298. agno/os/routers/health.py +31 -0
  299. agno/os/routers/home.py +52 -0
  300. agno/os/routers/knowledge/__init__.py +3 -0
  301. agno/os/routers/knowledge/knowledge.py +1008 -0
  302. agno/os/routers/knowledge/schemas.py +178 -0
  303. agno/os/routers/memory/__init__.py +3 -0
  304. agno/os/routers/memory/memory.py +661 -0
  305. agno/os/routers/memory/schemas.py +88 -0
  306. agno/os/routers/metrics/__init__.py +3 -0
  307. agno/os/routers/metrics/metrics.py +190 -0
  308. agno/os/routers/metrics/schemas.py +47 -0
  309. agno/os/routers/session/__init__.py +3 -0
  310. agno/os/routers/session/session.py +997 -0
  311. agno/os/routers/teams/__init__.py +3 -0
  312. agno/os/routers/teams/router.py +512 -0
  313. agno/os/routers/teams/schema.py +257 -0
  314. agno/os/routers/traces/__init__.py +3 -0
  315. agno/os/routers/traces/schemas.py +414 -0
  316. agno/os/routers/traces/traces.py +499 -0
  317. agno/os/routers/workflows/__init__.py +3 -0
  318. agno/os/routers/workflows/router.py +624 -0
  319. agno/os/routers/workflows/schema.py +75 -0
  320. agno/os/schema.py +534 -0
  321. agno/os/scopes.py +469 -0
  322. agno/{playground → os}/settings.py +7 -15
  323. agno/os/utils.py +973 -0
  324. agno/reasoning/anthropic.py +80 -0
  325. agno/reasoning/azure_ai_foundry.py +67 -0
  326. agno/reasoning/deepseek.py +63 -0
  327. agno/reasoning/default.py +97 -0
  328. agno/reasoning/gemini.py +73 -0
  329. agno/reasoning/groq.py +71 -0
  330. agno/reasoning/helpers.py +24 -1
  331. agno/reasoning/ollama.py +67 -0
  332. agno/reasoning/openai.py +86 -0
  333. agno/reasoning/step.py +2 -1
  334. agno/reasoning/vertexai.py +76 -0
  335. agno/run/__init__.py +6 -0
  336. agno/run/agent.py +822 -0
  337. agno/run/base.py +247 -0
  338. agno/run/cancel.py +81 -0
  339. agno/run/requirement.py +181 -0
  340. agno/run/team.py +767 -0
  341. agno/run/workflow.py +708 -0
  342. agno/session/__init__.py +10 -0
  343. agno/session/agent.py +260 -0
  344. agno/session/summary.py +265 -0
  345. agno/session/team.py +342 -0
  346. agno/session/workflow.py +501 -0
  347. agno/table.py +10 -0
  348. agno/team/__init__.py +37 -0
  349. agno/team/team.py +9536 -0
  350. agno/tools/__init__.py +7 -0
  351. agno/tools/agentql.py +120 -0
  352. agno/tools/airflow.py +22 -12
  353. agno/tools/api.py +122 -0
  354. agno/tools/apify.py +276 -83
  355. agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
  356. agno/tools/aws_lambda.py +28 -7
  357. agno/tools/aws_ses.py +66 -0
  358. agno/tools/baidusearch.py +11 -4
  359. agno/tools/bitbucket.py +292 -0
  360. agno/tools/brandfetch.py +213 -0
  361. agno/tools/bravesearch.py +106 -0
  362. agno/tools/brightdata.py +367 -0
  363. agno/tools/browserbase.py +209 -0
  364. agno/tools/calcom.py +32 -23
  365. agno/tools/calculator.py +24 -37
  366. agno/tools/cartesia.py +187 -0
  367. agno/tools/{clickup_tool.py → clickup.py} +17 -28
  368. agno/tools/confluence.py +91 -26
  369. agno/tools/crawl4ai.py +139 -43
  370. agno/tools/csv_toolkit.py +28 -22
  371. agno/tools/dalle.py +36 -22
  372. agno/tools/daytona.py +475 -0
  373. agno/tools/decorator.py +169 -14
  374. agno/tools/desi_vocal.py +23 -11
  375. agno/tools/discord.py +32 -29
  376. agno/tools/docker.py +716 -0
  377. agno/tools/duckdb.py +76 -81
  378. agno/tools/duckduckgo.py +43 -40
  379. agno/tools/e2b.py +703 -0
  380. agno/tools/eleven_labs.py +65 -54
  381. agno/tools/email.py +13 -5
  382. agno/tools/evm.py +129 -0
  383. agno/tools/exa.py +324 -42
  384. agno/tools/fal.py +39 -35
  385. agno/tools/file.py +196 -30
  386. agno/tools/file_generation.py +356 -0
  387. agno/tools/financial_datasets.py +288 -0
  388. agno/tools/firecrawl.py +108 -33
  389. agno/tools/function.py +960 -122
  390. agno/tools/giphy.py +34 -12
  391. agno/tools/github.py +1294 -97
  392. agno/tools/gmail.py +922 -0
  393. agno/tools/google_bigquery.py +117 -0
  394. agno/tools/google_drive.py +271 -0
  395. agno/tools/google_maps.py +253 -0
  396. agno/tools/googlecalendar.py +607 -107
  397. agno/tools/googlesheets.py +377 -0
  398. agno/tools/hackernews.py +20 -12
  399. agno/tools/jina.py +24 -14
  400. agno/tools/jira.py +48 -19
  401. agno/tools/knowledge.py +218 -0
  402. agno/tools/linear.py +82 -43
  403. agno/tools/linkup.py +58 -0
  404. agno/tools/local_file_system.py +15 -7
  405. agno/tools/lumalab.py +41 -26
  406. agno/tools/mcp/__init__.py +10 -0
  407. agno/tools/mcp/mcp.py +331 -0
  408. agno/tools/mcp/multi_mcp.py +347 -0
  409. agno/tools/mcp/params.py +24 -0
  410. agno/tools/mcp_toolbox.py +284 -0
  411. agno/tools/mem0.py +193 -0
  412. agno/tools/memory.py +419 -0
  413. agno/tools/mlx_transcribe.py +11 -9
  414. agno/tools/models/azure_openai.py +190 -0
  415. agno/tools/models/gemini.py +203 -0
  416. agno/tools/models/groq.py +158 -0
  417. agno/tools/models/morph.py +186 -0
  418. agno/tools/models/nebius.py +124 -0
  419. agno/tools/models_labs.py +163 -82
  420. agno/tools/moviepy_video.py +18 -13
  421. agno/tools/nano_banana.py +151 -0
  422. agno/tools/neo4j.py +134 -0
  423. agno/tools/newspaper.py +15 -4
  424. agno/tools/newspaper4k.py +19 -6
  425. agno/tools/notion.py +204 -0
  426. agno/tools/openai.py +181 -17
  427. agno/tools/openbb.py +27 -20
  428. agno/tools/opencv.py +321 -0
  429. agno/tools/openweather.py +233 -0
  430. agno/tools/oxylabs.py +385 -0
  431. agno/tools/pandas.py +25 -15
  432. agno/tools/parallel.py +314 -0
  433. agno/tools/postgres.py +238 -185
  434. agno/tools/pubmed.py +125 -13
  435. agno/tools/python.py +48 -35
  436. agno/tools/reasoning.py +283 -0
  437. agno/tools/reddit.py +207 -29
  438. agno/tools/redshift.py +406 -0
  439. agno/tools/replicate.py +69 -26
  440. agno/tools/resend.py +11 -6
  441. agno/tools/scrapegraph.py +179 -19
  442. agno/tools/searxng.py +23 -31
  443. agno/tools/serpapi.py +15 -10
  444. agno/tools/serper.py +255 -0
  445. agno/tools/shell.py +23 -12
  446. agno/tools/shopify.py +1519 -0
  447. agno/tools/slack.py +56 -14
  448. agno/tools/sleep.py +8 -6
  449. agno/tools/spider.py +35 -11
  450. agno/tools/spotify.py +919 -0
  451. agno/tools/sql.py +34 -19
  452. agno/tools/tavily.py +158 -8
  453. agno/tools/telegram.py +18 -8
  454. agno/tools/todoist.py +218 -0
  455. agno/tools/toolkit.py +134 -9
  456. agno/tools/trafilatura.py +388 -0
  457. agno/tools/trello.py +25 -28
  458. agno/tools/twilio.py +18 -9
  459. agno/tools/user_control_flow.py +78 -0
  460. agno/tools/valyu.py +228 -0
  461. agno/tools/visualization.py +467 -0
  462. agno/tools/webbrowser.py +28 -0
  463. agno/tools/webex.py +76 -0
  464. agno/tools/website.py +23 -19
  465. agno/tools/webtools.py +45 -0
  466. agno/tools/whatsapp.py +286 -0
  467. agno/tools/wikipedia.py +28 -19
  468. agno/tools/workflow.py +285 -0
  469. agno/tools/{twitter.py → x.py} +142 -46
  470. agno/tools/yfinance.py +41 -39
  471. agno/tools/youtube.py +34 -17
  472. agno/tools/zendesk.py +15 -5
  473. agno/tools/zep.py +454 -0
  474. agno/tools/zoom.py +86 -37
  475. agno/tracing/__init__.py +12 -0
  476. agno/tracing/exporter.py +157 -0
  477. agno/tracing/schemas.py +276 -0
  478. agno/tracing/setup.py +111 -0
  479. agno/utils/agent.py +938 -0
  480. agno/utils/audio.py +37 -1
  481. agno/utils/certs.py +27 -0
  482. agno/utils/code_execution.py +11 -0
  483. agno/utils/common.py +103 -20
  484. agno/utils/cryptography.py +22 -0
  485. agno/utils/dttm.py +33 -0
  486. agno/utils/events.py +700 -0
  487. agno/utils/functions.py +107 -37
  488. agno/utils/gemini.py +426 -0
  489. agno/utils/hooks.py +171 -0
  490. agno/utils/http.py +185 -0
  491. agno/utils/json_schema.py +159 -37
  492. agno/utils/knowledge.py +36 -0
  493. agno/utils/location.py +19 -0
  494. agno/utils/log.py +221 -8
  495. agno/utils/mcp.py +214 -0
  496. agno/utils/media.py +335 -14
  497. agno/utils/merge_dict.py +22 -1
  498. agno/utils/message.py +77 -2
  499. agno/utils/models/ai_foundry.py +50 -0
  500. agno/utils/models/claude.py +373 -0
  501. agno/utils/models/cohere.py +94 -0
  502. agno/utils/models/llama.py +85 -0
  503. agno/utils/models/mistral.py +100 -0
  504. agno/utils/models/openai_responses.py +140 -0
  505. agno/utils/models/schema_utils.py +153 -0
  506. agno/utils/models/watsonx.py +41 -0
  507. agno/utils/openai.py +257 -0
  508. agno/utils/pickle.py +1 -1
  509. agno/utils/pprint.py +124 -8
  510. agno/utils/print_response/agent.py +930 -0
  511. agno/utils/print_response/team.py +1914 -0
  512. agno/utils/print_response/workflow.py +1668 -0
  513. agno/utils/prompts.py +111 -0
  514. agno/utils/reasoning.py +108 -0
  515. agno/utils/response.py +163 -0
  516. agno/utils/serialize.py +32 -0
  517. agno/utils/shell.py +4 -4
  518. agno/utils/streamlit.py +487 -0
  519. agno/utils/string.py +204 -51
  520. agno/utils/team.py +139 -0
  521. agno/utils/timer.py +9 -2
  522. agno/utils/tokens.py +657 -0
  523. agno/utils/tools.py +19 -1
  524. agno/utils/whatsapp.py +305 -0
  525. agno/utils/yaml_io.py +3 -3
  526. agno/vectordb/__init__.py +2 -0
  527. agno/vectordb/base.py +87 -9
  528. agno/vectordb/cassandra/__init__.py +5 -1
  529. agno/vectordb/cassandra/cassandra.py +383 -27
  530. agno/vectordb/chroma/__init__.py +4 -0
  531. agno/vectordb/chroma/chromadb.py +748 -83
  532. agno/vectordb/clickhouse/__init__.py +7 -1
  533. agno/vectordb/clickhouse/clickhousedb.py +554 -53
  534. agno/vectordb/couchbase/__init__.py +3 -0
  535. agno/vectordb/couchbase/couchbase.py +1446 -0
  536. agno/vectordb/lancedb/__init__.py +5 -0
  537. agno/vectordb/lancedb/lance_db.py +730 -98
  538. agno/vectordb/langchaindb/__init__.py +5 -0
  539. agno/vectordb/langchaindb/langchaindb.py +163 -0
  540. agno/vectordb/lightrag/__init__.py +5 -0
  541. agno/vectordb/lightrag/lightrag.py +388 -0
  542. agno/vectordb/llamaindex/__init__.py +3 -0
  543. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  544. agno/vectordb/milvus/__init__.py +3 -0
  545. agno/vectordb/milvus/milvus.py +966 -78
  546. agno/vectordb/mongodb/__init__.py +9 -1
  547. agno/vectordb/mongodb/mongodb.py +1175 -172
  548. agno/vectordb/pgvector/__init__.py +8 -0
  549. agno/vectordb/pgvector/pgvector.py +599 -115
  550. agno/vectordb/pineconedb/__init__.py +5 -1
  551. agno/vectordb/pineconedb/pineconedb.py +406 -43
  552. agno/vectordb/qdrant/__init__.py +4 -0
  553. agno/vectordb/qdrant/qdrant.py +914 -61
  554. agno/vectordb/redis/__init__.py +9 -0
  555. agno/vectordb/redis/redisdb.py +682 -0
  556. agno/vectordb/singlestore/__init__.py +8 -1
  557. agno/vectordb/singlestore/singlestore.py +771 -0
  558. agno/vectordb/surrealdb/__init__.py +3 -0
  559. agno/vectordb/surrealdb/surrealdb.py +663 -0
  560. agno/vectordb/upstashdb/__init__.py +5 -0
  561. agno/vectordb/upstashdb/upstashdb.py +718 -0
  562. agno/vectordb/weaviate/__init__.py +8 -0
  563. agno/vectordb/weaviate/index.py +15 -0
  564. agno/vectordb/weaviate/weaviate.py +1009 -0
  565. agno/workflow/__init__.py +23 -1
  566. agno/workflow/agent.py +299 -0
  567. agno/workflow/condition.py +759 -0
  568. agno/workflow/loop.py +756 -0
  569. agno/workflow/parallel.py +853 -0
  570. agno/workflow/router.py +723 -0
  571. agno/workflow/step.py +1564 -0
  572. agno/workflow/steps.py +613 -0
  573. agno/workflow/types.py +556 -0
  574. agno/workflow/workflow.py +4327 -514
  575. agno-2.3.13.dist-info/METADATA +639 -0
  576. agno-2.3.13.dist-info/RECORD +613 -0
  577. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
  578. agno-2.3.13.dist-info/licenses/LICENSE +201 -0
  579. agno/api/playground.py +0 -91
  580. agno/api/schemas/playground.py +0 -22
  581. agno/api/schemas/user.py +0 -22
  582. agno/api/schemas/workspace.py +0 -46
  583. agno/api/user.py +0 -160
  584. agno/api/workspace.py +0 -151
  585. agno/cli/auth_server.py +0 -118
  586. agno/cli/config.py +0 -275
  587. agno/cli/console.py +0 -88
  588. agno/cli/credentials.py +0 -23
  589. agno/cli/entrypoint.py +0 -571
  590. agno/cli/operator.py +0 -355
  591. agno/cli/settings.py +0 -85
  592. agno/cli/ws/ws_cli.py +0 -817
  593. agno/constants.py +0 -13
  594. agno/document/__init__.py +0 -1
  595. agno/document/chunking/semantic.py +0 -47
  596. agno/document/chunking/strategy.py +0 -31
  597. agno/document/reader/__init__.py +0 -1
  598. agno/document/reader/arxiv_reader.py +0 -41
  599. agno/document/reader/base.py +0 -22
  600. agno/document/reader/csv_reader.py +0 -84
  601. agno/document/reader/docx_reader.py +0 -46
  602. agno/document/reader/firecrawl_reader.py +0 -99
  603. agno/document/reader/json_reader.py +0 -43
  604. agno/document/reader/pdf_reader.py +0 -219
  605. agno/document/reader/s3/pdf_reader.py +0 -46
  606. agno/document/reader/s3/text_reader.py +0 -51
  607. agno/document/reader/text_reader.py +0 -41
  608. agno/document/reader/website_reader.py +0 -175
  609. agno/document/reader/youtube_reader.py +0 -50
  610. agno/embedder/__init__.py +0 -1
  611. agno/embedder/azure_openai.py +0 -86
  612. agno/embedder/cohere.py +0 -72
  613. agno/embedder/fastembed.py +0 -37
  614. agno/embedder/google.py +0 -73
  615. agno/embedder/huggingface.py +0 -54
  616. agno/embedder/mistral.py +0 -80
  617. agno/embedder/ollama.py +0 -57
  618. agno/embedder/openai.py +0 -74
  619. agno/embedder/sentence_transformer.py +0 -38
  620. agno/embedder/voyageai.py +0 -64
  621. agno/eval/perf.py +0 -201
  622. agno/file/__init__.py +0 -1
  623. agno/file/file.py +0 -16
  624. agno/file/local/csv.py +0 -32
  625. agno/file/local/txt.py +0 -19
  626. agno/infra/app.py +0 -240
  627. agno/infra/base.py +0 -144
  628. agno/infra/context.py +0 -20
  629. agno/infra/db_app.py +0 -52
  630. agno/infra/resource.py +0 -205
  631. agno/infra/resources.py +0 -55
  632. agno/knowledge/agent.py +0 -230
  633. agno/knowledge/arxiv.py +0 -22
  634. agno/knowledge/combined.py +0 -22
  635. agno/knowledge/csv.py +0 -28
  636. agno/knowledge/csv_url.py +0 -19
  637. agno/knowledge/document.py +0 -20
  638. agno/knowledge/docx.py +0 -30
  639. agno/knowledge/json.py +0 -28
  640. agno/knowledge/langchain.py +0 -71
  641. agno/knowledge/llamaindex.py +0 -66
  642. agno/knowledge/pdf.py +0 -28
  643. agno/knowledge/pdf_url.py +0 -26
  644. agno/knowledge/s3/base.py +0 -60
  645. agno/knowledge/s3/pdf.py +0 -21
  646. agno/knowledge/s3/text.py +0 -23
  647. agno/knowledge/text.py +0 -30
  648. agno/knowledge/website.py +0 -88
  649. agno/knowledge/wikipedia.py +0 -31
  650. agno/knowledge/youtube.py +0 -22
  651. agno/memory/agent.py +0 -392
  652. agno/memory/classifier.py +0 -104
  653. agno/memory/db/__init__.py +0 -1
  654. agno/memory/db/base.py +0 -42
  655. agno/memory/db/mongodb.py +0 -189
  656. agno/memory/db/postgres.py +0 -203
  657. agno/memory/db/sqlite.py +0 -193
  658. agno/memory/memory.py +0 -15
  659. agno/memory/row.py +0 -36
  660. agno/memory/summarizer.py +0 -192
  661. agno/memory/summary.py +0 -19
  662. agno/memory/workflow.py +0 -38
  663. agno/models/google/gemini_openai.py +0 -26
  664. agno/models/ollama/hermes.py +0 -221
  665. agno/models/ollama/tools.py +0 -362
  666. agno/models/vertexai/gemini.py +0 -595
  667. agno/playground/__init__.py +0 -3
  668. agno/playground/async_router.py +0 -421
  669. agno/playground/deploy.py +0 -249
  670. agno/playground/operator.py +0 -92
  671. agno/playground/playground.py +0 -91
  672. agno/playground/schemas.py +0 -76
  673. agno/playground/serve.py +0 -55
  674. agno/playground/sync_router.py +0 -405
  675. agno/reasoning/agent.py +0 -68
  676. agno/run/response.py +0 -112
  677. agno/storage/agent/__init__.py +0 -0
  678. agno/storage/agent/base.py +0 -38
  679. agno/storage/agent/dynamodb.py +0 -350
  680. agno/storage/agent/json.py +0 -92
  681. agno/storage/agent/mongodb.py +0 -228
  682. agno/storage/agent/postgres.py +0 -367
  683. agno/storage/agent/session.py +0 -79
  684. agno/storage/agent/singlestore.py +0 -303
  685. agno/storage/agent/sqlite.py +0 -357
  686. agno/storage/agent/yaml.py +0 -93
  687. agno/storage/workflow/__init__.py +0 -0
  688. agno/storage/workflow/base.py +0 -40
  689. agno/storage/workflow/mongodb.py +0 -233
  690. agno/storage/workflow/postgres.py +0 -366
  691. agno/storage/workflow/session.py +0 -60
  692. agno/storage/workflow/sqlite.py +0 -359
  693. agno/tools/googlesearch.py +0 -88
  694. agno/utils/defaults.py +0 -57
  695. agno/utils/filesystem.py +0 -39
  696. agno/utils/git.py +0 -52
  697. agno/utils/json_io.py +0 -30
  698. agno/utils/load_env.py +0 -19
  699. agno/utils/py_io.py +0 -19
  700. agno/utils/pyproject.py +0 -18
  701. agno/utils/resource_filter.py +0 -31
  702. agno/vectordb/singlestore/s2vectordb.py +0 -390
  703. agno/vectordb/singlestore/s2vectordb2.py +0 -355
  704. agno/workspace/__init__.py +0 -0
  705. agno/workspace/config.py +0 -325
  706. agno/workspace/enums.py +0 -6
  707. agno/workspace/helpers.py +0 -48
  708. agno/workspace/operator.py +0 -758
  709. agno/workspace/settings.py +0 -63
  710. agno-0.1.2.dist-info/LICENSE +0 -375
  711. agno-0.1.2.dist-info/METADATA +0 -502
  712. agno-0.1.2.dist-info/RECORD +0 -352
  713. agno-0.1.2.dist-info/entry_points.txt +0 -3
  714. /agno/{cli → db/migrations}/__init__.py +0 -0
  715. /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
  716. /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
  717. /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
  718. /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
  719. /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
  720. /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
  721. /agno/{reranker → utils/models}/__init__.py +0 -0
  722. /agno/{storage → utils/print_response}/__init__.py +0 -0
  723. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/models/message.py CHANGED
@@ -1,11 +1,13 @@
1
1
  import json
2
2
  from time import time
3
3
  from typing import Any, Dict, List, Optional, Sequence, Union
4
+ from uuid import uuid4
4
5
 
5
6
  from pydantic import BaseModel, ConfigDict, Field
6
7
 
7
- from agno.media import Audio, AudioOutput, Image, Video
8
- from agno.utils.log import logger
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
9
11
 
10
12
 
11
13
  class MessageReferences(BaseModel):
@@ -14,19 +16,55 @@ class MessageReferences(BaseModel):
14
16
  # The query used to retrieve the references.
15
17
  query: str
16
18
  # References (from the vector database or function calls)
17
- references: Optional[List[Dict[str, Any]]] = None
19
+ references: Optional[List[Union[Dict[str, Any], str]]] = None
18
20
  # Time taken to retrieve the references.
19
21
  time: Optional[float] = None
20
22
 
21
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
+ # Search queries used to retrieve the citations
46
+ search_queries: Optional[List[str]] = None
47
+
48
+ # URLs of the citations.
49
+ urls: Optional[List[UrlCitation]] = None
50
+
51
+ # Document Citations
52
+ documents: Optional[List[DocumentCitation]] = None
53
+
54
+
22
55
  class Message(BaseModel):
23
56
  """Message sent to the Model"""
24
57
 
58
+ id: str = Field(default_factory=lambda: str(uuid4()))
59
+
25
60
  # The role of the message author.
26
- # One of system, developer, user, assistant, or tool.
61
+ # One of system, user, assistant, or tool.
27
62
  role: str
28
63
  # The contents of the message.
29
64
  content: Optional[Union[List[Any], str]] = None
65
+ # Compressed content of the message
66
+ compressed_content: Optional[str] = None
67
+
30
68
  # An optional name for the participant.
31
69
  # Provides the model information to differentiate between participants of the same role.
32
70
  name: Optional[str] = None
@@ -39,11 +77,26 @@ class Message(BaseModel):
39
77
  audio: Optional[Sequence[Audio]] = None
40
78
  images: Optional[Sequence[Image]] = None
41
79
  videos: Optional[Sequence[Video]] = None
80
+ files: Optional[Sequence[File]] = None
42
81
 
43
82
  # Output from the models
44
- audio_output: Optional[AudioOutput] = None
83
+ audio_output: Optional[Audio] = None
84
+ image_output: Optional[Image] = None
85
+ video_output: Optional[Video] = None
86
+ file_output: Optional[File] = None
87
+
88
+ # The thinking content from the model
89
+ redacted_reasoning_content: Optional[str] = None
90
+
91
+ # Data from the provider we might need on subsequent messages
92
+ provider_data: Optional[Dict[str, Any]] = None
93
+
94
+ # Citations received from the model
95
+ citations: Optional[Citations] = None
45
96
 
46
97
  # --- Data not sent to the Model API ---
98
+ # The reasoning content from the model
99
+ reasoning_content: Optional[str] = None
47
100
  # The name of the tool called
48
101
  tool_name: Optional[str] = None
49
102
  # Arguments passed to the tool
@@ -54,78 +107,347 @@ class Message(BaseModel):
54
107
  stop_after_tool_call: bool = False
55
108
  # When True, the message will be added to the agent's memory.
56
109
  add_to_agent_memory: bool = True
110
+ # This flag is enabled when a message is fetched from the agent's memory.
111
+ from_history: bool = False
57
112
  # Metrics for the message.
58
- metrics: Dict[str, Any] = Field(default_factory=dict)
113
+ metrics: Metrics = Field(default_factory=Metrics)
59
114
  # The references added to the message for RAG
60
115
  references: Optional[MessageReferences] = None
61
116
  # The Unix timestamp the message was created.
62
117
  created_at: int = Field(default_factory=lambda: int(time()))
118
+ # When True, the message will be sent to the Model but not persisted afterwards.
119
+ temporary: bool = False
63
120
 
64
- model_config = ConfigDict(extra="allow", populate_by_name=True)
121
+ model_config = ConfigDict(extra="allow", populate_by_name=True, arbitrary_types_allowed=True)
65
122
 
66
123
  def get_content_string(self) -> str:
67
124
  """Returns the content as a string."""
68
125
  if isinstance(self.content, str):
69
126
  return self.content
70
127
  if isinstance(self.content, list):
71
- import json
72
-
73
- return json.dumps(self.content)
128
+ if len(self.content) > 0 and isinstance(self.content[0], dict) and "text" in self.content[0]:
129
+ return self.content[0].get("text", "")
130
+ else:
131
+ return json.dumps(self.content)
74
132
  return ""
75
133
 
134
+ def get_content(self, use_compressed_content: bool = False) -> Optional[Union[List[Any], str]]:
135
+ """Return tool result content to send to API"""
136
+ if use_compressed_content and self.compressed_content is not None:
137
+ return self.compressed_content
138
+ return self.content
139
+
140
+ @classmethod
141
+ def from_dict(cls, data: Dict[str, Any]) -> "Message":
142
+ # Handle image reconstruction properly
143
+ if "images" in data and data["images"]:
144
+ reconstructed_images = []
145
+ for i, img_data in enumerate(data["images"]):
146
+ if isinstance(img_data, dict):
147
+ # If content is base64, decode it back to bytes
148
+ if "content" in img_data and isinstance(img_data["content"], str):
149
+ reconstructed_images.append(
150
+ Image.from_base64(
151
+ img_data["content"],
152
+ id=img_data.get("id"),
153
+ mime_type=img_data.get("mime_type"),
154
+ format=img_data.get("format"),
155
+ )
156
+ )
157
+ else:
158
+ # Regular image (filepath/url)
159
+ reconstructed_images.append(Image(**img_data))
160
+ else:
161
+ reconstructed_images.append(img_data)
162
+ data["images"] = reconstructed_images
163
+
164
+ # Handle audio reconstruction properly
165
+ if "audio" in data and data["audio"]:
166
+ reconstructed_audio = []
167
+ for i, aud_data in enumerate(data["audio"]):
168
+ if isinstance(aud_data, dict):
169
+ # If content is base64, decode it back to bytes
170
+ if "content" in aud_data and isinstance(aud_data["content"], str):
171
+ reconstructed_audio.append(
172
+ Audio.from_base64(
173
+ aud_data["content"],
174
+ id=aud_data.get("id"),
175
+ mime_type=aud_data.get("mime_type"),
176
+ transcript=aud_data.get("transcript"),
177
+ expires_at=aud_data.get("expires_at"),
178
+ sample_rate=aud_data.get("sample_rate", 24000),
179
+ channels=aud_data.get("channels", 1),
180
+ )
181
+ )
182
+ else:
183
+ reconstructed_audio.append(Audio(**aud_data))
184
+ else:
185
+ reconstructed_audio.append(aud_data)
186
+ data["audio"] = reconstructed_audio
187
+
188
+ # Handle video reconstruction properly
189
+ if "videos" in data and data["videos"]:
190
+ reconstructed_videos = []
191
+ for i, vid_data in enumerate(data["videos"]):
192
+ if isinstance(vid_data, dict):
193
+ # If content is base64, decode it back to bytes
194
+ if "content" in vid_data and isinstance(vid_data["content"], str):
195
+ reconstructed_videos.append(
196
+ Video.from_base64(
197
+ vid_data["content"],
198
+ id=vid_data.get("id"),
199
+ mime_type=vid_data.get("mime_type"),
200
+ format=vid_data.get("format"),
201
+ )
202
+ )
203
+ else:
204
+ reconstructed_videos.append(Video(**vid_data))
205
+ else:
206
+ reconstructed_videos.append(vid_data)
207
+ data["videos"] = reconstructed_videos
208
+
209
+ # Handle file reconstruction properly
210
+ if "files" in data and data["files"]:
211
+ reconstructed_files = []
212
+ for i, file_data in enumerate(data["files"]):
213
+ if isinstance(file_data, dict):
214
+ # If content is base64, decode it back to bytes
215
+ if "content" in file_data and isinstance(file_data["content"], str):
216
+ reconstructed_files.append(
217
+ File.from_base64(
218
+ file_data["content"],
219
+ id=file_data.get("id"),
220
+ mime_type=file_data.get("mime_type"),
221
+ filename=file_data.get("filename"),
222
+ name=file_data.get("name"),
223
+ format=file_data.get("format"),
224
+ )
225
+ )
226
+ else:
227
+ reconstructed_files.append(File(**file_data))
228
+ else:
229
+ reconstructed_files.append(file_data)
230
+ data["files"] = reconstructed_files
231
+
232
+ if "audio_output" in data and data["audio_output"]:
233
+ aud_data = data["audio_output"]
234
+ if isinstance(aud_data, dict):
235
+ if "content" in aud_data and isinstance(aud_data["content"], str):
236
+ data["audio_output"] = Audio.from_base64(
237
+ aud_data["content"],
238
+ id=aud_data.get("id"),
239
+ mime_type=aud_data.get("mime_type"),
240
+ transcript=aud_data.get("transcript"),
241
+ expires_at=aud_data.get("expires_at"),
242
+ sample_rate=aud_data.get("sample_rate", 24000),
243
+ channels=aud_data.get("channels", 1),
244
+ )
245
+ else:
246
+ data["audio_output"] = Audio(**aud_data)
247
+
248
+ if "image_output" in data and data["image_output"]:
249
+ img_data = data["image_output"]
250
+ if isinstance(img_data, dict):
251
+ if "content" in img_data and isinstance(img_data["content"], str):
252
+ data["image_output"] = Image.from_base64(
253
+ img_data["content"],
254
+ id=img_data.get("id"),
255
+ mime_type=img_data.get("mime_type"),
256
+ format=img_data.get("format"),
257
+ )
258
+ else:
259
+ data["image_output"] = Image(**img_data)
260
+
261
+ if "video_output" in data and data["video_output"]:
262
+ vid_data = data["video_output"]
263
+ if isinstance(vid_data, dict):
264
+ if "content" in vid_data and isinstance(vid_data["content"], str):
265
+ data["video_output"] = Video.from_base64(
266
+ vid_data["content"],
267
+ id=vid_data.get("id"),
268
+ mime_type=vid_data.get("mime_type"),
269
+ format=vid_data.get("format"),
270
+ )
271
+ else:
272
+ data["video_output"] = Video(**vid_data)
273
+
274
+ return cls(**data)
275
+
76
276
  def to_dict(self) -> Dict[str, Any]:
77
- _dict = self.model_dump(
78
- exclude_none=True,
79
- include={"role", "content", "audio", "name", "tool_call_id", "tool_calls"},
80
- )
277
+ """Returns the message as a dictionary."""
278
+ message_dict = {
279
+ "id": self.id,
280
+ "content": self.content,
281
+ "reasoning_content": self.reasoning_content,
282
+ "from_history": self.from_history,
283
+ "compressed_content": self.compressed_content,
284
+ "stop_after_tool_call": self.stop_after_tool_call,
285
+ "role": self.role,
286
+ "name": self.name,
287
+ "tool_call_id": self.tool_call_id,
288
+ "tool_name": self.tool_name,
289
+ "tool_args": self.tool_args,
290
+ "tool_call_error": self.tool_call_error,
291
+ "tool_calls": self.tool_calls,
292
+ "redacted_reasoning_content": self.redacted_reasoning_content,
293
+ "provider_data": self.provider_data,
294
+ }
295
+ # Filter out None and empty collections
296
+ message_dict = {
297
+ k: v for k, v in message_dict.items() if v is not None and not (isinstance(v, (list, dict)) and len(v) == 0)
298
+ }
299
+
300
+ # Convert media objects to dictionaries
301
+ if self.images:
302
+ message_dict["images"] = [img.to_dict() for img in self.images]
303
+ if self.audio:
304
+ message_dict["audio"] = [aud.to_dict() for aud in self.audio]
305
+ if self.videos:
306
+ message_dict["videos"] = [vid.to_dict() for vid in self.videos]
307
+ if self.files:
308
+ message_dict["files"] = [file.to_dict() for file in self.files]
309
+ if self.audio_output:
310
+ message_dict["audio_output"] = self.audio_output.to_dict()
81
311
 
82
- # Add a message's output as now input (for multi-turn audio)
83
- if self.audio_output is not None:
84
- _dict["content"] = None
85
- _dict["audio"] = {"id": self.audio_output.id}
312
+ if self.references:
313
+ message_dict["references"] = self.references.model_dump()
314
+ if self.metrics:
315
+ message_dict["metrics"] = self.metrics.to_dict()
316
+ if not message_dict["metrics"]:
317
+ message_dict.pop("metrics")
86
318
 
87
- # Manually add the content field even if it is None
88
- if self.content is None:
89
- _dict["content"] = None
319
+ message_dict["created_at"] = self.created_at
320
+ return message_dict
90
321
 
91
- return _dict
322
+ def to_function_call_dict(self) -> Dict[str, Any]:
323
+ return {
324
+ "content": self.content,
325
+ "tool_call_id": self.tool_call_id,
326
+ "tool_name": self.tool_name,
327
+ "tool_args": self.tool_args,
328
+ "tool_call_error": self.tool_call_error,
329
+ "metrics": self.metrics,
330
+ "created_at": self.created_at,
331
+ }
92
332
 
93
- def log(self, level: Optional[str] = None):
333
+ def log(self, metrics: bool = True, level: Optional[str] = None, use_compressed_content: bool = False):
94
334
  """Log the message to the console
95
335
 
96
- @param level: The level to log the message at. One of debug, info, warning, or error.
97
- Defaults to debug.
336
+ Args:
337
+ metrics (bool): Whether to log the metrics.
338
+ level (str): The level to log the message at. One of debug, info, warning, or error.
339
+ Defaults to debug.
340
+ use_compressed_content (bool): Whether to use compressed content.
98
341
  """
99
- _logger = logger.debug
100
- if level == "debug":
101
- _logger = logger.debug
102
- elif level == "info":
103
- _logger = logger.info
342
+ _logger = log_debug
343
+ if level == "info":
344
+ _logger = log_info
104
345
  elif level == "warning":
105
- _logger = logger.warning
346
+ _logger = log_warning
106
347
  elif level == "error":
107
- _logger = logger.error
348
+ _logger = log_error
349
+
350
+ try:
351
+ import shutil
352
+
353
+ terminal_width = shutil.get_terminal_size().columns
354
+ except Exception:
355
+ terminal_width = 80 # fallback width
356
+
357
+ header = f" {self.role} "
358
+ _logger(f"{header.center(terminal_width - 20, '=')}")
108
359
 
109
- _logger(f"============== {self.role} ==============")
110
360
  if self.name:
111
361
  _logger(f"Name: {self.name}")
112
362
  if self.tool_call_id:
113
363
  _logger(f"Tool call Id: {self.tool_call_id}")
364
+ if self.reasoning_content:
365
+ _logger(f"<reasoning>\n{self.reasoning_content}\n</reasoning>")
114
366
  if self.content:
115
- if isinstance(self.content, str) or isinstance(self.content, list):
116
- _logger(self.content)
117
- elif isinstance(self.content, dict):
118
- _logger(json.dumps(self.content, indent=2))
367
+ if use_compressed_content and self.compressed_content:
368
+ _logger("Compressed content:\n" + self.compressed_content)
369
+ else:
370
+ if isinstance(self.content, str) or isinstance(self.content, list):
371
+ _logger(self.content)
372
+ elif isinstance(self.content, dict):
373
+ _logger(json.dumps(self.content, indent=2))
119
374
  if self.tool_calls:
120
- _logger(f"Tool Calls: {json.dumps(self.tool_calls, indent=2)}")
375
+ tool_calls_list = ["Tool Calls:"]
376
+ for tool_call in self.tool_calls:
377
+ tool_id = tool_call.get("id")
378
+ function_name = tool_call.get("function", {}).get("name")
379
+ tool_calls_list.append(f" - ID: '{tool_id}'") if tool_id else None
380
+ tool_calls_list.append(f" Name: '{function_name}'") if function_name else None
381
+ tool_call_arguments = tool_call.get("function", {}).get("arguments")
382
+ if tool_call_arguments:
383
+ try:
384
+ tool_call_args: dict = (
385
+ tool_call_arguments
386
+ if isinstance(tool_call_arguments, dict)
387
+ else json.loads(tool_call_arguments)
388
+ )
389
+ if tool_call_args:
390
+ # Ensure tool_call_args is a dictionary before calling .items()
391
+ if isinstance(tool_call_args, dict):
392
+ arguments = ", ".join(f"{k}: {v}" for k, v in tool_call_args.items())
393
+ tool_calls_list.append(f" Arguments: '{arguments}'")
394
+ else:
395
+ tool_calls_list.append(f" Arguments: '{tool_call_args}'")
396
+ except json.JSONDecodeError:
397
+ tool_calls_list.append(" Arguments: 'Invalid JSON format'")
398
+ tool_calls_str = "\n".join(tool_calls_list)
399
+
400
+ _logger(tool_calls_str)
121
401
  if self.images:
122
402
  _logger(f"Images added: {len(self.images)}")
123
403
  if self.videos:
124
404
  _logger(f"Videos added: {len(self.videos)}")
125
405
  if self.audio:
126
406
  _logger(f"Audio Files added: {len(self.audio)}")
407
+ if self.files:
408
+ _logger(f"Files added: {len(self.files)}")
409
+
410
+ metrics_header = " TOOL METRICS " if self.role == "tool" else " METRICS "
411
+ if metrics and self.metrics is not None and self.metrics != Metrics():
412
+ _logger(metrics_header, center=True, symbol="*")
413
+
414
+ # Token metrics
415
+ token_metrics = []
416
+ if self.metrics.input_tokens and self.metrics.input_tokens > 0:
417
+ token_metrics.append(f"input={self.metrics.input_tokens}")
418
+ if self.metrics.output_tokens and self.metrics.output_tokens > 0:
419
+ token_metrics.append(f"output={self.metrics.output_tokens}")
420
+ if self.metrics.total_tokens and self.metrics.total_tokens > 0:
421
+ token_metrics.append(f"total={self.metrics.total_tokens}")
422
+ if self.metrics.cache_read_tokens and self.metrics.cache_read_tokens > 0:
423
+ token_metrics.append(f"cached={self.metrics.cache_read_tokens}")
424
+ if self.metrics.cache_write_tokens and self.metrics.cache_write_tokens > 0:
425
+ token_metrics.append(f"cache_write_tokens={self.metrics.cache_write_tokens}")
426
+ if self.metrics.reasoning_tokens and self.metrics.reasoning_tokens > 0:
427
+ token_metrics.append(f"reasoning={self.metrics.reasoning_tokens}")
428
+ if self.metrics.audio_total_tokens and self.metrics.audio_total_tokens > 0:
429
+ token_metrics.append(f"audio={self.metrics.audio_total_tokens}")
430
+ if token_metrics:
431
+ _logger(f"* Tokens: {', '.join(token_metrics)}")
432
+
433
+ # Time related metrics
434
+ if self.metrics.duration is not None and self.metrics.duration > 0:
435
+ _logger(f"* Duration: {self.metrics.duration:.4f}s")
436
+ if self.metrics.output_tokens and self.metrics.duration and self.metrics.duration > 0:
437
+ _logger(
438
+ f"* Tokens per second: {self.metrics.output_tokens / self.metrics.duration:.4f} tokens/s"
439
+ )
440
+ if self.metrics.time_to_first_token is not None and self.metrics.time_to_first_token > 0:
441
+ _logger(f"* Time to first token: {self.metrics.time_to_first_token:.4f}s")
442
+
443
+ # Non-generic metrics
444
+ if self.metrics.provider_metrics:
445
+ _logger(f"* Provider metrics: {self.metrics.provider_metrics}")
446
+ if self.metrics.additional_metrics:
447
+ _logger(f"* Additional metrics: {self.metrics.additional_metrics}")
448
+
449
+ _logger(metrics_header, center=True, symbol="*")
127
450
 
128
451
  def content_is_valid(self) -> bool:
129
452
  """Check if the message content is valid."""
130
-
131
453
  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"]