agno 1.8.0__py3-none-any.whl → 2.0.0a1__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 (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2781 -4126
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +9 -64
  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/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1749 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1438 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +888 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1051 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1417 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +10 -10
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1515 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/media.py +2 -2
  137. agno/memory/__init__.py +2 -10
  138. agno/memory/manager.py +1003 -148
  139. agno/models/aimlapi/__init__.py +2 -2
  140. agno/models/aimlapi/aimlapi.py +6 -6
  141. agno/models/anthropic/claude.py +129 -82
  142. agno/models/aws/bedrock.py +107 -175
  143. agno/models/aws/claude.py +64 -18
  144. agno/models/azure/ai_foundry.py +73 -23
  145. agno/models/base.py +347 -287
  146. agno/models/cerebras/cerebras.py +84 -27
  147. agno/models/cohere/chat.py +106 -98
  148. agno/models/dashscope/dashscope.py +14 -5
  149. agno/models/google/gemini.py +123 -53
  150. agno/models/groq/groq.py +97 -35
  151. agno/models/huggingface/huggingface.py +92 -27
  152. agno/models/ibm/watsonx.py +72 -13
  153. agno/models/litellm/chat.py +85 -13
  154. agno/models/message.py +38 -144
  155. agno/models/meta/llama.py +85 -49
  156. agno/models/metrics.py +120 -0
  157. agno/models/mistral/mistral.py +90 -21
  158. agno/models/ollama/__init__.py +0 -2
  159. agno/models/ollama/chat.py +84 -46
  160. agno/models/openai/chat.py +135 -27
  161. agno/models/openai/responses.py +233 -115
  162. agno/models/perplexity/perplexity.py +26 -2
  163. agno/models/portkey/portkey.py +0 -7
  164. agno/models/response.py +14 -8
  165. agno/models/utils.py +20 -0
  166. agno/models/vercel/__init__.py +2 -2
  167. agno/models/vercel/v0.py +1 -1
  168. agno/models/vllm/__init__.py +2 -2
  169. agno/models/vllm/vllm.py +3 -3
  170. agno/models/xai/xai.py +10 -10
  171. agno/os/__init__.py +3 -0
  172. agno/os/app.py +393 -0
  173. agno/os/auth.py +47 -0
  174. agno/os/config.py +103 -0
  175. agno/os/interfaces/agui/__init__.py +3 -0
  176. agno/os/interfaces/agui/agui.py +31 -0
  177. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  178. agno/{app → os/interfaces}/agui/utils.py +65 -28
  179. agno/os/interfaces/base.py +21 -0
  180. agno/os/interfaces/slack/__init__.py +3 -0
  181. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  182. agno/os/interfaces/slack/slack.py +33 -0
  183. agno/os/interfaces/whatsapp/__init__.py +3 -0
  184. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  185. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  186. agno/os/router.py +843 -0
  187. agno/os/routers/__init__.py +3 -0
  188. agno/os/routers/evals/__init__.py +3 -0
  189. agno/os/routers/evals/evals.py +204 -0
  190. agno/os/routers/evals/schemas.py +142 -0
  191. agno/os/routers/evals/utils.py +161 -0
  192. agno/os/routers/knowledge/__init__.py +3 -0
  193. agno/os/routers/knowledge/knowledge.py +413 -0
  194. agno/os/routers/knowledge/schemas.py +118 -0
  195. agno/os/routers/memory/__init__.py +3 -0
  196. agno/os/routers/memory/memory.py +179 -0
  197. agno/os/routers/memory/schemas.py +58 -0
  198. agno/os/routers/metrics/__init__.py +3 -0
  199. agno/os/routers/metrics/metrics.py +58 -0
  200. agno/os/routers/metrics/schemas.py +47 -0
  201. agno/os/routers/session/__init__.py +3 -0
  202. agno/os/routers/session/session.py +163 -0
  203. agno/os/schema.py +892 -0
  204. agno/{app/playground → os}/settings.py +8 -15
  205. agno/os/utils.py +270 -0
  206. agno/reasoning/azure_ai_foundry.py +4 -4
  207. agno/reasoning/deepseek.py +4 -4
  208. agno/reasoning/default.py +6 -11
  209. agno/reasoning/groq.py +4 -4
  210. agno/reasoning/helpers.py +4 -6
  211. agno/reasoning/ollama.py +4 -4
  212. agno/reasoning/openai.py +4 -4
  213. agno/run/{response.py → agent.py} +144 -72
  214. agno/run/base.py +44 -58
  215. agno/run/cancel.py +83 -0
  216. agno/run/team.py +133 -77
  217. agno/run/workflow.py +537 -12
  218. agno/session/__init__.py +10 -0
  219. agno/session/agent.py +244 -0
  220. agno/session/summary.py +225 -0
  221. agno/session/team.py +262 -0
  222. agno/{storage/session/v2 → session}/workflow.py +47 -24
  223. agno/team/__init__.py +15 -16
  224. agno/team/team.py +2967 -4243
  225. agno/tools/agentql.py +14 -5
  226. agno/tools/airflow.py +9 -4
  227. agno/tools/api.py +7 -3
  228. agno/tools/apify.py +2 -46
  229. agno/tools/arxiv.py +8 -3
  230. agno/tools/aws_lambda.py +7 -5
  231. agno/tools/aws_ses.py +7 -1
  232. agno/tools/baidusearch.py +4 -1
  233. agno/tools/bitbucket.py +4 -4
  234. agno/tools/brandfetch.py +14 -11
  235. agno/tools/bravesearch.py +4 -1
  236. agno/tools/brightdata.py +42 -22
  237. agno/tools/browserbase.py +13 -4
  238. agno/tools/calcom.py +12 -10
  239. agno/tools/calculator.py +10 -27
  240. agno/tools/cartesia.py +18 -13
  241. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  242. agno/tools/confluence.py +71 -18
  243. agno/tools/crawl4ai.py +7 -1
  244. agno/tools/csv_toolkit.py +9 -8
  245. agno/tools/dalle.py +18 -11
  246. agno/tools/daytona.py +13 -16
  247. agno/tools/decorator.py +6 -3
  248. agno/tools/desi_vocal.py +16 -7
  249. agno/tools/discord.py +11 -8
  250. agno/tools/docker.py +30 -42
  251. agno/tools/duckdb.py +34 -53
  252. agno/tools/duckduckgo.py +8 -7
  253. agno/tools/e2b.py +62 -62
  254. agno/tools/eleven_labs.py +35 -28
  255. agno/tools/email.py +4 -1
  256. agno/tools/evm.py +7 -1
  257. agno/tools/exa.py +19 -14
  258. agno/tools/fal.py +29 -29
  259. agno/tools/file.py +9 -8
  260. agno/tools/financial_datasets.py +25 -44
  261. agno/tools/firecrawl.py +22 -22
  262. agno/tools/function.py +68 -17
  263. agno/tools/giphy.py +22 -10
  264. agno/tools/github.py +48 -126
  265. agno/tools/gmail.py +46 -62
  266. agno/tools/google_bigquery.py +7 -6
  267. agno/tools/google_maps.py +11 -26
  268. agno/tools/googlesearch.py +7 -2
  269. agno/tools/googlesheets.py +21 -17
  270. agno/tools/hackernews.py +9 -5
  271. agno/tools/jina.py +5 -4
  272. agno/tools/jira.py +18 -9
  273. agno/tools/knowledge.py +31 -32
  274. agno/tools/linear.py +18 -33
  275. agno/tools/linkup.py +5 -1
  276. agno/tools/local_file_system.py +8 -5
  277. agno/tools/lumalab.py +31 -19
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +32 -14
  282. agno/tools/models/gemini.py +58 -31
  283. agno/tools/models/groq.py +29 -20
  284. agno/tools/models/nebius.py +27 -11
  285. agno/tools/models_labs.py +39 -15
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +134 -0
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +57 -26
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +62 -46
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +54 -41
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +95 -118
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/location.py +2 -2
  337. agno/utils/log.py +2 -2
  338. agno/utils/mcp.py +11 -5
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/claude.py +6 -4
  342. agno/utils/models/mistral.py +8 -7
  343. agno/utils/models/schema_utils.py +3 -3
  344. agno/utils/pprint.py +33 -32
  345. agno/utils/print_response/agent.py +779 -0
  346. agno/utils/print_response/team.py +1565 -0
  347. agno/utils/print_response/workflow.py +1451 -0
  348. agno/utils/prompts.py +14 -14
  349. agno/utils/reasoning.py +87 -0
  350. agno/utils/response.py +42 -42
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +356 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2394 -696
  383. agno-2.0.0a1.dist-info/METADATA +355 -0
  384. agno-2.0.0a1.dist-info/RECORD +514 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -698
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.0.dist-info/METADATA +0 -979
  568. agno-1.8.0.dist-info/RECORD +0 -565
  569. agno-1.8.0.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
agno/models/response.py CHANGED
@@ -3,8 +3,9 @@ from enum import Enum
3
3
  from time import time
4
4
  from typing import Any, Dict, List, Optional
5
5
 
6
- from agno.media import AudioResponse, ImageArtifact
7
- from agno.models.message import Citations, MessageMetrics
6
+ from agno.media import AudioArtifact, AudioResponse, ImageArtifact, VideoArtifact
7
+ from agno.models.message import Citations
8
+ from agno.models.metrics import Metrics
8
9
  from agno.tools.function import UserInputField
9
10
 
10
11
 
@@ -26,7 +27,7 @@ class ToolExecution:
26
27
  tool_args: Optional[Dict[str, Any]] = None
27
28
  tool_call_error: Optional[bool] = None
28
29
  result: Optional[str] = None
29
- metrics: Optional[MessageMetrics] = None
30
+ metrics: Optional[Metrics] = None
30
31
 
31
32
  # If True, the agent will stop executing after this tool call.
32
33
  stop_after_tool_call: bool = False
@@ -74,7 +75,7 @@ class ToolExecution:
74
75
  if "user_input_schema" in data
75
76
  else None,
76
77
  external_execution_required=data.get("external_execution_required"),
77
- metrics=MessageMetrics(**(data.get("metrics", {}) or {})),
78
+ metrics=Metrics(**(data.get("metrics", {}) or {})),
78
79
  )
79
80
 
80
81
 
@@ -87,7 +88,11 @@ class ModelResponse:
87
88
  content: Optional[Any] = None
88
89
  parsed: Optional[Any] = None
89
90
  audio: Optional[AudioResponse] = None
90
- image: Optional[ImageArtifact] = None
91
+
92
+ # Unified media fields for LLM-generated and tool-generated media artifacts
93
+ images: Optional[List[ImageArtifact]] = None
94
+ videos: Optional[List[VideoArtifact]] = None
95
+ audios: Optional[List[AudioArtifact]] = None
91
96
 
92
97
  # Model tool calls
93
98
  tool_calls: List[Dict[str, Any]] = field(default_factory=list)
@@ -99,18 +104,19 @@ class ModelResponse:
99
104
 
100
105
  provider_data: Optional[Dict[str, Any]] = None
101
106
 
102
- thinking: Optional[str] = None
103
- redacted_thinking: Optional[str] = None
107
+ redacted_reasoning_content: Optional[str] = None
104
108
  reasoning_content: Optional[str] = None
105
109
 
106
110
  citations: Optional[Citations] = None
107
111
 
108
- response_usage: Optional[Any] = None
112
+ response_usage: Optional[Metrics] = None
109
113
 
110
114
  created_at: int = int(time())
111
115
 
112
116
  extra: Optional[Dict[str, Any]] = None
113
117
 
118
+ updated_session_state: Optional[Dict[str, Any]] = None
119
+
114
120
 
115
121
  class FileType(str, Enum):
116
122
  MP4 = "mp4"
agno/models/utils.py ADDED
@@ -0,0 +1,20 @@
1
+ from agno.models.base import Model
2
+
3
+
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
9
+
10
+ return OpenAIChat(id=model_id)
11
+ elif model_provider == "anthropic":
12
+ from agno.models.anthropic import Claude
13
+
14
+ return Claude(id=model_id)
15
+ elif model_provider == "gemini":
16
+ from agno.models.google import Gemini
17
+
18
+ return Gemini(id=model_id)
19
+ else:
20
+ raise ValueError(f"Model provider {model_provider} not supported")
@@ -1,3 +1,3 @@
1
- from agno.models.vercel.v0 import v0
1
+ from agno.models.vercel.v0 import V0
2
2
 
3
- __all__ = ["v0"]
3
+ __all__ = ["V0"]
agno/models/vercel/v0.py CHANGED
@@ -6,7 +6,7 @@ from agno.models.openai.like import OpenAILike
6
6
 
7
7
 
8
8
  @dataclass
9
- class v0(OpenAILike):
9
+ class V0(OpenAILike):
10
10
  """
11
11
  Class for interacting with the v0 API.
12
12
 
@@ -1,3 +1,3 @@
1
- from agno.models.vllm.vllm import vLLM
1
+ from agno.models.vllm.vllm import VLLM
2
2
 
3
- __all__ = ["vLLM"]
3
+ __all__ = ["VLLM"]
agno/models/vllm/vllm.py CHANGED
@@ -9,7 +9,7 @@ from agno.utils.log import log_debug
9
9
 
10
10
 
11
11
  @dataclass
12
- class vLLM(OpenAILike):
12
+ class VLLM(OpenAILike):
13
13
  """
14
14
  Class for interacting with vLLM models via OpenAI-compatible API.
15
15
 
@@ -26,8 +26,8 @@ class vLLM(OpenAILike):
26
26
  """
27
27
 
28
28
  id: str = "not-set"
29
- name: str = "vLLM"
30
- provider: str = "vLLM"
29
+ name: str = "VLLM"
30
+ provider: str = "VLLM"
31
31
 
32
32
  api_key: Optional[str] = getenv("VLLM_API_KEY") or "EMPTY"
33
33
  base_url: Optional[str] = getenv("VLLM_BASE_URL", "http://localhost:8000/v1/")
agno/models/xai/xai.py CHANGED
@@ -65,7 +65,7 @@ class xAI(OpenAILike):
65
65
 
66
66
  return request_params
67
67
 
68
- def parse_provider_response(
68
+ def _parse_provider_response(
69
69
  self,
70
70
  response: ChatCompletion,
71
71
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
@@ -73,21 +73,21 @@ class xAI(OpenAILike):
73
73
  """
74
74
  Parse the xAI response into a ModelResponse.
75
75
  """
76
- model_response = super().parse_provider_response(response, response_format)
76
+ model_response = super()._parse_provider_response(response, response_format)
77
77
 
78
- if hasattr(response, "citations") and response.citations:
78
+ if hasattr(response, "citations") and response.citations: # type: ignore
79
79
  citations = Citations()
80
80
  url_citations = []
81
- for citation_url in response.citations:
81
+ for citation_url in response.citations: # type: ignore
82
82
  url_citations.append(UrlCitation(url=str(citation_url)))
83
83
 
84
84
  citations.urls = url_citations
85
- citations.raw = response.citations
85
+ citations.raw = response.citations # type: ignore
86
86
  model_response.citations = citations
87
87
 
88
88
  return model_response
89
89
 
90
- def parse_provider_response_delta(self, response_delta: ChatCompletionChunk) -> ModelResponse:
90
+ def _parse_provider_response_delta(self, response_delta: ChatCompletionChunk) -> ModelResponse:
91
91
  """
92
92
  Parse the xAI streaming response.
93
93
 
@@ -97,16 +97,16 @@ class xAI(OpenAILike):
97
97
  Returns:
98
98
  ModelResponse: Parsed response data
99
99
  """
100
- model_response = super().parse_provider_response_delta(response_delta)
100
+ model_response = super()._parse_provider_response_delta(response_delta)
101
101
 
102
- if hasattr(response_delta, "citations") and response_delta.citations:
102
+ if hasattr(response_delta, "citations") and response_delta.citations: # type: ignore
103
103
  citations = Citations()
104
104
  url_citations = []
105
- for citation_url in response_delta.citations:
105
+ for citation_url in response_delta.citations: # type: ignore
106
106
  url_citations.append(UrlCitation(url=str(citation_url)))
107
107
 
108
108
  citations.urls = url_citations
109
- citations.raw = response_delta.citations
109
+ citations.raw = response_delta.citations # type: ignore
110
110
  model_response.citations = citations
111
111
 
112
112
  return model_response
agno/os/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ from agno.os.app import AgentOS
2
+
3
+ __all__ = ["AgentOS"]
agno/os/app.py ADDED
@@ -0,0 +1,393 @@
1
+ from os import getenv
2
+ from typing import Any, Dict, List, Optional, Tuple, Union
3
+ from uuid import uuid4
4
+
5
+ from fastapi import FastAPI, HTTPException
6
+ from fastapi.responses import JSONResponse
7
+ from rich import box
8
+ from rich.panel import Panel
9
+ from starlette.middleware.cors import CORSMiddleware
10
+ from starlette.requests import Request
11
+
12
+ from agno.agent.agent import Agent
13
+ from agno.os.config import (
14
+ AgentOSConfig,
15
+ DatabaseConfig,
16
+ EvalsConfig,
17
+ EvalsDomainConfig,
18
+ KnowledgeConfig,
19
+ KnowledgeDomainConfig,
20
+ MemoryConfig,
21
+ MemoryDomainConfig,
22
+ MetricsConfig,
23
+ MetricsDomainConfig,
24
+ SessionConfig,
25
+ SessionDomainConfig,
26
+ )
27
+ from agno.os.interfaces.base import BaseInterface
28
+ from agno.os.router import get_base_router
29
+ from agno.os.routers.evals import get_eval_router
30
+ from agno.os.routers.knowledge import get_knowledge_router
31
+ from agno.os.routers.memory import get_memory_router
32
+ from agno.os.routers.metrics import get_metrics_router
33
+ from agno.os.routers.session import get_session_router
34
+ from agno.os.settings import AgnoAPISettings
35
+ from agno.os.utils import generate_id
36
+ from agno.team.team import Team
37
+ from agno.workflow.workflow import Workflow
38
+
39
+
40
+ class AgentOS:
41
+ host_url: Optional[str] = None
42
+
43
+ def __init__(
44
+ self,
45
+ os_id: Optional[str] = None,
46
+ description: Optional[str] = None,
47
+ agents: Optional[List[Agent]] = None,
48
+ teams: Optional[List[Team]] = None,
49
+ workflows: Optional[List[Workflow]] = None,
50
+ interfaces: Optional[List[BaseInterface]] = None,
51
+ config: Optional[Union[str, AgentOSConfig]] = None,
52
+ settings: Optional[AgnoAPISettings] = None,
53
+ fastapi_app: Optional[FastAPI] = None,
54
+ telemetry: bool = True,
55
+ ):
56
+ if not agents and not workflows and not teams:
57
+ raise ValueError("Either agents, teams or workflows must be provided.")
58
+
59
+ self.config = self._load_yaml_config(config) if isinstance(config, str) else config
60
+ self.description = description
61
+
62
+ self.agents: Optional[List[Agent]] = agents
63
+ self.workflows: Optional[List[Workflow]] = workflows
64
+ self.teams: Optional[List[Team]] = teams
65
+ self.interfaces = interfaces or []
66
+
67
+ self.settings: AgnoAPISettings = settings or AgnoAPISettings()
68
+ self.fastapi_app: Optional[FastAPI] = fastapi_app
69
+
70
+ self.interfaces = interfaces or []
71
+
72
+ self.os_id: Optional[str] = os_id
73
+ self.description = description
74
+
75
+ self.telemetry = telemetry
76
+
77
+ self.interfaces_loaded: List[Tuple[str, str]] = []
78
+
79
+ if self.agents:
80
+ for agent in self.agents:
81
+ agent.initialize_agent()
82
+
83
+ # Required for the built-in routes to work
84
+ agent.store_events = True
85
+
86
+ if self.teams:
87
+ for team in self.teams:
88
+ team.initialize_team()
89
+
90
+ # Required for the built-in routes to work
91
+ team.store_events = True
92
+
93
+ for member in team.members:
94
+ if isinstance(member, Agent):
95
+ member.team_id = None
96
+ member.initialize_agent()
97
+ elif isinstance(member, Team):
98
+ member.initialize_team()
99
+
100
+ if self.workflows:
101
+ for workflow in self.workflows:
102
+ if not workflow.id:
103
+ workflow.id = generate_id(workflow.name)
104
+
105
+ if self.telemetry:
106
+ from agno.api.os import OSLaunch, log_os_telemetry
107
+
108
+ log_os_telemetry(launch=OSLaunch(os_id=self.os_id, data=self._get_telemetry_data()))
109
+
110
+ def _get_telemetry_data(self) -> Dict[str, Any]:
111
+ """Get the telemetry data for the OS"""
112
+ return {
113
+ "agents": [agent.id for agent in self.agents] if self.agents else None,
114
+ "teams": [team.id for team in self.teams] if self.teams else None,
115
+ "workflows": [workflow.id for workflow in self.workflows] if self.workflows else None,
116
+ "interfaces": [interface.type for interface in self.interfaces] if self.interfaces else None,
117
+ }
118
+
119
+ def _load_yaml_config(self, config_file_path: str) -> AgentOSConfig:
120
+ """Load a YAML config file and return the configuration as an AgentOSConfig instance."""
121
+ from pathlib import Path
122
+
123
+ import yaml
124
+
125
+ # Validate that the path points to a YAML file
126
+ path = Path(config_file_path)
127
+ if path.suffix.lower() not in [".yaml", ".yml"]:
128
+ raise ValueError(f"Config file must have a .yaml or .yml extension, got: {config_file_path}")
129
+
130
+ # Load the YAML file
131
+ with open(config_file_path, "r") as f:
132
+ return AgentOSConfig.model_validate(yaml.safe_load(f))
133
+
134
+ def _auto_discover_databases(self) -> None:
135
+ """Auto-discover the databases used by all contextual agents, teams and workflows."""
136
+ dbs = {}
137
+
138
+ for agent in self.agents or []:
139
+ if agent.db:
140
+ dbs[agent.db.id] = agent.db
141
+ if agent.knowledge and agent.knowledge.contents_db:
142
+ dbs[agent.knowledge.contents_db.id] = agent.knowledge.contents_db
143
+
144
+ for team in self.teams or []:
145
+ if team.db:
146
+ dbs[team.db.id] = team.db
147
+ if team.knowledge and team.knowledge.contents_db:
148
+ dbs[team.knowledge.contents_db.id] = team.knowledge.contents_db
149
+
150
+ for workflow in self.workflows or []:
151
+ if workflow.db:
152
+ dbs[workflow.db.id] = workflow.db
153
+
154
+ for interface in self.interfaces or []:
155
+ if interface.agent and interface.agent.db:
156
+ dbs[interface.agent.db.id] = interface.agent.db
157
+ elif interface.team and interface.team.db:
158
+ dbs[interface.team.db.id] = interface.team.db
159
+
160
+ self.dbs = dbs
161
+
162
+ def _auto_discover_knowledge_instances(self) -> None:
163
+ """Auto-discover the knowledge instances used by all contextual agents, teams and workflows."""
164
+ knowledge_instances = []
165
+ for agent in self.agents or []:
166
+ if agent.knowledge:
167
+ knowledge_instances.append(agent.knowledge)
168
+
169
+ for team in self.teams or []:
170
+ if team.knowledge:
171
+ knowledge_instances.append(team.knowledge)
172
+
173
+ self.knowledge_instances = knowledge_instances
174
+
175
+ def _get_session_config(self) -> SessionConfig:
176
+ session_config = self.config.session if self.config and self.config.session else SessionConfig()
177
+
178
+ if session_config.dbs is None:
179
+ session_config.dbs = []
180
+
181
+ multiple_dbs: bool = len(self.dbs.keys()) > 1
182
+ dbs_with_specific_config = [db.db_id for db in session_config.dbs]
183
+
184
+ for db_id in self.dbs.keys():
185
+ if db_id not in dbs_with_specific_config:
186
+ session_config.dbs.append(
187
+ DatabaseConfig(
188
+ db_id=db_id,
189
+ domain_config=SessionDomainConfig(
190
+ display_name="Sessions" if not multiple_dbs else "Sessions " + db_id
191
+ ),
192
+ )
193
+ )
194
+
195
+ return session_config
196
+
197
+ def _get_memory_config(self) -> MemoryConfig:
198
+ memory_config = self.config.memory if self.config and self.config.memory else MemoryConfig()
199
+
200
+ if memory_config.dbs is None:
201
+ memory_config.dbs = []
202
+
203
+ multiple_dbs: bool = len(self.dbs.keys()) > 1
204
+ dbs_with_specific_config = [db.db_id for db in memory_config.dbs]
205
+
206
+ for db_id in self.dbs.keys():
207
+ if db_id not in dbs_with_specific_config:
208
+ memory_config.dbs.append(
209
+ DatabaseConfig(
210
+ db_id=db_id,
211
+ domain_config=MemoryDomainConfig(
212
+ display_name="Memory" if not multiple_dbs else "Memory " + db_id
213
+ ),
214
+ )
215
+ )
216
+
217
+ return memory_config
218
+
219
+ def _get_knowledge_config(self) -> KnowledgeConfig:
220
+ knowledge_config = self.config.knowledge if self.config and self.config.knowledge else KnowledgeConfig()
221
+
222
+ if knowledge_config.dbs is None:
223
+ knowledge_config.dbs = []
224
+
225
+ multiple_dbs: bool = len(self.dbs.keys()) > 1
226
+ dbs_with_specific_config = [db.db_id for db in knowledge_config.dbs]
227
+
228
+ for db_id in self.dbs.keys():
229
+ if db_id not in dbs_with_specific_config:
230
+ knowledge_config.dbs.append(
231
+ DatabaseConfig(
232
+ db_id=db_id,
233
+ domain_config=KnowledgeDomainConfig(
234
+ display_name="Knowledge" if not multiple_dbs else "Knowledge " + db_id
235
+ ),
236
+ )
237
+ )
238
+
239
+ return knowledge_config
240
+
241
+ def _get_metrics_config(self) -> MetricsConfig:
242
+ metrics_config = self.config.metrics if self.config and self.config.metrics else MetricsConfig()
243
+
244
+ if metrics_config.dbs is None:
245
+ metrics_config.dbs = []
246
+
247
+ multiple_dbs: bool = len(self.dbs.keys()) > 1
248
+ dbs_with_specific_config = [db.db_id for db in metrics_config.dbs]
249
+
250
+ for db_id in self.dbs.keys():
251
+ if db_id not in dbs_with_specific_config:
252
+ metrics_config.dbs.append(
253
+ DatabaseConfig(
254
+ db_id=db_id,
255
+ domain_config=MetricsDomainConfig(
256
+ display_name="Metrics" if not multiple_dbs else "Metrics " + db_id
257
+ ),
258
+ )
259
+ )
260
+
261
+ return metrics_config
262
+
263
+ def _get_evals_config(self) -> EvalsConfig:
264
+ evals_config = self.config.evals if self.config and self.config.evals else EvalsConfig()
265
+
266
+ if evals_config.dbs is None:
267
+ evals_config.dbs = []
268
+
269
+ multiple_dbs: bool = len(self.dbs.keys()) > 1
270
+ dbs_with_specific_config = [db.db_id for db in evals_config.dbs]
271
+
272
+ for db_id in self.dbs.keys():
273
+ if db_id not in dbs_with_specific_config:
274
+ evals_config.dbs.append(
275
+ DatabaseConfig(
276
+ db_id=db_id,
277
+ domain_config=EvalsDomainConfig(display_name="Evals" if not multiple_dbs else "Evals " + db_id),
278
+ )
279
+ )
280
+
281
+ return evals_config
282
+
283
+ def _setup_routers(self) -> None:
284
+ """Add all routers to the FastAPI app."""
285
+ if not self.dbs or not self.fastapi_app:
286
+ return
287
+
288
+ routers = [
289
+ get_session_router(dbs=self.dbs),
290
+ get_memory_router(dbs=self.dbs),
291
+ get_eval_router(dbs=self.dbs, agents=self.agents, teams=self.teams),
292
+ get_metrics_router(dbs=self.dbs),
293
+ get_knowledge_router(knowledge_instances=self.knowledge_instances),
294
+ ]
295
+
296
+ for router in routers:
297
+ self.fastapi_app.include_router(router)
298
+
299
+ def set_os_id(self) -> str:
300
+ # If os_id is already set, keep it instead of overriding with UUID
301
+ if self.os_id is None:
302
+ self.os_id = str(uuid4())
303
+
304
+ return self.os_id
305
+
306
+ def get_app(self) -> FastAPI:
307
+ if not self.fastapi_app:
308
+ self.fastapi_app = FastAPI(
309
+ title=self.settings.title,
310
+ docs_url="/docs" if self.settings.docs_enabled else None,
311
+ redoc_url="/redoc" if self.settings.docs_enabled else None,
312
+ openapi_url="/openapi.json" if self.settings.docs_enabled else None,
313
+ )
314
+
315
+ if not self.fastapi_app:
316
+ raise Exception("API App could not be created.")
317
+
318
+ @self.fastapi_app.exception_handler(HTTPException)
319
+ async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
320
+ return JSONResponse(
321
+ status_code=exc.status_code,
322
+ content={"detail": str(exc.detail)},
323
+ )
324
+
325
+ async def general_exception_handler(request: Request, call_next):
326
+ try:
327
+ return await call_next(request)
328
+ except Exception as e:
329
+ return JSONResponse(
330
+ status_code=e.status_code if hasattr(e, "status_code") else 500, # type: ignore
331
+ content={"detail": str(e)},
332
+ )
333
+
334
+ self.fastapi_app.middleware("http")(general_exception_handler)
335
+
336
+ self.fastapi_app.include_router(get_base_router(self, settings=self.settings))
337
+
338
+ for interface in self.interfaces:
339
+ interface_router = interface.get_router()
340
+ self.fastapi_app.include_router(interface_router)
341
+ self.interfaces_loaded.append((interface.type, interface.router_prefix))
342
+
343
+ self._auto_discover_databases()
344
+ self._auto_discover_knowledge_instances()
345
+ self._setup_routers()
346
+
347
+ self.fastapi_app.add_middleware(
348
+ CORSMiddleware,
349
+ allow_origins=self.settings.cors_origin_list, # type: ignore
350
+ allow_credentials=True,
351
+ allow_methods=["*"],
352
+ allow_headers=["*"],
353
+ expose_headers=["*"],
354
+ )
355
+
356
+ return self.fastapi_app
357
+
358
+ def serve(
359
+ self,
360
+ app: Union[str, FastAPI],
361
+ *,
362
+ host: str = "localhost",
363
+ port: int = 7777,
364
+ reload: bool = False,
365
+ **kwargs,
366
+ ):
367
+ import uvicorn
368
+
369
+ if getenv("AGNO_API_RUNTIME", "").lower() == "stg":
370
+ public_endpoint = "https://os-stg.agno.com/"
371
+ else:
372
+ public_endpoint = "https://os.agno.com/"
373
+
374
+ # Create a terminal panel to announce OS initialization and provide useful info
375
+ from rich.align import Align
376
+ from rich.console import Console, Group
377
+
378
+ aligned_endpoint = Align.center(f"[bold cyan]{public_endpoint}[/bold cyan]")
379
+ connection_endpoint = f"\n\n[bold dark_orange]Running on:[/bold dark_orange] http://{host}:{port}"
380
+
381
+ console = Console()
382
+ console.print(
383
+ Panel(
384
+ Group(aligned_endpoint, connection_endpoint),
385
+ title="AgentOS",
386
+ expand=False,
387
+ border_style="dark_orange",
388
+ box=box.DOUBLE_EDGE,
389
+ padding=(2, 2),
390
+ )
391
+ )
392
+
393
+ uvicorn.run(app=app, host=host, port=port, reload=reload, **kwargs)
agno/os/auth.py ADDED
@@ -0,0 +1,47 @@
1
+ from typing import Optional
2
+
3
+ from fastapi import Header, HTTPException
4
+ from fastapi.security import HTTPBearer
5
+
6
+ from agno.os.settings import AgnoAPISettings
7
+
8
+ # Create a global HTTPBearer instance
9
+ security = HTTPBearer(auto_error=False)
10
+
11
+
12
+ def get_authentication_dependency(settings: AgnoAPISettings):
13
+ """
14
+ Create an authentication dependency function for FastAPI routes.
15
+
16
+ Args:
17
+ settings: The API settings containing the security key
18
+
19
+ Returns:
20
+ A dependency function that can be used with FastAPI's Depends()
21
+ """
22
+
23
+ def auth_dependency(authorization: Optional[str] = Header(None)) -> bool:
24
+ # If no security key is set, skip authentication entirely
25
+ if not settings or not settings.os_security_key:
26
+ return True
27
+
28
+ # If security is enabled but no authorization header provided, fail
29
+ if not authorization:
30
+ raise HTTPException(status_code=401, detail="Authorization header required")
31
+
32
+ # Check if the authorization header starts with "Bearer "
33
+ if not authorization.startswith("Bearer "):
34
+ raise HTTPException(
35
+ status_code=401, detail="Invalid authorization header format. Expected 'Bearer <token>'"
36
+ )
37
+
38
+ # Extract the token from the authorization header
39
+ token = authorization[7:] # Remove "Bearer " prefix
40
+
41
+ # Verify the token
42
+ if token != settings.os_security_key:
43
+ raise HTTPException(status_code=401, detail="Invalid authentication token")
44
+
45
+ return True
46
+
47
+ return auth_dependency