agno 2.2.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (575) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +51 -0
  3. agno/agent/agent.py +10405 -0
  4. agno/api/__init__.py +0 -0
  5. agno/api/agent.py +28 -0
  6. agno/api/api.py +40 -0
  7. agno/api/evals.py +22 -0
  8. agno/api/os.py +17 -0
  9. agno/api/routes.py +13 -0
  10. agno/api/schemas/__init__.py +9 -0
  11. agno/api/schemas/agent.py +16 -0
  12. agno/api/schemas/evals.py +16 -0
  13. agno/api/schemas/os.py +14 -0
  14. agno/api/schemas/response.py +6 -0
  15. agno/api/schemas/team.py +16 -0
  16. agno/api/schemas/utils.py +21 -0
  17. agno/api/schemas/workflows.py +16 -0
  18. agno/api/settings.py +53 -0
  19. agno/api/team.py +30 -0
  20. agno/api/workflow.py +28 -0
  21. agno/cloud/aws/base.py +214 -0
  22. agno/cloud/aws/s3/__init__.py +2 -0
  23. agno/cloud/aws/s3/api_client.py +43 -0
  24. agno/cloud/aws/s3/bucket.py +195 -0
  25. agno/cloud/aws/s3/object.py +57 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +598 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2042 -0
  33. agno/db/dynamo/schemas.py +314 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +1795 -0
  37. agno/db/firestore/schemas.py +140 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1335 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1160 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1328 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/__init__.py +0 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/mongo/__init__.py +17 -0
  51. agno/db/mongo/async_mongo.py +2026 -0
  52. agno/db/mongo/mongo.py +1982 -0
  53. agno/db/mongo/schemas.py +87 -0
  54. agno/db/mongo/utils.py +259 -0
  55. agno/db/mysql/__init__.py +3 -0
  56. agno/db/mysql/mysql.py +2308 -0
  57. agno/db/mysql/schemas.py +138 -0
  58. agno/db/mysql/utils.py +355 -0
  59. agno/db/postgres/__init__.py +4 -0
  60. agno/db/postgres/async_postgres.py +1927 -0
  61. agno/db/postgres/postgres.py +2260 -0
  62. agno/db/postgres/schemas.py +139 -0
  63. agno/db/postgres/utils.py +442 -0
  64. agno/db/redis/__init__.py +3 -0
  65. agno/db/redis/redis.py +1660 -0
  66. agno/db/redis/schemas.py +123 -0
  67. agno/db/redis/utils.py +346 -0
  68. agno/db/schemas/__init__.py +4 -0
  69. agno/db/schemas/culture.py +120 -0
  70. agno/db/schemas/evals.py +33 -0
  71. agno/db/schemas/knowledge.py +40 -0
  72. agno/db/schemas/memory.py +46 -0
  73. agno/db/schemas/metrics.py +0 -0
  74. agno/db/singlestore/__init__.py +3 -0
  75. agno/db/singlestore/schemas.py +130 -0
  76. agno/db/singlestore/singlestore.py +2272 -0
  77. agno/db/singlestore/utils.py +384 -0
  78. agno/db/sqlite/__init__.py +4 -0
  79. agno/db/sqlite/async_sqlite.py +2293 -0
  80. agno/db/sqlite/schemas.py +133 -0
  81. agno/db/sqlite/sqlite.py +2288 -0
  82. agno/db/sqlite/utils.py +431 -0
  83. agno/db/surrealdb/__init__.py +3 -0
  84. agno/db/surrealdb/metrics.py +292 -0
  85. agno/db/surrealdb/models.py +309 -0
  86. agno/db/surrealdb/queries.py +71 -0
  87. agno/db/surrealdb/surrealdb.py +1353 -0
  88. agno/db/surrealdb/utils.py +147 -0
  89. agno/db/utils.py +116 -0
  90. agno/debug.py +18 -0
  91. agno/eval/__init__.py +14 -0
  92. agno/eval/accuracy.py +834 -0
  93. agno/eval/performance.py +773 -0
  94. agno/eval/reliability.py +306 -0
  95. agno/eval/utils.py +119 -0
  96. agno/exceptions.py +161 -0
  97. agno/filters.py +354 -0
  98. agno/guardrails/__init__.py +6 -0
  99. agno/guardrails/base.py +19 -0
  100. agno/guardrails/openai.py +144 -0
  101. agno/guardrails/pii.py +94 -0
  102. agno/guardrails/prompt_injection.py +52 -0
  103. agno/integrations/__init__.py +0 -0
  104. agno/integrations/discord/__init__.py +3 -0
  105. agno/integrations/discord/client.py +203 -0
  106. agno/knowledge/__init__.py +5 -0
  107. agno/knowledge/chunking/__init__.py +0 -0
  108. agno/knowledge/chunking/agentic.py +79 -0
  109. agno/knowledge/chunking/document.py +91 -0
  110. agno/knowledge/chunking/fixed.py +57 -0
  111. agno/knowledge/chunking/markdown.py +151 -0
  112. agno/knowledge/chunking/recursive.py +63 -0
  113. agno/knowledge/chunking/row.py +39 -0
  114. agno/knowledge/chunking/semantic.py +86 -0
  115. agno/knowledge/chunking/strategy.py +165 -0
  116. agno/knowledge/content.py +74 -0
  117. agno/knowledge/document/__init__.py +5 -0
  118. agno/knowledge/document/base.py +58 -0
  119. agno/knowledge/embedder/__init__.py +5 -0
  120. agno/knowledge/embedder/aws_bedrock.py +343 -0
  121. agno/knowledge/embedder/azure_openai.py +210 -0
  122. agno/knowledge/embedder/base.py +23 -0
  123. agno/knowledge/embedder/cohere.py +323 -0
  124. agno/knowledge/embedder/fastembed.py +62 -0
  125. agno/knowledge/embedder/fireworks.py +13 -0
  126. agno/knowledge/embedder/google.py +258 -0
  127. agno/knowledge/embedder/huggingface.py +94 -0
  128. agno/knowledge/embedder/jina.py +182 -0
  129. agno/knowledge/embedder/langdb.py +22 -0
  130. agno/knowledge/embedder/mistral.py +206 -0
  131. agno/knowledge/embedder/nebius.py +13 -0
  132. agno/knowledge/embedder/ollama.py +154 -0
  133. agno/knowledge/embedder/openai.py +195 -0
  134. agno/knowledge/embedder/sentence_transformer.py +63 -0
  135. agno/knowledge/embedder/together.py +13 -0
  136. agno/knowledge/embedder/vllm.py +262 -0
  137. agno/knowledge/embedder/voyageai.py +165 -0
  138. agno/knowledge/knowledge.py +1988 -0
  139. agno/knowledge/reader/__init__.py +7 -0
  140. agno/knowledge/reader/arxiv_reader.py +81 -0
  141. agno/knowledge/reader/base.py +95 -0
  142. agno/knowledge/reader/csv_reader.py +166 -0
  143. agno/knowledge/reader/docx_reader.py +82 -0
  144. agno/knowledge/reader/field_labeled_csv_reader.py +292 -0
  145. agno/knowledge/reader/firecrawl_reader.py +201 -0
  146. agno/knowledge/reader/json_reader.py +87 -0
  147. agno/knowledge/reader/markdown_reader.py +137 -0
  148. agno/knowledge/reader/pdf_reader.py +431 -0
  149. agno/knowledge/reader/pptx_reader.py +101 -0
  150. agno/knowledge/reader/reader_factory.py +313 -0
  151. agno/knowledge/reader/s3_reader.py +89 -0
  152. agno/knowledge/reader/tavily_reader.py +194 -0
  153. agno/knowledge/reader/text_reader.py +115 -0
  154. agno/knowledge/reader/web_search_reader.py +372 -0
  155. agno/knowledge/reader/website_reader.py +455 -0
  156. agno/knowledge/reader/wikipedia_reader.py +59 -0
  157. agno/knowledge/reader/youtube_reader.py +78 -0
  158. agno/knowledge/remote_content/__init__.py +0 -0
  159. agno/knowledge/remote_content/remote_content.py +88 -0
  160. agno/knowledge/reranker/__init__.py +3 -0
  161. agno/knowledge/reranker/base.py +14 -0
  162. agno/knowledge/reranker/cohere.py +64 -0
  163. agno/knowledge/reranker/infinity.py +195 -0
  164. agno/knowledge/reranker/sentence_transformer.py +54 -0
  165. agno/knowledge/types.py +39 -0
  166. agno/knowledge/utils.py +189 -0
  167. agno/media.py +462 -0
  168. agno/memory/__init__.py +3 -0
  169. agno/memory/manager.py +1327 -0
  170. agno/models/__init__.py +0 -0
  171. agno/models/aimlapi/__init__.py +5 -0
  172. agno/models/aimlapi/aimlapi.py +45 -0
  173. agno/models/anthropic/__init__.py +5 -0
  174. agno/models/anthropic/claude.py +757 -0
  175. agno/models/aws/__init__.py +15 -0
  176. agno/models/aws/bedrock.py +701 -0
  177. agno/models/aws/claude.py +378 -0
  178. agno/models/azure/__init__.py +18 -0
  179. agno/models/azure/ai_foundry.py +485 -0
  180. agno/models/azure/openai_chat.py +131 -0
  181. agno/models/base.py +2175 -0
  182. agno/models/cerebras/__init__.py +12 -0
  183. agno/models/cerebras/cerebras.py +501 -0
  184. agno/models/cerebras/cerebras_openai.py +112 -0
  185. agno/models/cohere/__init__.py +5 -0
  186. agno/models/cohere/chat.py +389 -0
  187. agno/models/cometapi/__init__.py +5 -0
  188. agno/models/cometapi/cometapi.py +57 -0
  189. agno/models/dashscope/__init__.py +5 -0
  190. agno/models/dashscope/dashscope.py +91 -0
  191. agno/models/deepinfra/__init__.py +5 -0
  192. agno/models/deepinfra/deepinfra.py +28 -0
  193. agno/models/deepseek/__init__.py +5 -0
  194. agno/models/deepseek/deepseek.py +61 -0
  195. agno/models/defaults.py +1 -0
  196. agno/models/fireworks/__init__.py +5 -0
  197. agno/models/fireworks/fireworks.py +26 -0
  198. agno/models/google/__init__.py +5 -0
  199. agno/models/google/gemini.py +1085 -0
  200. agno/models/groq/__init__.py +5 -0
  201. agno/models/groq/groq.py +556 -0
  202. agno/models/huggingface/__init__.py +5 -0
  203. agno/models/huggingface/huggingface.py +491 -0
  204. agno/models/ibm/__init__.py +5 -0
  205. agno/models/ibm/watsonx.py +422 -0
  206. agno/models/internlm/__init__.py +3 -0
  207. agno/models/internlm/internlm.py +26 -0
  208. agno/models/langdb/__init__.py +1 -0
  209. agno/models/langdb/langdb.py +48 -0
  210. agno/models/litellm/__init__.py +14 -0
  211. agno/models/litellm/chat.py +468 -0
  212. agno/models/litellm/litellm_openai.py +25 -0
  213. agno/models/llama_cpp/__init__.py +5 -0
  214. agno/models/llama_cpp/llama_cpp.py +22 -0
  215. agno/models/lmstudio/__init__.py +5 -0
  216. agno/models/lmstudio/lmstudio.py +25 -0
  217. agno/models/message.py +434 -0
  218. agno/models/meta/__init__.py +12 -0
  219. agno/models/meta/llama.py +475 -0
  220. agno/models/meta/llama_openai.py +78 -0
  221. agno/models/metrics.py +120 -0
  222. agno/models/mistral/__init__.py +5 -0
  223. agno/models/mistral/mistral.py +432 -0
  224. agno/models/nebius/__init__.py +3 -0
  225. agno/models/nebius/nebius.py +54 -0
  226. agno/models/nexus/__init__.py +3 -0
  227. agno/models/nexus/nexus.py +22 -0
  228. agno/models/nvidia/__init__.py +5 -0
  229. agno/models/nvidia/nvidia.py +28 -0
  230. agno/models/ollama/__init__.py +5 -0
  231. agno/models/ollama/chat.py +441 -0
  232. agno/models/openai/__init__.py +9 -0
  233. agno/models/openai/chat.py +883 -0
  234. agno/models/openai/like.py +27 -0
  235. agno/models/openai/responses.py +1050 -0
  236. agno/models/openrouter/__init__.py +5 -0
  237. agno/models/openrouter/openrouter.py +66 -0
  238. agno/models/perplexity/__init__.py +5 -0
  239. agno/models/perplexity/perplexity.py +187 -0
  240. agno/models/portkey/__init__.py +3 -0
  241. agno/models/portkey/portkey.py +81 -0
  242. agno/models/requesty/__init__.py +5 -0
  243. agno/models/requesty/requesty.py +52 -0
  244. agno/models/response.py +199 -0
  245. agno/models/sambanova/__init__.py +5 -0
  246. agno/models/sambanova/sambanova.py +28 -0
  247. agno/models/siliconflow/__init__.py +5 -0
  248. agno/models/siliconflow/siliconflow.py +25 -0
  249. agno/models/together/__init__.py +5 -0
  250. agno/models/together/together.py +25 -0
  251. agno/models/utils.py +266 -0
  252. agno/models/vercel/__init__.py +3 -0
  253. agno/models/vercel/v0.py +26 -0
  254. agno/models/vertexai/__init__.py +0 -0
  255. agno/models/vertexai/claude.py +70 -0
  256. agno/models/vllm/__init__.py +3 -0
  257. agno/models/vllm/vllm.py +78 -0
  258. agno/models/xai/__init__.py +3 -0
  259. agno/models/xai/xai.py +113 -0
  260. agno/os/__init__.py +3 -0
  261. agno/os/app.py +876 -0
  262. agno/os/auth.py +57 -0
  263. agno/os/config.py +104 -0
  264. agno/os/interfaces/__init__.py +1 -0
  265. agno/os/interfaces/a2a/__init__.py +3 -0
  266. agno/os/interfaces/a2a/a2a.py +42 -0
  267. agno/os/interfaces/a2a/router.py +250 -0
  268. agno/os/interfaces/a2a/utils.py +924 -0
  269. agno/os/interfaces/agui/__init__.py +3 -0
  270. agno/os/interfaces/agui/agui.py +47 -0
  271. agno/os/interfaces/agui/router.py +144 -0
  272. agno/os/interfaces/agui/utils.py +534 -0
  273. agno/os/interfaces/base.py +25 -0
  274. agno/os/interfaces/slack/__init__.py +3 -0
  275. agno/os/interfaces/slack/router.py +148 -0
  276. agno/os/interfaces/slack/security.py +30 -0
  277. agno/os/interfaces/slack/slack.py +47 -0
  278. agno/os/interfaces/whatsapp/__init__.py +3 -0
  279. agno/os/interfaces/whatsapp/router.py +211 -0
  280. agno/os/interfaces/whatsapp/security.py +53 -0
  281. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  282. agno/os/mcp.py +292 -0
  283. agno/os/middleware/__init__.py +7 -0
  284. agno/os/middleware/jwt.py +233 -0
  285. agno/os/router.py +1763 -0
  286. agno/os/routers/__init__.py +3 -0
  287. agno/os/routers/evals/__init__.py +3 -0
  288. agno/os/routers/evals/evals.py +430 -0
  289. agno/os/routers/evals/schemas.py +142 -0
  290. agno/os/routers/evals/utils.py +162 -0
  291. agno/os/routers/health.py +31 -0
  292. agno/os/routers/home.py +52 -0
  293. agno/os/routers/knowledge/__init__.py +3 -0
  294. agno/os/routers/knowledge/knowledge.py +997 -0
  295. agno/os/routers/knowledge/schemas.py +178 -0
  296. agno/os/routers/memory/__init__.py +3 -0
  297. agno/os/routers/memory/memory.py +515 -0
  298. agno/os/routers/memory/schemas.py +62 -0
  299. agno/os/routers/metrics/__init__.py +3 -0
  300. agno/os/routers/metrics/metrics.py +190 -0
  301. agno/os/routers/metrics/schemas.py +47 -0
  302. agno/os/routers/session/__init__.py +3 -0
  303. agno/os/routers/session/session.py +997 -0
  304. agno/os/schema.py +1055 -0
  305. agno/os/settings.py +43 -0
  306. agno/os/utils.py +630 -0
  307. agno/py.typed +0 -0
  308. agno/reasoning/__init__.py +0 -0
  309. agno/reasoning/anthropic.py +80 -0
  310. agno/reasoning/azure_ai_foundry.py +67 -0
  311. agno/reasoning/deepseek.py +63 -0
  312. agno/reasoning/default.py +97 -0
  313. agno/reasoning/gemini.py +73 -0
  314. agno/reasoning/groq.py +71 -0
  315. agno/reasoning/helpers.py +63 -0
  316. agno/reasoning/ollama.py +67 -0
  317. agno/reasoning/openai.py +86 -0
  318. agno/reasoning/step.py +31 -0
  319. agno/reasoning/vertexai.py +76 -0
  320. agno/run/__init__.py +6 -0
  321. agno/run/agent.py +787 -0
  322. agno/run/base.py +229 -0
  323. agno/run/cancel.py +81 -0
  324. agno/run/messages.py +32 -0
  325. agno/run/team.py +753 -0
  326. agno/run/workflow.py +708 -0
  327. agno/session/__init__.py +10 -0
  328. agno/session/agent.py +295 -0
  329. agno/session/summary.py +265 -0
  330. agno/session/team.py +392 -0
  331. agno/session/workflow.py +205 -0
  332. agno/team/__init__.py +37 -0
  333. agno/team/team.py +8793 -0
  334. agno/tools/__init__.py +10 -0
  335. agno/tools/agentql.py +120 -0
  336. agno/tools/airflow.py +69 -0
  337. agno/tools/api.py +122 -0
  338. agno/tools/apify.py +314 -0
  339. agno/tools/arxiv.py +127 -0
  340. agno/tools/aws_lambda.py +53 -0
  341. agno/tools/aws_ses.py +66 -0
  342. agno/tools/baidusearch.py +89 -0
  343. agno/tools/bitbucket.py +292 -0
  344. agno/tools/brandfetch.py +213 -0
  345. agno/tools/bravesearch.py +106 -0
  346. agno/tools/brightdata.py +367 -0
  347. agno/tools/browserbase.py +209 -0
  348. agno/tools/calcom.py +255 -0
  349. agno/tools/calculator.py +151 -0
  350. agno/tools/cartesia.py +187 -0
  351. agno/tools/clickup.py +244 -0
  352. agno/tools/confluence.py +240 -0
  353. agno/tools/crawl4ai.py +158 -0
  354. agno/tools/csv_toolkit.py +185 -0
  355. agno/tools/dalle.py +110 -0
  356. agno/tools/daytona.py +475 -0
  357. agno/tools/decorator.py +262 -0
  358. agno/tools/desi_vocal.py +108 -0
  359. agno/tools/discord.py +161 -0
  360. agno/tools/docker.py +716 -0
  361. agno/tools/duckdb.py +379 -0
  362. agno/tools/duckduckgo.py +91 -0
  363. agno/tools/e2b.py +703 -0
  364. agno/tools/eleven_labs.py +196 -0
  365. agno/tools/email.py +67 -0
  366. agno/tools/evm.py +129 -0
  367. agno/tools/exa.py +396 -0
  368. agno/tools/fal.py +127 -0
  369. agno/tools/file.py +240 -0
  370. agno/tools/file_generation.py +350 -0
  371. agno/tools/financial_datasets.py +288 -0
  372. agno/tools/firecrawl.py +143 -0
  373. agno/tools/function.py +1187 -0
  374. agno/tools/giphy.py +93 -0
  375. agno/tools/github.py +1760 -0
  376. agno/tools/gmail.py +922 -0
  377. agno/tools/google_bigquery.py +117 -0
  378. agno/tools/google_drive.py +270 -0
  379. agno/tools/google_maps.py +253 -0
  380. agno/tools/googlecalendar.py +674 -0
  381. agno/tools/googlesearch.py +98 -0
  382. agno/tools/googlesheets.py +377 -0
  383. agno/tools/hackernews.py +77 -0
  384. agno/tools/jina.py +101 -0
  385. agno/tools/jira.py +170 -0
  386. agno/tools/knowledge.py +218 -0
  387. agno/tools/linear.py +426 -0
  388. agno/tools/linkup.py +58 -0
  389. agno/tools/local_file_system.py +90 -0
  390. agno/tools/lumalab.py +183 -0
  391. agno/tools/mcp/__init__.py +10 -0
  392. agno/tools/mcp/mcp.py +331 -0
  393. agno/tools/mcp/multi_mcp.py +347 -0
  394. agno/tools/mcp/params.py +24 -0
  395. agno/tools/mcp_toolbox.py +284 -0
  396. agno/tools/mem0.py +193 -0
  397. agno/tools/memori.py +339 -0
  398. agno/tools/memory.py +419 -0
  399. agno/tools/mlx_transcribe.py +139 -0
  400. agno/tools/models/__init__.py +0 -0
  401. agno/tools/models/azure_openai.py +190 -0
  402. agno/tools/models/gemini.py +203 -0
  403. agno/tools/models/groq.py +158 -0
  404. agno/tools/models/morph.py +186 -0
  405. agno/tools/models/nebius.py +124 -0
  406. agno/tools/models_labs.py +195 -0
  407. agno/tools/moviepy_video.py +349 -0
  408. agno/tools/neo4j.py +134 -0
  409. agno/tools/newspaper.py +46 -0
  410. agno/tools/newspaper4k.py +93 -0
  411. agno/tools/notion.py +204 -0
  412. agno/tools/openai.py +202 -0
  413. agno/tools/openbb.py +160 -0
  414. agno/tools/opencv.py +321 -0
  415. agno/tools/openweather.py +233 -0
  416. agno/tools/oxylabs.py +385 -0
  417. agno/tools/pandas.py +102 -0
  418. agno/tools/parallel.py +314 -0
  419. agno/tools/postgres.py +257 -0
  420. agno/tools/pubmed.py +188 -0
  421. agno/tools/python.py +205 -0
  422. agno/tools/reasoning.py +283 -0
  423. agno/tools/reddit.py +467 -0
  424. agno/tools/replicate.py +117 -0
  425. agno/tools/resend.py +62 -0
  426. agno/tools/scrapegraph.py +222 -0
  427. agno/tools/searxng.py +152 -0
  428. agno/tools/serpapi.py +116 -0
  429. agno/tools/serper.py +255 -0
  430. agno/tools/shell.py +53 -0
  431. agno/tools/slack.py +136 -0
  432. agno/tools/sleep.py +20 -0
  433. agno/tools/spider.py +116 -0
  434. agno/tools/sql.py +154 -0
  435. agno/tools/streamlit/__init__.py +0 -0
  436. agno/tools/streamlit/components.py +113 -0
  437. agno/tools/tavily.py +254 -0
  438. agno/tools/telegram.py +48 -0
  439. agno/tools/todoist.py +218 -0
  440. agno/tools/tool_registry.py +1 -0
  441. agno/tools/toolkit.py +146 -0
  442. agno/tools/trafilatura.py +388 -0
  443. agno/tools/trello.py +274 -0
  444. agno/tools/twilio.py +186 -0
  445. agno/tools/user_control_flow.py +78 -0
  446. agno/tools/valyu.py +228 -0
  447. agno/tools/visualization.py +467 -0
  448. agno/tools/webbrowser.py +28 -0
  449. agno/tools/webex.py +76 -0
  450. agno/tools/website.py +54 -0
  451. agno/tools/webtools.py +45 -0
  452. agno/tools/whatsapp.py +286 -0
  453. agno/tools/wikipedia.py +63 -0
  454. agno/tools/workflow.py +278 -0
  455. agno/tools/x.py +335 -0
  456. agno/tools/yfinance.py +257 -0
  457. agno/tools/youtube.py +184 -0
  458. agno/tools/zendesk.py +82 -0
  459. agno/tools/zep.py +454 -0
  460. agno/tools/zoom.py +382 -0
  461. agno/utils/__init__.py +0 -0
  462. agno/utils/agent.py +820 -0
  463. agno/utils/audio.py +49 -0
  464. agno/utils/certs.py +27 -0
  465. agno/utils/code_execution.py +11 -0
  466. agno/utils/common.py +132 -0
  467. agno/utils/dttm.py +13 -0
  468. agno/utils/enum.py +22 -0
  469. agno/utils/env.py +11 -0
  470. agno/utils/events.py +696 -0
  471. agno/utils/format_str.py +16 -0
  472. agno/utils/functions.py +166 -0
  473. agno/utils/gemini.py +426 -0
  474. agno/utils/hooks.py +57 -0
  475. agno/utils/http.py +74 -0
  476. agno/utils/json_schema.py +234 -0
  477. agno/utils/knowledge.py +36 -0
  478. agno/utils/location.py +19 -0
  479. agno/utils/log.py +255 -0
  480. agno/utils/mcp.py +214 -0
  481. agno/utils/media.py +352 -0
  482. agno/utils/merge_dict.py +41 -0
  483. agno/utils/message.py +118 -0
  484. agno/utils/models/__init__.py +0 -0
  485. agno/utils/models/ai_foundry.py +43 -0
  486. agno/utils/models/claude.py +358 -0
  487. agno/utils/models/cohere.py +87 -0
  488. agno/utils/models/llama.py +78 -0
  489. agno/utils/models/mistral.py +98 -0
  490. agno/utils/models/openai_responses.py +140 -0
  491. agno/utils/models/schema_utils.py +153 -0
  492. agno/utils/models/watsonx.py +41 -0
  493. agno/utils/openai.py +257 -0
  494. agno/utils/pickle.py +32 -0
  495. agno/utils/pprint.py +178 -0
  496. agno/utils/print_response/__init__.py +0 -0
  497. agno/utils/print_response/agent.py +842 -0
  498. agno/utils/print_response/team.py +1724 -0
  499. agno/utils/print_response/workflow.py +1668 -0
  500. agno/utils/prompts.py +111 -0
  501. agno/utils/reasoning.py +108 -0
  502. agno/utils/response.py +163 -0
  503. agno/utils/response_iterator.py +17 -0
  504. agno/utils/safe_formatter.py +24 -0
  505. agno/utils/serialize.py +32 -0
  506. agno/utils/shell.py +22 -0
  507. agno/utils/streamlit.py +487 -0
  508. agno/utils/string.py +231 -0
  509. agno/utils/team.py +139 -0
  510. agno/utils/timer.py +41 -0
  511. agno/utils/tools.py +102 -0
  512. agno/utils/web.py +23 -0
  513. agno/utils/whatsapp.py +305 -0
  514. agno/utils/yaml_io.py +25 -0
  515. agno/vectordb/__init__.py +3 -0
  516. agno/vectordb/base.py +127 -0
  517. agno/vectordb/cassandra/__init__.py +5 -0
  518. agno/vectordb/cassandra/cassandra.py +501 -0
  519. agno/vectordb/cassandra/extra_param_mixin.py +11 -0
  520. agno/vectordb/cassandra/index.py +13 -0
  521. agno/vectordb/chroma/__init__.py +5 -0
  522. agno/vectordb/chroma/chromadb.py +929 -0
  523. agno/vectordb/clickhouse/__init__.py +9 -0
  524. agno/vectordb/clickhouse/clickhousedb.py +835 -0
  525. agno/vectordb/clickhouse/index.py +9 -0
  526. agno/vectordb/couchbase/__init__.py +3 -0
  527. agno/vectordb/couchbase/couchbase.py +1442 -0
  528. agno/vectordb/distance.py +7 -0
  529. agno/vectordb/lancedb/__init__.py +6 -0
  530. agno/vectordb/lancedb/lance_db.py +995 -0
  531. agno/vectordb/langchaindb/__init__.py +5 -0
  532. agno/vectordb/langchaindb/langchaindb.py +163 -0
  533. agno/vectordb/lightrag/__init__.py +5 -0
  534. agno/vectordb/lightrag/lightrag.py +388 -0
  535. agno/vectordb/llamaindex/__init__.py +3 -0
  536. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  537. agno/vectordb/milvus/__init__.py +4 -0
  538. agno/vectordb/milvus/milvus.py +1182 -0
  539. agno/vectordb/mongodb/__init__.py +9 -0
  540. agno/vectordb/mongodb/mongodb.py +1417 -0
  541. agno/vectordb/pgvector/__init__.py +12 -0
  542. agno/vectordb/pgvector/index.py +23 -0
  543. agno/vectordb/pgvector/pgvector.py +1462 -0
  544. agno/vectordb/pineconedb/__init__.py +5 -0
  545. agno/vectordb/pineconedb/pineconedb.py +747 -0
  546. agno/vectordb/qdrant/__init__.py +5 -0
  547. agno/vectordb/qdrant/qdrant.py +1134 -0
  548. agno/vectordb/redis/__init__.py +9 -0
  549. agno/vectordb/redis/redisdb.py +694 -0
  550. agno/vectordb/search.py +7 -0
  551. agno/vectordb/singlestore/__init__.py +10 -0
  552. agno/vectordb/singlestore/index.py +41 -0
  553. agno/vectordb/singlestore/singlestore.py +763 -0
  554. agno/vectordb/surrealdb/__init__.py +3 -0
  555. agno/vectordb/surrealdb/surrealdb.py +699 -0
  556. agno/vectordb/upstashdb/__init__.py +5 -0
  557. agno/vectordb/upstashdb/upstashdb.py +718 -0
  558. agno/vectordb/weaviate/__init__.py +8 -0
  559. agno/vectordb/weaviate/index.py +15 -0
  560. agno/vectordb/weaviate/weaviate.py +1005 -0
  561. agno/workflow/__init__.py +23 -0
  562. agno/workflow/agent.py +299 -0
  563. agno/workflow/condition.py +738 -0
  564. agno/workflow/loop.py +735 -0
  565. agno/workflow/parallel.py +824 -0
  566. agno/workflow/router.py +702 -0
  567. agno/workflow/step.py +1432 -0
  568. agno/workflow/steps.py +592 -0
  569. agno/workflow/types.py +520 -0
  570. agno/workflow/workflow.py +4321 -0
  571. agno-2.2.13.dist-info/METADATA +614 -0
  572. agno-2.2.13.dist-info/RECORD +575 -0
  573. agno-2.2.13.dist-info/WHEEL +5 -0
  574. agno-2.2.13.dist-info/licenses/LICENSE +201 -0
  575. agno-2.2.13.dist-info/top_level.txt +1 -0
agno/tools/pubmed.py ADDED
@@ -0,0 +1,188 @@
1
+ import json
2
+ from typing import Any, Dict, List, Optional
3
+ from xml.etree import ElementTree
4
+
5
+ import httpx
6
+
7
+ from agno.tools import Toolkit
8
+ from agno.utils.log import log_debug
9
+
10
+
11
+ class PubmedTools(Toolkit):
12
+ def __init__(
13
+ self,
14
+ email: str = "your_email@example.com",
15
+ max_results: Optional[int] = None,
16
+ results_expanded: bool = False,
17
+ enable_search_pubmed: bool = True,
18
+ all: bool = False,
19
+ **kwargs,
20
+ ):
21
+ self.max_results: Optional[int] = max_results
22
+ self.email: str = email
23
+ self.results_expanded: bool = results_expanded
24
+
25
+ tools: List[Any] = []
26
+ if enable_search_pubmed or all:
27
+ tools.append(self.search_pubmed)
28
+
29
+ super().__init__(name="pubmed", tools=tools, **kwargs)
30
+
31
+ def fetch_pubmed_ids(self, query: str, max_results: int, email: str) -> List[str]:
32
+ url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
33
+ params = {
34
+ "db": "pubmed",
35
+ "term": query,
36
+ "retmax": max_results,
37
+ "email": email,
38
+ "usehistory": "y",
39
+ }
40
+ response = httpx.get(url, params=params) # type: ignore
41
+ root = ElementTree.fromstring(response.content)
42
+ return [id_elem.text for id_elem in root.findall(".//Id") if id_elem.text is not None]
43
+
44
+ def fetch_details(self, pubmed_ids: List[str]) -> ElementTree.Element:
45
+ url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi"
46
+ params = {"db": "pubmed", "id": ",".join(pubmed_ids), "retmode": "xml"}
47
+ response = httpx.get(url, params=params)
48
+ return ElementTree.fromstring(response.content)
49
+
50
+ def parse_details(self, xml_root: ElementTree.Element) -> List[Dict[str, Any]]:
51
+ articles = []
52
+ for article in xml_root.findall(".//PubmedArticle"):
53
+ # Get existing fields
54
+ pub_date = article.find(".//PubDate/Year")
55
+ title = article.find(".//ArticleTitle")
56
+
57
+ # Handle abstract sections with labels (methods, results, etc.)
58
+ abstract_sections = article.findall(".//AbstractText")
59
+ abstract_text = ""
60
+ if abstract_sections:
61
+ for section in abstract_sections:
62
+ label = section.get("Label", "")
63
+ if label:
64
+ abstract_text += f"{label}: {section.text}\n\n"
65
+ else:
66
+ abstract_text += f"{section.text}\n\n"
67
+ abstract_text = abstract_text.strip()
68
+ else:
69
+ abstract_text = "No abstract available"
70
+
71
+ # Get first author
72
+ first_author_elem = article.find(".//AuthorList/Author[1]")
73
+ first_author = "Unknown"
74
+ if first_author_elem is not None:
75
+ last_name = first_author_elem.find("LastName")
76
+ fore_name = first_author_elem.find("ForeName")
77
+ if last_name is not None and fore_name is not None:
78
+ first_author = f"{last_name.text}, {fore_name.text}"
79
+ elif last_name is not None and last_name.text:
80
+ first_author = last_name.text
81
+
82
+ # Get DOI
83
+ doi_elem = article.find(".//ArticleIdList/ArticleId[@IdType='doi']")
84
+ doi = doi_elem.text if doi_elem is not None else "No DOI available"
85
+
86
+ # Get PMID for URL construction
87
+ pmid_elem = article.find(".//PMID")
88
+ pmid = pmid_elem.text if pmid_elem is not None else ""
89
+ pubmed_url = f"https://pubmed.ncbi.nlm.nih.gov/{pmid}/" if pmid else "No URL available"
90
+
91
+ # Check if full text is available via PMC
92
+ pmc_elem = article.find(".//ArticleIdList/ArticleId[@IdType='pmc']")
93
+ full_text_url = "Not available"
94
+ if pmc_elem is not None:
95
+ full_text_url = f"https://www.ncbi.nlm.nih.gov/pmc/articles/{pmc_elem.text}/"
96
+ elif doi_elem is not None:
97
+ full_text_url = f"https://doi.org/{doi}"
98
+
99
+ # Get keywords
100
+ keywords = []
101
+ for keyword in article.findall(".//KeywordList/Keyword"):
102
+ if keyword.text:
103
+ keywords.append(keyword.text)
104
+
105
+ # Get MeSH terms (useful for understanding medical context)
106
+ mesh_terms = []
107
+ for mesh in article.findall(".//MeshHeading/DescriptorName"):
108
+ if mesh.text:
109
+ mesh_terms.append(mesh.text)
110
+
111
+ # Get journal info
112
+ journal_elem = article.find(".//Journal/Title")
113
+ journal = journal_elem.text if journal_elem is not None else "Unknown Journal"
114
+
115
+ # Publication type (research article, review, etc.)
116
+ pub_types = []
117
+ for pub_type in article.findall(".//PublicationTypeList/PublicationType"):
118
+ if pub_type.text:
119
+ pub_types.append(pub_type.text)
120
+
121
+ articles.append(
122
+ {
123
+ "Published": pub_date.text if pub_date is not None else "No date available",
124
+ "Title": title.text if title is not None else "No title available",
125
+ "Summary": abstract_text,
126
+ "First_Author": first_author,
127
+ "DOI": doi,
128
+ "PubMed_URL": pubmed_url,
129
+ "Full_Text_URL": full_text_url,
130
+ "Keywords": ", ".join(keywords) if keywords else "No keywords available",
131
+ "MeSH_Terms": ", ".join(mesh_terms) if mesh_terms else "No MeSH terms available",
132
+ "Journal": journal,
133
+ "Publication_Type": ", ".join(pub_types) if pub_types else "Not specified",
134
+ }
135
+ )
136
+
137
+ return articles
138
+
139
+ def search_pubmed(self, query: str, max_results: Optional[int] = 10) -> str:
140
+ """Use this function to search PubMed for articles.
141
+
142
+ Args:
143
+ query (str): The search query.
144
+ max_results (int): The maximum number of results to return (default 10).
145
+
146
+ Returns:
147
+ str: A JSON string containing the search results.
148
+ """
149
+ try:
150
+ log_debug(f"Searching PubMed for: {query}")
151
+ max_results = max_results or self.max_results or 10
152
+ ids = self.fetch_pubmed_ids(query, max_results, self.email)
153
+ details_root = self.fetch_details(ids)
154
+ articles = self.parse_details(details_root)
155
+
156
+ # Create result strings based on configured detail level
157
+ results = []
158
+ for article in articles:
159
+ if self.results_expanded:
160
+ # Comprehensive format with all metadata
161
+ article_text = (
162
+ f"Published: {article.get('Published')}\n"
163
+ f"Title: {article.get('Title')}\n"
164
+ f"First Author: {article.get('First_Author')}\n"
165
+ f"Journal: {article.get('Journal')}\n"
166
+ f"Publication Type: {article.get('Publication_Type')}\n"
167
+ f"DOI: {article.get('DOI')}\n"
168
+ f"PubMed URL: {article.get('PubMed_URL')}\n"
169
+ f"Full Text URL: {article.get('Full_Text_URL')}\n"
170
+ f"Keywords: {article.get('Keywords')}\n"
171
+ f"MeSH Terms: {article.get('MeSH_Terms')}\n"
172
+ f"Summary:\n{article.get('Summary')}"
173
+ )
174
+ else:
175
+ # Concise format with just essential information
176
+ summary = article.get("Summary", "")
177
+ article_text = (
178
+ f"Title: {article.get('Title')}\n"
179
+ f"Published: {article.get('Published')}\n"
180
+ f"Summary: {summary[:200]}..."
181
+ if len(summary) > 200
182
+ else f"Summary: {summary}"
183
+ )
184
+ results.append(article_text)
185
+
186
+ return json.dumps(results)
187
+ except Exception as e:
188
+ return f"Could not fetch articles. Error: {e}"
agno/tools/python.py ADDED
@@ -0,0 +1,205 @@
1
+ import functools
2
+ import runpy
3
+ from pathlib import Path
4
+ from typing import Any, List, Optional
5
+
6
+ from agno.tools import Toolkit
7
+ from agno.utils.log import log_debug, log_info, logger
8
+
9
+
10
+ @functools.lru_cache(maxsize=None)
11
+ def warn() -> None:
12
+ logger.warning("PythonTools can run arbitrary code, please provide human supervision.")
13
+
14
+
15
+ class PythonTools(Toolkit):
16
+ def __init__(
17
+ self,
18
+ base_dir: Optional[Path] = None,
19
+ safe_globals: Optional[dict] = None,
20
+ safe_locals: Optional[dict] = None,
21
+ **kwargs,
22
+ ):
23
+ self.base_dir: Path = base_dir or Path.cwd()
24
+
25
+ # Restricted global and local scope
26
+ self.safe_globals: dict = safe_globals or globals()
27
+ self.safe_locals: dict = safe_locals or locals()
28
+
29
+ tools: List[Any] = [
30
+ self.save_to_file_and_run,
31
+ self.run_python_code,
32
+ self.pip_install_package,
33
+ self.uv_pip_install_package,
34
+ self.run_python_file_return_variable,
35
+ self.read_file,
36
+ self.list_files,
37
+ ]
38
+
39
+ super().__init__(name="python_tools", tools=tools, **kwargs)
40
+
41
+ def save_to_file_and_run(
42
+ self, file_name: str, code: str, variable_to_return: Optional[str] = None, overwrite: bool = True
43
+ ) -> str:
44
+ """This function saves Python code to a file called `file_name` and then runs it.
45
+ If successful, returns the value of `variable_to_return` if provided otherwise returns a success message.
46
+ If failed, returns an error message.
47
+
48
+ Make sure the file_name ends with `.py`
49
+
50
+ :param file_name: The name of the file the code will be saved to.
51
+ :param code: The code to save and run.
52
+ :param variable_to_return: The variable to return.
53
+ :param overwrite: Overwrite the file if it already exists.
54
+ :return: if run is successful, the value of `variable_to_return` if provided else file name.
55
+ """
56
+ try:
57
+ warn()
58
+ file_path = self.base_dir.joinpath(file_name)
59
+ log_debug(f"Saving code to {file_path}")
60
+ if not file_path.parent.exists():
61
+ file_path.parent.mkdir(parents=True, exist_ok=True)
62
+ if file_path.exists() and not overwrite:
63
+ return f"File {file_name} already exists"
64
+ file_path.write_text(code, encoding="utf-8")
65
+ log_info(f"Saved: {file_path}")
66
+ log_info(f"Running {file_path}")
67
+ globals_after_run = runpy.run_path(str(file_path), init_globals=self.safe_globals, run_name="__main__")
68
+
69
+ if variable_to_return:
70
+ variable_value = globals_after_run.get(variable_to_return)
71
+ if variable_value is None:
72
+ return f"Variable {variable_to_return} not found"
73
+ log_debug(f"Variable {variable_to_return} value: {variable_value}")
74
+ return str(variable_value)
75
+ else:
76
+ return f"successfully ran {str(file_path)}"
77
+ except Exception as e:
78
+ logger.error(f"Error saving and running code: {e}")
79
+ return f"Error saving and running code: {e}"
80
+
81
+ def run_python_file_return_variable(self, file_name: str, variable_to_return: Optional[str] = None) -> str:
82
+ """This function runs code in a Python file.
83
+ If successful, returns the value of `variable_to_return` if provided otherwise returns a success message.
84
+ If failed, returns an error message.
85
+
86
+ :param file_name: The name of the file to run.
87
+ :param variable_to_return: The variable to return.
88
+ :return: if run is successful, the value of `variable_to_return` if provided else file name.
89
+ """
90
+ try:
91
+ warn()
92
+ file_path = self.base_dir.joinpath(file_name)
93
+
94
+ log_info(f"Running {file_path}")
95
+ globals_after_run = runpy.run_path(str(file_path), init_globals=self.safe_globals, run_name="__main__")
96
+ if variable_to_return:
97
+ variable_value = globals_after_run.get(variable_to_return)
98
+ if variable_value is None:
99
+ return f"Variable {variable_to_return} not found"
100
+ log_debug(f"Variable {variable_to_return} value: {variable_value}")
101
+ return str(variable_value)
102
+ else:
103
+ return f"successfully ran {str(file_path)}"
104
+ except Exception as e:
105
+ logger.error(f"Error running file: {e}")
106
+ return f"Error running file: {e}"
107
+
108
+ def read_file(self, file_name: str) -> str:
109
+ """Reads the contents of the file `file_name` and returns the contents if successful.
110
+
111
+ :param file_name: The name of the file to read.
112
+ :return: The contents of the file if successful, otherwise returns an error message.
113
+ """
114
+ try:
115
+ log_info(f"Reading file: {file_name}")
116
+ file_path = self.base_dir.joinpath(file_name)
117
+ contents = file_path.read_text(encoding="utf-8")
118
+ return str(contents)
119
+ except Exception as e:
120
+ logger.error(f"Error reading file: {e}")
121
+ return f"Error reading file: {e}"
122
+
123
+ def list_files(self) -> str:
124
+ """Returns a list of files in the base directory
125
+
126
+ :return: Comma separated list of files in the base directory.
127
+ """
128
+ try:
129
+ log_info(f"Reading files in : {self.base_dir}")
130
+ files = [str(file_path.name) for file_path in self.base_dir.iterdir()]
131
+ return ", ".join(files)
132
+ except Exception as e:
133
+ logger.error(f"Error reading files: {e}")
134
+ return f"Error reading files: {e}"
135
+
136
+ def run_python_code(self, code: str, variable_to_return: Optional[str] = None) -> str:
137
+ """This function to runs Python code in the current environment.
138
+ If successful, returns the value of `variable_to_return` if provided otherwise returns a success message.
139
+ If failed, returns an error message.
140
+
141
+ Returns the value of `variable_to_return` if successful, otherwise returns an error message.
142
+
143
+ :param code: The code to run.
144
+ :param variable_to_return: The variable to return.
145
+ :return: value of `variable_to_return` if successful, otherwise returns an error message.
146
+ """
147
+ try:
148
+ warn()
149
+
150
+ log_debug(f"Running code:\n\n{code}\n\n")
151
+ exec(code, self.safe_globals, self.safe_locals)
152
+
153
+ if variable_to_return:
154
+ variable_value = self.safe_locals.get(variable_to_return)
155
+ if variable_value is None:
156
+ return f"Variable {variable_to_return} not found"
157
+ log_debug(f"Variable {variable_to_return} value: {variable_value}")
158
+ return str(variable_value)
159
+ else:
160
+ return "successfully ran python code"
161
+ except Exception as e:
162
+ logger.error(f"Error running python code: {e}")
163
+ return f"Error running python code: {e}"
164
+
165
+ def pip_install_package(self, package_name: str) -> str:
166
+ """This function installs a package using pip in the current environment.
167
+ If successful, returns a success message.
168
+ If failed, returns an error message.
169
+
170
+ :param package_name: The name of the package to install.
171
+ :return: success message if successful, otherwise returns an error message.
172
+ """
173
+ try:
174
+ warn()
175
+
176
+ log_debug(f"Installing package {package_name}")
177
+ import subprocess
178
+ import sys
179
+
180
+ subprocess.check_call([sys.executable, "-m", "pip", "install", package_name])
181
+ return f"successfully installed package {package_name}"
182
+ except Exception as e:
183
+ logger.error(f"Error installing package {package_name}: {e}")
184
+ return f"Error installing package {package_name}: {e}"
185
+
186
+ def uv_pip_install_package(self, package_name: str) -> str:
187
+ """This function installs a package using uv and pip in the current environment.
188
+ If successful, returns a success message.
189
+ If failed, returns an error message.
190
+
191
+ :param package_name: The name of the package to install.
192
+ :return: success message if successful, otherwise returns an error message.
193
+ """
194
+ try:
195
+ warn()
196
+
197
+ log_debug(f"Installing package {package_name}")
198
+ import subprocess
199
+ import sys
200
+
201
+ subprocess.check_call([sys.executable, "-m", "uv", "pip", "install", package_name])
202
+ return f"successfully installed package {package_name}"
203
+ except Exception as e:
204
+ logger.error(f"Error installing package {package_name}: {e}")
205
+ return f"Error installing package {package_name}: {e}"
@@ -0,0 +1,283 @@
1
+ from textwrap import dedent
2
+ from typing import Any, Dict, List, Optional
3
+
4
+ from agno.reasoning.step import NextAction, ReasoningStep
5
+ from agno.tools import Toolkit
6
+ from agno.utils.log import log_debug, log_error
7
+
8
+
9
+ class ReasoningTools(Toolkit):
10
+ def __init__(
11
+ self,
12
+ enable_think: bool = True,
13
+ enable_analyze: bool = True,
14
+ all: bool = False,
15
+ instructions: Optional[str] = None,
16
+ add_instructions: bool = False,
17
+ add_few_shot: bool = False,
18
+ few_shot_examples: Optional[str] = None,
19
+ **kwargs,
20
+ ):
21
+ """A toolkit that provides step-by-step reasoning tools: Think and Analyze."""
22
+
23
+ # Add instructions for using this toolkit
24
+ if instructions is None:
25
+ self.instructions = "<reasoning_instructions>\n" + self.DEFAULT_INSTRUCTIONS
26
+ if add_few_shot:
27
+ if few_shot_examples is not None:
28
+ self.instructions += "\n" + few_shot_examples
29
+ else:
30
+ self.instructions += "\n" + self.FEW_SHOT_EXAMPLES
31
+ self.instructions += "\n</reasoning_instructions>\n"
32
+ else:
33
+ self.instructions = instructions
34
+
35
+ tools: List[Any] = []
36
+ # Prefer new flags; fallback to legacy ones
37
+ if all or enable_think:
38
+ tools.append(self.think)
39
+ if all or enable_analyze:
40
+ tools.append(self.analyze)
41
+
42
+ super().__init__(
43
+ name="reasoning_tools",
44
+ instructions=self.instructions,
45
+ add_instructions=add_instructions,
46
+ tools=tools,
47
+ **kwargs,
48
+ )
49
+
50
+ def think(
51
+ self,
52
+ session_state: Dict[str, Any],
53
+ title: str,
54
+ thought: str,
55
+ action: Optional[str] = None,
56
+ confidence: float = 0.8,
57
+ ) -> str:
58
+ """Use this tool as a scratchpad to reason about the question and work through it step-by-step.
59
+ This tool will help you break down complex problems into logical steps and track the reasoning process.
60
+ You can call it as many times as needed. These internal thoughts are never revealed to the user.
61
+
62
+ Args:
63
+ title: A concise title for this step
64
+ thought: Your detailed thought for this step
65
+ action: What you'll do based on this thought
66
+ confidence: How confident you are about this thought (0.0 to 1.0)
67
+
68
+ Returns:
69
+ A list of previous thoughts and the new thought
70
+ """
71
+ try:
72
+ log_debug(f"Thought about {title}")
73
+
74
+ # Create a reasoning step
75
+ reasoning_step = ReasoningStep(
76
+ title=title,
77
+ reasoning=thought,
78
+ action=action,
79
+ next_action=NextAction.CONTINUE,
80
+ confidence=confidence,
81
+ )
82
+
83
+ current_run_id = session_state.get("current_run_id", None)
84
+
85
+ # Add this step to the Agent's session state
86
+ if session_state is None:
87
+ session_state = {}
88
+ if "reasoning_steps" not in session_state:
89
+ session_state["reasoning_steps"] = {}
90
+ if current_run_id not in session_state["reasoning_steps"]:
91
+ session_state["reasoning_steps"][current_run_id] = []
92
+ session_state["reasoning_steps"][current_run_id].append(reasoning_step.model_dump_json())
93
+
94
+ # Return all previous reasoning_steps and the new reasoning_step
95
+ if "reasoning_steps" in session_state and current_run_id in session_state["reasoning_steps"]:
96
+ formatted_reasoning_steps = ""
97
+ for i, step in enumerate(session_state["reasoning_steps"][current_run_id], 1):
98
+ step_parsed = ReasoningStep.model_validate_json(step)
99
+ step_str = dedent(f"""\
100
+ Step {i}:
101
+ Title: {step_parsed.title}
102
+ Reasoning: {step_parsed.reasoning}
103
+ Action: {step_parsed.action}
104
+ Confidence: {step_parsed.confidence}
105
+ """)
106
+ formatted_reasoning_steps += step_str + "\n"
107
+ return formatted_reasoning_steps.strip()
108
+ return reasoning_step.model_dump_json()
109
+ except Exception as e:
110
+ log_error(f"Error recording thought: {e}")
111
+ return f"Error recording thought: {e}"
112
+
113
+ def analyze(
114
+ self,
115
+ session_state: Dict[str, Any],
116
+ title: str,
117
+ result: str,
118
+ analysis: str,
119
+ next_action: str = "continue",
120
+ confidence: float = 0.8,
121
+ ) -> str:
122
+ """Use this tool to analyze results from a reasoning step and determine next actions.
123
+
124
+ Args:
125
+ title: A concise title for this analysis step
126
+ result: The outcome of the previous action
127
+ analysis: Your analysis of the results
128
+ next_action: What to do next ("continue", "validate", or "final_answer")
129
+ confidence: How confident you are in this analysis (0.0 to 1.0)
130
+
131
+ Returns:
132
+ A list of previous thoughts and the new analysis
133
+ """
134
+ try:
135
+ log_debug(f"Analyzed {title}")
136
+
137
+ # Map string next_action to enum
138
+ next_action_enum = NextAction.CONTINUE
139
+ if next_action.lower() == "validate":
140
+ next_action_enum = NextAction.VALIDATE
141
+ elif next_action.lower() in ["final", "final_answer", "finalize"]:
142
+ next_action_enum = NextAction.FINAL_ANSWER
143
+
144
+ # Create a reasoning step for the analysis
145
+ reasoning_step = ReasoningStep(
146
+ title=title,
147
+ result=result,
148
+ reasoning=analysis,
149
+ next_action=next_action_enum,
150
+ confidence=confidence,
151
+ )
152
+
153
+ current_run_id = session_state.get("current_run_id", None)
154
+ # Add this step to the Agent's session state
155
+ if session_state is None:
156
+ session_state = {}
157
+ if "reasoning_steps" not in session_state:
158
+ session_state["reasoning_steps"] = {}
159
+ if current_run_id not in session_state["reasoning_steps"]:
160
+ session_state["reasoning_steps"][current_run_id] = []
161
+ session_state["reasoning_steps"][current_run_id].append(reasoning_step.model_dump_json())
162
+
163
+ # Return all previous reasoning_steps and the new reasoning_step
164
+ if "reasoning_steps" in session_state and current_run_id in session_state["reasoning_steps"]:
165
+ formatted_reasoning_steps = ""
166
+ for i, step in enumerate(session_state["reasoning_steps"][current_run_id], 1):
167
+ step_parsed = ReasoningStep.model_validate_json(step)
168
+ step_str = dedent(f"""\
169
+ Step {i}:
170
+ Title: {step_parsed.title}
171
+ Reasoning: {step_parsed.reasoning}
172
+ Action: {step_parsed.action}
173
+ Confidence: {step_parsed.confidence}
174
+ """)
175
+ formatted_reasoning_steps += step_str + "\n"
176
+ return formatted_reasoning_steps.strip()
177
+ return reasoning_step.model_dump_json()
178
+ except Exception as e:
179
+ log_error(f"Error recording analysis: {e}")
180
+ return f"Error recording analysis: {e}"
181
+
182
+ # --------------------------------------------------------------------------------
183
+ # Default instructions and few-shot examples
184
+ # --------------------------------------------------------------------------------
185
+
186
+ DEFAULT_INSTRUCTIONS = dedent(
187
+ """\
188
+ You have access to the `think` and `analyze` tools to work through problems step-by-step and structure your thought process. You must ALWAYS `think` before making tool calls or generating a response.
189
+
190
+ 1. **Think** (scratchpad):
191
+ - Purpose: Use the `think` tool as a scratchpad to break down complex problems, outline steps, and decide on immediate actions within your reasoning flow. Use this to structure your internal monologue.
192
+ - Usage: Call `think` before making tool calls or generating a response. Explain your reasoning and specify the intended action (e.g., "make a tool call", "perform calculation", "ask clarifying question").
193
+
194
+ 2. **Analyze** (evaluation):
195
+ - Purpose: Evaluate the result of a think step or a set of tool calls. Assess if the result is expected, sufficient, or requires further investigation.
196
+ - Usage: Call `analyze` after a set of tool calls. Determine the `next_action` based on your analysis: `continue` (more reasoning needed), `validate` (seek external confirmation/validation if possible), or `final_answer` (ready to conclude).
197
+ - Explain your reasoning highlighting whether the result is correct/sufficient.
198
+
199
+ ## IMPORTANT GUIDELINES
200
+ - **Always Think First:** You MUST use the `think` tool before making tool calls or generating a response.
201
+ - **Iterate to Solve:** Use the `think` and `analyze` tools iteratively to build a clear reasoning path. The typical flow is `Think` -> [`Tool Calls` if needed] -> [`Analyze` if needed] -> ... -> `final_answer`. Repeat this cycle until you reach a satisfactory conclusion.
202
+ - **Make multiple tool calls in parallel:** After a `think` step, you can make multiple tool calls in parallel.
203
+ - **Keep Thoughts Internal:** The reasoning steps (thoughts and analyses) are for your internal process only. Do not share them directly with the user.
204
+ - **Conclude Clearly:** When your analysis determines the `next_action` is `final_answer`, provide a concise and accurate final answer to the user."""
205
+ )
206
+
207
+ FEW_SHOT_EXAMPLES = dedent(
208
+ """
209
+ Below are examples demonstrating how to use the `think` and `analyze` tools.
210
+
211
+ ### Examples
212
+
213
+ **Example 1: Simple Fact Retrieval**
214
+
215
+ *User Request:* How many continents are there on Earth?
216
+
217
+ *Agent's Internal Process:*
218
+
219
+ ```tool_call
220
+ think(
221
+ title="Understand Request",
222
+ thought="The user wants to know the standard number of continents on Earth. This is a common piece of knowledge.",
223
+ action="Recall or verify the number of continents.",
224
+ confidence=0.95
225
+ )
226
+ ```
227
+ *--(Agent internally recalls the fact)--*
228
+ ```tool_call
229
+ analyze(
230
+ title="Evaluate Fact",
231
+ result="Standard geographical models list 7 continents: Africa, Antarctica, Asia, Australia, Europe, North America, South America.",
232
+ analysis="The recalled information directly answers the user's question accurately.",
233
+ next_action="final_answer",
234
+ confidence=1.0
235
+ )
236
+ ```
237
+
238
+ *Agent's Final Answer to User:*
239
+ There are 7 continents on Earth: Africa, Antarctica, Asia, Australia, Europe, North America, and South America.
240
+
241
+ **Example 2: Multi-Step Information Gathering**
242
+
243
+ *User Request:* What is the capital of France and its current population?
244
+
245
+ *Agent's Internal Process:*
246
+
247
+ ```tool_call
248
+ think(
249
+ title="Plan Information Retrieval",
250
+ thought="The user needs two pieces of information: the capital of France and its current population. I should use external tools (like search) to find the most up-to-date and accurate information.",
251
+ action="First, search for the capital of France.",
252
+ confidence=0.95
253
+ )
254
+ ```
255
+
256
+ *Perform multiple tool calls in parallel*
257
+ *--(Tool call 1: search(query="capital of France"))--*
258
+ *--(Tool call 2: search(query="population of Paris current"))--*
259
+ *--(Tool Result 1: "Paris")--*
260
+ *--(Tool Result 2: "Approximately 2.1 million (city proper, estimate for early 2024)")--*
261
+
262
+ ```tool_call
263
+ analyze(
264
+ title="Analyze Capital Search Result",
265
+ result="The search result indicates Paris is the capital of France.",
266
+ analysis="This provides the first piece of requested information. Now I need to find the population of Paris.",
267
+ next_action="continue",
268
+ confidence=1.0
269
+ )
270
+ ```
271
+ ```tool_call
272
+ analyze(
273
+ title="Analyze Population Search Result",
274
+ result="The search provided an estimated population figure for Paris.",
275
+ analysis="I now have both the capital and its estimated population. I can provide the final answer.",
276
+ next_action="final_answer",
277
+ confidence=0.9
278
+ )
279
+ ```
280
+
281
+ *Agent's Final Answer to User:*
282
+ The capital of France is Paris. Its estimated population (city proper) is approximately 2.1 million as of early 2024."""
283
+ )