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,218 @@
1
+ import json
2
+ from textwrap import dedent
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ from agno.knowledge.document import Document
6
+ from agno.knowledge.knowledge import Knowledge
7
+ from agno.tools import Toolkit
8
+ from agno.utils.log import log_debug, log_error
9
+
10
+
11
+ class KnowledgeTools(Toolkit):
12
+ def __init__(
13
+ self,
14
+ knowledge: Knowledge,
15
+ enable_think: bool = True,
16
+ enable_search: bool = True,
17
+ enable_analyze: bool = True,
18
+ instructions: Optional[str] = None,
19
+ add_instructions: bool = True,
20
+ add_few_shot: bool = False,
21
+ few_shot_examples: Optional[str] = None,
22
+ all: bool = False,
23
+ **kwargs,
24
+ ):
25
+ if knowledge is None:
26
+ raise ValueError("knowledge must be provided when using KnowledgeTools")
27
+
28
+ # Add instructions for using this toolkit
29
+ if instructions is None:
30
+ self.instructions = self.DEFAULT_INSTRUCTIONS
31
+ if add_few_shot:
32
+ if few_shot_examples is not None:
33
+ self.instructions += "\n" + few_shot_examples
34
+ else:
35
+ self.instructions += "\n" + self.FEW_SHOT_EXAMPLES
36
+ else:
37
+ self.instructions = instructions
38
+
39
+ # The knowledge to search
40
+ self.knowledge: Knowledge = knowledge
41
+
42
+ tools: List[Any] = []
43
+ if enable_think or all:
44
+ tools.append(self.think)
45
+ if enable_search or all:
46
+ tools.append(self.search_knowledge)
47
+ if enable_analyze or all:
48
+ tools.append(self.analyze)
49
+
50
+ super().__init__(
51
+ name="knowledge_tools",
52
+ tools=tools,
53
+ instructions=self.instructions,
54
+ add_instructions=add_instructions,
55
+ **kwargs,
56
+ )
57
+
58
+ def think(self, session_state: Dict[str, Any], thought: str) -> str:
59
+ """Use this tool as a scratchpad to reason about the question, refine your approach, brainstorm search terms, or revise your plan.
60
+
61
+ Call `Think` whenever you need to figure out what to do next, analyze the user's question, or plan your approach.
62
+ You should use this tool as frequently as needed.
63
+
64
+ Args:
65
+ thought: Your thought process and reasoning.
66
+
67
+ Returns:
68
+ str: The full log of reasoning and the new thought.
69
+ """
70
+ try:
71
+ log_debug(f"Thought: {thought}")
72
+
73
+ # Add the thought to the Agent state
74
+ if session_state is None:
75
+ session_state = {}
76
+ if "thoughts" not in session_state:
77
+ session_state["thoughts"] = []
78
+ session_state["thoughts"].append(thought)
79
+
80
+ # Return the full log of thoughts and the new thought
81
+ thoughts = "\n".join([f"- {t}" for t in session_state["thoughts"]])
82
+ formatted_thoughts = dedent(
83
+ f"""Thoughts:
84
+ {thoughts}
85
+ """
86
+ ).strip()
87
+ return formatted_thoughts
88
+ except Exception as e:
89
+ log_error(f"Error recording thought: {e}")
90
+ return f"Error recording thought: {e}"
91
+
92
+ def search_knowledge(self, session_state: Dict[str, Any], query: str) -> str:
93
+ """Use this tool to search the knowledge base for relevant information.
94
+ After thinking through the question, use this tool as many times as needed to search for relevant information.
95
+
96
+ Args:
97
+ query: The query to search the knowledge base for.
98
+
99
+ Returns:
100
+ str: A string containing the response from the knowledge base.
101
+ """
102
+ try:
103
+ log_debug(f"Searching knowledge base: {query}")
104
+
105
+ # Get the relevant documents from the knowledge base
106
+ relevant_docs: List[Document] = self.knowledge.search(query=query)
107
+ if len(relevant_docs) == 0:
108
+ return "No documents found"
109
+ return json.dumps([doc.to_dict() for doc in relevant_docs])
110
+ except Exception as e:
111
+ log_error(f"Error searching knowledge base: {e}")
112
+ return f"Error searching knowledge base: {e}"
113
+
114
+ def analyze(self, session_state: Dict[str, Any], analysis: str) -> str:
115
+ """Use this tool to evaluate whether the returned documents are correct and sufficient.
116
+ If not, go back to "Think" or "Search" with refined queries.
117
+
118
+ Args:
119
+ analysis: A thought to think about and log.
120
+
121
+ Returns:
122
+ str: The full log of thoughts and the new thought.
123
+ """
124
+ try:
125
+ log_debug(f"Analysis: {analysis}")
126
+
127
+ # Add the thought to the Agent state
128
+ if session_state is None:
129
+ session_state = {}
130
+ if "analysis" not in session_state:
131
+ session_state["analysis"] = []
132
+ session_state["analysis"].append(analysis)
133
+
134
+ # Return the full log of thoughts and the new thought
135
+ analysis = "\n".join([f"- {a}" for a in session_state["analysis"]])
136
+ formatted_analysis = dedent(
137
+ f"""Analysis:
138
+ {analysis}
139
+ """
140
+ ).strip()
141
+ return formatted_analysis
142
+ except Exception as e:
143
+ log_error(f"Error recording analysis: {e}")
144
+ return f"Error recording analysis: {e}"
145
+
146
+ DEFAULT_INSTRUCTIONS = dedent("""\
147
+ You have access to the Think, Search, and Analyze tools that will help you search your knowledge for relevant information. Use these tools as frequently as needed to find the most relevant information.
148
+
149
+ ## How to use the Think, Search, and Analyze tools:
150
+ 1. **Think**
151
+ - Purpose: A scratchpad for planning, brainstorming keywords, and refining your approach. You never reveal your "Think" content to the user.
152
+ - Usage: Call `think` whenever you need to figure out what to do next, analyze your approach, or decide new search terms before (or after) you look up documents.
153
+
154
+ 2. **Search**
155
+ - Purpose: Executes a query against the knowledge base.
156
+ - Usage: Call `search` with a clear query string whenever you want to retrieve documents or data. You can and should call this tool multiple times in one conversation.
157
+ - For complex topics, use multiple focused searches rather than one broad search
158
+ - Try different phrasing and keywords if initial searches don't yield useful results
159
+ - Use quotes for exact phrases and OR for alternative terms (e.g., "protein synthesis" OR "protein formation")
160
+
161
+ 3. **Analyze**
162
+ - Purpose: Evaluate whether the returned documents are correct and sufficient. If not, go back to "Think" or "Search" with refined queries.
163
+ - Usage: Call `analyze` after getting search results to verify the quality and correctness of that information. Consider:
164
+ - Relevance: Do the documents directly address the user's question?
165
+ - Completeness: Is there enough information to provide a thorough answer?
166
+ - Reliability: Are the sources credible and up-to-date?
167
+ - Consistency: Do the documents agree or contradict each other?
168
+
169
+ **Important Guidelines**:
170
+ - Do not include your internal chain-of-thought in direct user responses.
171
+ - Use "Think" to reason internally. These notes are never exposed to the user.
172
+ - Iterate through the cycle (Think → Search → Analyze) as many times as needed until you have a final answer.
173
+ - When you do provide a final answer to the user, be clear, concise, and accurate.
174
+ - If search results are sparse or contradictory, acknowledge limitations in your response.
175
+ - Synthesize information from multiple sources rather than relying on a single document.\
176
+ """)
177
+
178
+ FEW_SHOT_EXAMPLES = dedent("""\
179
+ You can refer to the examples below as guidance for how to use each tool.
180
+ ### Examples
181
+
182
+ #### Example 1: Multiple Searches and Analysis
183
+
184
+ User: What are the recommended dietary guidelines for someone with mild hypertension?
185
+ Think: The user is asking about dietary guidelines for mild hypertension. I'll start broad, then refine if needed.
186
+ Search: "dietary guidelines for mild hypertension", "salt intake recommendations for mild hypertension"
187
+ Analyze: I got one document referencing the DASH diet, but it's quite brief. I might need more info about salt intake recommendations specifically.
188
+ Think: Let me refine my search to see if there are official guidelines from recognized health organizations.
189
+ Search: "WHO or American Heart Association guidelines for hypertension", "fruits and vegetables for mild hypertension"
190
+ Analyze: The new documents mention daily sodium limits, recommended fruit/vegetable intake, and more. This seems thorough. I'm ready to formulate the answer.
191
+
192
+ Final Answer: For mild hypertension, the guidelines typically recommend following the DASH diet, which emphasizes ...
193
+
194
+ #### Example 2: Invalid or Insufficient Search Results
195
+
196
+ User: Do you have any documentation on the 'XYZ Project' from last year?
197
+ Think: I'll try searching for 'XYZ Project last year' but if that fails, I'll look for internal code names or older references.
198
+ Search: "XYZ Project last year"
199
+ Analyze: No relevant documents. Let me refine my search to check for 'XYZ Project' in different date ranges or alternate titles.
200
+ Think: Possibly it's under 'XYZ Initiative' or 'XYZ Rollout.' Let's do a second search.
201
+ Search: "XYZ Initiative OR 'XYZ Rollout' from last year"
202
+ Analyze: Found a relevant archive for 'XYZ Initiative'. Looks correct and references last year's timeline. I'll proceed with that info.
203
+
204
+ Final Answer: Yes, we have some archived documentation under the name 'XYZ Initiative.' It includes ...
205
+
206
+ #### Example 3: Synthesizing Complex Information
207
+
208
+ User: How do quantum computers differ from classical computers in terms of performance?
209
+ Think: This is a technical question requiring clear explanations of quantum vs. classical computing performance characteristics.
210
+ Search: "quantum computing performance vs classical computing"
211
+ Analyze: Found general information but need more specifics on actual performance metrics and use cases.
212
+ Think: Let me search for specific quantum advantages and limitations.
213
+ Search: "quantum supremacy examples", "quantum computing limitations"
214
+ Search: "quantum computing speedup for specific algorithms"
215
+ Analyze: Now I have concrete examples of quantum speedup for certain algorithms, limitations for others, and real-world benchmarks.
216
+
217
+ Final Answer: Quantum computers differ from classical computers in three key ways: [synthesized explanation with specific examples]...\
218
+ """)
agno/tools/linear.py CHANGED
@@ -1,47 +1,38 @@
1
1
  from os import getenv
2
- from typing import Optional
2
+ from typing import Any, List, Optional
3
3
 
4
4
  import requests
5
5
 
6
6
  from agno.tools import Toolkit
7
- from agno.utils.log import logger
7
+ from agno.utils.log import log_info, logger
8
8
 
9
9
 
10
10
  class LinearTools(Toolkit):
11
11
  def __init__(
12
12
  self,
13
- get_user_details: bool = True,
14
- get_issue_details: bool = True,
15
- create_issue: bool = True,
16
- update_issue: bool = True,
17
- get_user_assigned_issues: bool = True,
18
- get_workflow_issues: bool = True,
19
- get_high_priority_issues: bool = True,
13
+ api_key: Optional[str] = None,
14
+ **kwargs,
20
15
  ):
21
- super().__init__(name="linear tools")
22
- self.api_token = getenv("LINEAR_API_KEY")
16
+ self.api_key = api_key or getenv("LINEAR_API_KEY")
23
17
 
24
- if not self.api_token:
25
- api_error_message = "API token 'LINEAR_API_KEY' is missing. Please set it as an environment variable."
26
- logger.error(api_error_message)
18
+ if not self.api_key:
19
+ raise ValueError("Linear API key is required")
27
20
 
28
21
  self.endpoint = "https://api.linear.app/graphql"
29
- self.headers = {"Authorization": f"{self.api_token}"}
30
-
31
- if get_user_details:
32
- self.register(self.get_user_details)
33
- if get_issue_details:
34
- self.register(self.get_issue_details)
35
- if create_issue:
36
- self.register(self.create_issue)
37
- if update_issue:
38
- self.register(self.update_issue)
39
- if get_user_assigned_issues:
40
- self.register(self.get_user_assigned_issues)
41
- if get_workflow_issues:
42
- self.register(self.get_workflow_issues)
43
- if get_high_priority_issues:
44
- self.register(self.get_high_priority_issues)
22
+ self.headers = {"Authorization": f"{self.api_key}"}
23
+
24
+ tools: List[Any] = [
25
+ self.get_user_details,
26
+ self.get_teams_details,
27
+ self.get_issue_details,
28
+ self.create_issue,
29
+ self.update_issue,
30
+ self.get_user_assigned_issues,
31
+ self.get_workflow_issues,
32
+ self.get_high_priority_issues,
33
+ ]
34
+
35
+ super().__init__(name="linear_tools", tools=tools, **kwargs)
45
36
 
46
37
  def _execute_query(self, query, variables=None):
47
38
  """Helper method to execute GraphQL queries with optional variables."""
@@ -56,7 +47,7 @@ class LinearTools(Toolkit):
56
47
  logger.error(f"GraphQL Error: {data['errors']}")
57
48
  raise Exception(f"GraphQL Error: {data['errors']}")
58
49
 
59
- logger.info("GraphQL query executed successfully.")
50
+ log_info("GraphQL query executed successfully.")
60
51
  return data.get("data")
61
52
 
62
53
  except requests.exceptions.RequestException as e:
@@ -94,7 +85,7 @@ class LinearTools(Toolkit):
94
85
 
95
86
  if response.get("viewer"):
96
87
  user = response["viewer"]
97
- logger.info(
88
+ log_info(
98
89
  f"Retrieved authenticated user details with name: {user['name']}, ID: {user['id']}, Email: {user['email']}"
99
90
  )
100
91
  return str(user)
@@ -106,6 +97,44 @@ class LinearTools(Toolkit):
106
97
  logger.error(f"Error fetching authenticated user details: {e}")
107
98
  raise
108
99
 
100
+ def get_teams_details(self) -> Optional[str]:
101
+ """
102
+ Fetch the list of authenticated teams.
103
+ It will return the unique ID and team name for each team, from the viewer object in the GraphQL response.
104
+
105
+ Returns:
106
+ str or None: A dictionary containing team details like team name, id.
107
+
108
+ Raises:
109
+ Exception: If an error occurs during the query execution or data retrieval.
110
+ """
111
+
112
+ query = """
113
+ query Teams {
114
+ teams {
115
+ nodes {
116
+ id
117
+ name
118
+ }
119
+ }
120
+ }
121
+ """
122
+
123
+ try:
124
+ response = self._execute_query(query)
125
+
126
+ if response.get("teams"):
127
+ teams = response["teams"]["nodes"]
128
+ log_info(f"Retrieved authenticated team details: {teams}")
129
+ return str(teams)
130
+ else:
131
+ logger.error("Failed to retrieve the current user details")
132
+ return None
133
+
134
+ except Exception as e:
135
+ logger.error(f"Error fetching authenticated user details: {e}")
136
+ raise
137
+
109
138
  def get_issue_details(self, issue_id: str) -> Optional[str]:
110
139
  """
111
140
  Retrieve details of a specific issue by issue ID.
@@ -136,7 +165,7 @@ class LinearTools(Toolkit):
136
165
 
137
166
  if response.get("issue"):
138
167
  issue = response["issue"]
139
- logger.info(f"Issue '{issue['title']}' retrieved successfully with ID {issue['id']}.")
168
+ log_info(f"Issue '{issue['title']}' retrieved successfully with ID {issue['id']}.")
140
169
  return str(issue)
141
170
  else:
142
171
  logger.error(f"Failed to retrieve issue with ID {issue_id}.")
@@ -147,7 +176,12 @@ class LinearTools(Toolkit):
147
176
  raise
148
177
 
149
178
  def create_issue(
150
- self, title: str, description: str, team_id: str, project_id: str, assignee_id: str
179
+ self,
180
+ title: str,
181
+ description: str,
182
+ team_id: str,
183
+ project_id: Optional[str] = None,
184
+ assignee_id: Optional[str] = None,
151
185
  ) -> Optional[str]:
152
186
  """
153
187
  Create a new issue within a specific project and team.
@@ -156,6 +190,8 @@ class LinearTools(Toolkit):
156
190
  title (str): The title of the new issue.
157
191
  description (str): The description of the new issue.
158
192
  team_id (str): The unique identifier of the team in which to create the issue.
193
+ project_id (Optional[str]): The ID of the project (optional).
194
+ assignee_id (Optional[str]): The ID of the assignee (optional).
159
195
 
160
196
  Returns:
161
197
  str or None: A string containing the created issue's details like issue id and issue title.
@@ -166,7 +202,7 @@ class LinearTools(Toolkit):
166
202
  """
167
203
 
168
204
  query = """
169
- mutation IssueCreate ($title: String!, $description: String!, $teamId: String!, $projectId: String!, $assigneeId: String!){
205
+ mutation IssueCreate ($title: String!, $description: String!, $teamId: String!, $projectId: String, $assigneeId: String){
170
206
  issueCreate(
171
207
  input: { title: $title, description: $description, teamId: $teamId, projectId: $projectId, assigneeId: $assigneeId}
172
208
  ) {
@@ -184,16 +220,19 @@ class LinearTools(Toolkit):
184
220
  "title": title,
185
221
  "description": description,
186
222
  "teamId": team_id,
187
- "projectId": project_id,
188
- "assigneeId": assignee_id,
189
223
  }
224
+ if project_id is not None:
225
+ variables["projectId"] = project_id
226
+ if assignee_id is not None:
227
+ variables["assigneeId"] = assignee_id
228
+
190
229
  try:
191
230
  response = self._execute_query(query, variables)
192
- logger.info(f"Response: {response}")
231
+ log_info(f"Response: {response}")
193
232
 
194
233
  if response["issueCreate"]["success"]:
195
234
  issue = response["issueCreate"]["issue"]
196
- logger.info(f"Issue '{issue['title']}' created successfully with ID {issue['id']}")
235
+ log_info(f"Issue '{issue['title']}' created successfully with ID {issue['id']}")
197
236
  return str(issue)
198
237
  else:
199
238
  logger.error("Issue creation failed.")
@@ -244,7 +283,7 @@ class LinearTools(Toolkit):
244
283
 
245
284
  if response["issueUpdate"]["success"]:
246
285
  issue = response["issueUpdate"]["issue"]
247
- logger.info(f"Issue ID {issue_id} updated successfully.")
286
+ log_info(f"Issue ID {issue_id} updated successfully.")
248
287
  return str(issue)
249
288
  else:
250
289
  logger.error(f"Failed to update issue ID {issue_id}. Success flag was false.")
@@ -292,7 +331,7 @@ class LinearTools(Toolkit):
292
331
  if response.get("user"):
293
332
  user = response["user"]
294
333
  issues = user["assignedIssues"]["nodes"]
295
- logger.info(f"Retrieved {len(issues)} issues assigned to user '{user['name']}' (ID: {user['id']}).")
334
+ log_info(f"Retrieved {len(issues)} issues assigned to user '{user['name']}' (ID: {user['id']}).")
296
335
  return str(issues)
297
336
  else:
298
337
  logger.error("Failed to retrieve user or issues.")
@@ -335,7 +374,7 @@ class LinearTools(Toolkit):
335
374
 
336
375
  if response.get("workflowState"):
337
376
  issues = response["workflowState"]["issues"]["nodes"]
338
- logger.info(f"Retrieved {len(issues)} issues in workflow state ID {workflow_id}.")
377
+ log_info(f"Retrieved {len(issues)} issues in workflow state ID {workflow_id}.")
339
378
  return str(issues)
340
379
  else:
341
380
  logger.error("Failed to retrieve issues for the specified workflow state.")
@@ -376,7 +415,7 @@ class LinearTools(Toolkit):
376
415
 
377
416
  if response.get("issues"):
378
417
  high_priority_issues = response["issues"]["nodes"]
379
- logger.info(f"Retrieved {len(high_priority_issues)} high-priority issues.")
418
+ log_info(f"Retrieved {len(high_priority_issues)} high-priority issues.")
380
419
  return str(high_priority_issues)
381
420
  else:
382
421
  logger.error("Failed to retrieve high-priority issues.")
agno/tools/linkup.py ADDED
@@ -0,0 +1,58 @@
1
+ from os import getenv
2
+ from typing import Any, List, Literal, Optional
3
+
4
+ from agno.tools import Toolkit
5
+ from agno.utils.log import logger
6
+
7
+ try:
8
+ from linkup import LinkupClient
9
+ except ImportError:
10
+ raise ImportError("`linkup-sdk` not installed. Please install using `pip install linkup-sdk`")
11
+
12
+
13
+ class LinkupTools(Toolkit):
14
+ def __init__(
15
+ self,
16
+ api_key: Optional[str] = None,
17
+ depth: Literal["standard", "deep"] = "standard",
18
+ output_type: Literal["sourcedAnswer", "searchResults"] = "searchResults",
19
+ enable_web_search_with_linkup: bool = True,
20
+ all: bool = False,
21
+ **kwargs,
22
+ ):
23
+ self.api_key = api_key or getenv("LINKUP_API_KEY")
24
+ if not self.api_key:
25
+ logger.error("LINKUP_API_KEY not set. Please set the LINKUP_API_KEY environment variable.")
26
+
27
+ self.linkup = LinkupClient(api_key=api_key)
28
+ self.depth = depth
29
+ self.output_type = output_type
30
+
31
+ tools: List[Any] = []
32
+ if all or enable_web_search_with_linkup:
33
+ tools.append(self.web_search_with_linkup)
34
+
35
+ super().__init__(name="linkup_tools", tools=tools, **kwargs)
36
+
37
+ def web_search_with_linkup(self, query: str, depth: Optional[str] = None, output_type: Optional[str] = None) -> str:
38
+ """
39
+ Use this function to search the web for a given query.
40
+ This function uses the Linkup API to provide realtime online information about the query.
41
+
42
+ Args:
43
+ query (str): Query to search for.
44
+ depth (str): (deep|standard) Depth of the search. Defaults to 'standard'.
45
+ output_type (str): (sourcedAnswer|searchResults) Type of output. Defaults to 'searchResults'.
46
+
47
+ Returns:
48
+ str: string of results related to the query.
49
+ """
50
+ try:
51
+ response = self.linkup.search(
52
+ query=query,
53
+ depth=depth or self.depth, # type: ignore
54
+ output_type=output_type or self.output_type, # type: ignore
55
+ )
56
+ return response
57
+ except Exception as e:
58
+ return f"Error: {str(e)}"
@@ -1,10 +1,9 @@
1
- import os
2
1
  from pathlib import Path
3
2
  from typing import Optional
4
3
  from uuid import uuid4
5
4
 
6
5
  from agno.tools import Toolkit
7
- from agno.utils.log import logger
6
+ from agno.utils.log import log_debug, logger
8
7
 
9
8
 
10
9
  class LocalFileSystemTools(Toolkit):
@@ -12,6 +11,9 @@ class LocalFileSystemTools(Toolkit):
12
11
  self,
13
12
  target_directory: Optional[str] = None,
14
13
  default_extension: str = "txt",
14
+ enable_write_file: bool = True,
15
+ all: bool = False,
16
+ **kwargs,
15
17
  ):
16
18
  """
17
19
  Initialize the WriteToLocal toolkit.
@@ -19,15 +21,18 @@ class LocalFileSystemTools(Toolkit):
19
21
  target_directory (Optional[str]): Default directory to write files to. Creates if doesn't exist.
20
22
  default_extension (str): Default file extension to use if none specified.
21
23
  """
22
- super().__init__(name="write_to_local")
23
24
 
24
- self.target_directory = target_directory or os.getcwd()
25
+ self.target_directory = target_directory or str(Path.cwd())
25
26
  self.default_extension = default_extension.lstrip(".")
26
27
 
27
28
  target_path = Path(self.target_directory)
28
29
  target_path.mkdir(parents=True, exist_ok=True)
29
30
 
30
- self.register(self.write_file)
31
+ tools = []
32
+ if all or enable_write_file:
33
+ tools.append(self.write_file)
34
+
35
+ super().__init__(name="write_to_local", tools=tools, **kwargs)
31
36
 
32
37
  def write_file(
33
38
  self,
@@ -50,8 +55,11 @@ class LocalFileSystemTools(Toolkit):
50
55
  filename = filename or str(uuid4())
51
56
  directory = directory or self.target_directory
52
57
  if filename and "." in filename:
53
- filename, file_ext = os.path.splitext(filename)
54
- extension = extension or file_ext.lstrip(".")
58
+ path_obj = Path(filename)
59
+ filename = path_obj.stem
60
+ extension = extension or path_obj.suffix.lstrip(".")
61
+
62
+ log_debug(f"Writing file to local system: {filename}")
55
63
 
56
64
  extension = (extension or self.default_extension).lstrip(".")
57
65