Skip to content

Commit 3184322

Browse files
dirkbrndysolanky
andauthored
chore: Release 1.7.8 (#4092)
# Changelog ## New Features: - **Output model**: Added support for `output_model` on Agents and Teams to generate the final response from `output_model` instead of `model` ## Improvements: - **Support for OpenAI Flex Processing**: Added `service_tier` to `OpenAIChat` and `OpenAIResponses`. ## Bug Fixes: - **Print Response:** - Fixed `show_member_responses` not working correctly on `Team` - Fixed printing of MCP responses on streamable HTTP - **Session State on Team**: Fixed precedence for session state from sessions DB. - **`YouTubeTranscriptApi` has no attribute `get_transcript` :** - The `YoutubeTranscriptApi` is updated and now uses `.fetch(video_id)` for getting transcripts. - **HITL streaming:** - Added the required attributes- `tools_requiring_confirmation`, `tools_requiring_user_input`, `tools_awaiting_external_execution` on the class `BaseAgentRunResponseEvent` - If you are using streaming, it is recommended to pass the `run_id` and a list of `updated_tools` to the `continue_run` or `acontinue_run` method. --------- Co-authored-by: Yash Pratap Solanky <101447028+ysolanky@users.noreply.github.com> Co-authored-by: ysolanky <yash@phidata.com>
1 parent e989bab commit 3184322

File tree

4 files changed

+60
-5
lines changed

4 files changed

+60
-5
lines changed

libs/agno/agno/team/team.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5689,6 +5689,13 @@ def _get_user_message(
56895689
return Message.model_validate(message)
56905690
except Exception as e:
56915691
log_warning(f"Failed to validate message: {e}")
5692+
elif isinstance(message, BaseModel):
5693+
try:
5694+
# Create a user message with the BaseModel content
5695+
content = message.model_dump_json(indent=2, exclude_none=True)
5696+
return Message(role="user", content=content)
5697+
except Exception as e:
5698+
log_warning(f"Failed to convert BaseModel to message: {e}")
56925699

56935700
def get_messages_for_parser_model(
56945701
self, model_response: ModelResponse, response_format: Optional[Union[Dict, Type[BaseModel]]]
@@ -7119,9 +7126,10 @@ def load_team_session(self, session: TeamSession):
71197126
# If the session_state is already set, merge the session_state from the database with the current session_state
71207127
if self.session_state is not None and len(self.session_state) > 0:
71217128
# This updates session_state_from_db
7122-
merge_dictionaries(session_state_from_db, self.session_state)
7123-
# Update the current session_state
7124-
self.session_state = session_state_from_db
7129+
merge_dictionaries(self.session_state, session_state_from_db)
7130+
else:
7131+
# Update the current session_state
7132+
self.session_state = session_state_from_db
71257133

71267134
if "team_session_state" in session.session_data:
71277135
team_session_state_from_db = session.session_data.get("team_session_state")

libs/agno/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "agno"
3-
version = "1.7.7"
3+
version = "1.7.8"
44
description = "Agno: a lightweight library for building Multi-Agent Systems"
55
requires-python = ">=3.7,<4"
66
readme = "README.md"

libs/agno/tests/integration/teams/test_event_streaming.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def test_intermediate_steps_with_tools():
139139
assert len(events[TeamRunEvent.run_response_content]) > 1
140140
assert len(events[TeamRunEvent.run_completed]) == 1
141141
assert len(events[TeamRunEvent.tool_call_started]) == 1
142-
assert events[TeamRunEvent.tool_call_started][0].tool.tool_name == "get_current_stock_price"
142+
assert events[TeamRunEvent.tool_call_started][0].tool.tool_name == "get_current_stock_price" or "transfer_task_to_member"
143143
assert len(events[TeamRunEvent.tool_call_completed]) == 1
144144
assert events[TeamRunEvent.tool_call_completed][0].content is not None
145145
assert events[TeamRunEvent.tool_call_completed][0].tool.result is not None

libs/agno/tests/integration/teams/test_team_session_state.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import uuid
12
import pytest
23

34
from agno.models.openai.chat import OpenAIChat
@@ -142,3 +143,49 @@ def test_team_session_state_on_run(route_team):
142143
"test_key": "test_value",
143144
"something_else": "other_value",
144145
}, "Merging session state should work"
146+
147+
148+
def test_session_state_db_precedence(route_team, team_storage):
149+
"""Test that DB session_state takes precedence over agent's in-memory session_state when switching sessions."""
150+
# Set up two sessions with different session_state
151+
session_id_1 = "session_db"
152+
session_id_2 = "session_mem"
153+
154+
# Simulate a session in storage with a specific session_state
155+
db_state = {"db_key": "db_value", "shared_key": "db"}
156+
team_storage.upsert(
157+
session=type("TeamSession", (), {
158+
"session_id": session_id_1,
159+
"session_data": {
160+
"session_state": db_state.copy(),
161+
"session_name": "db_session"
162+
},
163+
"team_session_id": str(uuid.uuid4()),
164+
"team_id": str(uuid.uuid4()),
165+
"user_id": None,
166+
"team_data": None,
167+
"extra_data": None,
168+
})()
169+
)
170+
171+
# Set agent's in-memory session_state to something different
172+
route_team.session_state = {"mem_key": "mem_value", "shared_key": "mem"}
173+
route_team.session_id = session_id_2
174+
route_team.session_name = "mem_session"
175+
176+
# Run with the in-memory session (should use in-memory state)
177+
route_team.run("Test in-memory", session_id=session_id_2)
178+
assert route_team.session_state == {"current_session_id": session_id_2, "mem_key": "mem_value", "shared_key": "mem"}
179+
assert route_team.session_name == "mem_session"
180+
181+
# Now switch to the DB session (should load and take precedence)
182+
route_team.run("Test DB", session_id=session_id_1)
183+
# The session_state should now match the DB's, not the in-memory one
184+
expected_state = {"current_session_id": session_id_1, **db_state}
185+
assert route_team.session_state == expected_state
186+
assert route_team.session_name == "db_session"
187+
188+
# If we switch back to the in-memory session, it should restore the old state
189+
route_team.run("Test in-memory again", session_id=session_id_2)
190+
assert route_team.session_state == {"current_session_id": session_id_2, "mem_key": "mem_value", "shared_key": "mem"}
191+
assert route_team.session_name == "mem_session"

0 commit comments

Comments
 (0)