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
@@ -1,3 +1,4 @@
1
+ import json
1
2
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Set, Union, get_args
2
3
 
3
4
  from pydantic import BaseModel
@@ -25,10 +26,12 @@ def print_response(
25
26
  show_message: bool = True,
26
27
  show_reasoning: bool = True,
27
28
  show_full_reasoning: bool = False,
29
+ show_member_responses: Optional[bool] = None,
28
30
  tags_to_include_in_markdown: Optional[Set[str]] = None,
29
31
  session_id: Optional[str] = None,
30
32
  session_state: Optional[Dict[str, Any]] = None,
31
33
  user_id: Optional[str] = None,
34
+ run_id: Optional[str] = None,
32
35
  audio: Optional[Sequence[Audio]] = None,
33
36
  images: Optional[Sequence[Image]] = None,
34
37
  videos: Optional[Sequence[Video]] = None,
@@ -80,11 +83,13 @@ def print_response(
80
83
  # Run the agent
81
84
  run_response: TeamRunOutput = team.run( # type: ignore
82
85
  input=input,
86
+ run_id=run_id,
83
87
  images=images,
84
88
  audio=audio,
85
89
  videos=videos,
86
90
  files=files,
87
91
  stream=False,
92
+ stream_events=True,
88
93
  session_id=session_id,
89
94
  session_state=session_state,
90
95
  user_id=user_id,
@@ -152,7 +157,7 @@ def print_response(
152
157
 
153
158
  if isinstance(run_response, TeamRunOutput):
154
159
  # Handle member responses
155
- if team.show_members_responses:
160
+ if show_member_responses:
156
161
  for member_response in run_response.member_responses:
157
162
  # Handle member reasoning
158
163
  reasoning_steps = []
@@ -225,11 +230,23 @@ def print_response(
225
230
  panels.append(member_response_panel)
226
231
 
227
232
  if member_response.citations is not None and member_response.citations.urls is not None:
228
- md_content = "\n".join(
233
+ md_lines = []
234
+
235
+ # Add search queries if present
236
+ if member_response.citations.search_queries:
237
+ md_lines.append("**Search Queries:**")
238
+ for query in member_response.citations.search_queries:
239
+ md_lines.append(f"- {query}")
240
+ md_lines.append("") # Empty line before URLs
241
+
242
+ # Add URL citations
243
+ md_lines.extend(
229
244
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
230
245
  for i, citation in enumerate(member_response.citations.urls)
231
246
  if citation.url # Only include citations with valid URLs
232
247
  )
248
+
249
+ md_content = "\n".join(md_lines)
233
250
  if md_content: # Only create panel if there are citations
234
251
  citations_panel = create_panel(
235
252
  content=Markdown(md_content),
@@ -258,6 +275,15 @@ def print_response(
258
275
  # Join with blank lines between items
259
276
  tool_calls_text = "\n\n".join(lines)
260
277
 
278
+ # Add compression stats at end of tool calls
279
+ if team.compression_manager is not None and team.compression_manager.stats:
280
+ stats = team.compression_manager.stats
281
+ saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
282
+ orig = stats.get("original_size", 1)
283
+ if stats.get("tool_results_compressed", 0) > 0:
284
+ tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
285
+ team.compression_manager.stats.clear()
286
+
261
287
  team_tool_calls_panel = create_panel(
262
288
  content=tool_calls_text,
263
289
  title="Team Tool Calls",
@@ -280,11 +306,23 @@ def print_response(
280
306
 
281
307
  # Add citations
282
308
  if run_response.citations is not None and run_response.citations.urls is not None:
283
- md_content = "\n".join(
309
+ md_lines = []
310
+
311
+ # Add search queries if present
312
+ if run_response.citations.search_queries:
313
+ md_lines.append("**Search Queries:**")
314
+ for query in run_response.citations.search_queries:
315
+ md_lines.append(f"- {query}")
316
+ md_lines.append("") # Empty line before URLs
317
+
318
+ # Add URL citations
319
+ md_lines.extend(
284
320
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
285
321
  for i, citation in enumerate(run_response.citations.urls)
286
322
  if citation.url # Only include citations with valid URLs
287
323
  )
324
+
325
+ md_content = "\n".join(md_lines)
288
326
  if md_content: # Only create panel if there are citations
289
327
  citations_panel = create_panel(
290
328
  content=Markdown(md_content),
@@ -323,17 +361,18 @@ def print_response_stream(
323
361
  show_message: bool = True,
324
362
  show_reasoning: bool = True,
325
363
  show_full_reasoning: bool = False,
364
+ show_member_responses: Optional[bool] = None,
326
365
  tags_to_include_in_markdown: Optional[Set[str]] = None,
327
366
  session_id: Optional[str] = None,
328
367
  session_state: Optional[Dict[str, Any]] = None,
329
368
  user_id: Optional[str] = None,
369
+ run_id: Optional[str] = None,
330
370
  audio: Optional[Sequence[Audio]] = None,
331
371
  images: Optional[Sequence[Image]] = None,
332
372
  videos: Optional[Sequence[Video]] = None,
333
373
  files: Optional[Sequence[File]] = None,
334
374
  markdown: bool = False,
335
375
  stream_events: bool = False,
336
- stream_intermediate_steps: bool = False, # type: ignore
337
376
  knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
338
377
  add_history_to_context: Optional[bool] = None,
339
378
  dependencies: Optional[Dict[str, Any]] = None,
@@ -405,6 +444,7 @@ def print_response_stream(
405
444
  session_id=session_id,
406
445
  session_state=session_state,
407
446
  user_id=user_id,
447
+ run_id=run_id,
408
448
  knowledge_filters=knowledge_filters,
409
449
  add_history_to_context=add_history_to_context,
410
450
  dependencies=dependencies,
@@ -412,7 +452,7 @@ def print_response_stream(
412
452
  add_session_state_to_context=add_session_state_to_context,
413
453
  metadata=metadata,
414
454
  debug_mode=debug_mode,
415
- yield_run_response=True,
455
+ yield_run_output=True,
416
456
  **kwargs,
417
457
  )
418
458
 
@@ -448,6 +488,11 @@ def print_response_stream(
448
488
  _response_content = JSON(resp.content.model_dump_json(exclude_none=True), indent=2) # type: ignore
449
489
  except Exception as e:
450
490
  log_warning(f"Failed to convert response to JSON: {e}")
491
+ elif team.output_schema is not None and isinstance(resp.content, dict):
492
+ try:
493
+ _response_content = JSON(json.dumps(resp.content), indent=2) # type: ignore
494
+ except Exception as e:
495
+ log_warning(f"Failed to convert response to JSON: {e}")
451
496
  if hasattr(resp, "reasoning_content") and resp.reasoning_content is not None: # type: ignore
452
497
  _response_reasoning_content += resp.reasoning_content # type: ignore
453
498
  if hasattr(resp, "reasoning_steps") and resp.reasoning_steps is not None: # type: ignore
@@ -470,7 +515,7 @@ def print_response_stream(
470
515
  team_tool_calls.append(tool)
471
516
 
472
517
  # Collect member tool calls, avoiding duplicates
473
- if hasattr(resp, "member_responses") and resp.member_responses:
518
+ if show_member_responses and hasattr(resp, "member_responses") and resp.member_responses:
474
519
  for member_response in resp.member_responses:
475
520
  member_id = None
476
521
  if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
@@ -532,7 +577,9 @@ def print_response_stream(
532
577
  panels.append(status)
533
578
 
534
579
  # Process member responses and their tool calls
535
- for member_response in resp.member_responses if hasattr(resp, "member_responses") else []:
580
+ for member_response in (
581
+ resp.member_responses if show_member_responses and hasattr(resp, "member_responses") else []
582
+ ):
536
583
  member_id = None
537
584
  member_name = "Team Member"
538
585
  if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
@@ -565,7 +612,7 @@ def print_response_stream(
565
612
  panels.append(member_tool_calls_panel)
566
613
 
567
614
  # Process member response content
568
- if team.show_members_responses and member_id is not None:
615
+ if show_member_responses and member_id is not None:
569
616
  show_markdown = False
570
617
  if markdown:
571
618
  show_markdown = True
@@ -608,6 +655,14 @@ def print_response_stream(
608
655
  # Join with blank lines between items
609
656
  tool_calls_text = "\n\n".join(lines)
610
657
 
658
+ # Add compression stats if available (don't clear - will be cleared in final_panels)
659
+ if team.compression_manager is not None and team.compression_manager.stats:
660
+ stats = team.compression_manager.stats
661
+ saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
662
+ orig = stats.get("original_size", 1)
663
+ if stats.get("tool_results_compressed", 0) > 0:
664
+ tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
665
+
611
666
  team_tool_calls_panel = create_panel(
612
667
  content=tool_calls_text,
613
668
  title="Team Tool Calls",
@@ -634,11 +689,23 @@ def print_response_stream(
634
689
 
635
690
  # Add citations
636
691
  if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
637
- md_content = "\n".join(
692
+ md_lines = []
693
+
694
+ # Add search queries if present
695
+ if resp.citations.search_queries:
696
+ md_lines.append("**Search Queries:**")
697
+ for query in resp.citations.search_queries:
698
+ md_lines.append(f"- {query}")
699
+ md_lines.append("") # Empty line before URLs
700
+
701
+ # Add URL citations
702
+ md_lines.extend(
638
703
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
639
704
  for i, citation in enumerate(resp.citations.urls)
640
705
  if citation.url # Only include citations with valid URLs
641
706
  )
707
+
708
+ md_content = "\n".join(md_lines)
642
709
  if md_content: # Only create panel if there are citations
643
710
  citations_panel = create_panel(
644
711
  content=Markdown(md_content),
@@ -708,7 +775,7 @@ def print_response_stream(
708
775
  final_panels.append(thinking_panel)
709
776
 
710
777
  # Add member tool calls and responses in correct order
711
- if run_response is not None and hasattr(run_response, "member_responses"):
778
+ if show_member_responses and run_response is not None and hasattr(run_response, "member_responses"):
712
779
  for i, member_response in enumerate(run_response.member_responses): # type: ignore
713
780
  member_id = None
714
781
  if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
@@ -778,11 +845,23 @@ def print_response_stream(
778
845
 
779
846
  # Add citations if any
780
847
  if member_response.citations is not None and member_response.citations.urls is not None:
781
- md_content = "\n".join(
848
+ md_lines = []
849
+
850
+ # Add search queries if present
851
+ if member_response.citations.search_queries:
852
+ md_lines.append("**Search Queries:**")
853
+ for query in member_response.citations.search_queries:
854
+ md_lines.append(f"- {query}")
855
+ md_lines.append("") # Empty line before URLs
856
+
857
+ # Add URL citations
858
+ md_lines.extend(
782
859
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
783
860
  for i, citation in enumerate(member_response.citations.urls)
784
861
  if citation.url # Only include citations with valid URLs
785
862
  )
863
+
864
+ md_content = "\n".join(md_lines)
786
865
  if md_content: # Only create panel if there are citations
787
866
  citations_panel = create_panel(
788
867
  content=Markdown(md_content),
@@ -810,6 +889,15 @@ def print_response_stream(
810
889
 
811
890
  tool_calls_text = "\n\n".join(lines)
812
891
 
892
+ # Add compression stats at end of tool calls
893
+ if team.compression_manager is not None and team.compression_manager.stats:
894
+ stats = team.compression_manager.stats
895
+ saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
896
+ orig = stats.get("original_size", 1)
897
+ if stats.get("tool_results_compressed", 0) > 0:
898
+ tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
899
+ team.compression_manager.stats.clear()
900
+
813
901
  team_tool_calls_panel = create_panel(
814
902
  content=tool_calls_text,
815
903
  title="Team Tool Calls",
@@ -833,11 +921,23 @@ def print_response_stream(
833
921
 
834
922
  # Add team citations
835
923
  if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
836
- md_content = "\n".join(
924
+ md_lines = []
925
+
926
+ # Add search queries if present
927
+ if resp.citations.search_queries:
928
+ md_lines.append("**Search Queries:**")
929
+ for query in resp.citations.search_queries:
930
+ md_lines.append(f"- {query}")
931
+ md_lines.append("") # Empty line before URLs
932
+
933
+ # Add URL citations
934
+ md_lines.extend(
837
935
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
838
936
  for i, citation in enumerate(resp.citations.urls)
839
937
  if citation.url # Only include citations with valid URLs
840
938
  )
939
+
940
+ md_content = "\n".join(md_lines)
841
941
  if md_content: # Only create panel if there are citations
842
942
  citations_panel = create_panel(
843
943
  content=Markdown(md_content),
@@ -857,10 +957,12 @@ async def aprint_response(
857
957
  show_message: bool = True,
858
958
  show_reasoning: bool = True,
859
959
  show_full_reasoning: bool = False,
960
+ show_member_responses: Optional[bool] = None,
860
961
  tags_to_include_in_markdown: Optional[Set[str]] = None,
861
962
  session_id: Optional[str] = None,
862
963
  session_state: Optional[Dict[str, Any]] = None,
863
964
  user_id: Optional[str] = None,
965
+ run_id: Optional[str] = None,
864
966
  audio: Optional[Sequence[Audio]] = None,
865
967
  images: Optional[Sequence[Image]] = None,
866
968
  videos: Optional[Sequence[Video]] = None,
@@ -912,11 +1014,13 @@ async def aprint_response(
912
1014
  # Run the agent
913
1015
  run_response: TeamRunOutput = await team.arun( # type: ignore
914
1016
  input=input,
1017
+ run_id=run_id,
915
1018
  images=images,
916
1019
  audio=audio,
917
1020
  videos=videos,
918
1021
  files=files,
919
1022
  stream=False,
1023
+ stream_events=True,
920
1024
  session_id=session_id,
921
1025
  session_state=session_state,
922
1026
  user_id=user_id,
@@ -984,7 +1088,7 @@ async def aprint_response(
984
1088
 
985
1089
  if isinstance(run_response, TeamRunOutput):
986
1090
  # Handle member responses
987
- if team.show_members_responses:
1091
+ if show_member_responses:
988
1092
  for member_response in run_response.member_responses:
989
1093
  # Handle member reasoning
990
1094
  reasoning_steps = []
@@ -1057,11 +1161,23 @@ async def aprint_response(
1057
1161
  panels.append(member_response_panel)
1058
1162
 
1059
1163
  if member_response.citations is not None and member_response.citations.urls is not None:
1060
- md_content = "\n".join(
1164
+ md_lines = []
1165
+
1166
+ # Add search queries if present
1167
+ if member_response.citations.search_queries:
1168
+ md_lines.append("**Search Queries:**")
1169
+ for query in member_response.citations.search_queries:
1170
+ md_lines.append(f"- {query}")
1171
+ md_lines.append("") # Empty line before URLs
1172
+
1173
+ # Add URL citations
1174
+ md_lines.extend(
1061
1175
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
1062
1176
  for i, citation in enumerate(member_response.citations.urls)
1063
1177
  if citation.url # Only include citations with valid URLs
1064
1178
  )
1179
+
1180
+ md_content = "\n".join(md_lines)
1065
1181
  if md_content:
1066
1182
  citations_panel = create_panel(
1067
1183
  content=Markdown(md_content),
@@ -1088,6 +1204,15 @@ async def aprint_response(
1088
1204
 
1089
1205
  tool_calls_text = "\n\n".join(lines)
1090
1206
 
1207
+ # Add compression stats at end of tool calls
1208
+ if team.compression_manager is not None and team.compression_manager.stats:
1209
+ stats = team.compression_manager.stats
1210
+ saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
1211
+ orig = stats.get("original_size", 1)
1212
+ if stats.get("tool_results_compressed", 0) > 0:
1213
+ tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
1214
+ team.compression_manager.stats.clear()
1215
+
1091
1216
  team_tool_calls_panel = create_panel(
1092
1217
  content=tool_calls_text,
1093
1218
  title="Team Tool Calls",
@@ -1110,11 +1235,23 @@ async def aprint_response(
1110
1235
 
1111
1236
  # Add citations
1112
1237
  if run_response.citations is not None and run_response.citations.urls is not None:
1113
- md_content = "\n".join(
1238
+ md_lines = []
1239
+
1240
+ # Add search queries if present
1241
+ if run_response.citations.search_queries:
1242
+ md_lines.append("**Search Queries:**")
1243
+ for query in run_response.citations.search_queries:
1244
+ md_lines.append(f"- {query}")
1245
+ md_lines.append("") # Empty line before URLs
1246
+
1247
+ # Add URL citations
1248
+ md_lines.extend(
1114
1249
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
1115
1250
  for i, citation in enumerate(run_response.citations.urls)
1116
1251
  if citation.url # Only include citations with valid URLs
1117
1252
  )
1253
+
1254
+ md_content = "\n".join(md_lines)
1118
1255
  if md_content: # Only create panel if there are citations
1119
1256
  citations_panel = create_panel(
1120
1257
  content=Markdown(md_content),
@@ -1153,17 +1290,18 @@ async def aprint_response_stream(
1153
1290
  show_message: bool = True,
1154
1291
  show_reasoning: bool = True,
1155
1292
  show_full_reasoning: bool = False,
1293
+ show_member_responses: Optional[bool] = None,
1156
1294
  tags_to_include_in_markdown: Optional[Set[str]] = None,
1157
1295
  session_id: Optional[str] = None,
1158
1296
  session_state: Optional[Dict[str, Any]] = None,
1159
1297
  user_id: Optional[str] = None,
1298
+ run_id: Optional[str] = None,
1160
1299
  audio: Optional[Sequence[Audio]] = None,
1161
1300
  images: Optional[Sequence[Image]] = None,
1162
1301
  videos: Optional[Sequence[Video]] = None,
1163
1302
  files: Optional[Sequence[File]] = None,
1164
1303
  markdown: bool = False,
1165
1304
  stream_events: bool = False,
1166
- stream_intermediate_steps: bool = False, # type: ignore
1167
1305
  knowledge_filters: Optional[Union[Dict[str, Any], List[FilterExpr]]] = None,
1168
1306
  add_history_to_context: Optional[bool] = None,
1169
1307
  dependencies: Optional[Dict[str, Any]] = None,
@@ -1245,6 +1383,7 @@ async def aprint_response_stream(
1245
1383
  session_id=session_id,
1246
1384
  session_state=session_state,
1247
1385
  user_id=user_id,
1386
+ run_id=run_id,
1248
1387
  knowledge_filters=knowledge_filters,
1249
1388
  add_history_to_context=add_history_to_context,
1250
1389
  add_dependencies_to_context=add_dependencies_to_context,
@@ -1252,7 +1391,7 @@ async def aprint_response_stream(
1252
1391
  dependencies=dependencies,
1253
1392
  metadata=metadata,
1254
1393
  debug_mode=debug_mode,
1255
- yield_run_response=True,
1394
+ yield_run_output=True,
1256
1395
  **kwargs,
1257
1396
  ):
1258
1397
  if team_markdown is None:
@@ -1277,6 +1416,11 @@ async def aprint_response_stream(
1277
1416
  _response_content = JSON(resp.content.model_dump_json(exclude_none=True), indent=2) # type: ignore
1278
1417
  except Exception as e:
1279
1418
  log_warning(f"Failed to convert response to JSON: {e}")
1419
+ elif team.output_schema is not None and isinstance(resp.content, dict):
1420
+ try:
1421
+ _response_content = JSON(json.dumps(resp.content), indent=2) # type: ignore
1422
+ except Exception as e:
1423
+ log_warning(f"Failed to convert response to JSON: {e}")
1280
1424
  if hasattr(resp, "reasoning_content") and resp.reasoning_content is not None: # type: ignore
1281
1425
  _response_reasoning_content += resp.reasoning_content # type: ignore
1282
1426
  if hasattr(resp, "reasoning_steps") and resp.reasoning_steps is not None: # type: ignore
@@ -1299,7 +1443,7 @@ async def aprint_response_stream(
1299
1443
  team_tool_calls.append(tool)
1300
1444
 
1301
1445
  # Collect member tool calls, avoiding duplicates
1302
- if hasattr(resp, "member_responses") and resp.member_responses:
1446
+ if show_member_responses and hasattr(resp, "member_responses") and resp.member_responses:
1303
1447
  for member_response in resp.member_responses:
1304
1448
  member_id = None
1305
1449
  if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
@@ -1360,7 +1504,9 @@ async def aprint_response_stream(
1360
1504
  panels.append(status)
1361
1505
 
1362
1506
  # Process member responses and their tool calls
1363
- for member_response in resp.member_responses if hasattr(resp, "member_responses") else []:
1507
+ for member_response in (
1508
+ resp.member_responses if show_member_responses and hasattr(resp, "member_responses") else []
1509
+ ):
1364
1510
  member_id = None
1365
1511
  member_name = "Team Member"
1366
1512
  if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
@@ -1393,7 +1539,7 @@ async def aprint_response_stream(
1393
1539
  panels.append(member_tool_calls_panel)
1394
1540
 
1395
1541
  # Process member response content
1396
- if team.show_members_responses and member_id is not None:
1542
+ if show_member_responses and member_id is not None:
1397
1543
  show_markdown = False
1398
1544
  if markdown:
1399
1545
  show_markdown = True
@@ -1436,6 +1582,14 @@ async def aprint_response_stream(
1436
1582
  # Join with blank lines between items
1437
1583
  tool_calls_text = "\n\n".join(lines)
1438
1584
 
1585
+ # Add compression stats if available (don't clear - will be cleared in final_panels)
1586
+ if team.compression_manager is not None and team.compression_manager.stats:
1587
+ stats = team.compression_manager.stats
1588
+ saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
1589
+ orig = stats.get("original_size", 1)
1590
+ if stats.get("tool_results_compressed", 0) > 0:
1591
+ tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
1592
+
1439
1593
  team_tool_calls_panel = create_panel(
1440
1594
  content=tool_calls_text,
1441
1595
  title="Team Tool Calls",
@@ -1463,11 +1617,23 @@ async def aprint_response_stream(
1463
1617
 
1464
1618
  # Add citations
1465
1619
  if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
1466
- md_content = "\n".join(
1620
+ md_lines = []
1621
+
1622
+ # Add search queries if present
1623
+ if resp.citations.search_queries:
1624
+ md_lines.append("**Search Queries:**")
1625
+ for query in resp.citations.search_queries:
1626
+ md_lines.append(f"- {query}")
1627
+ md_lines.append("") # Empty line before URLs
1628
+
1629
+ # Add URL citations
1630
+ md_lines.extend(
1467
1631
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
1468
1632
  for i, citation in enumerate(resp.citations.urls)
1469
1633
  if citation.url # Only include citations with valid URLs
1470
1634
  )
1635
+
1636
+ md_content = "\n".join(md_lines)
1471
1637
  if md_content: # Only create panel if there are citations
1472
1638
  citations_panel = create_panel(
1473
1639
  content=Markdown(md_content),
@@ -1537,7 +1703,7 @@ async def aprint_response_stream(
1537
1703
  final_panels.append(thinking_panel)
1538
1704
 
1539
1705
  # Add member tool calls and responses in correct order
1540
- if run_response is not None and hasattr(run_response, "member_responses"):
1706
+ if show_member_responses and run_response is not None and hasattr(run_response, "member_responses"):
1541
1707
  for i, member_response in enumerate(run_response.member_responses):
1542
1708
  member_id = None
1543
1709
  if isinstance(member_response, RunOutput) and member_response.agent_id is not None:
@@ -1624,11 +1790,23 @@ async def aprint_response_stream(
1624
1790
 
1625
1791
  # Add citations if any
1626
1792
  if member_response.citations is not None and member_response.citations.urls is not None:
1627
- md_content = "\n".join(
1793
+ md_lines = []
1794
+
1795
+ # Add search queries if present
1796
+ if member_response.citations.search_queries:
1797
+ md_lines.append("**Search Queries:**")
1798
+ for query in member_response.citations.search_queries:
1799
+ md_lines.append(f"- {query}")
1800
+ md_lines.append("") # Empty line before URLs
1801
+
1802
+ # Add URL citations
1803
+ md_lines.extend(
1628
1804
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
1629
1805
  for i, citation in enumerate(member_response.citations.urls)
1630
1806
  if citation.url # Only include citations with valid URLs
1631
1807
  )
1808
+
1809
+ md_content = "\n".join(md_lines)
1632
1810
  if md_content: # Only create panel if there are citations
1633
1811
  citations_panel = create_panel(
1634
1812
  content=Markdown(md_content),
@@ -1656,6 +1834,15 @@ async def aprint_response_stream(
1656
1834
 
1657
1835
  tool_calls_text = "\n\n".join(lines)
1658
1836
 
1837
+ # Add compression stats at end of tool calls
1838
+ if team.compression_manager is not None and team.compression_manager.stats:
1839
+ stats = team.compression_manager.stats
1840
+ saved = stats.get("original_size", 0) - stats.get("compressed_size", 0)
1841
+ orig = stats.get("original_size", 1)
1842
+ if stats.get("tool_results_compressed", 0) > 0:
1843
+ tool_calls_text += f"\n\ncompressed: {stats.get('tool_results_compressed', 0)} | Saved: {saved:,} chars ({saved / orig * 100:.0f}%)"
1844
+ team.compression_manager.stats.clear()
1845
+
1659
1846
  team_tool_calls_panel = create_panel(
1660
1847
  content=tool_calls_text,
1661
1848
  title="Team Tool Calls",
@@ -1679,11 +1866,23 @@ async def aprint_response_stream(
1679
1866
 
1680
1867
  # Add team citations
1681
1868
  if hasattr(resp, "citations") and resp.citations is not None and resp.citations.urls is not None:
1682
- md_content = "\n".join(
1869
+ md_lines = []
1870
+
1871
+ # Add search queries if present
1872
+ if resp.citations.search_queries:
1873
+ md_lines.append("**Search Queries:**")
1874
+ for query in resp.citations.search_queries:
1875
+ md_lines.append(f"- {query}")
1876
+ md_lines.append("") # Empty line before URLs
1877
+
1878
+ # Add URL citations
1879
+ md_lines.extend(
1683
1880
  f"{i + 1}. [{citation.title or citation.url}]({citation.url})"
1684
1881
  for i, citation in enumerate(resp.citations.urls)
1685
1882
  if citation.url # Only include citations with valid URLs
1686
1883
  )
1884
+
1885
+ md_content = "\n".join(md_lines)
1687
1886
  if md_content: # Only create panel if there are citations
1688
1887
  citations_panel = create_panel(
1689
1888
  content=Markdown(md_content),
@@ -203,7 +203,6 @@ def print_response_stream(
203
203
  videos: Optional[List[Video]] = None,
204
204
  files: Optional[List[File]] = None,
205
205
  stream_events: bool = False,
206
- stream_intermediate_steps: bool = False,
207
206
  markdown: bool = True,
208
207
  show_time: bool = True,
209
208
  show_step_details: bool = True,
@@ -1042,7 +1041,6 @@ async def aprint_response_stream(
1042
1041
  videos: Optional[List[Video]] = None,
1043
1042
  files: Optional[List[File]] = None,
1044
1043
  stream_events: bool = False,
1045
- stream_intermediate_steps: bool = False,
1046
1044
  markdown: bool = True,
1047
1045
  show_time: bool = True,
1048
1046
  show_step_details: bool = True,
agno/utils/prompts.py CHANGED
@@ -6,7 +6,7 @@ from pydantic import BaseModel
6
6
  from agno.utils.log import log_warning
7
7
 
8
8
 
9
- def get_json_output_prompt(output_schema: Union[str, list, BaseModel]) -> str:
9
+ def get_json_output_prompt(output_schema: Union[str, list, dict, BaseModel]) -> str:
10
10
  """Return the JSON output prompt for the Agent.
11
11
 
12
12
  This is added to the system prompt when the output_schema is set and structured_outputs is False.
@@ -22,11 +22,13 @@ def get_json_output_prompt(output_schema: Union[str, list, BaseModel]) -> str:
22
22
  json_output_prompt += "\n<json_fields>"
23
23
  json_output_prompt += f"\n{json.dumps(output_schema)}"
24
24
  json_output_prompt += "\n</json_fields>"
25
- elif (
26
- issubclass(type(output_schema), BaseModel)
27
- or issubclass(output_schema, BaseModel) # type: ignore
28
- or isinstance(output_schema, BaseModel)
29
- ): # type: ignore
25
+ elif isinstance(output_schema, dict):
26
+ json_output_prompt += "\n<json_fields>"
27
+ json_output_prompt += f"\n{json.dumps(output_schema)}"
28
+ json_output_prompt += "\n</json_fields>"
29
+ elif (isinstance(output_schema, type) and issubclass(output_schema, BaseModel)) or isinstance(
30
+ output_schema, BaseModel
31
+ ):
30
32
  json_schema = output_schema.model_json_schema()
31
33
  if json_schema is not None:
32
34
  response_model_properties = {}
agno/utils/remote.py ADDED
@@ -0,0 +1,23 @@
1
+ import json
2
+ from typing import Any, Dict, List, Union
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from agno.models.message import Message
7
+
8
+
9
+ def serialize_input(
10
+ input: Union[str, Dict[str, Any], List[Any], BaseModel, List[Message]],
11
+ ) -> str:
12
+ """Serialize the input to a string."""
13
+ if isinstance(input, str):
14
+ return input
15
+ elif isinstance(input, dict):
16
+ return json.dumps(input)
17
+ elif isinstance(input, list):
18
+ if any(isinstance(item, Message) for item in input):
19
+ return json.dumps([item.to_dict() for item in input])
20
+ else:
21
+ return json.dumps(input)
22
+ elif isinstance(input, BaseModel):
23
+ return input.model_dump_json()
agno/utils/response.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import AsyncIterator, Iterator, List, Set, Union
1
+ from typing import List, Set, Union
2
2
 
3
3
  from agno.exceptions import RunCancelledException
4
4
  from agno.models.response import ToolExecution
@@ -149,15 +149,3 @@ def get_paused_content(run_output: RunOutput) -> str:
149
149
  elif external_execution_required:
150
150
  paused_content = "I have tools to execute, but it needs external execution."
151
151
  return paused_content
152
-
153
-
154
- def generator_wrapper(
155
- event: Union[RunOutputEvent, TeamRunOutputEvent],
156
- ) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
157
- yield event
158
-
159
-
160
- async def async_generator_wrapper(
161
- event: Union[RunOutputEvent, TeamRunOutputEvent],
162
- ) -> AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
163
- yield event