agno 2.0.8__py3-none-any.whl → 2.0.10__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 (48) hide show
  1. agno/agent/agent.py +13 -8
  2. agno/db/base.py +14 -0
  3. agno/db/dynamo/dynamo.py +107 -27
  4. agno/db/firestore/firestore.py +109 -33
  5. agno/db/gcs_json/gcs_json_db.py +100 -20
  6. agno/db/in_memory/in_memory_db.py +95 -20
  7. agno/db/json/json_db.py +101 -21
  8. agno/db/migrations/v1_to_v2.py +181 -35
  9. agno/db/mongo/mongo.py +251 -26
  10. agno/db/mysql/mysql.py +307 -6
  11. agno/db/postgres/postgres.py +279 -33
  12. agno/db/redis/redis.py +99 -22
  13. agno/db/singlestore/singlestore.py +319 -38
  14. agno/db/sqlite/sqlite.py +339 -23
  15. agno/models/anthropic/claude.py +0 -20
  16. agno/models/aws/claude.py +1 -1
  17. agno/models/huggingface/huggingface.py +2 -1
  18. agno/models/ollama/chat.py +28 -2
  19. agno/models/openai/chat.py +7 -0
  20. agno/models/openai/responses.py +8 -8
  21. agno/os/interfaces/base.py +2 -0
  22. agno/os/interfaces/slack/router.py +50 -10
  23. agno/os/interfaces/slack/slack.py +6 -4
  24. agno/os/interfaces/whatsapp/router.py +7 -4
  25. agno/os/router.py +18 -0
  26. agno/os/utils.py +2 -2
  27. agno/reasoning/azure_ai_foundry.py +2 -2
  28. agno/reasoning/deepseek.py +2 -2
  29. agno/reasoning/groq.py +2 -2
  30. agno/reasoning/ollama.py +2 -2
  31. agno/reasoning/openai.py +2 -2
  32. agno/run/base.py +15 -2
  33. agno/team/team.py +10 -12
  34. agno/tools/mcp_toolbox.py +284 -0
  35. agno/tools/scrapegraph.py +58 -31
  36. agno/tools/whatsapp.py +1 -1
  37. agno/utils/models/claude.py +2 -2
  38. agno/utils/print_response/agent.py +2 -2
  39. agno/utils/print_response/team.py +6 -6
  40. agno/utils/reasoning.py +22 -1
  41. agno/utils/string.py +9 -0
  42. agno/workflow/workflow.py +11 -7
  43. {agno-2.0.8.dist-info → agno-2.0.10.dist-info}/METADATA +4 -1
  44. {agno-2.0.8.dist-info → agno-2.0.10.dist-info}/RECORD +47 -47
  45. agno/utils/models/aws_claude.py +0 -170
  46. {agno-2.0.8.dist-info → agno-2.0.10.dist-info}/WHEEL +0 -0
  47. {agno-2.0.8.dist-info → agno-2.0.10.dist-info}/licenses/LICENSE +0 -0
  48. {agno-2.0.8.dist-info → agno-2.0.10.dist-info}/top_level.txt +0 -0
@@ -406,25 +406,25 @@ class OpenAIResponses(Model):
406
406
 
407
407
  messages_to_format = messages
408
408
  previous_response_id: Optional[str] = None
409
-
409
+
410
410
  if self._using_reasoning_model() and self.store is not False:
411
411
  # Detect whether we're chaining via previous_response_id. If so, we should NOT
412
412
  # re-send prior function_call items; the Responses API already has the state and
413
413
  # expects only the corresponding function_call_output items.
414
-
414
+
415
415
  for msg in reversed(messages):
416
416
  if (
417
- msg.role == "assistant"
418
- and hasattr(msg, "provider_data")
419
- and msg.provider_data
417
+ msg.role == "assistant"
418
+ and hasattr(msg, "provider_data")
419
+ and msg.provider_data
420
420
  and "response_id" in msg.provider_data
421
421
  ):
422
422
  previous_response_id = msg.provider_data["response_id"]
423
423
  msg_index = messages.index(msg)
424
-
424
+
425
425
  # Include messages after this assistant message
426
- messages_to_format = messages[msg_index + 1:]
427
-
426
+ messages_to_format = messages[msg_index + 1 :]
427
+
428
428
  break
429
429
 
430
430
  # Build a mapping from function_call id (fc_*) → call_id (call_*) from prior assistant tool_calls
@@ -5,6 +5,7 @@ from fastapi import APIRouter
5
5
 
6
6
  from agno.agent import Agent
7
7
  from agno.team import Team
8
+ from agno.workflow.workflow import Workflow
8
9
 
9
10
 
10
11
  class BaseInterface(ABC):
@@ -13,6 +14,7 @@ class BaseInterface(ABC):
13
14
  router_prefix: str = ""
14
15
  agent: Optional[Agent] = None
15
16
  team: Optional[Team] = None
17
+ workflow: Optional[Workflow] = None
16
18
 
17
19
  router: APIRouter
18
20
 
@@ -1,16 +1,49 @@
1
1
  from typing import Optional
2
2
 
3
3
  from fastapi import APIRouter, BackgroundTasks, HTTPException, Request
4
+ from pydantic import BaseModel, Field
4
5
 
5
6
  from agno.agent.agent import Agent
6
7
  from agno.os.interfaces.slack.security import verify_slack_signature
7
8
  from agno.team.team import Team
8
9
  from agno.tools.slack import SlackTools
9
10
  from agno.utils.log import log_info
11
+ from agno.workflow.workflow import Workflow
10
12
 
11
13
 
12
- def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
13
- @router.post("/events")
14
+ class SlackEventResponse(BaseModel):
15
+ """Response model for Slack event processing"""
16
+
17
+ status: str = Field(default="ok", description="Processing status")
18
+
19
+
20
+ class SlackChallengeResponse(BaseModel):
21
+ """Response model for Slack URL verification challenge"""
22
+
23
+ challenge: str = Field(description="Challenge string to echo back to Slack")
24
+
25
+
26
+ def attach_routes(
27
+ router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None, workflow: Optional[Workflow] = None
28
+ ) -> APIRouter:
29
+ # Determine entity type for documentation
30
+ entity_type = "agent" if agent else "team" if team else "workflow" if workflow else "unknown"
31
+ entity_name = getattr(agent or team or workflow, "name", f"Unnamed {entity_type}")
32
+
33
+ @router.post(
34
+ "/events",
35
+ operation_id=f"slack_events_{entity_type}",
36
+ summary=f"Process Slack Events for {entity_type.title()}",
37
+ description=f"Process incoming Slack events and route them to the configured {entity_type}: {entity_name}",
38
+ tags=["Slack", f"Slack-{entity_type.title()}"],
39
+ response_model=SlackEventResponse,
40
+ response_model_exclude_none=True,
41
+ responses={
42
+ 200: {"description": "Event processed successfully"},
43
+ 400: {"description": "Missing Slack headers"},
44
+ 403: {"description": "Invalid Slack signature"},
45
+ },
46
+ )
14
47
  async def slack_events(request: Request, background_tasks: BackgroundTasks):
15
48
  body = await request.body()
16
49
  timestamp = request.headers.get("X-Slack-Request-Timestamp")
@@ -26,7 +59,7 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
26
59
 
27
60
  # Handle URL verification
28
61
  if data.get("type") == "url_verification":
29
- return {"challenge": data.get("challenge")}
62
+ return SlackChallengeResponse(challenge=data.get("challenge"))
30
63
 
31
64
  # Process other event types (e.g., message events) asynchronously
32
65
  if "event" in data:
@@ -37,7 +70,7 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
37
70
  else:
38
71
  background_tasks.add_task(_process_slack_event, event)
39
72
 
40
- return {"status": "ok"}
73
+ return SlackEventResponse(status="ok")
41
74
 
42
75
  async def _process_slack_event(event: dict):
43
76
  if event.get("type") == "message":
@@ -57,12 +90,19 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
57
90
  response = await agent.arun(message_text, user_id=user if user else None, session_id=session_id)
58
91
  elif team:
59
92
  response = await team.arun(message_text, user_id=user if user else None, session_id=session_id) # type: ignore
93
+ elif workflow:
94
+ response = await workflow.arun(message_text, user_id=user if user else None, session_id=session_id) # type: ignore
60
95
 
61
- if response.reasoning_content:
62
- _send_slack_message(
63
- channel=channel_id, message=f"Reasoning: \n{response.reasoning_content}", thread_ts=ts, italics=True
64
- )
65
- _send_slack_message(channel=channel_id, message=response.content or "", thread_ts=ts)
96
+ if response:
97
+ if hasattr(response, "reasoning_content") and response.reasoning_content:
98
+ _send_slack_message(
99
+ channel=channel_id,
100
+ message=f"Reasoning: \n{response.reasoning_content}",
101
+ thread_ts=ts,
102
+ italics=True,
103
+ )
104
+
105
+ _send_slack_message(channel=channel_id, message=response.content or "", thread_ts=ts)
66
106
 
67
107
  def _send_slack_message(channel: str, thread_ts: str, message: str, italics: bool = False):
68
108
  if len(message) <= 40000:
@@ -85,6 +125,6 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
85
125
  formatted_batch = "\n".join([f"_{line}_" for line in batch_message.split("\n")])
86
126
  SlackTools().send_message_thread(channel=channel, text=formatted_batch or "", thread_ts=thread_ts)
87
127
  else:
88
- SlackTools().send_message_thread(channel=channel, text=message or "", thread_ts=thread_ts)
128
+ SlackTools().send_message_thread(channel=channel, text=batch_message or "", thread_ts=thread_ts)
89
129
 
90
130
  return router
@@ -7,6 +7,7 @@ from agno.agent.agent import Agent
7
7
  from agno.os.interfaces.base import BaseInterface
8
8
  from agno.os.interfaces.slack.router import attach_routes
9
9
  from agno.team.team import Team
10
+ from agno.workflow.workflow import Workflow
10
11
 
11
12
  logger = logging.getLogger(__name__)
12
13
 
@@ -16,17 +17,18 @@ class Slack(BaseInterface):
16
17
 
17
18
  router: APIRouter
18
19
 
19
- def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
20
+ def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None, workflow: Optional[Workflow] = None):
20
21
  self.agent = agent
21
22
  self.team = team
23
+ self.workflow = workflow
22
24
 
23
- if not (self.agent or self.team):
24
- raise ValueError("Slack requires an agent or a team")
25
+ if not (self.agent or self.team or self.workflow):
26
+ raise ValueError("Slack requires an agent, team or workflow")
25
27
 
26
28
  def get_router(self, **kwargs) -> APIRouter:
27
29
  # Cannot be overridden
28
30
  self.router = APIRouter(prefix="/slack", tags=["Slack"])
29
31
 
30
- self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
32
+ self.router = attach_routes(router=self.router, agent=self.agent, team=self.team, workflow=self.workflow)
31
33
 
32
34
  return self.router
@@ -19,6 +19,9 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
19
19
  if agent is None and team is None:
20
20
  raise ValueError("Either agent or team must be provided.")
21
21
 
22
+ # Create WhatsApp tools instance once for reuse
23
+ whatsapp_tools = WhatsAppTools(async_mode=True)
24
+
22
25
  @router.get("/status")
23
26
  async def status():
24
27
  return {"status": "available"}
@@ -185,9 +188,9 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
185
188
  if italics:
186
189
  # Handle multi-line messages by making each line italic
187
190
  formatted_message = "\n".join([f"_{line}_" for line in message.split("\n")])
188
- await WhatsAppTools().send_text_message_async(recipient=recipient, text=formatted_message)
191
+ await whatsapp_tools.send_text_message_async(recipient=recipient, text=formatted_message)
189
192
  else:
190
- await WhatsAppTools().send_text_message_async(recipient=recipient, text=message)
193
+ await whatsapp_tools.send_text_message_async(recipient=recipient, text=message)
191
194
  return
192
195
 
193
196
  # Split message into batches of 4000 characters (WhatsApp message limit is 4096)
@@ -199,8 +202,8 @@ def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Option
199
202
  if italics:
200
203
  # Handle multi-line messages by making each line italic
201
204
  formatted_batch = "\n".join([f"_{line}_" for line in batch_message.split("\n")])
202
- await WhatsAppTools().send_text_message_async(recipient=recipient, text=formatted_batch)
205
+ await whatsapp_tools.send_text_message_async(recipient=recipient, text=formatted_batch)
203
206
  else:
204
- await WhatsAppTools().send_text_message_async(recipient=recipient, text=batch_message)
207
+ await whatsapp_tools.send_text_message_async(recipient=recipient, text=batch_message)
205
208
 
206
209
  return router
agno/os/router.py CHANGED
@@ -72,6 +72,24 @@ async def _get_request_kwargs(request: Request, endpoint_func: Callable) -> Dict
72
72
  sig = inspect.signature(endpoint_func)
73
73
  known_fields = set(sig.parameters.keys())
74
74
  kwargs = {key: value for key, value in form_data.items() if key not in known_fields}
75
+
76
+ # Handle JSON parameters. They are passed as strings and need to be deserialized.
77
+
78
+ if session_state := kwargs.get("session_state"):
79
+ try:
80
+ session_state_dict = json.loads(session_state) # type: ignore
81
+ kwargs["session_state"] = session_state_dict
82
+ except json.JSONDecodeError:
83
+ kwargs.pop("session_state")
84
+ log_warning(f"Invalid session_state parameter couldn't be loaded: {session_state}")
85
+ if dependencies := kwargs.get("dependencies"):
86
+ try:
87
+ dependencies_dict = json.loads(dependencies) # type: ignore
88
+ kwargs["dependencies"] = dependencies_dict
89
+ except json.JSONDecodeError:
90
+ kwargs.pop("dependencies")
91
+ log_warning(f"Invalid dependencies parameter couldn't be loaded: {dependencies}")
92
+
75
93
  return kwargs
76
94
 
77
95
 
agno/os/utils.py CHANGED
@@ -57,7 +57,7 @@ def get_run_input(run_dict: Dict[str, Any], is_workflow_run: bool = False) -> st
57
57
  if is_workflow_run:
58
58
  step_executor_runs = run_dict.get("step_executor_runs", [])
59
59
  if step_executor_runs:
60
- for message in step_executor_runs[0].get("messages", []):
60
+ for message in reversed(step_executor_runs[0].get("messages", [])):
61
61
  if message.get("role") == "user":
62
62
  return message.get("content", "")
63
63
 
@@ -70,7 +70,7 @@ def get_run_input(run_dict: Dict[str, Any], is_workflow_run: bool = False) -> st
70
70
  return str(input_value)
71
71
 
72
72
  if run_dict.get("messages") is not None:
73
- for message in run_dict["messages"]:
73
+ for message in reversed(run_dict["messages"]):
74
74
  if message.get("role") == "user":
75
75
  return message.get("content", "")
76
76
 
@@ -20,7 +20,7 @@ def get_ai_foundry_reasoning(reasoning_agent: "Agent", messages: List[Message])
20
20
  from agno.run.agent import RunOutput
21
21
 
22
22
  try:
23
- reasoning_agent_response: RunOutput = reasoning_agent.run(messages=messages)
23
+ reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
24
24
  except Exception as e:
25
25
  logger.warning(f"Reasoning error: {e}")
26
26
  return None
@@ -46,7 +46,7 @@ async def aget_ai_foundry_reasoning(reasoning_agent: "Agent", messages: List[Mes
46
46
  from agno.run.agent import RunOutput
47
47
 
48
48
  try:
49
- reasoning_agent_response: RunOutput = await reasoning_agent.arun(messages=messages)
49
+ reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
50
50
  except Exception as e:
51
51
  logger.warning(f"Reasoning error: {e}")
52
52
  return None
@@ -20,7 +20,7 @@ def get_deepseek_reasoning(reasoning_agent: "Agent", messages: List[Message]) ->
20
20
  message.role = "system"
21
21
 
22
22
  try:
23
- reasoning_agent_response: RunOutput = reasoning_agent.run(messages=messages)
23
+ reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
24
24
  except Exception as e:
25
25
  logger.warning(f"Reasoning error: {e}")
26
26
  return None
@@ -46,7 +46,7 @@ async def aget_deepseek_reasoning(reasoning_agent: "Agent", messages: List[Messa
46
46
  message.role = "system"
47
47
 
48
48
  try:
49
- reasoning_agent_response: RunOutput = await reasoning_agent.arun(messages=messages)
49
+ reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
50
50
  except Exception as e:
51
51
  logger.warning(f"Reasoning error: {e}")
52
52
  return None
agno/reasoning/groq.py CHANGED
@@ -20,7 +20,7 @@ def get_groq_reasoning(reasoning_agent: "Agent", messages: List[Message]) -> Opt
20
20
  message.role = "system"
21
21
 
22
22
  try:
23
- reasoning_agent_response: RunOutput = reasoning_agent.run(messages=messages)
23
+ reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
24
24
  except Exception as e:
25
25
  logger.warning(f"Reasoning error: {e}")
26
26
  return None
@@ -50,7 +50,7 @@ async def aget_groq_reasoning(reasoning_agent: "Agent", messages: List[Message])
50
50
  message.role = "system"
51
51
 
52
52
  try:
53
- reasoning_agent_response: RunOutput = await reasoning_agent.arun(messages=messages)
53
+ reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
54
54
  except Exception as e:
55
55
  logger.warning(f"Reasoning error: {e}")
56
56
  return None
agno/reasoning/ollama.py CHANGED
@@ -20,7 +20,7 @@ def get_ollama_reasoning(reasoning_agent: "Agent", messages: List[Message]) -> O
20
20
  from agno.run.agent import RunOutput
21
21
 
22
22
  try:
23
- reasoning_agent_response: RunOutput = reasoning_agent.run(messages=messages)
23
+ reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
24
24
  except Exception as e:
25
25
  logger.warning(f"Reasoning error: {e}")
26
26
  return None
@@ -46,7 +46,7 @@ async def aget_ollama_reasoning(reasoning_agent: "Agent", messages: List[Message
46
46
  from agno.run.agent import RunOutput
47
47
 
48
48
  try:
49
- reasoning_agent_response: RunOutput = await reasoning_agent.arun(messages=messages)
49
+ reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
50
50
  except Exception as e:
51
51
  logger.warning(f"Reasoning error: {e}")
52
52
  return None
agno/reasoning/openai.py CHANGED
@@ -29,7 +29,7 @@ def get_openai_reasoning(reasoning_agent: "Agent", messages: List[Message]) -> O
29
29
  from agno.run.agent import RunOutput
30
30
 
31
31
  try:
32
- reasoning_agent_response: RunOutput = reasoning_agent.run(messages=messages)
32
+ reasoning_agent_response: RunOutput = reasoning_agent.run(input=messages)
33
33
  except Exception as e:
34
34
  logger.warning(f"Reasoning error: {e}")
35
35
  return None
@@ -60,7 +60,7 @@ async def aget_openai_reasoning(reasoning_agent: "Agent", messages: List[Message
60
60
  message.role = "system"
61
61
 
62
62
  try:
63
- reasoning_agent_response: RunOutput = await reasoning_agent.arun(messages=messages)
63
+ reasoning_agent_response: RunOutput = await reasoning_agent.arun(input=messages)
64
64
  except Exception as e:
65
65
  logger.warning(f"Reasoning error: {e}")
66
66
  return None
agno/run/base.py CHANGED
@@ -117,6 +117,19 @@ class BaseRunOutputEvent:
117
117
 
118
118
  def to_json(self, separators=(", ", ": "), indent: Optional[int] = 2) -> str:
119
119
  import json
120
+ from datetime import date, datetime, time
121
+ from enum import Enum
122
+
123
+ def json_serializer(obj):
124
+ # Datetime like
125
+ if isinstance(obj, (datetime, date, time)):
126
+ return obj.isoformat()
127
+ # Enums
128
+ if isinstance(obj, Enum):
129
+ v = obj.value
130
+ return v if isinstance(v, (str, int, float, bool, type(None))) else obj.name
131
+ # Fallback to string
132
+ return str(obj)
120
133
 
121
134
  try:
122
135
  _dict = self.to_dict()
@@ -125,9 +138,9 @@ class BaseRunOutputEvent:
125
138
  raise
126
139
 
127
140
  if indent is None:
128
- return json.dumps(_dict, separators=separators)
141
+ return json.dumps(_dict, separators=separators, default=json_serializer, ensure_ascii=False)
129
142
  else:
130
- return json.dumps(_dict, indent=indent, separators=separators)
143
+ return json.dumps(_dict, indent=indent, separators=separators, default=json_serializer, ensure_ascii=False)
131
144
 
132
145
  @classmethod
133
146
  def from_dict(cls, data: Dict[str, Any]):
agno/team/team.py CHANGED
@@ -156,6 +156,8 @@ class Team:
156
156
  add_session_state_to_context: bool = False
157
157
  # Set to True to give the team tools to update the session_state dynamically
158
158
  enable_agentic_state: bool = False
159
+ # Set to True to overwrite the stored session_state with the session_state provided in the run
160
+ overwrite_db_session_state: bool = False
159
161
  # If True, cache the current Team session in memory for faster access
160
162
  cache_session: bool = False
161
163
 
@@ -364,6 +366,7 @@ class Team:
364
366
  session_state: Optional[Dict[str, Any]] = None,
365
367
  add_session_state_to_context: bool = False,
366
368
  enable_agentic_state: bool = False,
369
+ overwrite_db_session_state: bool = False,
367
370
  resolve_in_context: bool = True,
368
371
  cache_session: bool = False,
369
372
  description: Optional[str] = None,
@@ -453,6 +456,7 @@ class Team:
453
456
  self.session_state = session_state
454
457
  self.add_session_state_to_context = add_session_state_to_context
455
458
  self.enable_agentic_state = enable_agentic_state
459
+ self.overwrite_db_session_state = overwrite_db_session_state
456
460
  self.resolve_in_context = resolve_in_context
457
461
  self.cache_session = cache_session
458
462
 
@@ -1156,7 +1160,7 @@ class Team:
1156
1160
  self._update_metadata(session=team_session)
1157
1161
 
1158
1162
  # Update session state from DB
1159
- session_state = self._update_session_state(session=team_session, session_state=session_state)
1163
+ session_state = self._load_session_state(session=team_session, session_state=session_state)
1160
1164
 
1161
1165
  # Determine runtime dependencies
1162
1166
  run_dependencies = dependencies if dependencies is not None else self.dependencies
@@ -1780,7 +1784,7 @@ class Team:
1780
1784
  self._update_metadata(session=team_session)
1781
1785
 
1782
1786
  # Update session state from DB
1783
- session_state = self._update_session_state(session=team_session, session_state=session_state)
1787
+ session_state = self._load_session_state(session=team_session, session_state=session_state)
1784
1788
 
1785
1789
  # Determine run dependencies (runtime override takes priority)
1786
1790
  run_dependencies = dependencies if dependencies is not None else self.dependencies
@@ -2037,9 +2041,6 @@ class Team:
2037
2041
  if model_response.audio is not None:
2038
2042
  run_response.response_audio = model_response.audio
2039
2043
 
2040
- # Update the run_response created_at with the model response created_at
2041
- run_response.created_at = model_response.created_at
2042
-
2043
2044
  # Build a list of messages that should be added to the RunOutput
2044
2045
  messages_for_run_response = [m for m in run_messages.messages if m.add_to_agent_memory]
2045
2046
 
@@ -2099,7 +2100,6 @@ class Team:
2099
2100
  )
2100
2101
 
2101
2102
  # 3. Update TeamRunOutput
2102
- run_response.created_at = full_model_response.created_at
2103
2103
  if full_model_response.content is not None:
2104
2104
  run_response.content = full_model_response.content
2105
2105
  if full_model_response.reasoning_content is not None:
@@ -2189,7 +2189,6 @@ class Team:
2189
2189
  run_response.content = full_model_response.parsed
2190
2190
 
2191
2191
  # Update TeamRunOutput
2192
- run_response.created_at = full_model_response.created_at
2193
2192
  if full_model_response.content is not None:
2194
2193
  run_response.content = full_model_response.content
2195
2194
  if full_model_response.reasoning_content is not None:
@@ -2851,7 +2850,6 @@ class Team:
2851
2850
 
2852
2851
  # Update the TeamRunResponse content
2853
2852
  run_response.content = model_response.content
2854
- run_response.created_at = model_response.created_at
2855
2853
 
2856
2854
  if stream_intermediate_steps:
2857
2855
  yield self._handle_event(create_team_output_model_response_completed_event(run_response), run_response)
@@ -2909,7 +2907,6 @@ class Team:
2909
2907
 
2910
2908
  # Update the TeamRunResponse content
2911
2909
  run_response.content = model_response.content
2912
- run_response.created_at = model_response.created_at
2913
2910
 
2914
2911
  if stream_intermediate_steps:
2915
2912
  yield self._handle_event(create_team_output_model_response_completed_event(run_response), run_response)
@@ -4277,7 +4274,7 @@ class Team:
4277
4274
  system_message_content += f"{indent * ' '} - Name: {member.name}\n"
4278
4275
  if member.role is not None:
4279
4276
  system_message_content += f"{indent * ' '} - Role: {member.role}\n"
4280
- if member.tools is not None and self.add_member_tools_to_context:
4277
+ if member.tools and self.add_member_tools_to_context:
4281
4278
  system_message_content += f"{indent * ' '} - Member tools:\n"
4282
4279
  for _tool in member.tools:
4283
4280
  if isinstance(_tool, Toolkit):
@@ -6111,8 +6108,8 @@ class Team:
6111
6108
  self._upsert_session(session=session)
6112
6109
  log_debug(f"Created or updated TeamSession record: {session.session_id}")
6113
6110
 
6114
- def _update_session_state(self, session: TeamSession, session_state: Dict[str, Any]) -> Dict[str, Any]:
6115
- """Load the existing Agent from an AgentSession (from the database)"""
6111
+ def _load_session_state(self, session: TeamSession, session_state: Dict[str, Any]) -> Dict[str, Any]:
6112
+ """Load and return the stored session_state from the database, optionally merging it with the given one"""
6116
6113
 
6117
6114
  from agno.utils.merge_dict import merge_dictionaries
6118
6115
 
@@ -6125,6 +6122,7 @@ class Team:
6125
6122
  session_state_from_db is not None
6126
6123
  and isinstance(session_state_from_db, dict)
6127
6124
  and len(session_state_from_db) > 0
6125
+ and not self.overwrite_db_session_state
6128
6126
  ):
6129
6127
  # This preserves precedence: run_params > db_state > agent_defaults
6130
6128
  merged_state = session_state_from_db.copy()