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/utils/prompts.py ADDED
@@ -0,0 +1,111 @@
1
+ import json
2
+ from typing import Type, Union
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from agno.utils.log import log_warning
7
+
8
+
9
+ def get_json_output_prompt(output_schema: Union[str, list, BaseModel]) -> str:
10
+ """Return the JSON output prompt for the Agent.
11
+
12
+ This is added to the system prompt when the output_schema is set and structured_outputs is False.
13
+ """
14
+
15
+ json_output_prompt = "Provide your output as a JSON containing the following fields:"
16
+ if output_schema is not None:
17
+ if isinstance(output_schema, str):
18
+ json_output_prompt += "\n<json_fields>"
19
+ json_output_prompt += f"\n{output_schema}"
20
+ json_output_prompt += "\n</json_fields>"
21
+ elif isinstance(output_schema, list):
22
+ json_output_prompt += "\n<json_fields>"
23
+ json_output_prompt += f"\n{json.dumps(output_schema)}"
24
+ json_output_prompt += "\n</json_fields>"
25
+ elif (
26
+ issubclass(type(output_schema), BaseModel)
27
+ or issubclass(output_schema, BaseModel) # type: ignore
28
+ or isinstance(output_schema, BaseModel)
29
+ ): # type: ignore
30
+ json_schema = output_schema.model_json_schema()
31
+ if json_schema is not None:
32
+ response_model_properties = {}
33
+ json_schema_properties = json_schema.get("properties")
34
+ if json_schema_properties is not None:
35
+ for field_name, field_properties in json_schema_properties.items():
36
+ formatted_field_properties = {
37
+ prop_name: prop_value
38
+ for prop_name, prop_value in field_properties.items()
39
+ if prop_name != "title"
40
+ }
41
+ # Handle enum references
42
+ if "allOf" in formatted_field_properties:
43
+ ref = formatted_field_properties["allOf"][0].get("$ref", "")
44
+ if ref.startswith("#/$defs/"):
45
+ enum_name = ref.split("/")[-1]
46
+ formatted_field_properties["enum_type"] = enum_name
47
+
48
+ response_model_properties[field_name] = formatted_field_properties
49
+
50
+ json_schema_defs = json_schema.get("$defs")
51
+ if json_schema_defs is not None:
52
+ response_model_properties["$defs"] = {}
53
+ for def_name, def_properties in json_schema_defs.items():
54
+ # Handle both regular object definitions and enums
55
+ if "enum" in def_properties:
56
+ # This is an enum definition
57
+ response_model_properties["$defs"][def_name] = {
58
+ "type": "string",
59
+ "enum": def_properties["enum"],
60
+ "description": def_properties.get("description", ""),
61
+ }
62
+ else:
63
+ # This is a regular object definition
64
+ def_fields = def_properties.get("properties")
65
+ formatted_def_properties = {}
66
+ if def_fields is not None:
67
+ for field_name, field_properties in def_fields.items():
68
+ formatted_field_properties = {
69
+ prop_name: prop_value
70
+ for prop_name, prop_value in field_properties.items()
71
+ if prop_name != "title"
72
+ }
73
+ formatted_def_properties[field_name] = formatted_field_properties
74
+ if len(formatted_def_properties) > 0:
75
+ response_model_properties["$defs"][def_name] = formatted_def_properties
76
+
77
+ if len(response_model_properties) > 0:
78
+ json_output_prompt += "\n<json_fields>"
79
+ json_output_prompt += (
80
+ f"\n{json.dumps([key for key in response_model_properties.keys() if key != '$defs'])}"
81
+ )
82
+ json_output_prompt += "\n</json_fields>"
83
+ json_output_prompt += "\n\nHere are the properties for each field:"
84
+ json_output_prompt += "\n<json_field_properties>"
85
+ json_output_prompt += f"\n{json.dumps(response_model_properties, indent=2)}"
86
+ json_output_prompt += "\n</json_field_properties>"
87
+ else:
88
+ log_warning(f"Could not build json schema for {output_schema}")
89
+ else:
90
+ json_output_prompt += "Provide the output as JSON."
91
+
92
+ json_output_prompt += "\nStart your response with `{` and end it with `}`."
93
+ json_output_prompt += "\nYour output will be passed to json.loads() to convert it to a Python object."
94
+ json_output_prompt += "\nMake sure it only contains valid JSON."
95
+ return json_output_prompt
96
+
97
+
98
+ def get_response_model_format_prompt(output_schema: Type[BaseModel]) -> str:
99
+ """Return the format prompt for the response model."""
100
+
101
+ message = "Make sure your response is a valid string (NOT JSON) that mentions the following topics:"
102
+
103
+ # Extract field names and descriptions
104
+ for field_name, field_info in output_schema.model_fields.items():
105
+ description = field_info.description or ""
106
+ if description:
107
+ message += f"\n- {field_name}: {description}"
108
+ else:
109
+ message += f"\n- {field_name}"
110
+
111
+ return message
@@ -0,0 +1,108 @@
1
+ from typing import TYPE_CHECKING, List, Optional, Tuple, Union
2
+
3
+ from agno.models.message import Message
4
+ from agno.models.metrics import Metrics
5
+ from agno.reasoning.step import ReasoningStep
6
+
7
+ if TYPE_CHECKING:
8
+ from agno.run.agent import RunOutput
9
+ from agno.team.team import TeamRunOutput
10
+
11
+
12
+ def extract_thinking_content(content: str) -> Tuple[Optional[str], str]:
13
+ """Extract thinking content from response text between <think> tags."""
14
+ if not content or "</think>" not in content:
15
+ return None, content
16
+
17
+ # Find the end of thinking content
18
+ end_idx = content.find("</think>")
19
+
20
+ # Look for opening <think> tag, if not found, assume thinking starts at beginning
21
+ start_idx = content.find("<think>")
22
+ if start_idx == -1:
23
+ reasoning_content = content[:end_idx].strip()
24
+ else:
25
+ start_idx = start_idx + len("<think>")
26
+ reasoning_content = content[start_idx:end_idx].strip()
27
+
28
+ output_content = content[end_idx + len("</think>") :].strip()
29
+
30
+ return reasoning_content, output_content
31
+
32
+
33
+ def append_to_reasoning_content(run_response: Union["RunOutput", "TeamRunOutput"], content: str) -> None:
34
+ """Helper to append content to the reasoning_content field."""
35
+ if not hasattr(run_response, "reasoning_content") or not run_response.reasoning_content: # type: ignore
36
+ run_response.reasoning_content = content # type: ignore
37
+ else:
38
+ run_response.reasoning_content += content # type: ignore
39
+
40
+
41
+ def add_reasoning_step_to_metadata(
42
+ run_response: Union["RunOutput", "TeamRunOutput"], reasoning_step: ReasoningStep
43
+ ) -> None:
44
+ if run_response.reasoning_steps is None:
45
+ run_response.reasoning_steps = []
46
+
47
+ run_response.reasoning_steps.append(reasoning_step)
48
+
49
+
50
+ def add_reasoning_metrics_to_metadata(
51
+ run_response: Union["RunOutput", "TeamRunOutput"], reasoning_time_taken: float
52
+ ) -> None:
53
+ try:
54
+ # Initialize reasoning_messages if it doesn't exist
55
+ if run_response.reasoning_messages is None:
56
+ run_response.reasoning_messages = []
57
+
58
+ metrics_message = Message(
59
+ role="assistant",
60
+ content=run_response.reasoning_content,
61
+ metrics=Metrics(duration=reasoning_time_taken),
62
+ )
63
+
64
+ # Add the metrics message to the reasoning_messages
65
+ run_response.reasoning_messages.append(metrics_message)
66
+
67
+ except Exception as e:
68
+ # Log the error but don't crash
69
+ from agno.utils.log import log_error
70
+
71
+ log_error(f"Failed to add reasoning metrics to metadata: {str(e)}")
72
+
73
+
74
+ def update_run_output_with_reasoning(
75
+ run_response: Union["RunOutput", "TeamRunOutput"],
76
+ reasoning_steps: List[ReasoningStep],
77
+ reasoning_agent_messages: List[Message],
78
+ ) -> None:
79
+ # Update reasoning_steps
80
+ if run_response.reasoning_steps is None:
81
+ run_response.reasoning_steps = reasoning_steps
82
+ else:
83
+ run_response.reasoning_steps.extend(reasoning_steps)
84
+
85
+ # Update reasoning_messages
86
+ if run_response.reasoning_messages is None:
87
+ run_response.reasoning_messages = reasoning_agent_messages
88
+ else:
89
+ run_response.reasoning_messages.extend(reasoning_agent_messages)
90
+
91
+ # Create and store reasoning_content
92
+ reasoning_content = ""
93
+ for step in reasoning_steps:
94
+ if step.title:
95
+ reasoning_content += f"## {step.title}\n"
96
+ if step.reasoning:
97
+ reasoning_content += f"{step.reasoning}\n"
98
+ if step.action:
99
+ reasoning_content += f"Action: {step.action}\n"
100
+ if step.result:
101
+ reasoning_content += f"Result: {step.result}\n"
102
+ reasoning_content += "\n"
103
+
104
+ # Add to existing reasoning_content or set it
105
+ if not run_response.reasoning_content:
106
+ run_response.reasoning_content = reasoning_content
107
+ else:
108
+ run_response.reasoning_content += reasoning_content
agno/utils/response.py ADDED
@@ -0,0 +1,163 @@
1
+ from typing import AsyncIterator, Iterator, List, Set, Union
2
+
3
+ from agno.exceptions import RunCancelledException
4
+ from agno.models.response import ToolExecution
5
+ from agno.reasoning.step import ReasoningStep
6
+ from agno.run.agent import RunOutput, RunOutputEvent, RunPausedEvent
7
+ from agno.run.team import TeamRunOutput, TeamRunOutputEvent
8
+
9
+
10
+ def create_panel(content, title, border_style="blue"):
11
+ from rich.box import HEAVY
12
+ from rich.panel import Panel
13
+
14
+ return Panel(
15
+ content, title=title, title_align="left", border_style=border_style, box=HEAVY, expand=True, padding=(1, 1)
16
+ )
17
+
18
+
19
+ def build_reasoning_step_panel(
20
+ step_idx: int, step: ReasoningStep, show_full_reasoning: bool = False, color: str = "green"
21
+ ):
22
+ from rich.text import Text
23
+
24
+ # Build step content
25
+ step_content = Text.assemble()
26
+ if step.title is not None:
27
+ step_content.append(f"{step.title}\n", "bold")
28
+ if step.action is not None:
29
+ step_content.append(Text.from_markup(f"[bold]Action:[/bold] {step.action}\n", style="dim"))
30
+ if step.result is not None:
31
+ step_content.append(Text.from_markup(step.result, style="dim"))
32
+
33
+ if show_full_reasoning:
34
+ # Add detailed reasoning information if available
35
+ if step.reasoning is not None:
36
+ step_content.append(Text.from_markup(f"\n[bold]Reasoning:[/bold] {step.reasoning}", style="dim"))
37
+ if step.confidence is not None:
38
+ step_content.append(Text.from_markup(f"\n[bold]Confidence:[/bold] {step.confidence}", style="dim"))
39
+ return create_panel(content=step_content, title=f"Reasoning step {step_idx}", border_style=color)
40
+
41
+
42
+ def escape_markdown_tags(content: str, tags: Set[str]) -> str:
43
+ """Escape special tags in markdown content."""
44
+ escaped_content = content
45
+ for tag in tags:
46
+ # Escape opening tag
47
+ escaped_content = escaped_content.replace(f"<{tag}>", f"&lt;{tag}&gt;")
48
+ # Escape closing tag
49
+ escaped_content = escaped_content.replace(f"</{tag}>", f"&lt;/{tag}&gt;")
50
+ return escaped_content
51
+
52
+
53
+ def check_if_run_cancelled(run_output: Union[RunOutput, RunOutputEvent, TeamRunOutput, TeamRunOutputEvent]):
54
+ if run_output.is_cancelled:
55
+ raise RunCancelledException()
56
+
57
+
58
+ def format_tool_calls(tool_calls: List[ToolExecution]) -> List[str]:
59
+ """Format tool calls for display in a readable format.
60
+
61
+ Args:
62
+ tool_calls: List of tool call dictionaries containing tool_name and tool_args
63
+
64
+ Returns:
65
+ List[str]: List of formatted tool call strings
66
+ """
67
+ formatted_tool_calls = []
68
+
69
+ for tool_call in tool_calls:
70
+ if tool_call.tool_name is not None:
71
+ tool_name = tool_call.tool_name
72
+ args_str = ""
73
+ if tool_call.tool_args is not None and tool_call.tool_args: # Check if args exist and are non-empty
74
+ args_str = ", ".join(f"{k}={v}" for k, v in tool_call.tool_args.items())
75
+ formatted_tool_calls.append(f"{tool_name}({args_str})")
76
+
77
+ return formatted_tool_calls
78
+
79
+
80
+ def create_paused_run_output_panel(run_output: Union[RunPausedEvent, RunOutput]):
81
+ from rich.text import Text
82
+
83
+ tool_calls_content = Text("Run is paused. ")
84
+ if run_output.tools is not None:
85
+ if any(tc.requires_confirmation for tc in run_output.tools):
86
+ tool_calls_content.append("The following tool calls require confirmation:\n")
87
+ for tool_call in run_output.tools:
88
+ if tool_call.requires_confirmation:
89
+ args_str = ""
90
+ for arg, value in tool_call.tool_args.items() if tool_call.tool_args else {}:
91
+ args_str += f"{arg}={value}, "
92
+ args_str = args_str.rstrip(", ")
93
+ tool_calls_content.append(f"• {tool_call.tool_name}({args_str})\n")
94
+ if any(tc.requires_user_input for tc in run_output.tools):
95
+ tool_calls_content.append("The following tool calls require user input:\n")
96
+ for tool_call in run_output.tools:
97
+ if tool_call.requires_user_input:
98
+ args_str = ""
99
+ for arg, value in tool_call.tool_args.items() if tool_call.tool_args else {}:
100
+ args_str += f"{arg}={value}, "
101
+ args_str = args_str.rstrip(", ")
102
+ tool_calls_content.append(f"• {tool_call.tool_name}({args_str})\n")
103
+ if any(tc.external_execution_required for tc in run_output.tools):
104
+ tool_calls_content.append("The following tool calls require external execution:\n")
105
+ for tool_call in run_output.tools:
106
+ if tool_call.external_execution_required:
107
+ args_str = ""
108
+ for arg, value in tool_call.tool_args.items() if tool_call.tool_args else {}:
109
+ args_str += f"{arg}={value}, "
110
+ args_str = args_str.rstrip(", ")
111
+ tool_calls_content.append(f"• {tool_call.tool_name}({args_str})\n")
112
+
113
+ # Create panel for response
114
+ response_panel = create_panel(
115
+ content=tool_calls_content,
116
+ title="Run Paused",
117
+ border_style="blue",
118
+ )
119
+ return response_panel
120
+
121
+
122
+ def get_paused_content(run_output: RunOutput) -> str:
123
+ paused_content = ""
124
+ for tool in run_output.tools or []:
125
+ # Initialize flags for each tool
126
+ confirmation_required = False
127
+ user_input_required = False
128
+ external_execution_required = False
129
+
130
+ if tool.requires_confirmation is not None and tool.requires_confirmation is True and not tool.confirmed:
131
+ confirmation_required = True
132
+ if tool.requires_user_input is not None and tool.requires_user_input is True:
133
+ user_input_required = True
134
+ if tool.external_execution_required is not None and tool.external_execution_required is True:
135
+ external_execution_required = True
136
+
137
+ if confirmation_required and user_input_required and external_execution_required:
138
+ paused_content = "I have tools to execute, but I need confirmation, user input, or external execution."
139
+ elif confirmation_required and user_input_required:
140
+ paused_content = "I have tools to execute, but I need confirmation or user input."
141
+ elif confirmation_required and external_execution_required:
142
+ paused_content = "I have tools to execute, but I need confirmation or external execution."
143
+ elif user_input_required and external_execution_required:
144
+ paused_content = "I have tools to execute, but I need user input or external execution."
145
+ elif confirmation_required:
146
+ paused_content = "I have tools to execute, but I need confirmation."
147
+ elif user_input_required:
148
+ paused_content = "I have tools to execute, but I need user input."
149
+ elif external_execution_required:
150
+ paused_content = "I have tools to execute, but it needs external execution."
151
+ return paused_content
152
+
153
+
154
+ def generator_wrapper(
155
+ event: Union[RunOutputEvent, TeamRunOutputEvent],
156
+ ) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
157
+ yield event
158
+
159
+
160
+ async def async_generator_wrapper(
161
+ event: Union[RunOutputEvent, TeamRunOutputEvent],
162
+ ) -> AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
163
+ yield event
@@ -0,0 +1,17 @@
1
+ class ResponseIterator:
2
+ def __init__(self):
3
+ self.items = []
4
+ self.index = 0
5
+
6
+ def add(self, item):
7
+ self.items.append(item)
8
+
9
+ def __iter__(self):
10
+ return self
11
+
12
+ def __next__(self):
13
+ if self.index >= len(self.items):
14
+ raise StopIteration
15
+ item = self.items[self.index]
16
+ self.index += 1
17
+ return item
@@ -0,0 +1,24 @@
1
+ import string
2
+
3
+
4
+ class SafeFormatter(string.Formatter):
5
+ def get_value(self, key, args, kwargs):
6
+ """Handle missing keys by returning '{key}'."""
7
+ if key not in kwargs:
8
+ return f"{key}"
9
+ return kwargs[key]
10
+
11
+ def format_field(self, value, format_spec):
12
+ """
13
+ If Python sees something like 'somekey:"stuff"', it tries to parse
14
+ it as a format spec and might raise ValueError. We catch it here
15
+ and just return the literal placeholder.
16
+ """
17
+ if not format_spec:
18
+ return super().format_field(value, format_spec)
19
+
20
+ try:
21
+ return super().format_field(value, format_spec)
22
+ except ValueError:
23
+ # On invalid format specifiers, keep them literal
24
+ return f"{{{value}:{format_spec}}}"
@@ -0,0 +1,32 @@
1
+ """JSON serialization utilities for handling datetime and enum objects."""
2
+
3
+ from datetime import date, datetime, time
4
+ from enum import Enum
5
+ from typing import Any
6
+
7
+
8
+ def json_serializer(obj: Any) -> Any:
9
+ """Custom JSON serializer for objects not serializable by default json module.
10
+
11
+ Handles:
12
+ - datetime, date, time objects -> ISO format strings
13
+ - Enum objects -> their values (or names if values are not JSON-serializable)
14
+ - All other objects -> string representation
15
+
16
+ Args:
17
+ obj: Object to serialize
18
+
19
+ Returns:
20
+ JSON-serializable representation of the object
21
+ """
22
+ # Datetime like
23
+ if isinstance(obj, (datetime, date, time)):
24
+ return obj.isoformat()
25
+
26
+ # Enums
27
+ if isinstance(obj, Enum):
28
+ v = obj.value
29
+ return v if isinstance(v, (str, int, float, bool, type(None))) else obj.name
30
+
31
+ # Fallback to string
32
+ return str(obj)
agno/utils/shell.py ADDED
@@ -0,0 +1,22 @@
1
+ from typing import List
2
+
3
+ from agno.utils.log import log_debug, log_info, logger
4
+
5
+
6
+ def run_shell_command(args: List[str], tail: int = 100) -> str:
7
+ log_info(f"Running shell command: {args}")
8
+
9
+ import subprocess
10
+
11
+ try:
12
+ result = subprocess.run(args, capture_output=True, text=True)
13
+ log_debug(f"Result: {result}")
14
+ log_debug(f"Return code: {result.returncode}")
15
+ if result.returncode != 0:
16
+ return f"Error: {result.stderr}"
17
+
18
+ # return only the last n lines of the output
19
+ return "\n".join(result.stdout.split("\n")[-tail:])
20
+ except Exception as e:
21
+ logger.warning(f"Failed to run shell command: {e}")
22
+ return f"Error: {e}"