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
@@ -0,0 +1,499 @@
1
+ import logging
2
+ from typing import Optional, Union
3
+
4
+ from fastapi import Depends, HTTPException, Query
5
+ from fastapi.routing import APIRouter
6
+
7
+ from agno.db.base import AsyncBaseDb, BaseDb
8
+ from agno.os.auth import get_authentication_dependency
9
+ from agno.os.routers.traces.schemas import (
10
+ TraceDetail,
11
+ TraceNode,
12
+ TraceSessionStats,
13
+ TraceSummary,
14
+ )
15
+ from agno.os.schema import (
16
+ BadRequestResponse,
17
+ InternalServerErrorResponse,
18
+ NotFoundResponse,
19
+ PaginatedResponse,
20
+ PaginationInfo,
21
+ UnauthenticatedResponse,
22
+ ValidationErrorResponse,
23
+ )
24
+ from agno.os.settings import AgnoAPISettings
25
+ from agno.os.utils import get_db, parse_datetime_to_utc
26
+ from agno.utils.log import log_error
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ def get_traces_router(
32
+ dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
33
+ ) -> APIRouter:
34
+ """Create traces router with comprehensive OpenAPI documentation for trace endpoints."""
35
+ router = APIRouter(
36
+ dependencies=[Depends(get_authentication_dependency(settings))],
37
+ tags=["Traces"],
38
+ responses={
39
+ 400: {"description": "Bad Request", "model": BadRequestResponse},
40
+ 401: {"description": "Unauthorized", "model": UnauthenticatedResponse},
41
+ 404: {"description": "Not Found", "model": NotFoundResponse},
42
+ 422: {"description": "Validation Error", "model": ValidationErrorResponse},
43
+ 500: {"description": "Internal Server Error", "model": InternalServerErrorResponse},
44
+ },
45
+ )
46
+ return attach_routes(router=router, dbs=dbs)
47
+
48
+
49
+ def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
50
+ @router.get(
51
+ "/traces",
52
+ response_model=PaginatedResponse[TraceSummary],
53
+ response_model_exclude_none=True,
54
+ tags=["Traces"],
55
+ operation_id="get_traces",
56
+ summary="List Traces",
57
+ description=(
58
+ "Retrieve a paginated list of execution traces with optional filtering.\n\n"
59
+ "**Traces provide observability into:**\n"
60
+ "- Agent execution flows\n"
61
+ "- Model invocations and token usage\n"
62
+ "- Tool calls and their results\n"
63
+ "- Errors and performance bottlenecks\n\n"
64
+ "**Filtering Options:**\n"
65
+ "- By run, session, user, or agent ID\n"
66
+ "- By status (OK, ERROR)\n"
67
+ "- By time range\n\n"
68
+ "**Pagination:**\n"
69
+ "- Use `page` (1-indexed) and `limit` parameters\n"
70
+ "- Response includes pagination metadata (total_pages, total_count, etc.)\n\n"
71
+ "**Response Format:**\n"
72
+ "Returns summary information for each trace. Use GET `/traces/{trace_id}` for detailed hierarchy."
73
+ ),
74
+ responses={
75
+ 200: {
76
+ "description": "List of traces retrieved successfully",
77
+ "content": {
78
+ "application/json": {
79
+ "example": {
80
+ "data": [
81
+ {
82
+ "trace_id": "a1b2c3d4",
83
+ "name": "Stock_Price_Agent.run",
84
+ "status": "OK",
85
+ "duration": "1.2s",
86
+ "start_time": "2025-11-19T10:30:00.000000+00:00",
87
+ "total_spans": 4,
88
+ "error_count": 0,
89
+ "input": "What is the stock price of NVDA?",
90
+ "run_id": "run123",
91
+ "session_id": "session456",
92
+ "user_id": "user789",
93
+ "agent_id": "agent_stock",
94
+ "team_id": None,
95
+ "workflow_id": None,
96
+ "created_at": "2025-11-19T10:30:00+00:00",
97
+ }
98
+ ],
99
+ "meta": {
100
+ "page": 1,
101
+ "limit": 20,
102
+ "total_pages": 5,
103
+ "total_count": 95,
104
+ },
105
+ }
106
+ }
107
+ },
108
+ }
109
+ },
110
+ )
111
+ async def get_traces(
112
+ run_id: Optional[str] = Query(default=None, description="Filter by run ID"),
113
+ session_id: Optional[str] = Query(default=None, description="Filter by session ID"),
114
+ user_id: Optional[str] = Query(default=None, description="Filter by user ID"),
115
+ agent_id: Optional[str] = Query(default=None, description="Filter by agent ID"),
116
+ team_id: Optional[str] = Query(default=None, description="Filter by team ID"),
117
+ workflow_id: Optional[str] = Query(default=None, description="Filter by workflow ID"),
118
+ status: Optional[str] = Query(default=None, description="Filter by status (OK, ERROR)"),
119
+ start_time: Optional[str] = Query(
120
+ default=None,
121
+ description="Filter traces starting after this time (ISO 8601 format with timezone, e.g., '2025-11-19T10:00:00Z' or '2025-11-19T15:30:00+05:30'). Times are converted to UTC for comparison.",
122
+ ),
123
+ end_time: Optional[str] = Query(
124
+ default=None,
125
+ description="Filter traces ending before this time (ISO 8601 format with timezone, e.g., '2025-11-19T11:00:00Z' or '2025-11-19T16:30:00+05:30'). Times are converted to UTC for comparison.",
126
+ ),
127
+ page: int = Query(default=1, description="Page number (1-indexed)", ge=1),
128
+ limit: int = Query(default=20, description="Number of traces per page", ge=1, le=100),
129
+ db_id: Optional[str] = Query(default=None, description="Database ID to query traces from"),
130
+ ):
131
+ """Get list of traces with optional filters and pagination"""
132
+ import time as time_module
133
+
134
+ # Get database using db_id or default to first available
135
+ db = await get_db(dbs, db_id)
136
+
137
+ try:
138
+ start_time_ms = time_module.time() * 1000
139
+
140
+ # Convert ISO datetime strings to UTC datetime objects
141
+ start_time_dt = parse_datetime_to_utc(start_time, "start_time") if start_time else None
142
+ end_time_dt = parse_datetime_to_utc(end_time, "end_time") if end_time else None
143
+
144
+ if isinstance(db, AsyncBaseDb):
145
+ traces, total_count = await db.get_traces(
146
+ run_id=run_id,
147
+ session_id=session_id,
148
+ user_id=user_id,
149
+ agent_id=agent_id,
150
+ team_id=team_id,
151
+ workflow_id=workflow_id,
152
+ status=status,
153
+ start_time=start_time_dt,
154
+ end_time=end_time_dt,
155
+ limit=limit,
156
+ page=page,
157
+ )
158
+ else:
159
+ traces, total_count = db.get_traces(
160
+ run_id=run_id,
161
+ session_id=session_id,
162
+ user_id=user_id,
163
+ agent_id=agent_id,
164
+ team_id=team_id,
165
+ workflow_id=workflow_id,
166
+ status=status,
167
+ start_time=start_time_dt,
168
+ end_time=end_time_dt,
169
+ limit=limit,
170
+ page=page,
171
+ )
172
+
173
+ end_time_ms = time_module.time() * 1000
174
+ search_time_ms = round(end_time_ms - start_time_ms, 2)
175
+
176
+ # Calculate total pages
177
+ total_pages = (total_count + limit - 1) // limit if limit > 0 else 0
178
+
179
+ trace_inputs = {}
180
+ for trace in traces:
181
+ if isinstance(db, AsyncBaseDb):
182
+ spans = await db.get_spans(trace_id=trace.trace_id)
183
+ else:
184
+ spans = db.get_spans(trace_id=trace.trace_id)
185
+
186
+ # Find root span and extract input
187
+ root_span = next((s for s in spans if not s.parent_span_id), None)
188
+ if root_span and hasattr(root_span, "attributes"):
189
+ trace_inputs[trace.trace_id] = root_span.attributes.get("input.value")
190
+
191
+ # Build response
192
+ trace_summaries = [
193
+ TraceSummary.from_trace(trace, input=trace_inputs.get(trace.trace_id)) for trace in traces
194
+ ]
195
+
196
+ return PaginatedResponse(
197
+ data=trace_summaries,
198
+ meta=PaginationInfo(
199
+ page=page,
200
+ limit=limit,
201
+ total_pages=total_pages,
202
+ total_count=total_count,
203
+ search_time_ms=search_time_ms,
204
+ ),
205
+ )
206
+
207
+ except Exception as e:
208
+ log_error(f"Error retrieving traces: {e}")
209
+ raise HTTPException(status_code=500, detail=f"Error retrieving traces: {str(e)}")
210
+
211
+ @router.get(
212
+ "/traces/{trace_id}",
213
+ response_model=Union[TraceDetail, TraceNode],
214
+ response_model_exclude_none=True,
215
+ tags=["Traces"],
216
+ operation_id="get_trace",
217
+ summary="Get Trace or Span Detail",
218
+ description=(
219
+ "Retrieve detailed trace information with hierarchical span tree, or a specific span within the trace.\n\n"
220
+ "**Without span_id parameter:**\n"
221
+ "Returns the full trace with hierarchical span tree:\n"
222
+ "- Trace metadata (ID, status, duration, context)\n"
223
+ "- Hierarchical tree of all spans\n"
224
+ "- Each span includes timing, status, and type-specific metadata\n\n"
225
+ "**With span_id parameter:**\n"
226
+ "Returns details for a specific span within the trace:\n"
227
+ "- Span metadata (ID, name, type, timing)\n"
228
+ "- Status and error information\n"
229
+ "- Type-specific attributes (model, tokens, tool params, etc.)\n\n"
230
+ "**Span Hierarchy (full trace):**\n"
231
+ "The `tree` field contains root spans, each with potential `children`.\n"
232
+ "This recursive structure represents the execution flow:\n"
233
+ "```\n"
234
+ "Agent.run (root)\n"
235
+ " ├─ LLM.invoke\n"
236
+ " ├─ Tool.execute\n"
237
+ " │ └─ LLM.invoke (nested)\n"
238
+ " └─ LLM.invoke\n"
239
+ "```\n\n"
240
+ "**Span Types:**\n"
241
+ "- `AGENT`: Agent execution with input/output\n"
242
+ "- `LLM`: Model invocations with tokens and prompts\n"
243
+ "- `TOOL`: Tool calls with parameters and results"
244
+ ),
245
+ responses={
246
+ 200: {
247
+ "description": "Trace or span detail retrieved successfully",
248
+ "content": {
249
+ "application/json": {
250
+ "examples": {
251
+ "full_trace": {
252
+ "summary": "Full trace with hierarchy (no span_id)",
253
+ "value": {
254
+ "trace_id": "a1b2c3d4",
255
+ "name": "Stock_Price_Agent.run",
256
+ "status": "OK",
257
+ "duration": "1.2s",
258
+ "start_time": "2025-11-19T10:30:00.000000+00:00",
259
+ "end_time": "2025-11-19T10:30:01.200000+00:00",
260
+ "total_spans": 4,
261
+ "error_count": 0,
262
+ "input": "What is Tesla stock price?",
263
+ "output": "The current price of Tesla (TSLA) is $245.67.",
264
+ "error": None,
265
+ "run_id": "run123",
266
+ "session_id": "session456",
267
+ "user_id": "user789",
268
+ "agent_id": "stock_agent",
269
+ "team_id": None,
270
+ "workflow_id": None,
271
+ "created_at": "2025-11-19T10:30:00+00:00",
272
+ "tree": [
273
+ {
274
+ "id": "span1",
275
+ "name": "Stock_Price_Agent.run",
276
+ "type": "AGENT",
277
+ "duration": "1.2s",
278
+ "status": "OK",
279
+ "input": None,
280
+ "output": None,
281
+ "error": None,
282
+ "spans": [],
283
+ }
284
+ ],
285
+ },
286
+ },
287
+ "single_span": {
288
+ "summary": "Single span detail (with span_id)",
289
+ "value": {
290
+ "id": "span2",
291
+ "name": "gpt-4o-mini.invoke",
292
+ "type": "LLM",
293
+ "duration": "800ms",
294
+ "status": "OK",
295
+ "metadata": {"model": "gpt-4o-mini", "input_tokens": 120},
296
+ },
297
+ },
298
+ }
299
+ }
300
+ },
301
+ },
302
+ 404: {"description": "Trace or span not found", "model": NotFoundResponse},
303
+ },
304
+ )
305
+ async def get_trace(
306
+ trace_id: str,
307
+ span_id: Optional[str] = Query(default=None, description="Optional: Span ID to retrieve specific span"),
308
+ run_id: Optional[str] = Query(default=None, description="Optional: Run ID to retrieve trace for"),
309
+ db_id: Optional[str] = Query(default=None, description="Database ID to query trace from"),
310
+ ):
311
+ """Get detailed trace with hierarchical span tree, or a specific span within the trace"""
312
+ # Get database using db_id or default to first available
313
+ db = await get_db(dbs, db_id)
314
+
315
+ try:
316
+ # If span_id is provided, return just that span
317
+ if span_id:
318
+ if isinstance(db, AsyncBaseDb):
319
+ span = await db.get_span(span_id)
320
+ else:
321
+ span = db.get_span(span_id)
322
+
323
+ if span is None:
324
+ raise HTTPException(status_code=404, detail="Span not found")
325
+
326
+ # Verify the span belongs to the requested trace
327
+ if span.trace_id != trace_id:
328
+ raise HTTPException(status_code=404, detail=f"Span {span_id} does not belong to trace {trace_id}")
329
+
330
+ # Convert to TraceNode (without children since we're fetching a single span)
331
+ return TraceNode.from_span(span, spans=None)
332
+
333
+ # Otherwise, return full trace with hierarchy
334
+ # Get trace
335
+ if isinstance(db, AsyncBaseDb):
336
+ trace = await db.get_trace(trace_id=trace_id, run_id=run_id)
337
+ else:
338
+ trace = db.get_trace(trace_id=trace_id, run_id=run_id)
339
+
340
+ if trace is None:
341
+ raise HTTPException(status_code=404, detail="Trace not found")
342
+
343
+ # Get all spans for this trace
344
+ if isinstance(db, AsyncBaseDb):
345
+ spans = await db.get_spans(trace_id=trace_id)
346
+ else:
347
+ spans = db.get_spans(trace_id=trace_id)
348
+
349
+ # Build hierarchical response
350
+ return TraceDetail.from_trace_and_spans(trace, spans)
351
+
352
+ except HTTPException:
353
+ raise
354
+ except Exception as e:
355
+ log_error(f"Error retrieving trace {trace_id}: {e}")
356
+ raise HTTPException(status_code=500, detail=f"Error retrieving trace: {str(e)}")
357
+
358
+ @router.get(
359
+ "/trace_session_stats",
360
+ response_model=PaginatedResponse[TraceSessionStats],
361
+ response_model_exclude_none=True,
362
+ tags=["Traces"],
363
+ operation_id="get_trace_stats",
364
+ summary="Get Trace Statistics by Session",
365
+ description=(
366
+ "Retrieve aggregated trace statistics grouped by session ID with pagination.\n\n"
367
+ "**Provides insights into:**\n"
368
+ "- Total traces per session\n"
369
+ "- First and last trace timestamps per session\n"
370
+ "- Associated user and agent information\n\n"
371
+ "**Filtering Options:**\n"
372
+ "- By user ID\n"
373
+ "- By agent ID\n\n"
374
+ "**Use Cases:**\n"
375
+ "- Monitor session-level activity\n"
376
+ "- Track conversation flows\n"
377
+ "- Identify high-activity sessions\n"
378
+ "- Analyze user engagement patterns"
379
+ ),
380
+ responses={
381
+ 200: {
382
+ "description": "Trace statistics retrieved successfully",
383
+ "content": {
384
+ "application/json": {
385
+ "example": {
386
+ "data": [
387
+ {
388
+ "session_id": "37029bc6-1794-4ba8-a629-1efedc53dcad",
389
+ "user_id": "kaustubh@agno.com",
390
+ "agent_id": "hackernews-agent",
391
+ "team_id": None,
392
+ "total_traces": 5,
393
+ "first_trace_at": "2025-11-19T10:15:16+00:00",
394
+ "last_trace_at": "2025-11-19T10:21:30+00:00",
395
+ }
396
+ ],
397
+ "meta": {
398
+ "page": 1,
399
+ "limit": 20,
400
+ "total_pages": 3,
401
+ "total_count": 45,
402
+ },
403
+ }
404
+ }
405
+ },
406
+ },
407
+ 500: {"description": "Failed to retrieve statistics", "model": InternalServerErrorResponse},
408
+ },
409
+ )
410
+ async def get_trace_stats(
411
+ user_id: Optional[str] = Query(default=None, description="Filter by user ID"),
412
+ agent_id: Optional[str] = Query(default=None, description="Filter by agent ID"),
413
+ team_id: Optional[str] = Query(default=None, description="Filter by team ID"),
414
+ workflow_id: Optional[str] = Query(default=None, description="Filter by workflow ID"),
415
+ start_time: Optional[str] = Query(
416
+ default=None,
417
+ description="Filter sessions with traces created after this time (ISO 8601 format with timezone, e.g., '2025-11-19T10:00:00Z' or '2025-11-19T15:30:00+05:30'). Times are converted to UTC for comparison.",
418
+ ),
419
+ end_time: Optional[str] = Query(
420
+ default=None,
421
+ description="Filter sessions with traces created before this time (ISO 8601 format with timezone, e.g., '2025-11-19T11:00:00Z' or '2025-11-19T16:30:00+05:30'). Times are converted to UTC for comparison.",
422
+ ),
423
+ page: int = Query(default=1, description="Page number (1-indexed)", ge=1),
424
+ limit: int = Query(default=20, description="Number of sessions per page", ge=1, le=100),
425
+ db_id: Optional[str] = Query(default=None, description="Database ID to query statistics from"),
426
+ ):
427
+ """Get trace statistics grouped by session"""
428
+ import time as time_module
429
+
430
+ # Get database using db_id or default to first available
431
+ db = await get_db(dbs, db_id)
432
+
433
+ try:
434
+ start_time_ms = time_module.time() * 1000
435
+
436
+ # Convert ISO datetime strings to UTC datetime objects
437
+ start_time_dt = parse_datetime_to_utc(start_time, "start_time") if start_time else None
438
+ end_time_dt = parse_datetime_to_utc(end_time, "end_time") if end_time else None
439
+
440
+ if isinstance(db, AsyncBaseDb):
441
+ stats_list, total_count = await db.get_trace_stats(
442
+ user_id=user_id,
443
+ agent_id=agent_id,
444
+ team_id=team_id,
445
+ workflow_id=workflow_id,
446
+ start_time=start_time_dt,
447
+ end_time=end_time_dt,
448
+ limit=limit,
449
+ page=page,
450
+ )
451
+ else:
452
+ stats_list, total_count = db.get_trace_stats(
453
+ user_id=user_id,
454
+ agent_id=agent_id,
455
+ team_id=team_id,
456
+ workflow_id=workflow_id,
457
+ start_time=start_time_dt,
458
+ end_time=end_time_dt,
459
+ limit=limit,
460
+ page=page,
461
+ )
462
+
463
+ end_time_ms = time_module.time() * 1000
464
+ search_time_ms = round(end_time_ms - start_time_ms, 2)
465
+
466
+ # Calculate total pages
467
+ total_pages = (total_count + limit - 1) // limit if limit > 0 else 0
468
+
469
+ # Convert stats to response models (Pydantic auto-serializes datetime to ISO 8601)
470
+ stats_response = [
471
+ TraceSessionStats(
472
+ session_id=stat["session_id"],
473
+ user_id=stat.get("user_id"),
474
+ agent_id=stat.get("agent_id"),
475
+ team_id=stat.get("team_id"),
476
+ workflow_id=stat.get("workflow_id"),
477
+ total_traces=stat["total_traces"],
478
+ first_trace_at=stat["first_trace_at"],
479
+ last_trace_at=stat["last_trace_at"],
480
+ )
481
+ for stat in stats_list
482
+ ]
483
+
484
+ return PaginatedResponse(
485
+ data=stats_response,
486
+ meta=PaginationInfo(
487
+ page=page,
488
+ limit=limit,
489
+ total_pages=total_pages,
490
+ total_count=total_count,
491
+ search_time_ms=search_time_ms,
492
+ ),
493
+ )
494
+
495
+ except Exception as e:
496
+ log_error(f"Error retrieving trace statistics: {e}")
497
+ raise HTTPException(status_code=500, detail=f"Error retrieving statistics: {str(e)}")
498
+
499
+ return router
@@ -0,0 +1,3 @@
1
+ from agno.os.routers.workflows.router import get_websocket_router, get_workflow_router
2
+
3
+ __all__ = ["get_workflow_router", "get_websocket_router"]