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/agent/remote.py ADDED
@@ -0,0 +1,525 @@
1
+ import json
2
+ from dataclasses import dataclass, field
3
+ from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, List, Literal, Optional, Sequence, Tuple, Union, overload
4
+
5
+ from pydantic import BaseModel
6
+
7
+ from agno.media import Audio, File, Image, Video
8
+ from agno.models.base import Model
9
+ from agno.models.message import Message
10
+ from agno.models.response import ToolExecution
11
+ from agno.remote.base import BaseRemote, RemoteDb, RemoteKnowledge
12
+ from agno.run.agent import RunOutput, RunOutputEvent
13
+ from agno.utils.agent import validate_input
14
+ from agno.utils.log import log_warning
15
+ from agno.utils.remote import serialize_input
16
+
17
+ if TYPE_CHECKING:
18
+ from agno.os.routers.agents.schema import AgentResponse
19
+
20
+
21
+ @dataclass
22
+ class RemoteAgent(BaseRemote):
23
+ # Private cache for agent config with TTL: (config, timestamp)
24
+ _cached_agent_config: Optional[Tuple["AgentResponse", float]] = field(default=None, init=False, repr=False)
25
+
26
+ knowledge_filters: Optional[Dict[str, Any]] = None
27
+ enable_agentic_knowledge_filters: Optional[bool] = False
28
+ output_schema: Optional[Any] = None
29
+ store_media: bool = True
30
+ store_tool_messages: bool = True
31
+ store_history_messages: bool = True
32
+ send_media_to_model: bool = True
33
+ add_history_to_context: bool = False
34
+ num_history_runs: Optional[int] = None
35
+ num_history_messages: Optional[int] = None
36
+ debug_mode: bool = False
37
+ debug_level: Literal[1, 2] = 1
38
+
39
+ def __init__(
40
+ self,
41
+ base_url: str,
42
+ agent_id: str,
43
+ timeout: float = 60.0,
44
+ protocol: Literal["agentos", "a2a"] = "agentos",
45
+ a2a_protocol: Literal["json-rpc", "rest"] = "rest",
46
+ config_ttl: float = 300.0,
47
+ ):
48
+ """Initialize RemoteAgent for remote execution.
49
+
50
+ Supports two protocols:
51
+ - "agentos": Agno's proprietary AgentOS REST API (default)
52
+ - "a2a": A2A (Agent-to-Agent) protocol for cross-framework communication
53
+
54
+ Args:
55
+ base_url: Base URL for remote instance (e.g., "http://localhost:7777")
56
+ agent_id: ID of remote agent on the remote server
57
+ timeout: Request timeout in seconds (default: 60)
58
+ protocol: Communication protocol - "agentos" (default) or "a2a"
59
+ a2a_protocol: For A2A protocol only - Whether to use JSON-RPC or REST protocol.
60
+ config_ttl: Time-to-live for cached config in seconds (default: 300)
61
+ """
62
+ super().__init__(base_url, timeout, protocol, a2a_protocol, config_ttl)
63
+ self.agent_id = agent_id
64
+ self._cached_agent_config = None
65
+
66
+ @property
67
+ def id(self) -> str:
68
+ return self.agent_id
69
+
70
+ async def get_agent_config(self) -> "AgentResponse":
71
+ """
72
+ Get the agent config from remote.
73
+
74
+ For A2A protocol, returns a minimal AgentResponse since A2A servers
75
+ don't expose the same config endpoints as AgentOS. For AgentOS, always fetches fresh config.
76
+ """
77
+ from agno.os.routers.agents.schema import AgentResponse
78
+
79
+ if self.a2a_client:
80
+ from agno.client.a2a.schemas import AgentCard
81
+
82
+ agent_card: Optional[AgentCard] = await self.a2a_client.aget_agent_card()
83
+
84
+ return AgentResponse(
85
+ id=self.agent_id,
86
+ name=agent_card.name if agent_card else self.agent_id,
87
+ description=agent_card.description if agent_card else f"A2A agent: {self.agent_id}",
88
+ )
89
+
90
+ return await self.agentos_client.aget_agent(self.agent_id) # type: ignore
91
+
92
+ @property
93
+ def _agent_config(self) -> Optional["AgentResponse"]:
94
+ """
95
+ Get the agent config from remote, cached with TTL.
96
+ Returns None for A2A protocol since A2A servers don't expose agent config endpoints.
97
+ """
98
+ import time
99
+
100
+ from agno.os.routers.agents.schema import AgentResponse
101
+
102
+ if self.a2a_client:
103
+ from agno.client.a2a.schemas import AgentCard
104
+
105
+ agent_card: Optional[AgentCard] = self.a2a_client.get_agent_card()
106
+
107
+ return AgentResponse(
108
+ id=self.agent_id,
109
+ name=agent_card.name if agent_card else self.agent_id,
110
+ description=agent_card.description if agent_card else f"A2A agent: {self.agent_id}",
111
+ )
112
+
113
+ current_time = time.time()
114
+
115
+ # Check if cache is valid
116
+ if self._cached_agent_config is not None:
117
+ config, cached_at = self._cached_agent_config
118
+ if current_time - cached_at < self.config_ttl:
119
+ return config
120
+
121
+ # Fetch fresh config
122
+ config: AgentResponse = self.agentos_client.get_agent(self.agent_id) # type: ignore
123
+ self._cached_agent_config = (config, current_time)
124
+ return config
125
+
126
+ async def refresh_config(self) -> Optional["AgentResponse"]:
127
+ """
128
+ Force refresh the cached agent config.
129
+ Returns None for A2A protocol.
130
+ """
131
+ import time
132
+
133
+ from agno.os.routers.agents.schema import AgentResponse
134
+
135
+ if self.a2a_client:
136
+ self._cached_agent_config = None
137
+ return None
138
+
139
+ config: AgentResponse = await self.agentos_client.aget_agent(self.agent_id) # type: ignore
140
+ self._cached_agent_config = (config, time.time())
141
+ return config
142
+
143
+ @property
144
+ def name(self) -> Optional[str]:
145
+ if self._agent_config is not None:
146
+ return self._agent_config.name
147
+ return self.agent_id
148
+
149
+ @property
150
+ def description(self) -> Optional[str]:
151
+ if self._agent_config is not None:
152
+ return self._agent_config.description
153
+ return ""
154
+
155
+ def role(self) -> Optional[str]:
156
+ if self._agent_config is not None:
157
+ return self._agent_config.role
158
+ return None
159
+
160
+ @property
161
+ def tools(self) -> Optional[List[Dict[str, Any]]]:
162
+ if self._agent_config is not None:
163
+ try:
164
+ return json.loads(self._agent_config.tools["tools"]) if self._agent_config.tools else None
165
+ except Exception as e:
166
+ log_warning(f"Failed to load tools for agent {self.agent_id}: {e}")
167
+ return None
168
+ return None
169
+
170
+ @property
171
+ def db(self) -> Optional[RemoteDb]:
172
+ if (
173
+ self.agentos_client
174
+ and self._config
175
+ and self._agent_config is not None
176
+ and self._agent_config.db_id is not None
177
+ ):
178
+ return RemoteDb.from_config(
179
+ db_id=self._agent_config.db_id,
180
+ client=self.agentos_client,
181
+ config=self._config,
182
+ )
183
+ return None
184
+
185
+ @property
186
+ def knowledge(self) -> Optional[RemoteKnowledge]:
187
+ if self.agentos_client and self._agent_config is not None and self._agent_config.knowledge is not None:
188
+ return RemoteKnowledge(
189
+ client=self.agentos_client,
190
+ contents_db=RemoteDb(
191
+ id=self._agent_config.knowledge.get("db_id"), # type: ignore
192
+ client=self.agentos_client,
193
+ knowledge_table_name=self._agent_config.knowledge.get("knowledge_table"),
194
+ )
195
+ if self._agent_config.knowledge.get("db_id") is not None
196
+ else None,
197
+ )
198
+ return None
199
+
200
+ @property
201
+ def model(self) -> Optional[Model]:
202
+ # We don't expose the remote agent's models, since they can't be used by other services in AgentOS.
203
+ return None
204
+
205
+ async def aget_tools(self, **kwargs: Any) -> List[Dict]:
206
+ if self._agent_config is not None and self._agent_config.tools is not None:
207
+ return json.loads(self._agent_config.tools["tools"])
208
+ return []
209
+
210
+ @overload
211
+ async def arun(
212
+ self,
213
+ input: Union[str, List, Dict, Message, BaseModel, List[Message]],
214
+ *,
215
+ stream: Literal[False] = False,
216
+ user_id: Optional[str] = None,
217
+ session_id: Optional[str] = None,
218
+ session_state: Optional[Dict[str, Any]] = None,
219
+ audio: Optional[Sequence[Audio]] = None,
220
+ images: Optional[Sequence[Image]] = None,
221
+ videos: Optional[Sequence[Video]] = None,
222
+ files: Optional[Sequence[File]] = None,
223
+ stream_events: Optional[bool] = None,
224
+ retries: Optional[int] = None,
225
+ knowledge_filters: Optional[Dict[str, Any]] = None,
226
+ add_history_to_context: Optional[bool] = None,
227
+ add_dependencies_to_context: Optional[bool] = None,
228
+ add_session_state_to_context: Optional[bool] = None,
229
+ dependencies: Optional[Dict[str, Any]] = None,
230
+ metadata: Optional[Dict[str, Any]] = None,
231
+ auth_token: Optional[str] = None,
232
+ **kwargs: Any,
233
+ ) -> RunOutput: ...
234
+
235
+ @overload
236
+ def arun(
237
+ self,
238
+ input: Union[str, List, Dict, Message, BaseModel, List[Message]],
239
+ *,
240
+ stream: Literal[True] = True,
241
+ user_id: Optional[str] = None,
242
+ session_id: Optional[str] = None,
243
+ audio: Optional[Sequence[Audio]] = None,
244
+ images: Optional[Sequence[Image]] = None,
245
+ videos: Optional[Sequence[Video]] = None,
246
+ files: Optional[Sequence[File]] = None,
247
+ stream_events: Optional[bool] = None,
248
+ retries: Optional[int] = None,
249
+ knowledge_filters: Optional[Dict[str, Any]] = None,
250
+ add_history_to_context: Optional[bool] = None,
251
+ add_dependencies_to_context: Optional[bool] = None,
252
+ add_session_state_to_context: Optional[bool] = None,
253
+ dependencies: Optional[Dict[str, Any]] = None,
254
+ metadata: Optional[Dict[str, Any]] = None,
255
+ auth_token: Optional[str] = None,
256
+ **kwargs: Any,
257
+ ) -> AsyncIterator[RunOutputEvent]: ...
258
+
259
+ def arun( # type: ignore
260
+ self,
261
+ input: Union[str, List, Dict, Message, BaseModel, List[Message]],
262
+ *,
263
+ stream: Optional[bool] = None,
264
+ user_id: Optional[str] = None,
265
+ session_id: Optional[str] = None,
266
+ session_state: Optional[Dict[str, Any]] = None,
267
+ audio: Optional[Sequence[Audio]] = None,
268
+ images: Optional[Sequence[Image]] = None,
269
+ videos: Optional[Sequence[Video]] = None,
270
+ files: Optional[Sequence[File]] = None,
271
+ stream_events: Optional[bool] = None,
272
+ retries: Optional[int] = None,
273
+ knowledge_filters: Optional[Dict[str, Any]] = None,
274
+ add_history_to_context: Optional[bool] = None,
275
+ add_dependencies_to_context: Optional[bool] = None,
276
+ add_session_state_to_context: Optional[bool] = None,
277
+ dependencies: Optional[Dict[str, Any]] = None,
278
+ metadata: Optional[Dict[str, Any]] = None,
279
+ auth_token: Optional[str] = None,
280
+ **kwargs: Any,
281
+ ) -> Union[
282
+ RunOutput,
283
+ AsyncIterator[RunOutputEvent],
284
+ ]:
285
+ validated_input = validate_input(input)
286
+ serialized_input = serialize_input(validated_input)
287
+ headers = self._get_auth_headers(auth_token)
288
+
289
+ # A2A protocol path
290
+ if self.a2a_client:
291
+ return self._arun_a2a( # type: ignore[return-value]
292
+ message=serialized_input,
293
+ stream=stream or False,
294
+ user_id=user_id,
295
+ context_id=session_id, # Map session_id → context_id for A2A
296
+ audio=audio,
297
+ images=images,
298
+ videos=videos,
299
+ files=files,
300
+ headers=headers,
301
+ )
302
+
303
+ # AgentOS protocol path (default)
304
+ if self.agentos_client:
305
+ if stream:
306
+ # Handle streaming response
307
+ return self.agentos_client.run_agent_stream(
308
+ agent_id=self.agent_id,
309
+ message=serialized_input,
310
+ session_id=session_id,
311
+ user_id=user_id,
312
+ audio=audio,
313
+ images=images,
314
+ videos=videos,
315
+ files=files,
316
+ session_state=session_state,
317
+ stream_events=stream_events,
318
+ retries=retries,
319
+ knowledge_filters=knowledge_filters,
320
+ add_history_to_context=add_history_to_context,
321
+ add_dependencies_to_context=add_dependencies_to_context,
322
+ add_session_state_to_context=add_session_state_to_context,
323
+ dependencies=dependencies,
324
+ metadata=metadata,
325
+ headers=headers,
326
+ **kwargs,
327
+ )
328
+ else:
329
+ return self.agentos_client.run_agent( # type: ignore
330
+ agent_id=self.agent_id,
331
+ message=serialized_input,
332
+ session_id=session_id,
333
+ user_id=user_id,
334
+ audio=audio,
335
+ images=images,
336
+ videos=videos,
337
+ files=files,
338
+ session_state=session_state,
339
+ stream_events=stream_events,
340
+ retries=retries,
341
+ knowledge_filters=knowledge_filters,
342
+ add_history_to_context=add_history_to_context,
343
+ add_dependencies_to_context=add_dependencies_to_context,
344
+ add_session_state_to_context=add_session_state_to_context,
345
+ dependencies=dependencies,
346
+ metadata=metadata,
347
+ headers=headers,
348
+ **kwargs,
349
+ )
350
+ else:
351
+ raise ValueError("No client available")
352
+
353
+ def _arun_a2a(
354
+ self,
355
+ message: str,
356
+ stream: bool,
357
+ user_id: Optional[str],
358
+ context_id: Optional[str],
359
+ audio: Optional[Sequence[Audio]],
360
+ images: Optional[Sequence[Image]],
361
+ videos: Optional[Sequence[Video]],
362
+ files: Optional[Sequence[File]],
363
+ headers: Optional[Dict[str, str]],
364
+ ) -> Union[RunOutput, AsyncIterator[RunOutputEvent]]:
365
+ """Execute via A2A protocol.
366
+
367
+ Args:
368
+ message: Serialized message string
369
+ stream: Whether to stream the response
370
+ user_id: User identifier
371
+ context_id: Session/context ID (maps to session_id)
372
+ audio: Audio files to include
373
+ images: Images to include
374
+ videos: Videos to include
375
+ files: Files to include
376
+ headers: HTTP headers to include in the request (optional)
377
+
378
+ Returns:
379
+ RunOutput for non-streaming, AsyncIterator[RunOutputEvent] for streaming
380
+ """
381
+ if not self.a2a_client:
382
+ raise ValueError("A2A client not available")
383
+ from agno.client.a2a.utils import map_stream_events_to_run_events
384
+
385
+ if stream:
386
+ # Return async generator for streaming
387
+ event_stream = self.a2a_client.stream_message(
388
+ message=message,
389
+ context_id=context_id,
390
+ user_id=user_id,
391
+ images=list(images) if images else None,
392
+ audio=list(audio) if audio else None,
393
+ videos=list(videos) if videos else None,
394
+ files=list(files) if files else None,
395
+ headers=headers,
396
+ )
397
+ return map_stream_events_to_run_events(event_stream, agent_id=self.agent_id)
398
+ else:
399
+ # Return coroutine for non-streaming
400
+ return self._arun_a2a_send( # type: ignore[return-value]
401
+ message=message,
402
+ user_id=user_id,
403
+ context_id=context_id,
404
+ audio=audio,
405
+ images=images,
406
+ videos=videos,
407
+ files=files,
408
+ headers=headers,
409
+ )
410
+
411
+ async def _arun_a2a_send(
412
+ self,
413
+ message: str,
414
+ user_id: Optional[str],
415
+ context_id: Optional[str],
416
+ audio: Optional[Sequence[Audio]],
417
+ images: Optional[Sequence[Image]],
418
+ videos: Optional[Sequence[Video]],
419
+ files: Optional[Sequence[File]],
420
+ headers: Optional[Dict[str, str]],
421
+ ) -> RunOutput:
422
+ """Send a non-streaming A2A message and convert response to RunOutput."""
423
+ if not self.a2a_client:
424
+ raise ValueError("A2A client not available")
425
+ from agno.client.a2a.utils import map_task_result_to_run_output
426
+
427
+ task_result = await self.a2a_client.send_message(
428
+ message=message,
429
+ context_id=context_id,
430
+ user_id=user_id,
431
+ images=list(images) if images else None,
432
+ audio=list(audio) if audio else None,
433
+ videos=list(videos) if videos else None,
434
+ files=list(files) if files else None,
435
+ headers=headers,
436
+ )
437
+ return map_task_result_to_run_output(task_result, agent_id=self.agent_id, user_id=user_id)
438
+
439
+ @overload
440
+ async def acontinue_run(
441
+ self,
442
+ run_id: str,
443
+ updated_tools: List[ToolExecution],
444
+ stream: Literal[False] = False,
445
+ user_id: Optional[str] = None,
446
+ session_id: Optional[str] = None,
447
+ auth_token: Optional[str] = None,
448
+ **kwargs: Any,
449
+ ) -> RunOutput: ...
450
+
451
+ @overload
452
+ def acontinue_run(
453
+ self,
454
+ run_id: str,
455
+ updated_tools: List[ToolExecution],
456
+ stream: Literal[True] = True,
457
+ user_id: Optional[str] = None,
458
+ session_id: Optional[str] = None,
459
+ auth_token: Optional[str] = None,
460
+ **kwargs: Any,
461
+ ) -> AsyncIterator[RunOutputEvent]: ...
462
+
463
+ def acontinue_run( # type: ignore
464
+ self,
465
+ run_id: str, # type: ignore
466
+ updated_tools: List[ToolExecution],
467
+ stream: Optional[bool] = None,
468
+ user_id: Optional[str] = None,
469
+ session_id: Optional[str] = None,
470
+ auth_token: Optional[str] = None,
471
+ **kwargs: Any,
472
+ ) -> Union[
473
+ RunOutput,
474
+ AsyncIterator[RunOutputEvent],
475
+ ]:
476
+ headers = self._get_auth_headers(auth_token)
477
+
478
+ if self.agentos_client:
479
+ if stream:
480
+ # Handle streaming response
481
+ return self.agentos_client.continue_agent_run_stream( # type: ignore
482
+ agent_id=self.agent_id,
483
+ run_id=run_id,
484
+ user_id=user_id,
485
+ session_id=session_id,
486
+ tools=updated_tools,
487
+ headers=headers,
488
+ **kwargs,
489
+ )
490
+ else:
491
+ return self.agentos_client.continue_agent_run( # type: ignore
492
+ agent_id=self.agent_id,
493
+ run_id=run_id,
494
+ tools=updated_tools,
495
+ user_id=user_id,
496
+ session_id=session_id,
497
+ headers=headers,
498
+ **kwargs,
499
+ )
500
+
501
+ else:
502
+ raise ValueError("No client available")
503
+
504
+ async def acancel_run(self, run_id: str, auth_token: Optional[str] = None) -> bool:
505
+ """Cancel a running agent execution.
506
+
507
+ Args:
508
+ run_id (str): The run_id to cancel.
509
+ auth_token: Optional JWT token for authentication.
510
+
511
+ Returns:
512
+ bool: True if the run was successfully cancelled, False otherwise.
513
+ """
514
+ headers = self._get_auth_headers(auth_token)
515
+ if not self.agentos_client:
516
+ raise ValueError("AgentOS client not available")
517
+ try:
518
+ await self.agentos_client.cancel_agent_run(
519
+ agent_id=self.agent_id,
520
+ run_id=run_id,
521
+ headers=headers,
522
+ )
523
+ return True
524
+ except Exception:
525
+ return False
agno/api/api.py CHANGED
@@ -19,6 +19,7 @@ class Api:
19
19
  base_url=agno_api_settings.api_url,
20
20
  headers=self.headers,
21
21
  timeout=60,
22
+ http2=True,
22
23
  )
23
24
 
24
25
  def AsyncClient(self) -> HttpxAsyncClient:
@@ -26,6 +27,7 @@ class Api:
26
27
  base_url=agno_api_settings.api_url,
27
28
  headers=self.headers,
28
29
  timeout=60,
30
+ http2=True,
29
31
  )
30
32
 
31
33
 
@@ -0,0 +1,3 @@
1
+ from agno.client.os import AgentOSClient
2
+
3
+ __all__ = ["AgentOSClient"]
@@ -0,0 +1,10 @@
1
+ from agno.client.a2a.client import A2AClient
2
+ from agno.client.a2a.schemas import AgentCard, Artifact, StreamEvent, TaskResult
3
+
4
+ __all__ = [
5
+ "A2AClient",
6
+ "AgentCard",
7
+ "Artifact",
8
+ "StreamEvent",
9
+ "TaskResult",
10
+ ]