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/remote/base.py ADDED
@@ -0,0 +1,581 @@
1
+ import time
2
+ from abc import abstractmethod
3
+ from dataclasses import dataclass, field
4
+ from datetime import date
5
+ from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, List, Literal, Optional, Sequence, Tuple, Union
6
+
7
+ from pydantic import BaseModel
8
+
9
+ from agno.db.base import SessionType
10
+ from agno.media import Audio, File, Image, Video
11
+ from agno.models.message import Message
12
+ from agno.models.response import ToolExecution
13
+ from agno.run.agent import RunOutput, RunOutputEvent
14
+ from agno.run.team import TeamRunOutput, TeamRunOutputEvent
15
+ from agno.run.workflow import WorkflowRunOutput, WorkflowRunOutputEvent
16
+
17
+ if TYPE_CHECKING:
18
+ from fastapi import UploadFile
19
+
20
+ from agno.client import AgentOSClient
21
+ from agno.client.a2a import A2AClient
22
+ from agno.client.a2a.schemas import AgentCard
23
+ from agno.os.routers.evals.schemas import EvalSchema
24
+ from agno.os.routers.knowledge.schemas import (
25
+ ConfigResponseSchema,
26
+ ContentResponseSchema,
27
+ ContentStatusResponse,
28
+ VectorSearchResult,
29
+ )
30
+ from agno.os.routers.memory.schemas import OptimizeMemoriesResponse, UserMemorySchema, UserStatsSchema
31
+ from agno.os.routers.metrics.schemas import DayAggregatedMetrics, MetricsResponse
32
+ from agno.os.routers.traces.schemas import TraceDetail, TraceNode, TraceSessionStats, TraceSummary
33
+ from agno.os.schema import (
34
+ AgentSessionDetailSchema,
35
+ ConfigResponse,
36
+ PaginatedResponse,
37
+ RunSchema,
38
+ SessionSchema,
39
+ TeamRunSchema,
40
+ TeamSessionDetailSchema,
41
+ WorkflowRunSchema,
42
+ WorkflowSessionDetailSchema,
43
+ )
44
+
45
+
46
+ @dataclass
47
+ class RemoteDb:
48
+ id: str
49
+ client: "AgentOSClient"
50
+ session_table_name: Optional[str] = None
51
+ knowledge_table_name: Optional[str] = None
52
+ memory_table_name: Optional[str] = None
53
+ metrics_table_name: Optional[str] = None
54
+ eval_table_name: Optional[str] = None
55
+ traces_table_name: Optional[str] = None
56
+ spans_table_name: Optional[str] = None
57
+ culture_table_name: Optional[str] = None
58
+
59
+ @classmethod
60
+ def from_config(
61
+ cls,
62
+ db_id: str,
63
+ client: "AgentOSClient",
64
+ config: "ConfigResponse",
65
+ ) -> Optional["RemoteDb"]:
66
+ """Create a RemoteDb instance from an AgentResponse/TeamResponse/WorkflowResponse and ConfigResponse.
67
+
68
+ Args:
69
+ db_id (str): The id of the remote database
70
+ client: The AgentOSClient for remote operations.
71
+ config: The ConfigResponse containing database table information.
72
+
73
+ Returns:
74
+ RemoteDb instance if db_id is present, None otherwise.
75
+ """
76
+
77
+ session_table_name = None
78
+ knowledge_table_name = None
79
+ memory_table_name = None
80
+ metrics_table_name = None
81
+ eval_table_name = None
82
+ traces_table_name = None
83
+
84
+ if config and config.session and config.session.dbs is not None:
85
+ session_dbs = [db for db in config.session.dbs if db.db_id == db_id]
86
+ session_table_name = session_dbs[0].tables[0] if session_dbs and session_dbs[0].tables else None
87
+
88
+ if config and config.knowledge and config.knowledge.dbs is not None:
89
+ knowledge_dbs = [db for db in config.knowledge.dbs if db.db_id == db_id]
90
+ knowledge_table_name = knowledge_dbs[0].tables[0] if knowledge_dbs and knowledge_dbs[0].tables else None
91
+
92
+ if config and config.memory and config.memory.dbs is not None:
93
+ memory_dbs = [db for db in config.memory.dbs if db.db_id == db_id]
94
+ memory_table_name = memory_dbs[0].tables[0] if memory_dbs and memory_dbs[0].tables else None
95
+
96
+ if config and config.metrics and config.metrics.dbs is not None:
97
+ metrics_dbs = [db for db in config.metrics.dbs if db.db_id == db_id]
98
+ metrics_table_name = metrics_dbs[0].tables[0] if metrics_dbs and metrics_dbs[0].tables else None
99
+
100
+ if config and config.evals and config.evals.dbs is not None:
101
+ eval_dbs = [db for db in config.evals.dbs if db.db_id == db_id]
102
+ eval_table_name = eval_dbs[0].tables[0] if eval_dbs and eval_dbs[0].tables else None
103
+
104
+ if config and config.traces and config.traces.dbs is not None:
105
+ traces_dbs = [db for db in config.traces.dbs if db.db_id == db_id]
106
+ traces_table_name = traces_dbs[0].tables[0] if traces_dbs and traces_dbs[0].tables else None
107
+
108
+ return cls(
109
+ id=db_id,
110
+ client=client,
111
+ session_table_name=session_table_name,
112
+ knowledge_table_name=knowledge_table_name,
113
+ memory_table_name=memory_table_name,
114
+ metrics_table_name=metrics_table_name,
115
+ eval_table_name=eval_table_name,
116
+ traces_table_name=traces_table_name,
117
+ )
118
+
119
+ # SESSIONS
120
+ async def get_sessions(self, **kwargs: Any) -> "PaginatedResponse[SessionSchema]":
121
+ return await self.client.get_sessions(**kwargs)
122
+
123
+ async def get_session(
124
+ self, session_id: str, **kwargs: Any
125
+ ) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
126
+ return await self.client.get_session(session_id, **kwargs)
127
+
128
+ async def get_session_runs(
129
+ self, session_id: str, **kwargs: Any
130
+ ) -> List[Union["RunSchema", "TeamRunSchema", "WorkflowRunSchema"]]:
131
+ return await self.client.get_session_runs(session_id, **kwargs)
132
+
133
+ async def create_session(
134
+ self,
135
+ session_id: Optional[str] = None,
136
+ session_name: Optional[str] = None,
137
+ session_state: Optional[Dict[str, Any]] = None,
138
+ metadata: Optional[Dict[str, Any]] = None,
139
+ user_id: Optional[str] = None,
140
+ agent_id: Optional[str] = None,
141
+ team_id: Optional[str] = None,
142
+ workflow_id: Optional[str] = None,
143
+ **kwargs: Any,
144
+ ) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
145
+ return await self.client.create_session(
146
+ session_id=session_id,
147
+ session_name=session_name,
148
+ session_state=session_state,
149
+ metadata=metadata,
150
+ user_id=user_id,
151
+ agent_id=agent_id,
152
+ team_id=team_id,
153
+ workflow_id=workflow_id,
154
+ **kwargs,
155
+ )
156
+
157
+ async def get_session_run(
158
+ self, session_id: str, run_id: str, **kwargs: Any
159
+ ) -> Union["RunSchema", "TeamRunSchema", "WorkflowRunSchema"]:
160
+ return await self.client.get_session_run(session_id, run_id, **kwargs)
161
+
162
+ async def rename_session(
163
+ self, session_id: str, session_name: str, **kwargs: Any
164
+ ) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
165
+ return await self.client.rename_session(session_id, session_name, **kwargs)
166
+
167
+ async def update_session(
168
+ self, session_id: str, session_type: SessionType, **kwargs: Any
169
+ ) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
170
+ return await self.client.update_session(session_id=session_id, session_type=session_type, **kwargs)
171
+
172
+ async def delete_session(self, session_id: str, **kwargs: Any) -> None:
173
+ return await self.client.delete_session(session_id, **kwargs)
174
+
175
+ async def delete_sessions(self, session_ids: List[str], session_types: List[SessionType], **kwargs: Any) -> None:
176
+ return await self.client.delete_sessions(session_ids, session_types, **kwargs)
177
+
178
+ # MEMORIES
179
+ async def create_memory(self, memory: str, topics: List[str], user_id: str, **kwargs: Any) -> "UserMemorySchema":
180
+ return await self.client.create_memory(memory=memory, topics=topics, user_id=user_id, **kwargs)
181
+
182
+ async def delete_memory(self, memory_id: str, **kwargs: Any) -> None:
183
+ return await self.client.delete_memory(memory_id, **kwargs)
184
+
185
+ async def delete_memories(self, memory_ids: List[str], **kwargs: Any) -> None:
186
+ return await self.client.delete_memories(memory_ids, **kwargs)
187
+
188
+ async def get_memory(self, memory_id: str, **kwargs: Any) -> "UserMemorySchema":
189
+ return await self.client.get_memory(memory_id, **kwargs)
190
+
191
+ async def get_memories(self, user_id: Optional[str] = None, **kwargs: Any) -> "PaginatedResponse[UserMemorySchema]":
192
+ return await self.client.list_memories(user_id, **kwargs)
193
+
194
+ async def update_memory(self, memory_id: str, **kwargs: Any) -> "UserMemorySchema":
195
+ return await self.client.update_memory(memory_id, **kwargs)
196
+
197
+ async def get_user_memory_stats(self, **kwargs: Any) -> "PaginatedResponse[UserStatsSchema]":
198
+ return await self.client.get_user_memory_stats(**kwargs)
199
+
200
+ async def optimize_memories(self, **kwargs: Any) -> "OptimizeMemoriesResponse":
201
+ return await self.client.optimize_memories(**kwargs)
202
+
203
+ async def get_memory_topics(self, **kwargs: Any) -> List[str]:
204
+ return await self.client.get_memory_topics(**kwargs)
205
+
206
+ # TRACES
207
+ async def get_traces(self, **kwargs: Any) -> "PaginatedResponse[TraceSummary]":
208
+ return await self.client.get_traces(**kwargs)
209
+
210
+ async def get_trace(self, trace_id: str, **kwargs: Any) -> Union["TraceDetail", "TraceNode"]:
211
+ return await self.client.get_trace(trace_id, **kwargs)
212
+
213
+ async def get_trace_session_stats(self, **kwargs: Any) -> "PaginatedResponse[TraceSessionStats]":
214
+ return await self.client.get_trace_session_stats(**kwargs)
215
+
216
+ # EVALS
217
+ async def get_eval_runs(self, **kwargs: Any) -> "PaginatedResponse[EvalSchema]":
218
+ return await self.client.list_eval_runs(**kwargs)
219
+
220
+ async def get_eval_run(self, eval_run_id: str, **kwargs: Any) -> "EvalSchema":
221
+ return await self.client.get_eval_run(eval_run_id, **kwargs)
222
+
223
+ async def delete_eval_runs(self, eval_run_ids: List[str], **kwargs: Any) -> None:
224
+ return await self.client.delete_eval_runs(eval_run_ids, **kwargs)
225
+
226
+ async def update_eval_run(self, eval_run_id: str, **kwargs: Any) -> "EvalSchema":
227
+ return await self.client.update_eval_run(eval_run_id, **kwargs)
228
+
229
+ async def create_eval_run(self, **kwargs: Any) -> Optional["EvalSchema"]:
230
+ return await self.client.run_eval(**kwargs)
231
+
232
+ # METRICS
233
+ async def get_metrics(
234
+ self, starting_date: Optional[date] = None, ending_date: Optional[date] = None, **kwargs: Any
235
+ ) -> "MetricsResponse":
236
+ return await self.client.get_metrics(starting_date=starting_date, ending_date=ending_date, **kwargs)
237
+
238
+ async def refresh_metrics(self, **kwargs: Any) -> List["DayAggregatedMetrics"]:
239
+ return await self.client.refresh_metrics(**kwargs)
240
+
241
+ # OTHER
242
+ async def migrate_database(self, target_version: Optional[str] = None) -> None:
243
+ """Migrate the database to a target version.
244
+
245
+ Args:
246
+ target_version: Target version to migrate to
247
+ """
248
+
249
+ return await self.client.migrate_database(self.id, target_version)
250
+
251
+
252
+ @dataclass
253
+ class RemoteKnowledge:
254
+ client: "AgentOSClient"
255
+ contents_db: Optional[RemoteDb] = None
256
+
257
+ async def get_config(self, headers: Optional[Dict[str, str]] = None) -> "ConfigResponseSchema":
258
+ return await self.client.get_knowledge_config(
259
+ db_id=self.contents_db.id if self.contents_db else None, headers=headers
260
+ )
261
+
262
+ async def search_knowledge(self, query: str, **kwargs: Any) -> "PaginatedResponse[VectorSearchResult]":
263
+ return await self.client.search_knowledge(query, **kwargs)
264
+
265
+ async def upload_content(
266
+ self,
267
+ name: Optional[str] = None,
268
+ description: Optional[str] = None,
269
+ url: Optional[str] = None,
270
+ metadata: Optional[Dict[str, Any]] = None,
271
+ file: Optional[Union[File, "UploadFile"]] = None,
272
+ text_content: Optional[str] = None,
273
+ reader_id: Optional[str] = None,
274
+ chunker: Optional[str] = None,
275
+ chunk_size: Optional[int] = None,
276
+ chunk_overlap: Optional[int] = None,
277
+ db_id: Optional[str] = None,
278
+ **kwargs: Any,
279
+ ) -> "ContentResponseSchema":
280
+ return await self.client.upload_knowledge_content(
281
+ name=name,
282
+ description=description,
283
+ url=url,
284
+ metadata=metadata,
285
+ file=file,
286
+ text_content=text_content,
287
+ reader_id=reader_id,
288
+ chunker=chunker,
289
+ chunk_size=chunk_size,
290
+ chunk_overlap=chunk_overlap,
291
+ db_id=db_id,
292
+ **kwargs,
293
+ )
294
+
295
+ async def update_content(
296
+ self,
297
+ content_id: str,
298
+ name: Optional[str] = None,
299
+ description: Optional[str] = None,
300
+ metadata: Optional[Dict[str, Any]] = None,
301
+ reader_id: Optional[str] = None,
302
+ db_id: Optional[str] = None,
303
+ **kwargs: Any,
304
+ ) -> "ContentResponseSchema":
305
+ return await self.client.update_knowledge_content(
306
+ content_id=content_id,
307
+ name=name,
308
+ description=description,
309
+ metadata=metadata,
310
+ reader_id=reader_id,
311
+ db_id=db_id,
312
+ **kwargs,
313
+ )
314
+
315
+ async def get_content(
316
+ self,
317
+ limit: Optional[int] = None,
318
+ page: Optional[int] = None,
319
+ sort_by: Optional[str] = None,
320
+ sort_order: Optional[str] = None,
321
+ db_id: Optional[str] = None,
322
+ **kwargs: Any,
323
+ ) -> "PaginatedResponse[ContentResponseSchema]":
324
+ return await self.client.list_knowledge_content(
325
+ limit=limit, page=page, sort_by=sort_by, sort_order=sort_order, db_id=db_id, **kwargs
326
+ )
327
+
328
+ async def get_content_by_id(
329
+ self, content_id: str, db_id: Optional[str] = None, **kwargs: Any
330
+ ) -> "ContentResponseSchema":
331
+ return await self.client.get_knowledge_content(content_id=content_id, db_id=db_id, **kwargs)
332
+
333
+ async def delete_content_by_id(self, content_id: str, db_id: Optional[str] = None, **kwargs: Any) -> None:
334
+ await self.client.delete_knowledge_content(content_id=content_id, db_id=db_id, **kwargs)
335
+
336
+ async def delete_all_content(self, db_id: Optional[str] = None, **kwargs: Any) -> None:
337
+ await self.client.delete_all_knowledge_content(db_id=db_id, **kwargs)
338
+
339
+ async def get_content_status(
340
+ self, content_id: str, db_id: Optional[str] = None, **kwargs: Any
341
+ ) -> "ContentStatusResponse":
342
+ return await self.client.get_knowledge_content_status(content_id=content_id, db_id=db_id, **kwargs)
343
+
344
+
345
+ @dataclass
346
+ class BaseRemote:
347
+ # Private cache for OS config with TTL: (config, timestamp)
348
+ _cached_config: Optional[Tuple["ConfigResponse", float]] = field(default=None, init=False, repr=False)
349
+ # Private cache for agent card with TTL: (agent_card, timestamp)
350
+ _cached_agent_card: Optional[Tuple[Optional["AgentCard"], float]] = field(default=None, init=False, repr=False)
351
+
352
+ def __init__(
353
+ self,
354
+ base_url: str,
355
+ timeout: float = 60.0,
356
+ protocol: Literal["agentos", "a2a"] = "agentos",
357
+ a2a_protocol: Literal["json-rpc", "rest"] = "rest",
358
+ config_ttl: float = 300.0,
359
+ ):
360
+ """Initialize BaseRemote for remote execution.
361
+
362
+ Supports two protocols:
363
+ - "agentos": Agno's proprietary AgentOS REST API (default)
364
+ - "a2a": A2A (Agent-to-Agent) protocol for cross-framework communication
365
+
366
+ For local execution, provide agent/team/workflow instances.
367
+ For remote execution, provide base_url.
368
+
369
+ Args:
370
+ base_url: Base URL for remote instance (e.g., "http://localhost:7777")
371
+ timeout: Request timeout in seconds (default: 60)
372
+ protocol: Communication protocol - "agentos" (default) or "a2a"
373
+ a2a_protocol: For A2A protocol only - Whether to use JSON-RPC or REST protocol.
374
+ config_ttl: Time-to-live for cached config in seconds (default: 300)
375
+ """
376
+ self.base_url = base_url.rstrip("/")
377
+ self.timeout: float = timeout
378
+ self.protocol = protocol
379
+ self.a2a_protocol = a2a_protocol
380
+ self.config_ttl: float = config_ttl
381
+ self._cached_config = None
382
+ self._cached_agent_card = None
383
+
384
+ self.agentos_client = None
385
+ self.a2a_client = None
386
+
387
+ if protocol == "agentos":
388
+ self.agentos_client = self.get_os_client()
389
+ elif protocol == "a2a":
390
+ self.a2a_client = self.get_a2a_client()
391
+ else:
392
+ raise ValueError(f"Invalid protocol: {protocol}")
393
+
394
+ def get_os_client(self) -> "AgentOSClient":
395
+ """Get an AgentOSClient for fetching remote configuration.
396
+
397
+ This is used internally by AgentOS to fetch configuration from remote
398
+ AgentOS instances when this runner represents a remote resource.
399
+
400
+ Returns:
401
+ AgentOSClient: Client configured for this remote resource's base URL
402
+ """
403
+ from agno.client import AgentOSClient
404
+
405
+ return AgentOSClient(
406
+ base_url=self.base_url,
407
+ timeout=self.timeout,
408
+ )
409
+
410
+ def get_a2a_client(self) -> "A2AClient":
411
+ """Get an A2AClient for A2A protocol communication.
412
+
413
+ Returns cached client if available, otherwise creates a new one.
414
+ This method provides lazy initialization of the A2A client.
415
+
416
+ Returns:
417
+ A2AClient: Client configured for A2A protocol communication
418
+ """
419
+ from agno.client.a2a import A2AClient
420
+
421
+ return A2AClient(
422
+ base_url=self.base_url,
423
+ timeout=int(self.timeout),
424
+ protocol=self.a2a_protocol,
425
+ )
426
+
427
+ @property
428
+ def _config(self) -> Optional["ConfigResponse"]:
429
+ """Get the OS config from remote, cached with TTL."""
430
+ from agno.os.schema import ConfigResponse
431
+
432
+ if self.protocol == "a2a":
433
+ return None
434
+
435
+ current_time = time.time()
436
+
437
+ # Check if cache is valid
438
+ if self._cached_config is not None:
439
+ config, cached_at = self._cached_config
440
+ if current_time - cached_at < self.config_ttl:
441
+ return config
442
+
443
+ # Fetch fresh config
444
+ config: ConfigResponse = self.agentos_client.get_config() # type: ignore
445
+ self._cached_config = (config, current_time)
446
+ return config
447
+
448
+ async def refresh_os_config(self) -> "ConfigResponse":
449
+ """Force refresh the cached OS config."""
450
+ from agno.os.schema import ConfigResponse
451
+
452
+ config: ConfigResponse = await self.agentos_client.aget_config() # type: ignore
453
+ self._cached_config = (config, time.time())
454
+ return config
455
+
456
+ def _get_headers(self, auth_token: Optional[str] = None) -> Dict[str, str]:
457
+ """Get headers for HTTP requests.
458
+
459
+ Args:
460
+ auth_token: Optional JWT token for authentication
461
+
462
+ Returns:
463
+ Dict[str, str]: Headers including Content-Type and optional Authorization
464
+ """
465
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
466
+ if auth_token:
467
+ headers["Authorization"] = f"Bearer {auth_token}"
468
+ return headers
469
+
470
+ def _get_auth_headers(self, auth_token: Optional[str] = None) -> Optional[Dict[str, str]]:
471
+ """Get Authorization headers for HTTP requests.
472
+
473
+ Args:
474
+ auth_token: Optional JWT token for authentication
475
+
476
+ Returns:
477
+ Dict[str, str] with Authorization header if auth_token is provided, None otherwise
478
+ """
479
+ if auth_token:
480
+ return {"Authorization": f"Bearer {auth_token}"}
481
+ return None
482
+
483
+ def get_agent_card(self) -> Optional["AgentCard"]:
484
+ """Get agent card for A2A protocol agents, cached with TTL.
485
+
486
+ Fetches the agent card from the standard /.well-known/agent.json endpoint
487
+ to populate agent metadata (name, description, etc.) for A2A agents.
488
+
489
+ Returns None for non-A2A protocols or if the server doesn't support agent cards.
490
+ """
491
+ if self.protocol != "a2a":
492
+ return None
493
+
494
+ current_time = time.time()
495
+
496
+ # Check if cache is valid
497
+ if self._cached_agent_card is not None:
498
+ agent_card, cached_at = self._cached_agent_card
499
+ if current_time - cached_at < self.config_ttl:
500
+ return agent_card
501
+
502
+ try:
503
+ agent_card = self.a2a_client.get_agent_card() # type: ignore
504
+ self._cached_agent_card = (agent_card, current_time)
505
+ return agent_card
506
+ except Exception:
507
+ self._cached_agent_card = (None, current_time)
508
+ return None
509
+
510
+ async def aget_agent_card(self) -> Optional["AgentCard"]:
511
+ """Get agent card for A2A protocol agents, cached with TTL.
512
+
513
+ Fetches the agent card from the standard /.well-known/agent.json endpoint
514
+ to populate agent metadata (name, description, etc.) for A2A agents.
515
+
516
+ Returns None for non-A2A protocols or if the server doesn't support agent cards.
517
+ """
518
+ if self.protocol != "a2a":
519
+ return None
520
+
521
+ current_time = time.time()
522
+
523
+ # Check if cache is valid
524
+ if self._cached_agent_card is not None:
525
+ agent_card, cached_at = self._cached_agent_card
526
+ if current_time - cached_at < self.config_ttl:
527
+ return agent_card
528
+
529
+ try:
530
+ agent_card = await self.a2a_client.aget_agent_card() # type: ignore
531
+ self._cached_agent_card = (agent_card, current_time)
532
+ return agent_card
533
+ except Exception:
534
+ self._cached_agent_card = (None, current_time)
535
+ return None
536
+
537
+ @abstractmethod
538
+ def arun( # type: ignore
539
+ self,
540
+ input: Union[str, List, Dict, Message, BaseModel, List[Message]],
541
+ *,
542
+ stream: Optional[bool] = None,
543
+ user_id: Optional[str] = None,
544
+ session_id: Optional[str] = None,
545
+ session_state: Optional[Dict[str, Any]] = None,
546
+ audio: Optional[Sequence[Audio]] = None,
547
+ images: Optional[Sequence[Image]] = None,
548
+ videos: Optional[Sequence[Video]] = None,
549
+ files: Optional[Sequence[File]] = None,
550
+ stream_events: Optional[bool] = None,
551
+ retries: Optional[int] = None,
552
+ knowledge_filters: Optional[Dict[str, Any]] = None,
553
+ add_history_to_context: Optional[bool] = None,
554
+ add_dependencies_to_context: Optional[bool] = None,
555
+ add_session_state_to_context: Optional[bool] = None,
556
+ dependencies: Optional[Dict[str, Any]] = None,
557
+ metadata: Optional[Dict[str, Any]] = None,
558
+ auth_token: Optional[str] = None,
559
+ **kwargs: Any,
560
+ ) -> Union[
561
+ RunOutput,
562
+ TeamRunOutput,
563
+ WorkflowRunOutput,
564
+ AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent, WorkflowRunOutputEvent]],
565
+ ]:
566
+ raise NotImplementedError("arun method must be implemented by the subclass")
567
+
568
+ @abstractmethod
569
+ async def acontinue_run( # type: ignore
570
+ self,
571
+ run_id: str,
572
+ stream: Optional[bool] = None,
573
+ updated_tools: Optional[List[ToolExecution]] = None,
574
+ user_id: Optional[str] = None,
575
+ session_id: Optional[str] = None,
576
+ ) -> Union[RunOutput, TeamRunOutput, WorkflowRunOutput]:
577
+ raise NotImplementedError("acontinue_run method must be implemented by the subclass")
578
+
579
+ @abstractmethod
580
+ async def acancel_run(self, run_id: str) -> bool:
581
+ raise NotImplementedError("cancel_run method must be implemented by the subclass")
agno/run/__init__.py CHANGED
@@ -1,6 +1,4 @@
1
1
  from agno.run.base import RunContext, RunStatus
2
+ from agno.run.cancel import get_cancellation_manager, set_cancellation_manager
2
3
 
3
- __all__ = [
4
- "RunContext",
5
- "RunStatus",
6
- ]
4
+ __all__ = ["RunContext", "RunStatus", "get_cancellation_manager", "set_cancellation_manager"]