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
@@ -0,0 +1,757 @@
1
+ import json
2
+ from collections.abc import AsyncIterator
3
+ from dataclasses import asdict, dataclass
4
+ from os import getenv
5
+ from typing import Any, Dict, List, Optional, Type, Union
6
+
7
+ from pydantic import BaseModel
8
+
9
+ from agno.exceptions import ModelProviderError, ModelRateLimitError
10
+ from agno.models.base import Model
11
+ from agno.models.message import Citations, DocumentCitation, Message, UrlCitation
12
+ from agno.models.metrics import Metrics
13
+ from agno.models.response import ModelResponse
14
+ from agno.run.agent import RunOutput
15
+ from agno.utils.log import log_debug, log_error, log_warning
16
+ from agno.utils.models.claude import MCPServerConfiguration, format_messages, format_tools_for_model
17
+
18
+ try:
19
+ from anthropic import Anthropic as AnthropicClient
20
+ from anthropic import (
21
+ APIConnectionError,
22
+ APIStatusError,
23
+ RateLimitError,
24
+ )
25
+ from anthropic import (
26
+ AsyncAnthropic as AsyncAnthropicClient,
27
+ )
28
+ from anthropic.types import (
29
+ CitationPageLocation,
30
+ CitationsWebSearchResultLocation,
31
+ ContentBlockDeltaEvent,
32
+ ContentBlockStartEvent,
33
+ ContentBlockStopEvent,
34
+ MessageDeltaUsage,
35
+ # MessageDeltaEvent, # Currently broken
36
+ MessageStopEvent,
37
+ Usage,
38
+ )
39
+ from anthropic.types import (
40
+ Message as AnthropicMessage,
41
+ )
42
+ except ImportError as e:
43
+ raise ImportError("`anthropic` not installed. Please install it with `pip install anthropic`") from e
44
+
45
+ # Import Beta types
46
+ try:
47
+ from anthropic.types.beta import BetaRawContentBlockDeltaEvent, BetaTextDelta
48
+ from anthropic.types.beta.beta_message import BetaMessage
49
+ from anthropic.types.beta.beta_usage import BetaUsage
50
+ except ImportError as e:
51
+ raise ImportError(
52
+ "`anthropic` not installed or missing beta components. Please install with `pip install anthropic`"
53
+ ) from e
54
+
55
+
56
+ @dataclass
57
+ class Claude(Model):
58
+ """
59
+ A class representing Anthropic Claude model.
60
+
61
+ For more information, see: https://docs.anthropic.com/en/api/messages
62
+ """
63
+
64
+ # Models that DO NOT support extended thinking
65
+ # All future models are assumed to support thinking
66
+ # Based on official Anthropic documentation: https://docs.claude.com/en/docs/about-claude/models/overview
67
+ NON_THINKING_MODELS = {
68
+ # Claude Haiku 3 family (does not support thinking)
69
+ "claude-3-haiku-20240307",
70
+ # Claude Haiku 3.5 family (does not support thinking)
71
+ "claude-3-5-haiku-20241022",
72
+ "claude-3-5-haiku-latest",
73
+ }
74
+
75
+ id: str = "claude-sonnet-4-5-20250929"
76
+ name: str = "Claude"
77
+ provider: str = "Anthropic"
78
+
79
+ # Request parameters
80
+ max_tokens: Optional[int] = 8192
81
+ thinking: Optional[Dict[str, Any]] = None
82
+ temperature: Optional[float] = None
83
+ stop_sequences: Optional[List[str]] = None
84
+ top_p: Optional[float] = None
85
+ top_k: Optional[int] = None
86
+ cache_system_prompt: Optional[bool] = False
87
+ extended_cache_time: Optional[bool] = False
88
+ request_params: Optional[Dict[str, Any]] = None
89
+
90
+ # Anthropic beta and experimental features
91
+ betas: Optional[List[str]] = None # Enables specific experimental or newly released features.
92
+ context_management: Optional[Dict[str, Any]] = None
93
+ mcp_servers: Optional[List[MCPServerConfiguration]] = None
94
+ skills: Optional[List[Dict[str, str]]] = (
95
+ None # e.g., [{"type": "anthropic", "skill_id": "pptx", "version": "latest"}]
96
+ )
97
+
98
+ # Client parameters
99
+ api_key: Optional[str] = None
100
+ default_headers: Optional[Dict[str, Any]] = None
101
+ timeout: Optional[float] = None
102
+ client_params: Optional[Dict[str, Any]] = None
103
+
104
+ client: Optional[AnthropicClient] = None
105
+ async_client: Optional[AsyncAnthropicClient] = None
106
+
107
+ def __post_init__(self):
108
+ """Validate model configuration after initialization"""
109
+ # Validate thinking support immediately at model creation
110
+ if self.thinking:
111
+ self._validate_thinking_support()
112
+ # Set up skills configuration if skills are enabled
113
+ if self.skills:
114
+ self._setup_skills_configuration()
115
+
116
+ def _get_client_params(self) -> Dict[str, Any]:
117
+ client_params: Dict[str, Any] = {}
118
+
119
+ self.api_key = self.api_key or getenv("ANTHROPIC_API_KEY")
120
+ if not self.api_key:
121
+ log_error("ANTHROPIC_API_KEY not set. Please set the ANTHROPIC_API_KEY environment variable.")
122
+
123
+ # Add API key to client parameters
124
+ client_params["api_key"] = self.api_key
125
+ if self.timeout is not None:
126
+ client_params["timeout"] = self.timeout
127
+
128
+ # Add additional client parameters
129
+ if self.client_params is not None:
130
+ client_params.update(self.client_params)
131
+ if self.default_headers is not None:
132
+ client_params["default_headers"] = self.default_headers
133
+ return client_params
134
+
135
+ def _has_beta_features(self) -> bool:
136
+ """Check if the model has any Anthropic beta features enabled."""
137
+ return (
138
+ self.mcp_servers is not None
139
+ or self.context_management is not None
140
+ or self.skills is not None
141
+ or self.betas is not None
142
+ )
143
+
144
+ def get_client(self) -> AnthropicClient:
145
+ """
146
+ Returns an instance of the Anthropic client.
147
+ """
148
+ if self.client and not self.client.is_closed():
149
+ return self.client
150
+
151
+ _client_params = self._get_client_params()
152
+ self.client = AnthropicClient(**_client_params)
153
+ return self.client
154
+
155
+ def get_async_client(self) -> AsyncAnthropicClient:
156
+ """
157
+ Returns an instance of the async Anthropic client.
158
+ """
159
+ if self.async_client and not self.async_client.is_closed():
160
+ return self.async_client
161
+
162
+ _client_params = self._get_client_params()
163
+ self.async_client = AsyncAnthropicClient(**_client_params)
164
+ return self.async_client
165
+
166
+ def _validate_thinking_support(self) -> None:
167
+ """
168
+ Validate that the current model supports extended thinking.
169
+
170
+ Raises:
171
+ ValueError: If thinking is enabled but the model doesn't support it
172
+ """
173
+ if self.thinking and self.id in self.NON_THINKING_MODELS:
174
+ non_thinking_models = "\n - ".join(sorted(self.NON_THINKING_MODELS))
175
+ raise ValueError(
176
+ f"Model '{self.id}' does not support extended thinking.\n\n"
177
+ f"The following models do NOT support thinking:\n - {non_thinking_models}\n\n"
178
+ f"All other Claude models support extended thinking by default.\n"
179
+ f"For more information, see: https://docs.anthropic.com/en/docs/about-claude/models/overview"
180
+ )
181
+
182
+ def _setup_skills_configuration(self) -> None:
183
+ """
184
+ Set up configuration for Claude Agent Skills.
185
+ Automatically configures betas array with required values.
186
+
187
+ Skills enable document creation capabilities (PowerPoint, Excel, Word, PDF).
188
+ For more information, see: https://docs.claude.com/en/docs/agents-and-tools/agent-skills/quickstart
189
+ """
190
+ # Required betas for skills
191
+ required_betas = ["code-execution-2025-08-25", "skills-2025-10-02"]
192
+
193
+ # Initialize or merge betas
194
+ if self.betas is None:
195
+ self.betas = required_betas
196
+ else:
197
+ # Add required betas if not present
198
+ for beta in required_betas:
199
+ if beta not in self.betas:
200
+ self.betas.append(beta)
201
+
202
+ def get_request_params(self) -> Dict[str, Any]:
203
+ """
204
+ Generate keyword arguments for API requests.
205
+ """
206
+ # Validate thinking support if thinking is enabled
207
+ if self.thinking:
208
+ self._validate_thinking_support()
209
+
210
+ _request_params: Dict[str, Any] = {}
211
+ if self.max_tokens:
212
+ _request_params["max_tokens"] = self.max_tokens
213
+ if self.thinking:
214
+ _request_params["thinking"] = self.thinking
215
+ if self.temperature:
216
+ _request_params["temperature"] = self.temperature
217
+ if self.stop_sequences:
218
+ _request_params["stop_sequences"] = self.stop_sequences
219
+ if self.top_p:
220
+ _request_params["top_p"] = self.top_p
221
+ if self.top_k:
222
+ _request_params["top_k"] = self.top_k
223
+ if self.betas:
224
+ _request_params["betas"] = self.betas
225
+ if self.context_management:
226
+ _request_params["context_management"] = self.context_management
227
+ if self.mcp_servers:
228
+ _request_params["mcp_servers"] = [
229
+ {k: v for k, v in asdict(server).items() if v is not None} for server in self.mcp_servers
230
+ ]
231
+ if self.skills:
232
+ _request_params["betas"] = self.betas
233
+ _request_params["container"] = {"skills": self.skills}
234
+ if self.request_params:
235
+ _request_params.update(self.request_params)
236
+
237
+ return _request_params
238
+
239
+ def _prepare_request_kwargs(
240
+ self, system_message: str, tools: Optional[List[Dict[str, Any]]] = None
241
+ ) -> Dict[str, Any]:
242
+ """
243
+ Prepare the request keyword arguments for the API call.
244
+
245
+ Args:
246
+ system_message (str): The concatenated system messages.
247
+
248
+ Returns:
249
+ Dict[str, Any]: The request keyword arguments.
250
+ """
251
+ request_kwargs = self.get_request_params().copy()
252
+ if system_message:
253
+ if self.cache_system_prompt:
254
+ cache_control = (
255
+ {"type": "ephemeral", "ttl": "1h"}
256
+ if self.extended_cache_time is not None and self.extended_cache_time is True
257
+ else {"type": "ephemeral"}
258
+ )
259
+ request_kwargs["system"] = [{"text": system_message, "type": "text", "cache_control": cache_control}]
260
+ else:
261
+ request_kwargs["system"] = [{"text": system_message, "type": "text"}]
262
+
263
+ # Add code execution tool if skills are enabled
264
+ if self.skills:
265
+ code_execution_tool = {"type": "code_execution_20250825", "name": "code_execution"}
266
+ if tools:
267
+ # Add code_execution to existing tools, code execution is needed for generating and processing files
268
+ tools = tools + [code_execution_tool]
269
+ else:
270
+ tools = [code_execution_tool]
271
+
272
+ if tools:
273
+ request_kwargs["tools"] = format_tools_for_model(tools)
274
+
275
+ if request_kwargs:
276
+ log_debug(f"Calling {self.provider} with request parameters: {request_kwargs}", log_level=2)
277
+ return request_kwargs
278
+
279
+ def invoke(
280
+ self,
281
+ messages: List[Message],
282
+ assistant_message: Message,
283
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
284
+ tools: Optional[List[Dict[str, Any]]] = None,
285
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
286
+ run_response: Optional[RunOutput] = None,
287
+ ) -> ModelResponse:
288
+ """
289
+ Send a request to the Anthropic API to generate a response.
290
+ """
291
+ try:
292
+ if run_response and run_response.metrics:
293
+ run_response.metrics.set_time_to_first_token()
294
+
295
+ chat_messages, system_message = format_messages(messages)
296
+ request_kwargs = self._prepare_request_kwargs(system_message, tools)
297
+
298
+ if self._has_beta_features():
299
+ assistant_message.metrics.start_timer()
300
+ provider_response = self.get_client().beta.messages.create(
301
+ model=self.id,
302
+ messages=chat_messages, # type: ignore
303
+ **request_kwargs,
304
+ )
305
+ else:
306
+ assistant_message.metrics.start_timer()
307
+ provider_response = self.get_client().messages.create(
308
+ model=self.id,
309
+ messages=chat_messages, # type: ignore
310
+ **request_kwargs,
311
+ )
312
+
313
+ assistant_message.metrics.stop_timer()
314
+
315
+ # Parse the response into an Agno ModelResponse object
316
+ model_response = self._parse_provider_response(provider_response, response_format=response_format) # type: ignore
317
+
318
+ return model_response
319
+
320
+ except APIConnectionError as e:
321
+ log_error(f"Connection error while calling Claude API: {str(e)}")
322
+ raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
323
+ except RateLimitError as e:
324
+ log_warning(f"Rate limit exceeded: {str(e)}")
325
+ raise ModelRateLimitError(message=e.message, model_name=self.name, model_id=self.id) from e
326
+ except APIStatusError as e:
327
+ log_error(f"Claude API error (status {e.status_code}): {str(e)}")
328
+ raise ModelProviderError(
329
+ message=e.message, status_code=e.status_code, model_name=self.name, model_id=self.id
330
+ ) from e
331
+ except Exception as e:
332
+ log_error(f"Unexpected error calling Claude API: {str(e)}")
333
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
334
+
335
+ def invoke_stream(
336
+ self,
337
+ messages: List[Message],
338
+ assistant_message: Message,
339
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
340
+ tools: Optional[List[Dict[str, Any]]] = None,
341
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
342
+ run_response: Optional[RunOutput] = None,
343
+ ) -> Any:
344
+ """
345
+ Stream a response from the Anthropic API.
346
+
347
+ Args:
348
+ messages (List[Message]): A list of messages to send to the model.
349
+
350
+ Returns:
351
+ Any: The streamed response from the model.
352
+
353
+ Raises:
354
+ APIConnectionError: If there are network connectivity issues
355
+ RateLimitError: If the API rate limit is exceeded
356
+ APIStatusError: For other API-related errors
357
+ """
358
+ chat_messages, system_message = format_messages(messages)
359
+ request_kwargs = self._prepare_request_kwargs(system_message, tools)
360
+
361
+ try:
362
+ if run_response and run_response.metrics:
363
+ run_response.metrics.set_time_to_first_token()
364
+
365
+ # Beta features
366
+ if self._has_beta_features():
367
+ assistant_message.metrics.start_timer()
368
+ with self.get_client().beta.messages.stream(
369
+ model=self.id,
370
+ messages=chat_messages, # type: ignore
371
+ **request_kwargs,
372
+ ) as stream:
373
+ for chunk in stream:
374
+ yield self._parse_provider_response_delta(chunk) # type: ignore
375
+ else:
376
+ assistant_message.metrics.start_timer()
377
+ with self.get_client().messages.stream(
378
+ model=self.id,
379
+ messages=chat_messages, # type: ignore
380
+ **request_kwargs,
381
+ ) as stream:
382
+ for chunk in stream: # type: ignore
383
+ yield self._parse_provider_response_delta(chunk) # type: ignore
384
+
385
+ assistant_message.metrics.stop_timer()
386
+
387
+ except APIConnectionError as e:
388
+ log_error(f"Connection error while calling Claude API: {str(e)}")
389
+ raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
390
+ except RateLimitError as e:
391
+ log_warning(f"Rate limit exceeded: {str(e)}")
392
+ raise ModelRateLimitError(message=e.message, model_name=self.name, model_id=self.id) from e
393
+ except APIStatusError as e:
394
+ log_error(f"Claude API error (status {e.status_code}): {str(e)}")
395
+ raise ModelProviderError(
396
+ message=e.message, status_code=e.status_code, model_name=self.name, model_id=self.id
397
+ ) from e
398
+ except Exception as e:
399
+ log_error(f"Unexpected error calling Claude API: {str(e)}")
400
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
401
+
402
+ async def ainvoke(
403
+ self,
404
+ messages: List[Message],
405
+ assistant_message: Message,
406
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
407
+ tools: Optional[List[Dict[str, Any]]] = None,
408
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
409
+ run_response: Optional[RunOutput] = None,
410
+ ) -> ModelResponse:
411
+ """
412
+ Send an asynchronous request to the Anthropic API to generate a response.
413
+ """
414
+ try:
415
+ if run_response and run_response.metrics:
416
+ run_response.metrics.set_time_to_first_token()
417
+
418
+ chat_messages, system_message = format_messages(messages)
419
+ request_kwargs = self._prepare_request_kwargs(system_message, tools)
420
+
421
+ # Beta features
422
+ if self._has_beta_features():
423
+ assistant_message.metrics.start_timer()
424
+ provider_response = await self.get_async_client().beta.messages.create(
425
+ model=self.id,
426
+ messages=chat_messages, # type: ignore
427
+ **request_kwargs,
428
+ )
429
+ else:
430
+ assistant_message.metrics.start_timer()
431
+ provider_response = await self.get_async_client().messages.create(
432
+ model=self.id,
433
+ messages=chat_messages, # type: ignore
434
+ **request_kwargs,
435
+ )
436
+
437
+ assistant_message.metrics.stop_timer()
438
+
439
+ # Parse the response into an Agno ModelResponse object
440
+ model_response = self._parse_provider_response(provider_response, response_format=response_format) # type: ignore
441
+
442
+ return model_response
443
+
444
+ except APIConnectionError as e:
445
+ log_error(f"Connection error while calling Claude API: {str(e)}")
446
+ raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
447
+ except RateLimitError as e:
448
+ log_warning(f"Rate limit exceeded: {str(e)}")
449
+ raise ModelRateLimitError(message=e.message, model_name=self.name, model_id=self.id) from e
450
+ except APIStatusError as e:
451
+ log_error(f"Claude API error (status {e.status_code}): {str(e)}")
452
+ raise ModelProviderError(
453
+ message=e.message, status_code=e.status_code, model_name=self.name, model_id=self.id
454
+ ) from e
455
+ except Exception as e:
456
+ log_error(f"Unexpected error calling Claude API: {str(e)}")
457
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
458
+
459
+ async def ainvoke_stream(
460
+ self,
461
+ messages: List[Message],
462
+ assistant_message: Message,
463
+ response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
464
+ tools: Optional[List[Dict[str, Any]]] = None,
465
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
466
+ run_response: Optional[RunOutput] = None,
467
+ ) -> AsyncIterator[ModelResponse]:
468
+ """
469
+ Stream an asynchronous response from the Anthropic API.
470
+ Args:
471
+ messages (List[Message]): A list of messages to send to the model.
472
+ Returns:
473
+ AsyncIterator[ModelResponse]: An async iterator of processed model responses.
474
+ Raises:
475
+ APIConnectionError: If there are network connectivity issues
476
+ RateLimitError: If the API rate limit is exceeded
477
+ APIStatusError: For other API-related errors
478
+ """
479
+ try:
480
+ if run_response and run_response.metrics:
481
+ run_response.metrics.set_time_to_first_token()
482
+
483
+ chat_messages, system_message = format_messages(messages)
484
+ request_kwargs = self._prepare_request_kwargs(system_message, tools)
485
+
486
+ if self._has_beta_features():
487
+ assistant_message.metrics.start_timer()
488
+ async with self.get_async_client().beta.messages.stream(
489
+ model=self.id,
490
+ messages=chat_messages, # type: ignore
491
+ **request_kwargs,
492
+ ) as stream:
493
+ async for chunk in stream:
494
+ yield self._parse_provider_response_delta(chunk) # type: ignore
495
+ else:
496
+ assistant_message.metrics.start_timer()
497
+ async with self.get_async_client().messages.stream(
498
+ model=self.id,
499
+ messages=chat_messages, # type: ignore
500
+ **request_kwargs,
501
+ ) as stream:
502
+ async for chunk in stream: # type: ignore
503
+ yield self._parse_provider_response_delta(chunk) # type: ignore
504
+
505
+ assistant_message.metrics.stop_timer()
506
+
507
+ except APIConnectionError as e:
508
+ log_error(f"Connection error while calling Claude API: {str(e)}")
509
+ raise ModelProviderError(message=e.message, model_name=self.name, model_id=self.id) from e
510
+ except RateLimitError as e:
511
+ log_warning(f"Rate limit exceeded: {str(e)}")
512
+ raise ModelRateLimitError(message=e.message, model_name=self.name, model_id=self.id) from e
513
+ except APIStatusError as e:
514
+ log_error(f"Claude API error (status {e.status_code}): {str(e)}")
515
+ raise ModelProviderError(
516
+ message=e.message, status_code=e.status_code, model_name=self.name, model_id=self.id
517
+ ) from e
518
+ except Exception as e:
519
+ log_error(f"Unexpected error calling Claude API: {str(e)}")
520
+ raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
521
+
522
+ def get_system_message_for_model(self, tools: Optional[List[Any]] = None) -> Optional[str]:
523
+ if tools is not None and len(tools) > 0:
524
+ tool_call_prompt = "Do not reflect on the quality of the returned search results in your response\n\n"
525
+ return tool_call_prompt
526
+ return None
527
+
528
+ def _parse_provider_response(self, response: Union[AnthropicMessage, BetaMessage], **kwargs) -> ModelResponse:
529
+ """
530
+ Parse the Claude response into a ModelResponse.
531
+
532
+ Args:
533
+ response: Raw response from Anthropic
534
+
535
+ Returns:
536
+ ModelResponse: Parsed response data
537
+ """
538
+ model_response = ModelResponse()
539
+
540
+ # Add role (Claude always uses 'assistant')
541
+ model_response.role = response.role or "assistant"
542
+
543
+ if response.content:
544
+ for block in response.content:
545
+ if block.type == "text":
546
+ if model_response.content is None:
547
+ model_response.content = block.text
548
+ else:
549
+ model_response.content += block.text
550
+
551
+ # Capture citations from the response
552
+ if block.citations is not None:
553
+ if model_response.citations is None:
554
+ model_response.citations = Citations(raw=[], urls=[], documents=[])
555
+ for citation in block.citations:
556
+ model_response.citations.raw.append(citation.model_dump()) # type: ignore
557
+ # Web search citations
558
+ if isinstance(citation, CitationsWebSearchResultLocation):
559
+ model_response.citations.urls.append( # type: ignore
560
+ UrlCitation(url=citation.url, title=citation.cited_text)
561
+ )
562
+ # Document citations
563
+ elif isinstance(citation, CitationPageLocation):
564
+ model_response.citations.documents.append( # type: ignore
565
+ DocumentCitation(
566
+ document_title=citation.document_title,
567
+ cited_text=citation.cited_text,
568
+ )
569
+ )
570
+ elif block.type == "thinking":
571
+ model_response.reasoning_content = block.thinking
572
+ model_response.provider_data = {
573
+ "signature": block.signature,
574
+ }
575
+ elif block.type == "redacted_thinking":
576
+ model_response.redacted_reasoning_content = block.data
577
+
578
+ # Extract tool calls from the response
579
+ if response.stop_reason == "tool_use":
580
+ for block in response.content:
581
+ if block.type == "tool_use":
582
+ tool_name = block.name
583
+ tool_input = block.input
584
+
585
+ function_def = {"name": tool_name}
586
+ if tool_input:
587
+ function_def["arguments"] = json.dumps(tool_input)
588
+
589
+ model_response.extra = model_response.extra or {}
590
+
591
+ model_response.tool_calls.append(
592
+ {
593
+ "id": block.id,
594
+ "type": "function",
595
+ "function": function_def,
596
+ }
597
+ )
598
+
599
+ # Add usage metrics
600
+ if response.usage is not None:
601
+ model_response.response_usage = self._get_metrics(response.usage)
602
+
603
+ # Capture context management information if present
604
+ if self.context_management is not None and hasattr(response, "context_management"):
605
+ if response.context_management is not None: # type: ignore
606
+ model_response.provider_data = model_response.provider_data or {}
607
+ if hasattr(response.context_management, "model_dump"):
608
+ model_response.provider_data["context_management"] = response.context_management.model_dump() # type: ignore
609
+ else:
610
+ model_response.provider_data["context_management"] = response.context_management # type: ignore
611
+ # Extract file IDs if skills are enabled
612
+ if self.skills and response.content:
613
+ file_ids: List[str] = []
614
+ for block in response.content:
615
+ if block.type == "bash_code_execution_tool_result":
616
+ if hasattr(block, "content") and hasattr(block.content, "content"):
617
+ if isinstance(block.content.content, list):
618
+ for output_block in block.content.content:
619
+ if hasattr(output_block, "file_id"):
620
+ file_ids.append(output_block.file_id)
621
+
622
+ if file_ids:
623
+ if model_response.provider_data is None:
624
+ model_response.provider_data = {}
625
+ model_response.provider_data["file_ids"] = file_ids
626
+
627
+ return model_response
628
+
629
+ def _parse_provider_response_delta(
630
+ self,
631
+ response: Union[
632
+ ContentBlockStartEvent,
633
+ ContentBlockDeltaEvent,
634
+ ContentBlockStopEvent,
635
+ MessageStopEvent,
636
+ BetaRawContentBlockDeltaEvent,
637
+ ],
638
+ ) -> ModelResponse:
639
+ """
640
+ Parse the Claude streaming response into ModelProviderResponse objects.
641
+
642
+ Args:
643
+ response: Raw response chunk from Anthropic
644
+
645
+ Returns:
646
+ ModelResponse: Iterator of parsed response data
647
+ """
648
+ model_response = ModelResponse()
649
+
650
+ if isinstance(response, ContentBlockStartEvent):
651
+ if response.content_block.type == "redacted_reasoning_content":
652
+ model_response.redacted_reasoning_content = response.content_block.data
653
+
654
+ if isinstance(response, ContentBlockDeltaEvent):
655
+ # Handle text content
656
+ if response.delta.type == "text_delta":
657
+ model_response.content = response.delta.text
658
+ # Handle thinking content
659
+ elif response.delta.type == "thinking_delta":
660
+ model_response.reasoning_content = response.delta.thinking
661
+ elif response.delta.type == "signature_delta":
662
+ model_response.provider_data = {
663
+ "signature": response.delta.signature,
664
+ }
665
+
666
+ elif isinstance(response, ContentBlockStopEvent):
667
+ if response.content_block.type == "tool_use": # type: ignore
668
+ tool_use = response.content_block # type: ignore
669
+ tool_name = tool_use.name
670
+ tool_input = tool_use.input
671
+
672
+ function_def = {"name": tool_name}
673
+ if tool_input:
674
+ function_def["arguments"] = json.dumps(tool_input)
675
+
676
+ model_response.extra = model_response.extra or {}
677
+
678
+ model_response.tool_calls = [
679
+ {
680
+ "id": tool_use.id,
681
+ "type": "function",
682
+ "function": function_def,
683
+ }
684
+ ]
685
+
686
+ # Capture citations from the final response
687
+ elif isinstance(response, MessageStopEvent):
688
+ model_response.content = ""
689
+ model_response.citations = Citations(raw=[], urls=[], documents=[])
690
+ for block in response.message.content: # type: ignore
691
+ citations = getattr(block, "citations", None)
692
+ if not citations:
693
+ continue
694
+ for citation in citations:
695
+ model_response.citations.raw.append(citation.model_dump()) # type: ignore
696
+ # Web search citations
697
+ if isinstance(citation, CitationsWebSearchResultLocation):
698
+ model_response.citations.urls.append(UrlCitation(url=citation.url, title=citation.cited_text)) # type: ignore
699
+ # Document citations
700
+ elif isinstance(citation, CitationPageLocation):
701
+ model_response.citations.documents.append( # type: ignore
702
+ DocumentCitation(document_title=citation.document_title, cited_text=citation.cited_text)
703
+ )
704
+
705
+ # Capture context management information if present
706
+ if self.context_management is not None and hasattr(response.message, "context_management"): # type: ignore
707
+ context_mgmt = response.message.context_management # type: ignore
708
+ if context_mgmt is not None:
709
+ model_response.provider_data = model_response.provider_data or {}
710
+ if hasattr(context_mgmt, "model_dump"):
711
+ model_response.provider_data["context_management"] = context_mgmt.model_dump()
712
+ else:
713
+ model_response.provider_data["context_management"] = context_mgmt
714
+
715
+ if hasattr(response, "message") and hasattr(response.message, "usage") and response.message.usage is not None: # type: ignore
716
+ model_response.response_usage = self._get_metrics(response.message.usage) # type: ignore
717
+
718
+ # Capture the Beta response
719
+ try:
720
+ if (
721
+ isinstance(response, BetaRawContentBlockDeltaEvent)
722
+ and isinstance(response.delta, BetaTextDelta)
723
+ and response.delta.text is not None
724
+ ):
725
+ model_response.content = response.delta.text
726
+ except Exception as e:
727
+ log_error(f"Error parsing Beta response: {e}")
728
+
729
+ return model_response
730
+
731
+ def _get_metrics(self, response_usage: Union[Usage, MessageDeltaUsage, BetaUsage]) -> Metrics:
732
+ """
733
+ Parse the given Anthropic-specific usage into an Agno Metrics object.
734
+
735
+ Args:
736
+ response_usage: Usage data from Anthropic
737
+
738
+ Returns:
739
+ Metrics: Parsed metrics data
740
+ """
741
+ metrics = Metrics()
742
+
743
+ metrics.input_tokens = response_usage.input_tokens or 0
744
+ metrics.output_tokens = response_usage.output_tokens or 0
745
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
746
+ metrics.cache_read_tokens = response_usage.cache_read_input_tokens or 0
747
+ metrics.cache_write_tokens = response_usage.cache_creation_input_tokens or 0
748
+
749
+ # Anthropic-specific additional fields
750
+ if response_usage.server_tool_use:
751
+ metrics.provider_metrics = {"server_tool_use": response_usage.server_tool_use.model_dump()}
752
+ if isinstance(response_usage, Usage):
753
+ if response_usage.service_tier:
754
+ metrics.provider_metrics = metrics.provider_metrics or {}
755
+ metrics.provider_metrics["service_tier"] = response_usage.service_tier
756
+
757
+ return metrics