agno 2.1.2__py3-none-any.whl → 2.3.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. agno/agent/agent.py +5540 -2273
  2. agno/api/api.py +2 -0
  3. agno/api/os.py +1 -1
  4. agno/compression/__init__.py +3 -0
  5. agno/compression/manager.py +247 -0
  6. agno/culture/__init__.py +3 -0
  7. agno/culture/manager.py +956 -0
  8. agno/db/async_postgres/__init__.py +3 -0
  9. agno/db/base.py +689 -6
  10. agno/db/dynamo/dynamo.py +933 -37
  11. agno/db/dynamo/schemas.py +174 -10
  12. agno/db/dynamo/utils.py +63 -4
  13. agno/db/firestore/firestore.py +831 -9
  14. agno/db/firestore/schemas.py +51 -0
  15. agno/db/firestore/utils.py +102 -4
  16. agno/db/gcs_json/gcs_json_db.py +660 -12
  17. agno/db/gcs_json/utils.py +60 -26
  18. agno/db/in_memory/in_memory_db.py +287 -14
  19. agno/db/in_memory/utils.py +60 -2
  20. agno/db/json/json_db.py +590 -14
  21. agno/db/json/utils.py +60 -26
  22. agno/db/migrations/manager.py +199 -0
  23. agno/db/migrations/v1_to_v2.py +43 -13
  24. agno/db/migrations/versions/__init__.py +0 -0
  25. agno/db/migrations/versions/v2_3_0.py +938 -0
  26. agno/db/mongo/__init__.py +15 -1
  27. agno/db/mongo/async_mongo.py +2760 -0
  28. agno/db/mongo/mongo.py +879 -11
  29. agno/db/mongo/schemas.py +42 -0
  30. agno/db/mongo/utils.py +80 -8
  31. agno/db/mysql/__init__.py +2 -1
  32. agno/db/mysql/async_mysql.py +2912 -0
  33. agno/db/mysql/mysql.py +946 -68
  34. agno/db/mysql/schemas.py +72 -10
  35. agno/db/mysql/utils.py +198 -7
  36. agno/db/postgres/__init__.py +2 -1
  37. agno/db/postgres/async_postgres.py +2579 -0
  38. agno/db/postgres/postgres.py +942 -57
  39. agno/db/postgres/schemas.py +81 -18
  40. agno/db/postgres/utils.py +164 -2
  41. agno/db/redis/redis.py +671 -7
  42. agno/db/redis/schemas.py +50 -0
  43. agno/db/redis/utils.py +65 -7
  44. agno/db/schemas/__init__.py +2 -1
  45. agno/db/schemas/culture.py +120 -0
  46. agno/db/schemas/evals.py +1 -0
  47. agno/db/schemas/memory.py +17 -2
  48. agno/db/singlestore/schemas.py +63 -0
  49. agno/db/singlestore/singlestore.py +949 -83
  50. agno/db/singlestore/utils.py +60 -2
  51. agno/db/sqlite/__init__.py +2 -1
  52. agno/db/sqlite/async_sqlite.py +2911 -0
  53. agno/db/sqlite/schemas.py +62 -0
  54. agno/db/sqlite/sqlite.py +965 -46
  55. agno/db/sqlite/utils.py +169 -8
  56. agno/db/surrealdb/__init__.py +3 -0
  57. agno/db/surrealdb/metrics.py +292 -0
  58. agno/db/surrealdb/models.py +334 -0
  59. agno/db/surrealdb/queries.py +71 -0
  60. agno/db/surrealdb/surrealdb.py +1908 -0
  61. agno/db/surrealdb/utils.py +147 -0
  62. agno/db/utils.py +2 -0
  63. agno/eval/__init__.py +10 -0
  64. agno/eval/accuracy.py +75 -55
  65. agno/eval/agent_as_judge.py +861 -0
  66. agno/eval/base.py +29 -0
  67. agno/eval/performance.py +16 -7
  68. agno/eval/reliability.py +28 -16
  69. agno/eval/utils.py +35 -17
  70. agno/exceptions.py +27 -2
  71. agno/filters.py +354 -0
  72. agno/guardrails/prompt_injection.py +1 -0
  73. agno/hooks/__init__.py +3 -0
  74. agno/hooks/decorator.py +164 -0
  75. agno/integrations/discord/client.py +1 -1
  76. agno/knowledge/chunking/agentic.py +13 -10
  77. agno/knowledge/chunking/fixed.py +4 -1
  78. agno/knowledge/chunking/semantic.py +9 -4
  79. agno/knowledge/chunking/strategy.py +59 -15
  80. agno/knowledge/embedder/fastembed.py +1 -1
  81. agno/knowledge/embedder/nebius.py +1 -1
  82. agno/knowledge/embedder/ollama.py +8 -0
  83. agno/knowledge/embedder/openai.py +8 -8
  84. agno/knowledge/embedder/sentence_transformer.py +6 -2
  85. agno/knowledge/embedder/vllm.py +262 -0
  86. agno/knowledge/knowledge.py +1618 -318
  87. agno/knowledge/reader/base.py +6 -2
  88. agno/knowledge/reader/csv_reader.py +8 -10
  89. agno/knowledge/reader/docx_reader.py +5 -6
  90. agno/knowledge/reader/field_labeled_csv_reader.py +16 -20
  91. agno/knowledge/reader/json_reader.py +5 -4
  92. agno/knowledge/reader/markdown_reader.py +8 -8
  93. agno/knowledge/reader/pdf_reader.py +17 -19
  94. agno/knowledge/reader/pptx_reader.py +101 -0
  95. agno/knowledge/reader/reader_factory.py +32 -3
  96. agno/knowledge/reader/s3_reader.py +3 -3
  97. agno/knowledge/reader/tavily_reader.py +193 -0
  98. agno/knowledge/reader/text_reader.py +22 -10
  99. agno/knowledge/reader/web_search_reader.py +1 -48
  100. agno/knowledge/reader/website_reader.py +10 -10
  101. agno/knowledge/reader/wikipedia_reader.py +33 -1
  102. agno/knowledge/types.py +1 -0
  103. agno/knowledge/utils.py +72 -7
  104. agno/media.py +22 -6
  105. agno/memory/__init__.py +14 -1
  106. agno/memory/manager.py +544 -83
  107. agno/memory/strategies/__init__.py +15 -0
  108. agno/memory/strategies/base.py +66 -0
  109. agno/memory/strategies/summarize.py +196 -0
  110. agno/memory/strategies/types.py +37 -0
  111. agno/models/aimlapi/aimlapi.py +17 -0
  112. agno/models/anthropic/claude.py +515 -40
  113. agno/models/aws/bedrock.py +102 -21
  114. agno/models/aws/claude.py +131 -274
  115. agno/models/azure/ai_foundry.py +41 -19
  116. agno/models/azure/openai_chat.py +39 -8
  117. agno/models/base.py +1249 -525
  118. agno/models/cerebras/cerebras.py +91 -21
  119. agno/models/cerebras/cerebras_openai.py +21 -2
  120. agno/models/cohere/chat.py +40 -6
  121. agno/models/cometapi/cometapi.py +18 -1
  122. agno/models/dashscope/dashscope.py +2 -3
  123. agno/models/deepinfra/deepinfra.py +18 -1
  124. agno/models/deepseek/deepseek.py +69 -3
  125. agno/models/fireworks/fireworks.py +18 -1
  126. agno/models/google/gemini.py +877 -80
  127. agno/models/google/utils.py +22 -0
  128. agno/models/groq/groq.py +51 -18
  129. agno/models/huggingface/huggingface.py +17 -6
  130. agno/models/ibm/watsonx.py +16 -6
  131. agno/models/internlm/internlm.py +18 -1
  132. agno/models/langdb/langdb.py +13 -1
  133. agno/models/litellm/chat.py +44 -9
  134. agno/models/litellm/litellm_openai.py +18 -1
  135. agno/models/message.py +28 -5
  136. agno/models/meta/llama.py +47 -14
  137. agno/models/meta/llama_openai.py +22 -17
  138. agno/models/mistral/mistral.py +8 -4
  139. agno/models/nebius/nebius.py +6 -7
  140. agno/models/nvidia/nvidia.py +20 -3
  141. agno/models/ollama/chat.py +24 -8
  142. agno/models/openai/chat.py +104 -29
  143. agno/models/openai/responses.py +101 -81
  144. agno/models/openrouter/openrouter.py +60 -3
  145. agno/models/perplexity/perplexity.py +17 -1
  146. agno/models/portkey/portkey.py +7 -6
  147. agno/models/requesty/requesty.py +24 -4
  148. agno/models/response.py +73 -2
  149. agno/models/sambanova/sambanova.py +20 -3
  150. agno/models/siliconflow/siliconflow.py +19 -2
  151. agno/models/together/together.py +20 -3
  152. agno/models/utils.py +254 -8
  153. agno/models/vercel/v0.py +20 -3
  154. agno/models/vertexai/__init__.py +0 -0
  155. agno/models/vertexai/claude.py +190 -0
  156. agno/models/vllm/vllm.py +19 -14
  157. agno/models/xai/xai.py +19 -2
  158. agno/os/app.py +549 -152
  159. agno/os/auth.py +190 -3
  160. agno/os/config.py +23 -0
  161. agno/os/interfaces/a2a/router.py +8 -11
  162. agno/os/interfaces/a2a/utils.py +1 -1
  163. agno/os/interfaces/agui/router.py +18 -3
  164. agno/os/interfaces/agui/utils.py +152 -39
  165. agno/os/interfaces/slack/router.py +55 -37
  166. agno/os/interfaces/slack/slack.py +9 -1
  167. agno/os/interfaces/whatsapp/router.py +0 -1
  168. agno/os/interfaces/whatsapp/security.py +3 -1
  169. agno/os/mcp.py +110 -52
  170. agno/os/middleware/__init__.py +2 -0
  171. agno/os/middleware/jwt.py +676 -112
  172. agno/os/router.py +40 -1478
  173. agno/os/routers/agents/__init__.py +3 -0
  174. agno/os/routers/agents/router.py +599 -0
  175. agno/os/routers/agents/schema.py +261 -0
  176. agno/os/routers/evals/evals.py +96 -39
  177. agno/os/routers/evals/schemas.py +65 -33
  178. agno/os/routers/evals/utils.py +80 -10
  179. agno/os/routers/health.py +10 -4
  180. agno/os/routers/knowledge/knowledge.py +196 -38
  181. agno/os/routers/knowledge/schemas.py +82 -22
  182. agno/os/routers/memory/memory.py +279 -52
  183. agno/os/routers/memory/schemas.py +46 -17
  184. agno/os/routers/metrics/metrics.py +20 -8
  185. agno/os/routers/metrics/schemas.py +16 -16
  186. agno/os/routers/session/session.py +462 -34
  187. agno/os/routers/teams/__init__.py +3 -0
  188. agno/os/routers/teams/router.py +512 -0
  189. agno/os/routers/teams/schema.py +257 -0
  190. agno/os/routers/traces/__init__.py +3 -0
  191. agno/os/routers/traces/schemas.py +414 -0
  192. agno/os/routers/traces/traces.py +499 -0
  193. agno/os/routers/workflows/__init__.py +3 -0
  194. agno/os/routers/workflows/router.py +624 -0
  195. agno/os/routers/workflows/schema.py +75 -0
  196. agno/os/schema.py +256 -693
  197. agno/os/scopes.py +469 -0
  198. agno/os/utils.py +514 -36
  199. agno/reasoning/anthropic.py +80 -0
  200. agno/reasoning/gemini.py +73 -0
  201. agno/reasoning/openai.py +5 -0
  202. agno/reasoning/vertexai.py +76 -0
  203. agno/run/__init__.py +6 -0
  204. agno/run/agent.py +155 -32
  205. agno/run/base.py +55 -3
  206. agno/run/requirement.py +181 -0
  207. agno/run/team.py +125 -38
  208. agno/run/workflow.py +72 -18
  209. agno/session/agent.py +102 -89
  210. agno/session/summary.py +56 -15
  211. agno/session/team.py +164 -90
  212. agno/session/workflow.py +405 -40
  213. agno/table.py +10 -0
  214. agno/team/team.py +3974 -1903
  215. agno/tools/dalle.py +2 -4
  216. agno/tools/eleven_labs.py +23 -25
  217. agno/tools/exa.py +21 -16
  218. agno/tools/file.py +153 -23
  219. agno/tools/file_generation.py +16 -10
  220. agno/tools/firecrawl.py +15 -7
  221. agno/tools/function.py +193 -38
  222. agno/tools/gmail.py +238 -14
  223. agno/tools/google_drive.py +271 -0
  224. agno/tools/googlecalendar.py +36 -8
  225. agno/tools/googlesheets.py +20 -5
  226. agno/tools/jira.py +20 -0
  227. agno/tools/mcp/__init__.py +10 -0
  228. agno/tools/mcp/mcp.py +331 -0
  229. agno/tools/mcp/multi_mcp.py +347 -0
  230. agno/tools/mcp/params.py +24 -0
  231. agno/tools/mcp_toolbox.py +3 -3
  232. agno/tools/models/nebius.py +5 -5
  233. agno/tools/models_labs.py +20 -10
  234. agno/tools/nano_banana.py +151 -0
  235. agno/tools/notion.py +204 -0
  236. agno/tools/parallel.py +314 -0
  237. agno/tools/postgres.py +76 -36
  238. agno/tools/redshift.py +406 -0
  239. agno/tools/scrapegraph.py +1 -1
  240. agno/tools/shopify.py +1519 -0
  241. agno/tools/slack.py +18 -3
  242. agno/tools/spotify.py +919 -0
  243. agno/tools/tavily.py +146 -0
  244. agno/tools/toolkit.py +25 -0
  245. agno/tools/workflow.py +8 -1
  246. agno/tools/yfinance.py +12 -11
  247. agno/tracing/__init__.py +12 -0
  248. agno/tracing/exporter.py +157 -0
  249. agno/tracing/schemas.py +276 -0
  250. agno/tracing/setup.py +111 -0
  251. agno/utils/agent.py +938 -0
  252. agno/utils/cryptography.py +22 -0
  253. agno/utils/dttm.py +33 -0
  254. agno/utils/events.py +151 -3
  255. agno/utils/gemini.py +15 -5
  256. agno/utils/hooks.py +118 -4
  257. agno/utils/http.py +113 -2
  258. agno/utils/knowledge.py +12 -5
  259. agno/utils/log.py +1 -0
  260. agno/utils/mcp.py +92 -2
  261. agno/utils/media.py +187 -1
  262. agno/utils/merge_dict.py +3 -3
  263. agno/utils/message.py +60 -0
  264. agno/utils/models/ai_foundry.py +9 -2
  265. agno/utils/models/claude.py +49 -14
  266. agno/utils/models/cohere.py +9 -2
  267. agno/utils/models/llama.py +9 -2
  268. agno/utils/models/mistral.py +4 -2
  269. agno/utils/print_response/agent.py +109 -16
  270. agno/utils/print_response/team.py +223 -30
  271. agno/utils/print_response/workflow.py +251 -34
  272. agno/utils/streamlit.py +1 -1
  273. agno/utils/team.py +98 -9
  274. agno/utils/tokens.py +657 -0
  275. agno/vectordb/base.py +39 -7
  276. agno/vectordb/cassandra/cassandra.py +21 -5
  277. agno/vectordb/chroma/chromadb.py +43 -12
  278. agno/vectordb/clickhouse/clickhousedb.py +21 -5
  279. agno/vectordb/couchbase/couchbase.py +29 -5
  280. agno/vectordb/lancedb/lance_db.py +92 -181
  281. agno/vectordb/langchaindb/langchaindb.py +24 -4
  282. agno/vectordb/lightrag/lightrag.py +17 -3
  283. agno/vectordb/llamaindex/llamaindexdb.py +25 -5
  284. agno/vectordb/milvus/milvus.py +50 -37
  285. agno/vectordb/mongodb/__init__.py +7 -1
  286. agno/vectordb/mongodb/mongodb.py +36 -30
  287. agno/vectordb/pgvector/pgvector.py +201 -77
  288. agno/vectordb/pineconedb/pineconedb.py +41 -23
  289. agno/vectordb/qdrant/qdrant.py +67 -54
  290. agno/vectordb/redis/__init__.py +9 -0
  291. agno/vectordb/redis/redisdb.py +682 -0
  292. agno/vectordb/singlestore/singlestore.py +50 -29
  293. agno/vectordb/surrealdb/surrealdb.py +31 -41
  294. agno/vectordb/upstashdb/upstashdb.py +34 -6
  295. agno/vectordb/weaviate/weaviate.py +53 -14
  296. agno/workflow/__init__.py +2 -0
  297. agno/workflow/agent.py +299 -0
  298. agno/workflow/condition.py +120 -18
  299. agno/workflow/loop.py +77 -10
  300. agno/workflow/parallel.py +231 -143
  301. agno/workflow/router.py +118 -17
  302. agno/workflow/step.py +609 -170
  303. agno/workflow/steps.py +73 -6
  304. agno/workflow/types.py +96 -21
  305. agno/workflow/workflow.py +2039 -262
  306. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/METADATA +201 -66
  307. agno-2.3.13.dist-info/RECORD +613 -0
  308. agno/tools/googlesearch.py +0 -98
  309. agno/tools/mcp.py +0 -679
  310. agno/tools/memori.py +0 -339
  311. agno-2.1.2.dist-info/RECORD +0 -543
  312. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +0 -0
  313. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/licenses/LICENSE +0 -0
  314. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/session/team.py CHANGED
@@ -1,7 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import asdict, dataclass
4
- from typing import Any, Dict, List, Mapping, Optional, Union
4
+ from typing import Any, Dict, List, Mapping, Optional, Tuple, Union
5
+
6
+ from pydantic import BaseModel
5
7
 
6
8
  from agno.models.message import Message
7
9
  from agno.run.agent import RunOutput, RunStatus
@@ -111,77 +113,136 @@ class TeamSession:
111
113
 
112
114
  log_debug("Added RunOutput to Team Session")
113
115
 
114
- def get_messages_from_last_n_runs(
116
+ def get_messages(
115
117
  self,
116
- agent_id: Optional[str] = None,
117
118
  team_id: Optional[str] = None,
118
- last_n: Optional[int] = None,
119
- skip_role: Optional[str] = None,
120
- skip_status: Optional[List[RunStatus]] = None,
119
+ member_ids: Optional[List[str]] = None,
120
+ last_n_runs: Optional[int] = None,
121
+ limit: Optional[int] = None,
122
+ skip_roles: Optional[List[str]] = None,
123
+ skip_statuses: Optional[List[RunStatus]] = None,
121
124
  skip_history_messages: bool = True,
122
- member_runs: bool = False,
125
+ skip_member_messages: bool = True,
123
126
  ) -> List[Message]:
124
- """Returns the messages from the last_n runs, excluding previously tagged history messages.
125
- Args:
127
+ """Returns the messages belonging to the session that fit the given criteria.
126
128
 
127
- agent_id: The id of the agent to get the messages from.
129
+ Args:
128
130
  team_id: The id of the team to get the messages from.
129
- last_n: The number of runs to return from the end of the conversation. Defaults to all runs.
130
- skip_role: Skip messages with this role.
131
- skip_status: Skip messages with this status.
131
+ member_ids: The ids of the members to get the messages from.
132
+ last_n_runs: The number of runs to return messages from, counting from the latest. Defaults to all runs.
133
+ limit: The number of messages to return, counting from the latest. Defaults to all messages.
134
+ skip_roles: Skip messages with these roles.
135
+ skip_statuses: Skip messages with these statuses.
132
136
  skip_history_messages: Skip messages that were tagged as history in previous runs.
137
+ skip_member_messages: Skip messages created by members of the team.
138
+
133
139
  Returns:
134
- A list of Messages from the specified runs, excluding history messages.
140
+ A list of Messages belonging to the session.
135
141
  """
142
+
143
+ def _should_skip_message(
144
+ message: Message, skip_roles: Optional[List[str]] = None, skip_history_messages: bool = True
145
+ ) -> bool:
146
+ """Processes a message for history"""
147
+ # Skip messages that were tagged as history in previous runs
148
+ if hasattr(message, "from_history") and message.from_history and skip_history_messages:
149
+ return True
150
+
151
+ # Skip messages with specified role
152
+ if skip_roles and message.role in skip_roles:
153
+ return True
154
+ return False
155
+
156
+ if member_ids is not None and skip_member_messages:
157
+ log_debug("Member IDs to filter by were provided. The skip_member_messages flag will be ignored.")
158
+ skip_member_messages = False
159
+
136
160
  if not self.runs:
137
161
  return []
138
162
 
139
- if skip_status is None:
140
- skip_status = [RunStatus.paused, RunStatus.cancelled, RunStatus.error]
163
+ if skip_statuses is None:
164
+ skip_statuses = [RunStatus.paused, RunStatus.cancelled, RunStatus.error]
141
165
 
142
166
  session_runs = self.runs
143
167
 
144
- # Filter by agent_id and team_id
145
- if agent_id:
146
- session_runs = [run for run in session_runs if hasattr(run, "agent_id") and run.agent_id == agent_id] # type: ignore
168
+ # Filter by team_id and member_ids
147
169
  if team_id:
148
170
  session_runs = [run for run in session_runs if hasattr(run, "team_id") and run.team_id == team_id] # type: ignore
171
+ if member_ids:
172
+ session_runs = [run for run in session_runs if hasattr(run, "agent_id") and run.agent_id in member_ids] # type: ignore
149
173
 
150
- if not member_runs:
151
- # Filter for the main team runs
174
+ if skip_member_messages:
175
+ # Filter for the top-level runs (main team runs or agent runs when sharing session)
152
176
  session_runs = [run for run in session_runs if run.parent_run_id is None] # type: ignore
177
+
153
178
  # Filter by status
154
- session_runs = [run for run in session_runs if hasattr(run, "status") and run.status not in skip_status] # type: ignore
179
+ session_runs = [run for run in session_runs if hasattr(run, "status") and run.status not in skip_statuses] # type: ignore
155
180
 
156
- # Filter by last_n
157
- runs_to_process = session_runs[-last_n:] if last_n is not None else session_runs
158
181
  messages_from_history = []
159
182
  system_message = None
160
183
 
161
- for run_response in runs_to_process:
162
- if not (run_response and run_response.messages):
163
- continue
164
-
165
- for message in run_response.messages or []:
166
- # Skip messages that were tagged as history in previous runs
167
- if hasattr(message, "from_history") and message.from_history and skip_history_messages:
184
+ # Limit the number of messages returned if limit is set
185
+ if limit is not None:
186
+ for run_response in session_runs:
187
+ if not run_response or not run_response.messages:
168
188
  continue
169
189
 
170
- # Skip messages with specified role
171
- if skip_role and message.role == skip_role:
190
+ for message in run_response.messages or []:
191
+ if _should_skip_message(message, skip_roles, skip_history_messages):
192
+ continue
193
+
194
+ if message.role == "system":
195
+ # Only add the system message once
196
+ if system_message is None:
197
+ system_message = message
198
+ else:
199
+ messages_from_history.append(message)
200
+
201
+ if system_message:
202
+ messages_from_history = [system_message] + messages_from_history[
203
+ -(limit - 1) :
204
+ ] # Grab one less message then add the system message
205
+ else:
206
+ messages_from_history = messages_from_history[-limit:]
207
+
208
+ # Remove tool result messages that don't have an associated assistant message with tool calls
209
+ while len(messages_from_history) > 0 and messages_from_history[0].role == "tool":
210
+ messages_from_history.pop(0)
211
+ else:
212
+ # Filter by last_n runs
213
+ runs_to_process = session_runs[-last_n_runs:] if last_n_runs is not None else session_runs
214
+
215
+ for run_response in runs_to_process:
216
+ if not (run_response and run_response.messages):
172
217
  continue
173
218
 
174
- if message.role == "system":
175
- # Only add the system message once
176
- if system_message is None:
177
- system_message = message
178
- messages_from_history.append(system_message)
179
- else:
180
- messages_from_history.append(message)
219
+ for message in run_response.messages or []:
220
+ if _should_skip_message(message, skip_roles, skip_history_messages):
221
+ continue
222
+
223
+ if message.role == "system":
224
+ # Only add the system message once
225
+ if system_message is None:
226
+ system_message = message
227
+ messages_from_history.append(system_message)
228
+ else:
229
+ messages_from_history.append(message)
181
230
 
182
231
  log_debug(f"Getting messages from previous runs: {len(messages_from_history)}")
183
232
  return messages_from_history
184
233
 
234
+ def get_chat_history(self, last_n_runs: Optional[int] = None) -> List[Message]:
235
+ """Return the chat history (user and assistant messages) for the session.
236
+ Use get_messages() for more filtering options.
237
+
238
+ Args:
239
+ last_n_runs: Number of recent runs to include. If None, all runs will be considered.
240
+
241
+ Returns:
242
+ A list of user and assistant Messages belonging to the session.
243
+ """
244
+ return self.get_messages(skip_roles=["system", "tool"], skip_member_messages=True, last_n_runs=last_n_runs)
245
+
185
246
  def get_tool_calls(self, num_calls: Optional[int] = None) -> List[Dict[str, Any]]:
186
247
  """Returns a list of tool calls from the messages"""
187
248
 
@@ -200,69 +261,82 @@ class TeamSession:
200
261
  return tool_calls
201
262
  return tool_calls
202
263
 
203
- def get_messages_for_session(
204
- self,
205
- user_role: str = "user",
206
- assistant_role: Optional[List[str]] = None,
207
- skip_history_messages: bool = True,
208
- ) -> List[Message]:
209
- """Returns a list of messages for the session that iterate through user message and assistant response."""
264
+ def get_team_history(self, num_runs: Optional[int] = None) -> List[Tuple[str, str]]:
265
+ """Get team history as structured data (input, response pairs) -> This is the history of the team leader, not the members.
266
+
267
+ Args:
268
+ num_runs: Number of recent runs to include. If None, returns all available history.
269
+ """
270
+ if not self.runs:
271
+ return []
210
272
 
211
- if assistant_role is None:
212
- # TODO: Check if we still need CHATBOT as a role
213
- assistant_role = ["assistant", "model", "CHATBOT"]
273
+ from agno.run.base import RunStatus
214
274
 
215
- final_messages: List[Message] = []
216
- session_runs = self.runs
217
- if session_runs is None:
275
+ # Get completed runs only (exclude current/pending run)
276
+ completed_runs = [run for run in self.runs if run.status == RunStatus.completed and run.parent_run_id is None]
277
+
278
+ if num_runs is not None and len(completed_runs) > num_runs:
279
+ recent_runs = completed_runs[-num_runs:]
280
+ else:
281
+ recent_runs = completed_runs
282
+
283
+ if not recent_runs:
218
284
  return []
219
285
 
220
- for run_response in session_runs:
221
- if run_response and run_response.messages:
222
- user_message_from_run = None
223
- assistant_message_from_run = None
286
+ # Return structured data as list of (input, response) tuples
287
+ history_data = []
288
+ for run in recent_runs:
289
+ # Get input
290
+ input_str = ""
291
+ if run.input:
292
+ input_str = run.input.input_content_string()
224
293
 
225
- # Start from the beginning to look for the user message
226
- for message in run_response.messages or []:
227
- if hasattr(message, "from_history") and message.from_history and skip_history_messages:
228
- continue
229
- if message.role == user_role:
230
- user_message_from_run = message
231
- break
294
+ # Get response
295
+ response_str = ""
296
+ if run.content:
297
+ response_str = (
298
+ run.content.model_dump_json(indent=2, exclude_none=True)
299
+ if isinstance(run.content, BaseModel)
300
+ else str(run.content)
301
+ )
232
302
 
233
- # Start from the end to look for the assistant response
234
- for message in run_response.messages[::-1]:
235
- if hasattr(message, "from_history") and message.from_history and skip_history_messages:
236
- continue
237
- if message.role in assistant_role:
238
- assistant_message_from_run = message
239
- break
303
+ history_data.append((input_str, response_str))
240
304
 
241
- if user_message_from_run and assistant_message_from_run:
242
- final_messages.append(user_message_from_run)
243
- final_messages.append(assistant_message_from_run)
244
- return final_messages
305
+ return history_data
245
306
 
246
- def get_session_summary(self) -> Optional[SessionSummary]:
247
- """Get the session summary for the session"""
307
+ def get_team_history_context(self, num_runs: Optional[int] = None) -> Optional[str]:
308
+ """Get formatted team history context for steps
248
309
 
249
- if self.summary is None:
310
+ Args:
311
+ num_runs: Number of recent runs to include. If None, returns all available history.
312
+ """
313
+ history_data = self.get_team_history(num_runs)
314
+
315
+ if not history_data:
250
316
  return None
251
317
 
252
- return self.summary # type: ignore
318
+ # Format as team history context using the structured data
319
+ context_parts = ["<team_history_context>"]
253
320
 
254
- # Chat History functions
255
- def get_chat_history(self) -> List[Message]:
256
- """Get the chat history for the session"""
321
+ for i, (input_str, response_str) in enumerate(history_data, 1):
322
+ context_parts.append(f"[run-{i}]")
257
323
 
258
- messages = []
259
- if self.runs is None:
260
- return []
324
+ if input_str:
325
+ context_parts.append(f"input: {input_str}")
326
+ if response_str:
327
+ context_parts.append(f"response: {response_str}")
261
328
 
262
- for run in self.runs or []:
263
- if run.messages is None:
264
- continue
329
+ context_parts.append("") # Empty line between runs
330
+
331
+ context_parts.append("</team_history_context>")
332
+ context_parts.append("") # Empty line before current input
265
333
 
266
- messages.extend([msg for msg in run.messages or [] if not msg.from_history])
334
+ return "\n".join(context_parts)
267
335
 
268
- return messages
336
+ def get_session_summary(self) -> Optional[SessionSummary]:
337
+ """Get the session summary for the session"""
338
+
339
+ if self.summary is None:
340
+ return None
341
+
342
+ return self.summary # type: ignore