Skip to content

Python: fix: clear service_session_id in _agent_wrapper when propagate_session=True#5875

Open
benke520 wants to merge 1 commit into
microsoft:mainfrom
benke520:fix/propagate-session-service-id-conflict
Open

Python: fix: clear service_session_id in _agent_wrapper when propagate_session=True#5875
benke520 wants to merge 1 commit into
microsoft:mainfrom
benke520:fix/propagate-session-service-id-conflict

Conversation

@benke520
Copy link
Copy Markdown
Member

Summary

When propagate_session=True, the child agent inherits the parent's session.service_session_id. After the parent's first LLM call, MAF auto-populates this from the Responses API's conversation_id. The child sends it as previous_response_id, which the server rejects because the parent's ool_call is still pending — resulting in a 400 error.

Changes

  • _agents.py: In _agent_wrapper (inside Agent.as_tool()), save and clear service_session_id before calling the child agent, restore it in a inally block. This preserves session.state sharing while isolating the server-side conversation pointer.

Tests

Added 3 new tests:

  • est_chat_agent_as_tool_propagate_session_clears_service_session_id — verifies child sees service_session_id=None and parent gets it restored
  • est_chat_agent_as_tool_propagate_session_restores_service_session_id_on_error — verifies restore happens even if child raises
  • est_chat_agent_as_tool_propagate_session_no_service_session_id — verifies no-op when service_session_id is already None

All 106 tests in est_agents.py pass.

Fixes #5874

…n=True

When propagate_session=True, the child agent inherits the parent's
service_session_id. After the parent's first LLM call, MAF auto-populates
this from the Responses API conversation_id. The child sends it as
previous_response_id which the server rejects because the parent's
tool_call is still pending (400 error).

This fix saves and clears service_session_id before calling the child
agent and restores it in a finally block, preserving session.state
sharing while isolating the server-side conversation pointer.

Fixes microsoft#5874
Copilot AI review requested due to automatic review settings May 15, 2026 00:18
@github-actions github-actions Bot changed the title fix: clear service_session_id in _agent_wrapper when propagate_session=True Python: fix: clear service_session_id in _agent_wrapper when propagate_session=True May 15, 2026
@moonbox3
Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _agents.py4205287%461, 470, 525, 1034, 1079, 1152–1156, 1216, 1244, 1281, 1302, 1322–1323, 1328, 1375, 1417, 1439, 1441, 1454, 1460, 1505, 1507, 1516–1521, 1526, 1528, 1534–1535, 1542, 1544–1545, 1553–1554, 1557–1559, 1569–1574, 1578, 1583, 1585
TOTAL34070390388% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
6779 30 💤 0 ❌ 0 🔥 1m 48s ⏱️

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a Python agent-as-tool session propagation issue where a child agent can inherit the parent’s session.service_session_id, causing invalid previous_response_id usage and 400 errors with Responses-style APIs.

Changes:

  • Update Agent.as_tool(... propagate_session=True) wrapper to temporarily clear session.service_session_id during the child agent run and restore it afterward.
  • Add tests covering save/clear/restore behavior (including restore on child error).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
python/packages/core/agent_framework/_agents.py Clears and restores service_session_id around delegated run() when propagate_session=True.
python/packages/core/tests/core/test_agents.py Adds tests validating service_session_id isolation/restoration behavior for agent-as-tool.
Comments suppressed due to low confidence (1)

python/packages/core/agent_framework/_agents.py:577

  • The finally block only restores service_session_id when the original value was non-None. If the parent session starts with service_session_id=None, the child run can still set session.service_session_id (e.g., from streaming conversation_id propagation) and it will leak back to the parent. Consider always restoring the original value (including None), using a sentinel to distinguish “no session” vs “saved None”.
            finally:
                if session is not None and saved_service_session_id is not None:
                    session.service_session_id = saved_service_session_id

Comment on lines +556 to +560
saved_service_session_id = None
if session is not None and session.service_session_id is not None:
saved_service_session_id = session.service_session_id
session.service_session_id = None

Comment on lines +1075 to +1079
async def test_chat_agent_as_tool_propagate_session_no_service_session_id(client: SupportsChatGetResponse) -> None:
"""Test that when service_session_id is None, no save/restore is needed."""
agent = Agent(client=client, name="SubAgent", description="Sub agent")
tool = agent.as_tool(propagate_session=True)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: propagate_session=True breaks sub-agent when using Responses API (service_session_id conflict)

3 participants