agno 2.2.13__py3-none-any.whl → 2.4.3__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 (383) hide show
  1. agno/agent/__init__.py +6 -0
  2. agno/agent/agent.py +5252 -3145
  3. agno/agent/remote.py +525 -0
  4. agno/api/api.py +2 -0
  5. agno/client/__init__.py +3 -0
  6. agno/client/a2a/__init__.py +10 -0
  7. agno/client/a2a/client.py +554 -0
  8. agno/client/a2a/schemas.py +112 -0
  9. agno/client/a2a/utils.py +369 -0
  10. agno/client/os.py +2669 -0
  11. agno/compression/__init__.py +3 -0
  12. agno/compression/manager.py +247 -0
  13. agno/culture/manager.py +2 -2
  14. agno/db/base.py +927 -6
  15. agno/db/dynamo/dynamo.py +788 -2
  16. agno/db/dynamo/schemas.py +128 -0
  17. agno/db/dynamo/utils.py +26 -3
  18. agno/db/firestore/firestore.py +674 -50
  19. agno/db/firestore/schemas.py +41 -0
  20. agno/db/firestore/utils.py +25 -10
  21. agno/db/gcs_json/gcs_json_db.py +506 -3
  22. agno/db/gcs_json/utils.py +14 -2
  23. agno/db/in_memory/in_memory_db.py +203 -4
  24. agno/db/in_memory/utils.py +14 -2
  25. agno/db/json/json_db.py +498 -2
  26. agno/db/json/utils.py +14 -2
  27. agno/db/migrations/manager.py +199 -0
  28. agno/db/migrations/utils.py +19 -0
  29. agno/db/migrations/v1_to_v2.py +54 -16
  30. agno/db/migrations/versions/__init__.py +0 -0
  31. agno/db/migrations/versions/v2_3_0.py +977 -0
  32. agno/db/mongo/async_mongo.py +1013 -39
  33. agno/db/mongo/mongo.py +684 -4
  34. agno/db/mongo/schemas.py +48 -0
  35. agno/db/mongo/utils.py +17 -0
  36. agno/db/mysql/__init__.py +2 -1
  37. agno/db/mysql/async_mysql.py +2958 -0
  38. agno/db/mysql/mysql.py +722 -53
  39. agno/db/mysql/schemas.py +77 -11
  40. agno/db/mysql/utils.py +151 -8
  41. agno/db/postgres/async_postgres.py +1254 -137
  42. agno/db/postgres/postgres.py +2316 -93
  43. agno/db/postgres/schemas.py +153 -21
  44. agno/db/postgres/utils.py +22 -7
  45. agno/db/redis/redis.py +531 -3
  46. agno/db/redis/schemas.py +36 -0
  47. agno/db/redis/utils.py +31 -15
  48. agno/db/schemas/evals.py +1 -0
  49. agno/db/schemas/memory.py +20 -9
  50. agno/db/singlestore/schemas.py +70 -1
  51. agno/db/singlestore/singlestore.py +737 -74
  52. agno/db/singlestore/utils.py +13 -3
  53. agno/db/sqlite/async_sqlite.py +1069 -89
  54. agno/db/sqlite/schemas.py +133 -1
  55. agno/db/sqlite/sqlite.py +2203 -165
  56. agno/db/sqlite/utils.py +21 -11
  57. agno/db/surrealdb/models.py +25 -0
  58. agno/db/surrealdb/surrealdb.py +603 -1
  59. agno/db/utils.py +60 -0
  60. agno/eval/__init__.py +26 -3
  61. agno/eval/accuracy.py +25 -12
  62. agno/eval/agent_as_judge.py +871 -0
  63. agno/eval/base.py +29 -0
  64. agno/eval/performance.py +10 -4
  65. agno/eval/reliability.py +22 -13
  66. agno/eval/utils.py +2 -1
  67. agno/exceptions.py +42 -0
  68. agno/hooks/__init__.py +3 -0
  69. agno/hooks/decorator.py +164 -0
  70. agno/integrations/discord/client.py +13 -2
  71. agno/knowledge/__init__.py +4 -0
  72. agno/knowledge/chunking/code.py +90 -0
  73. agno/knowledge/chunking/document.py +65 -4
  74. agno/knowledge/chunking/fixed.py +4 -1
  75. agno/knowledge/chunking/markdown.py +102 -11
  76. agno/knowledge/chunking/recursive.py +2 -2
  77. agno/knowledge/chunking/semantic.py +130 -48
  78. agno/knowledge/chunking/strategy.py +18 -0
  79. agno/knowledge/embedder/azure_openai.py +0 -1
  80. agno/knowledge/embedder/google.py +1 -1
  81. agno/knowledge/embedder/mistral.py +1 -1
  82. agno/knowledge/embedder/nebius.py +1 -1
  83. agno/knowledge/embedder/openai.py +16 -12
  84. agno/knowledge/filesystem.py +412 -0
  85. agno/knowledge/knowledge.py +4261 -1199
  86. agno/knowledge/protocol.py +134 -0
  87. agno/knowledge/reader/arxiv_reader.py +3 -2
  88. agno/knowledge/reader/base.py +9 -7
  89. agno/knowledge/reader/csv_reader.py +91 -42
  90. agno/knowledge/reader/docx_reader.py +9 -10
  91. agno/knowledge/reader/excel_reader.py +225 -0
  92. agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
  93. agno/knowledge/reader/firecrawl_reader.py +3 -2
  94. agno/knowledge/reader/json_reader.py +16 -22
  95. agno/knowledge/reader/markdown_reader.py +15 -14
  96. agno/knowledge/reader/pdf_reader.py +33 -28
  97. agno/knowledge/reader/pptx_reader.py +9 -10
  98. agno/knowledge/reader/reader_factory.py +135 -1
  99. agno/knowledge/reader/s3_reader.py +8 -16
  100. agno/knowledge/reader/tavily_reader.py +3 -3
  101. agno/knowledge/reader/text_reader.py +15 -14
  102. agno/knowledge/reader/utils/__init__.py +17 -0
  103. agno/knowledge/reader/utils/spreadsheet.py +114 -0
  104. agno/knowledge/reader/web_search_reader.py +8 -65
  105. agno/knowledge/reader/website_reader.py +16 -13
  106. agno/knowledge/reader/wikipedia_reader.py +36 -3
  107. agno/knowledge/reader/youtube_reader.py +3 -2
  108. agno/knowledge/remote_content/__init__.py +33 -0
  109. agno/knowledge/remote_content/config.py +266 -0
  110. agno/knowledge/remote_content/remote_content.py +105 -17
  111. agno/knowledge/utils.py +76 -22
  112. agno/learn/__init__.py +71 -0
  113. agno/learn/config.py +463 -0
  114. agno/learn/curate.py +185 -0
  115. agno/learn/machine.py +725 -0
  116. agno/learn/schemas.py +1114 -0
  117. agno/learn/stores/__init__.py +38 -0
  118. agno/learn/stores/decision_log.py +1156 -0
  119. agno/learn/stores/entity_memory.py +3275 -0
  120. agno/learn/stores/learned_knowledge.py +1583 -0
  121. agno/learn/stores/protocol.py +117 -0
  122. agno/learn/stores/session_context.py +1217 -0
  123. agno/learn/stores/user_memory.py +1495 -0
  124. agno/learn/stores/user_profile.py +1220 -0
  125. agno/learn/utils.py +209 -0
  126. agno/media.py +22 -6
  127. agno/memory/__init__.py +14 -1
  128. agno/memory/manager.py +223 -8
  129. agno/memory/strategies/__init__.py +15 -0
  130. agno/memory/strategies/base.py +66 -0
  131. agno/memory/strategies/summarize.py +196 -0
  132. agno/memory/strategies/types.py +37 -0
  133. agno/models/aimlapi/aimlapi.py +17 -0
  134. agno/models/anthropic/claude.py +434 -59
  135. agno/models/aws/bedrock.py +121 -20
  136. agno/models/aws/claude.py +131 -274
  137. agno/models/azure/ai_foundry.py +10 -6
  138. agno/models/azure/openai_chat.py +33 -10
  139. agno/models/base.py +1162 -561
  140. agno/models/cerebras/cerebras.py +120 -24
  141. agno/models/cerebras/cerebras_openai.py +21 -2
  142. agno/models/cohere/chat.py +65 -6
  143. agno/models/cometapi/cometapi.py +18 -1
  144. agno/models/dashscope/dashscope.py +2 -3
  145. agno/models/deepinfra/deepinfra.py +18 -1
  146. agno/models/deepseek/deepseek.py +69 -3
  147. agno/models/fireworks/fireworks.py +18 -1
  148. agno/models/google/gemini.py +959 -89
  149. agno/models/google/utils.py +22 -0
  150. agno/models/groq/groq.py +48 -18
  151. agno/models/huggingface/huggingface.py +17 -6
  152. agno/models/ibm/watsonx.py +16 -6
  153. agno/models/internlm/internlm.py +18 -1
  154. agno/models/langdb/langdb.py +13 -1
  155. agno/models/litellm/chat.py +88 -9
  156. agno/models/litellm/litellm_openai.py +18 -1
  157. agno/models/message.py +24 -5
  158. agno/models/meta/llama.py +40 -13
  159. agno/models/meta/llama_openai.py +22 -21
  160. agno/models/metrics.py +12 -0
  161. agno/models/mistral/mistral.py +8 -4
  162. agno/models/n1n/__init__.py +3 -0
  163. agno/models/n1n/n1n.py +57 -0
  164. agno/models/nebius/nebius.py +6 -7
  165. agno/models/nvidia/nvidia.py +20 -3
  166. agno/models/ollama/__init__.py +2 -0
  167. agno/models/ollama/chat.py +17 -6
  168. agno/models/ollama/responses.py +100 -0
  169. agno/models/openai/__init__.py +2 -0
  170. agno/models/openai/chat.py +117 -26
  171. agno/models/openai/open_responses.py +46 -0
  172. agno/models/openai/responses.py +110 -32
  173. agno/models/openrouter/__init__.py +2 -0
  174. agno/models/openrouter/openrouter.py +67 -2
  175. agno/models/openrouter/responses.py +146 -0
  176. agno/models/perplexity/perplexity.py +19 -1
  177. agno/models/portkey/portkey.py +7 -6
  178. agno/models/requesty/requesty.py +19 -2
  179. agno/models/response.py +20 -2
  180. agno/models/sambanova/sambanova.py +20 -3
  181. agno/models/siliconflow/siliconflow.py +19 -2
  182. agno/models/together/together.py +20 -3
  183. agno/models/vercel/v0.py +20 -3
  184. agno/models/vertexai/claude.py +124 -4
  185. agno/models/vllm/vllm.py +19 -14
  186. agno/models/xai/xai.py +19 -2
  187. agno/os/app.py +467 -137
  188. agno/os/auth.py +253 -5
  189. agno/os/config.py +22 -0
  190. agno/os/interfaces/a2a/a2a.py +7 -6
  191. agno/os/interfaces/a2a/router.py +635 -26
  192. agno/os/interfaces/a2a/utils.py +32 -33
  193. agno/os/interfaces/agui/agui.py +5 -3
  194. agno/os/interfaces/agui/router.py +26 -16
  195. agno/os/interfaces/agui/utils.py +97 -57
  196. agno/os/interfaces/base.py +7 -7
  197. agno/os/interfaces/slack/router.py +16 -7
  198. agno/os/interfaces/slack/slack.py +7 -7
  199. agno/os/interfaces/whatsapp/router.py +35 -7
  200. agno/os/interfaces/whatsapp/security.py +3 -1
  201. agno/os/interfaces/whatsapp/whatsapp.py +11 -8
  202. agno/os/managers.py +326 -0
  203. agno/os/mcp.py +652 -79
  204. agno/os/middleware/__init__.py +4 -0
  205. agno/os/middleware/jwt.py +718 -115
  206. agno/os/middleware/trailing_slash.py +27 -0
  207. agno/os/router.py +105 -1558
  208. agno/os/routers/agents/__init__.py +3 -0
  209. agno/os/routers/agents/router.py +655 -0
  210. agno/os/routers/agents/schema.py +288 -0
  211. agno/os/routers/components/__init__.py +3 -0
  212. agno/os/routers/components/components.py +475 -0
  213. agno/os/routers/database.py +155 -0
  214. agno/os/routers/evals/evals.py +111 -18
  215. agno/os/routers/evals/schemas.py +38 -5
  216. agno/os/routers/evals/utils.py +80 -11
  217. agno/os/routers/health.py +3 -3
  218. agno/os/routers/knowledge/knowledge.py +284 -35
  219. agno/os/routers/knowledge/schemas.py +14 -2
  220. agno/os/routers/memory/memory.py +274 -11
  221. agno/os/routers/memory/schemas.py +44 -3
  222. agno/os/routers/metrics/metrics.py +30 -15
  223. agno/os/routers/metrics/schemas.py +10 -6
  224. agno/os/routers/registry/__init__.py +3 -0
  225. agno/os/routers/registry/registry.py +337 -0
  226. agno/os/routers/session/session.py +143 -14
  227. agno/os/routers/teams/__init__.py +3 -0
  228. agno/os/routers/teams/router.py +550 -0
  229. agno/os/routers/teams/schema.py +280 -0
  230. agno/os/routers/traces/__init__.py +3 -0
  231. agno/os/routers/traces/schemas.py +414 -0
  232. agno/os/routers/traces/traces.py +549 -0
  233. agno/os/routers/workflows/__init__.py +3 -0
  234. agno/os/routers/workflows/router.py +757 -0
  235. agno/os/routers/workflows/schema.py +139 -0
  236. agno/os/schema.py +157 -584
  237. agno/os/scopes.py +469 -0
  238. agno/os/settings.py +3 -0
  239. agno/os/utils.py +574 -185
  240. agno/reasoning/anthropic.py +85 -1
  241. agno/reasoning/azure_ai_foundry.py +93 -1
  242. agno/reasoning/deepseek.py +102 -2
  243. agno/reasoning/default.py +6 -7
  244. agno/reasoning/gemini.py +87 -3
  245. agno/reasoning/groq.py +109 -2
  246. agno/reasoning/helpers.py +6 -7
  247. agno/reasoning/manager.py +1238 -0
  248. agno/reasoning/ollama.py +93 -1
  249. agno/reasoning/openai.py +115 -1
  250. agno/reasoning/vertexai.py +85 -1
  251. agno/registry/__init__.py +3 -0
  252. agno/registry/registry.py +68 -0
  253. agno/remote/__init__.py +3 -0
  254. agno/remote/base.py +581 -0
  255. agno/run/__init__.py +2 -4
  256. agno/run/agent.py +134 -19
  257. agno/run/base.py +49 -1
  258. agno/run/cancel.py +65 -52
  259. agno/run/cancellation_management/__init__.py +9 -0
  260. agno/run/cancellation_management/base.py +78 -0
  261. agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
  262. agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
  263. agno/run/requirement.py +181 -0
  264. agno/run/team.py +111 -19
  265. agno/run/workflow.py +2 -1
  266. agno/session/agent.py +57 -92
  267. agno/session/summary.py +1 -1
  268. agno/session/team.py +62 -115
  269. agno/session/workflow.py +353 -57
  270. agno/skills/__init__.py +17 -0
  271. agno/skills/agent_skills.py +377 -0
  272. agno/skills/errors.py +32 -0
  273. agno/skills/loaders/__init__.py +4 -0
  274. agno/skills/loaders/base.py +27 -0
  275. agno/skills/loaders/local.py +216 -0
  276. agno/skills/skill.py +65 -0
  277. agno/skills/utils.py +107 -0
  278. agno/skills/validator.py +277 -0
  279. agno/table.py +10 -0
  280. agno/team/__init__.py +5 -1
  281. agno/team/remote.py +447 -0
  282. agno/team/team.py +3769 -2202
  283. agno/tools/brandfetch.py +27 -18
  284. agno/tools/browserbase.py +225 -16
  285. agno/tools/crawl4ai.py +3 -0
  286. agno/tools/duckduckgo.py +25 -71
  287. agno/tools/exa.py +0 -21
  288. agno/tools/file.py +14 -13
  289. agno/tools/file_generation.py +12 -6
  290. agno/tools/firecrawl.py +15 -7
  291. agno/tools/function.py +94 -113
  292. agno/tools/google_bigquery.py +11 -2
  293. agno/tools/google_drive.py +4 -3
  294. agno/tools/knowledge.py +9 -4
  295. agno/tools/mcp/mcp.py +301 -18
  296. agno/tools/mcp/multi_mcp.py +269 -14
  297. agno/tools/mem0.py +11 -10
  298. agno/tools/memory.py +47 -46
  299. agno/tools/mlx_transcribe.py +10 -7
  300. agno/tools/models/nebius.py +5 -5
  301. agno/tools/models_labs.py +20 -10
  302. agno/tools/nano_banana.py +151 -0
  303. agno/tools/parallel.py +0 -7
  304. agno/tools/postgres.py +76 -36
  305. agno/tools/python.py +14 -6
  306. agno/tools/reasoning.py +30 -23
  307. agno/tools/redshift.py +406 -0
  308. agno/tools/shopify.py +1519 -0
  309. agno/tools/spotify.py +919 -0
  310. agno/tools/tavily.py +4 -1
  311. agno/tools/toolkit.py +253 -18
  312. agno/tools/websearch.py +93 -0
  313. agno/tools/website.py +1 -1
  314. agno/tools/wikipedia.py +1 -1
  315. agno/tools/workflow.py +56 -48
  316. agno/tools/yfinance.py +12 -11
  317. agno/tracing/__init__.py +12 -0
  318. agno/tracing/exporter.py +161 -0
  319. agno/tracing/schemas.py +276 -0
  320. agno/tracing/setup.py +112 -0
  321. agno/utils/agent.py +251 -10
  322. agno/utils/cryptography.py +22 -0
  323. agno/utils/dttm.py +33 -0
  324. agno/utils/events.py +264 -7
  325. agno/utils/hooks.py +111 -3
  326. agno/utils/http.py +161 -2
  327. agno/utils/mcp.py +49 -8
  328. agno/utils/media.py +22 -1
  329. agno/utils/models/ai_foundry.py +9 -2
  330. agno/utils/models/claude.py +20 -5
  331. agno/utils/models/cohere.py +9 -2
  332. agno/utils/models/llama.py +9 -2
  333. agno/utils/models/mistral.py +4 -2
  334. agno/utils/os.py +0 -0
  335. agno/utils/print_response/agent.py +99 -16
  336. agno/utils/print_response/team.py +223 -24
  337. agno/utils/print_response/workflow.py +0 -2
  338. agno/utils/prompts.py +8 -6
  339. agno/utils/remote.py +23 -0
  340. agno/utils/response.py +1 -13
  341. agno/utils/string.py +91 -2
  342. agno/utils/team.py +62 -12
  343. agno/utils/tokens.py +657 -0
  344. agno/vectordb/base.py +15 -2
  345. agno/vectordb/cassandra/cassandra.py +1 -1
  346. agno/vectordb/chroma/__init__.py +2 -1
  347. agno/vectordb/chroma/chromadb.py +468 -23
  348. agno/vectordb/clickhouse/clickhousedb.py +1 -1
  349. agno/vectordb/couchbase/couchbase.py +6 -2
  350. agno/vectordb/lancedb/lance_db.py +7 -38
  351. agno/vectordb/lightrag/lightrag.py +7 -6
  352. agno/vectordb/milvus/milvus.py +118 -84
  353. agno/vectordb/mongodb/__init__.py +2 -1
  354. agno/vectordb/mongodb/mongodb.py +14 -31
  355. agno/vectordb/pgvector/pgvector.py +120 -66
  356. agno/vectordb/pineconedb/pineconedb.py +2 -19
  357. agno/vectordb/qdrant/__init__.py +2 -1
  358. agno/vectordb/qdrant/qdrant.py +33 -56
  359. agno/vectordb/redis/__init__.py +2 -1
  360. agno/vectordb/redis/redisdb.py +19 -31
  361. agno/vectordb/singlestore/singlestore.py +17 -9
  362. agno/vectordb/surrealdb/surrealdb.py +2 -38
  363. agno/vectordb/weaviate/__init__.py +2 -1
  364. agno/vectordb/weaviate/weaviate.py +7 -3
  365. agno/workflow/__init__.py +5 -1
  366. agno/workflow/agent.py +2 -2
  367. agno/workflow/condition.py +12 -10
  368. agno/workflow/loop.py +28 -9
  369. agno/workflow/parallel.py +21 -13
  370. agno/workflow/remote.py +362 -0
  371. agno/workflow/router.py +12 -9
  372. agno/workflow/step.py +261 -36
  373. agno/workflow/steps.py +12 -8
  374. agno/workflow/types.py +40 -77
  375. agno/workflow/workflow.py +939 -213
  376. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
  377. agno-2.4.3.dist-info/RECORD +677 -0
  378. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
  379. agno/tools/googlesearch.py +0 -98
  380. agno/tools/memori.py +0 -339
  381. agno-2.2.13.dist-info/RECORD +0 -575
  382. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
  383. {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
agno/utils/events.py CHANGED
@@ -5,8 +5,12 @@ from agno.models.message import Citations
5
5
  from agno.models.response import ToolExecution
6
6
  from agno.reasoning.step import ReasoningStep
7
7
  from agno.run.agent import (
8
+ CompressionCompletedEvent,
9
+ CompressionStartedEvent,
8
10
  MemoryUpdateCompletedEvent,
9
11
  MemoryUpdateStartedEvent,
12
+ ModelRequestCompletedEvent,
13
+ ModelRequestStartedEvent,
10
14
  OutputModelResponseCompletedEvent,
11
15
  OutputModelResponseStartedEvent,
12
16
  ParserModelResponseCompletedEvent,
@@ -16,6 +20,7 @@ from agno.run.agent import (
16
20
  PreHookCompletedEvent,
17
21
  PreHookStartedEvent,
18
22
  ReasoningCompletedEvent,
23
+ ReasoningContentDeltaEvent,
19
24
  ReasoningStartedEvent,
20
25
  ReasoningStepEvent,
21
26
  RunCancelledEvent,
@@ -33,10 +38,16 @@ from agno.run.agent import (
33
38
  SessionSummaryCompletedEvent,
34
39
  SessionSummaryStartedEvent,
35
40
  ToolCallCompletedEvent,
41
+ ToolCallErrorEvent,
36
42
  ToolCallStartedEvent,
37
43
  )
44
+ from agno.run.requirement import RunRequirement
45
+ from agno.run.team import CompressionCompletedEvent as TeamCompressionCompletedEvent
46
+ from agno.run.team import CompressionStartedEvent as TeamCompressionStartedEvent
38
47
  from agno.run.team import MemoryUpdateCompletedEvent as TeamMemoryUpdateCompletedEvent
39
48
  from agno.run.team import MemoryUpdateStartedEvent as TeamMemoryUpdateStartedEvent
49
+ from agno.run.team import ModelRequestCompletedEvent as TeamModelRequestCompletedEvent
50
+ from agno.run.team import ModelRequestStartedEvent as TeamModelRequestStartedEvent
40
51
  from agno.run.team import OutputModelResponseCompletedEvent as TeamOutputModelResponseCompletedEvent
41
52
  from agno.run.team import OutputModelResponseStartedEvent as TeamOutputModelResponseStartedEvent
42
53
  from agno.run.team import ParserModelResponseCompletedEvent as TeamParserModelResponseCompletedEvent
@@ -46,6 +57,7 @@ from agno.run.team import PostHookStartedEvent as TeamPostHookStartedEvent
46
57
  from agno.run.team import PreHookCompletedEvent as TeamPreHookCompletedEvent
47
58
  from agno.run.team import PreHookStartedEvent as TeamPreHookStartedEvent
48
59
  from agno.run.team import ReasoningCompletedEvent as TeamReasoningCompletedEvent
60
+ from agno.run.team import ReasoningContentDeltaEvent as TeamReasoningContentDeltaEvent
49
61
  from agno.run.team import ReasoningStartedEvent as TeamReasoningStartedEvent
50
62
  from agno.run.team import ReasoningStepEvent as TeamReasoningStepEvent
51
63
  from agno.run.team import RunCancelledEvent as TeamRunCancelledEvent
@@ -58,6 +70,7 @@ from agno.run.team import SessionSummaryCompletedEvent as TeamSessionSummaryComp
58
70
  from agno.run.team import SessionSummaryStartedEvent as TeamSessionSummaryStartedEvent
59
71
  from agno.run.team import TeamRunEvent, TeamRunInput, TeamRunOutput, TeamRunOutputEvent
60
72
  from agno.run.team import ToolCallCompletedEvent as TeamToolCallCompletedEvent
73
+ from agno.run.team import ToolCallErrorEvent as TeamToolCallErrorEvent
61
74
  from agno.run.team import ToolCallStartedEvent as TeamToolCallStartedEvent
62
75
  from agno.session.summary import SessionSummary
63
76
 
@@ -136,7 +149,9 @@ def create_run_completed_event(from_run_response: RunOutput) -> RunCompletedEven
136
149
 
137
150
 
138
151
  def create_run_paused_event(
139
- from_run_response: RunOutput, tools: Optional[List[ToolExecution]] = None
152
+ from_run_response: RunOutput,
153
+ tools: Optional[List[ToolExecution]] = None,
154
+ requirements: Optional[List[RunRequirement]] = None,
140
155
  ) -> RunPausedEvent:
141
156
  return RunPausedEvent(
142
157
  session_id=from_run_response.session_id,
@@ -144,6 +159,7 @@ def create_run_paused_event(
144
159
  agent_name=from_run_response.agent_name, # type: ignore
145
160
  run_id=from_run_response.run_id,
146
161
  tools=tools,
162
+ requirements=requirements,
147
163
  content=from_run_response.content,
148
164
  )
149
165
 
@@ -157,23 +173,41 @@ def create_run_continued_event(from_run_response: RunOutput) -> RunContinuedEven
157
173
  )
158
174
 
159
175
 
160
- def create_team_run_error_event(from_run_response: TeamRunOutput, error: str) -> TeamRunErrorEvent:
176
+ def create_team_run_error_event(
177
+ from_run_response: TeamRunOutput,
178
+ error: str,
179
+ error_type: Optional[str] = None,
180
+ error_id: Optional[str] = None,
181
+ additional_data: Optional[Dict[str, Any]] = None,
182
+ ) -> TeamRunErrorEvent:
161
183
  return TeamRunErrorEvent(
162
184
  session_id=from_run_response.session_id,
163
185
  team_id=from_run_response.team_id, # type: ignore
164
186
  team_name=from_run_response.team_name, # type: ignore
165
187
  run_id=from_run_response.run_id,
166
188
  content=error,
189
+ error_type=error_type,
190
+ error_id=error_id,
191
+ additional_data=additional_data,
167
192
  )
168
193
 
169
194
 
170
- def create_run_error_event(from_run_response: RunOutput, error: str) -> RunErrorEvent:
195
+ def create_run_error_event(
196
+ from_run_response: RunOutput,
197
+ error: str,
198
+ error_type: Optional[str] = None,
199
+ error_id: Optional[str] = None,
200
+ additional_data: Optional[Dict[str, Any]] = None,
201
+ ) -> RunErrorEvent:
171
202
  return RunErrorEvent(
172
203
  session_id=from_run_response.session_id,
173
204
  agent_id=from_run_response.agent_id, # type: ignore
174
205
  agent_name=from_run_response.agent_name, # type: ignore
175
206
  run_id=from_run_response.run_id,
176
207
  content=error,
208
+ error_type=error_type,
209
+ error_id=error_id,
210
+ additional_data=additional_data,
177
211
  )
178
212
 
179
213
 
@@ -323,21 +357,27 @@ def create_team_memory_update_started_event(from_run_response: TeamRunOutput) ->
323
357
  )
324
358
 
325
359
 
326
- def create_memory_update_completed_event(from_run_response: RunOutput) -> MemoryUpdateCompletedEvent:
360
+ def create_memory_update_completed_event(
361
+ from_run_response: RunOutput, memories: Optional[List[Any]] = None
362
+ ) -> MemoryUpdateCompletedEvent:
327
363
  return MemoryUpdateCompletedEvent(
328
364
  session_id=from_run_response.session_id,
329
365
  agent_id=from_run_response.agent_id, # type: ignore
330
366
  agent_name=from_run_response.agent_name, # type: ignore
331
367
  run_id=from_run_response.run_id,
368
+ memories=memories,
332
369
  )
333
370
 
334
371
 
335
- def create_team_memory_update_completed_event(from_run_response: TeamRunOutput) -> TeamMemoryUpdateCompletedEvent:
372
+ def create_team_memory_update_completed_event(
373
+ from_run_response: TeamRunOutput, memories: Optional[List[Any]] = None
374
+ ) -> TeamMemoryUpdateCompletedEvent:
336
375
  return TeamMemoryUpdateCompletedEvent(
337
376
  session_id=from_run_response.session_id,
338
377
  team_id=from_run_response.team_id, # type: ignore
339
378
  team_name=from_run_response.team_name, # type: ignore
340
379
  run_id=from_run_response.run_id,
380
+ memories=memories,
341
381
  )
342
382
 
343
383
 
@@ -417,6 +457,19 @@ def create_reasoning_step_event(
417
457
  )
418
458
 
419
459
 
460
+ def create_reasoning_content_delta_event(
461
+ from_run_response: RunOutput, reasoning_content: str
462
+ ) -> ReasoningContentDeltaEvent:
463
+ """Create an event for streaming reasoning content chunks."""
464
+ return ReasoningContentDeltaEvent(
465
+ session_id=from_run_response.session_id,
466
+ agent_id=from_run_response.agent_id, # type: ignore
467
+ agent_name=from_run_response.agent_name, # type: ignore
468
+ run_id=from_run_response.run_id,
469
+ reasoning_content=reasoning_content,
470
+ )
471
+
472
+
420
473
  def create_team_reasoning_step_event(
421
474
  from_run_response: TeamRunOutput, reasoning_step: ReasoningStep, reasoning_content: str
422
475
  ) -> TeamReasoningStepEvent:
@@ -431,6 +484,19 @@ def create_team_reasoning_step_event(
431
484
  )
432
485
 
433
486
 
487
+ def create_team_reasoning_content_delta_event(
488
+ from_run_response: TeamRunOutput, reasoning_content: str
489
+ ) -> TeamReasoningContentDeltaEvent:
490
+ """Create an event for streaming reasoning content chunks for Team."""
491
+ return TeamReasoningContentDeltaEvent(
492
+ session_id=from_run_response.session_id,
493
+ team_id=from_run_response.team_id, # type: ignore
494
+ team_name=from_run_response.team_name, # type: ignore
495
+ run_id=from_run_response.run_id,
496
+ reasoning_content=reasoning_content,
497
+ )
498
+
499
+
434
500
  def create_reasoning_completed_event(
435
501
  from_run_response: RunOutput, content: Optional[Any] = None, content_type: Optional[str] = None
436
502
  ) -> ReasoningCompletedEvent:
@@ -511,6 +577,32 @@ def create_team_tool_call_completed_event(
511
577
  )
512
578
 
513
579
 
580
+ def create_tool_call_error_event(
581
+ from_run_response: RunOutput, tool: ToolExecution, error: Optional[str] = None
582
+ ) -> ToolCallErrorEvent:
583
+ return ToolCallErrorEvent(
584
+ session_id=from_run_response.session_id,
585
+ agent_id=from_run_response.agent_id, # type: ignore
586
+ agent_name=from_run_response.agent_name, # type: ignore
587
+ run_id=from_run_response.run_id,
588
+ tool=tool,
589
+ error=error,
590
+ )
591
+
592
+
593
+ def create_team_tool_call_error_event(
594
+ from_run_response: TeamRunOutput, tool: ToolExecution, error: Optional[str] = None
595
+ ) -> TeamToolCallErrorEvent:
596
+ return TeamToolCallErrorEvent(
597
+ session_id=from_run_response.session_id,
598
+ team_id=from_run_response.team_id, # type: ignore
599
+ team_name=from_run_response.team_name, # type: ignore
600
+ run_id=from_run_response.run_id,
601
+ tool=tool,
602
+ error=error,
603
+ )
604
+
605
+
514
606
  def create_run_output_content_event(
515
607
  from_run_response: RunOutput,
516
608
  content: Optional[Any] = None,
@@ -681,6 +773,150 @@ def create_team_output_model_response_completed_event(
681
773
  )
682
774
 
683
775
 
776
+ def create_model_request_started_event(
777
+ from_run_response: RunOutput,
778
+ model: Optional[str] = None,
779
+ model_provider: Optional[str] = None,
780
+ ) -> ModelRequestStartedEvent:
781
+ return ModelRequestStartedEvent(
782
+ session_id=from_run_response.session_id,
783
+ agent_id=from_run_response.agent_id, # type: ignore
784
+ agent_name=from_run_response.agent_name, # type: ignore
785
+ run_id=from_run_response.run_id,
786
+ model=model,
787
+ model_provider=model_provider,
788
+ )
789
+
790
+
791
+ def create_model_request_completed_event(
792
+ from_run_response: RunOutput,
793
+ model: Optional[str] = None,
794
+ model_provider: Optional[str] = None,
795
+ input_tokens: Optional[int] = None,
796
+ output_tokens: Optional[int] = None,
797
+ total_tokens: Optional[int] = None,
798
+ time_to_first_token: Optional[float] = None,
799
+ reasoning_tokens: Optional[int] = None,
800
+ cache_read_tokens: Optional[int] = None,
801
+ cache_write_tokens: Optional[int] = None,
802
+ ) -> ModelRequestCompletedEvent:
803
+ return ModelRequestCompletedEvent(
804
+ session_id=from_run_response.session_id,
805
+ agent_id=from_run_response.agent_id, # type: ignore
806
+ agent_name=from_run_response.agent_name, # type: ignore
807
+ run_id=from_run_response.run_id,
808
+ model=model,
809
+ model_provider=model_provider,
810
+ input_tokens=input_tokens,
811
+ output_tokens=output_tokens,
812
+ total_tokens=total_tokens,
813
+ time_to_first_token=time_to_first_token,
814
+ reasoning_tokens=reasoning_tokens,
815
+ cache_read_tokens=cache_read_tokens,
816
+ cache_write_tokens=cache_write_tokens,
817
+ )
818
+
819
+
820
+ def create_team_model_request_started_event(
821
+ from_run_response: TeamRunOutput,
822
+ model: Optional[str] = None,
823
+ model_provider: Optional[str] = None,
824
+ ) -> TeamModelRequestStartedEvent:
825
+ return TeamModelRequestStartedEvent(
826
+ session_id=from_run_response.session_id,
827
+ team_id=from_run_response.team_id, # type: ignore
828
+ team_name=from_run_response.team_name, # type: ignore
829
+ run_id=from_run_response.run_id,
830
+ model=model,
831
+ model_provider=model_provider,
832
+ )
833
+
834
+
835
+ def create_team_model_request_completed_event(
836
+ from_run_response: TeamRunOutput,
837
+ model: Optional[str] = None,
838
+ model_provider: Optional[str] = None,
839
+ input_tokens: Optional[int] = None,
840
+ output_tokens: Optional[int] = None,
841
+ total_tokens: Optional[int] = None,
842
+ time_to_first_token: Optional[float] = None,
843
+ reasoning_tokens: Optional[int] = None,
844
+ cache_read_tokens: Optional[int] = None,
845
+ cache_write_tokens: Optional[int] = None,
846
+ ) -> TeamModelRequestCompletedEvent:
847
+ return TeamModelRequestCompletedEvent(
848
+ session_id=from_run_response.session_id,
849
+ team_id=from_run_response.team_id, # type: ignore
850
+ team_name=from_run_response.team_name, # type: ignore
851
+ run_id=from_run_response.run_id,
852
+ model=model,
853
+ model_provider=model_provider,
854
+ input_tokens=input_tokens,
855
+ output_tokens=output_tokens,
856
+ total_tokens=total_tokens,
857
+ time_to_first_token=time_to_first_token,
858
+ reasoning_tokens=reasoning_tokens,
859
+ cache_read_tokens=cache_read_tokens,
860
+ cache_write_tokens=cache_write_tokens,
861
+ )
862
+
863
+
864
+ def create_compression_started_event(
865
+ from_run_response: RunOutput,
866
+ ) -> CompressionStartedEvent:
867
+ return CompressionStartedEvent(
868
+ session_id=from_run_response.session_id,
869
+ agent_id=from_run_response.agent_id, # type: ignore
870
+ agent_name=from_run_response.agent_name, # type: ignore
871
+ run_id=from_run_response.run_id,
872
+ )
873
+
874
+
875
+ def create_compression_completed_event(
876
+ from_run_response: RunOutput,
877
+ tool_results_compressed: Optional[int] = None,
878
+ original_size: Optional[int] = None,
879
+ compressed_size: Optional[int] = None,
880
+ ) -> CompressionCompletedEvent:
881
+ return CompressionCompletedEvent(
882
+ session_id=from_run_response.session_id,
883
+ agent_id=from_run_response.agent_id, # type: ignore
884
+ agent_name=from_run_response.agent_name, # type: ignore
885
+ run_id=from_run_response.run_id,
886
+ tool_results_compressed=tool_results_compressed,
887
+ original_size=original_size,
888
+ compressed_size=compressed_size,
889
+ )
890
+
891
+
892
+ def create_team_compression_started_event(
893
+ from_run_response: TeamRunOutput,
894
+ ) -> TeamCompressionStartedEvent:
895
+ return TeamCompressionStartedEvent(
896
+ session_id=from_run_response.session_id,
897
+ team_id=from_run_response.team_id, # type: ignore
898
+ team_name=from_run_response.team_name, # type: ignore
899
+ run_id=from_run_response.run_id,
900
+ )
901
+
902
+
903
+ def create_team_compression_completed_event(
904
+ from_run_response: TeamRunOutput,
905
+ tool_results_compressed: Optional[int] = None,
906
+ original_size: Optional[int] = None,
907
+ compressed_size: Optional[int] = None,
908
+ ) -> TeamCompressionCompletedEvent:
909
+ return TeamCompressionCompletedEvent(
910
+ session_id=from_run_response.session_id,
911
+ team_id=from_run_response.team_id, # type: ignore
912
+ team_name=from_run_response.team_name, # type: ignore
913
+ run_id=from_run_response.run_id,
914
+ tool_results_compressed=tool_results_compressed,
915
+ original_size=original_size,
916
+ compressed_size=compressed_size,
917
+ )
918
+
919
+
684
920
  def handle_event(
685
921
  event: Union[RunOutputEvent, TeamRunOutputEvent],
686
922
  run_response: Union[RunOutput, TeamRunOutput],
@@ -688,9 +924,30 @@ def handle_event(
688
924
  store_events: bool = False,
689
925
  ) -> Union[RunOutputEvent, TeamRunOutputEvent]:
690
926
  # We only store events that are not run_response_content events
691
- events_to_skip = [event.value for event in events_to_skip] if events_to_skip else []
692
- if store_events and event.event not in events_to_skip:
927
+ _events_to_skip: List[str] = [event.value for event in events_to_skip] if events_to_skip else []
928
+ if store_events and event.event not in _events_to_skip:
693
929
  if run_response.events is None:
694
930
  run_response.events = []
695
931
  run_response.events.append(event) # type: ignore
696
932
  return event
933
+
934
+
935
+ def add_error_event(
936
+ error: RunErrorEvent,
937
+ events: Optional[List[RunOutputEvent]],
938
+ ):
939
+ if events is None:
940
+ events = []
941
+ events.append(error)
942
+
943
+ return events
944
+
945
+
946
+ def add_team_error_event(
947
+ error: TeamRunErrorEvent,
948
+ events: Optional[List[Union[RunOutputEvent, TeamRunOutputEvent]]],
949
+ ):
950
+ if events is None:
951
+ events = []
952
+ events.append(error)
953
+ return events
agno/utils/hooks.py CHANGED
@@ -1,14 +1,112 @@
1
+ from copy import deepcopy
1
2
  from typing import Any, Callable, Dict, List, Optional, Union
2
3
 
4
+ from agno.eval.base import BaseEval
3
5
  from agno.guardrails.base import BaseGuardrail
6
+ from agno.hooks.decorator import HOOK_RUN_IN_BACKGROUND_ATTR
4
7
  from agno.utils.log import log_warning
5
8
 
9
+ # Keys that should be deep copied for background hooks to prevent race conditions
10
+ BACKGROUND_HOOK_COPY_KEYS = frozenset(
11
+ {"run_input", "run_context", "run_output", "session_state", "dependencies", "metadata"}
12
+ )
6
13
 
7
- def normalize_hooks(
8
- hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail]]],
14
+
15
+ def copy_args_for_background(args: Dict[str, Any]) -> Dict[str, Any]:
16
+ """
17
+ Create a copy of hook arguments for background execution.
18
+
19
+ This deep copies run_input, run_context, run_output, session_state, dependencies,
20
+ and metadata to prevent race conditions when hooks run in the background.
21
+
22
+ Args:
23
+ args: The original arguments dictionary
24
+
25
+ Returns:
26
+ A new dictionary with copied values for sensitive keys
27
+ """
28
+ copied_args = {}
29
+ for key, value in args.items():
30
+ if key in BACKGROUND_HOOK_COPY_KEYS and value is not None:
31
+ try:
32
+ copied_args[key] = deepcopy(value)
33
+ except Exception:
34
+ # If deepcopy fails (e.g., for non-copyable objects), use the original
35
+ log_warning(f"Could not deepcopy {key} for background hook, using original reference")
36
+ copied_args[key] = value
37
+ else:
38
+ copied_args[key] = value
39
+ return copied_args
40
+
41
+
42
+ def should_run_hook_in_background(hook: Callable[..., Any]) -> bool:
43
+ """
44
+ Check if a hook function should run in background.
45
+
46
+ This checks for the _agno_run_in_background attribute set by the @hook decorator.
47
+
48
+ Args:
49
+ hook: The hook function to check
50
+
51
+ Returns:
52
+ True if the hook is decorated with @hook(run_in_background=True)
53
+ """
54
+ return getattr(hook, HOOK_RUN_IN_BACKGROUND_ATTR, False)
55
+
56
+
57
+ def normalize_pre_hooks(
58
+ hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]],
59
+ async_mode: bool = False,
60
+ ) -> Optional[List[Callable[..., Any]]]:
61
+ """Normalize pre-hooks to a list format.
62
+
63
+ Args:
64
+ hooks: List of hook functions, guardrails, or eval instances
65
+ async_mode: Whether to use async versions of methods
66
+ """
67
+ result_hooks: List[Callable[..., Any]] = []
68
+
69
+ if hooks is not None:
70
+ for hook in hooks:
71
+ if isinstance(hook, BaseGuardrail):
72
+ if async_mode:
73
+ result_hooks.append(hook.async_check)
74
+ else:
75
+ result_hooks.append(hook.check)
76
+ elif isinstance(hook, BaseEval):
77
+ # Extract pre_check method
78
+ method = hook.async_pre_check if async_mode else hook.pre_check
79
+
80
+ from functools import partial
81
+
82
+ wrapped = partial(method)
83
+ wrapped.__name__ = method.__name__ # type: ignore
84
+ setattr(wrapped, HOOK_RUN_IN_BACKGROUND_ATTR, getattr(hook, "run_in_background", False))
85
+ result_hooks.append(wrapped)
86
+ else:
87
+ # Check if the hook is async and used within sync methods
88
+ if not async_mode:
89
+ import asyncio
90
+
91
+ if asyncio.iscoroutinefunction(hook):
92
+ raise ValueError(
93
+ f"Cannot use {hook.__name__} (an async hook) with `run()`. Use `arun()` instead."
94
+ )
95
+
96
+ result_hooks.append(hook)
97
+ return result_hooks if result_hooks else None
98
+
99
+
100
+ def normalize_post_hooks(
101
+ hooks: Optional[List[Union[Callable[..., Any], BaseGuardrail, BaseEval]]],
9
102
  async_mode: bool = False,
10
103
  ) -> Optional[List[Callable[..., Any]]]:
11
- """Normalize hooks to a list format"""
104
+ """Normalize post-hooks to a list format.
105
+
106
+ Args:
107
+ hooks: List of hook functions, guardrails, or eval instances
108
+ async_mode: Whether to use async versions of methods
109
+ """
12
110
  result_hooks: List[Callable[..., Any]] = []
13
111
 
14
112
  if hooks is not None:
@@ -18,6 +116,16 @@ def normalize_hooks(
18
116
  result_hooks.append(hook.async_check)
19
117
  else:
20
118
  result_hooks.append(hook.check)
119
+ elif isinstance(hook, BaseEval):
120
+ # Extract post_check method
121
+ method = hook.async_post_check if async_mode else hook.post_check # type: ignore[assignment]
122
+
123
+ from functools import partial
124
+
125
+ wrapped = partial(method)
126
+ wrapped.__name__ = method.__name__ # type: ignore
127
+ setattr(wrapped, HOOK_RUN_IN_BACKGROUND_ATTR, getattr(hook, "run_in_background", False))
128
+ result_hooks.append(wrapped)
21
129
  else:
22
130
  # Check if the hook is async and used within sync methods
23
131
  if not async_mode: