Python: Persist Foundry hosted agent session IDs - #7512
Conversation
There was a problem hiding this comment.
🟡 Not ready to approve
The new promotion logic can set conversation_id even when options["store"] is explicitly False, which appears to violate the base client’s storage semantics.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
This PR fixes Foundry hosted-agent session continuity in the Python Foundry integration by promoting the durable hosted session handle (agent_session_id / session.id) into the framework’s conversation_id field on the first turn, so it can be persisted as session.service_session_id and reused on subsequent turns.
Changes:
- Added a Foundry-local helper to extract a hosted agent session ID from Foundry response payload shapes.
- Updated non-streaming and streaming parsing to prefer the hosted session ID over transient Responses API IDs on first turn.
- Added/extended unit tests to validate hosted session ID promotion and suppression behavior.
File summaries
| File | Description |
|---|---|
| python/packages/foundry/agent_framework_foundry/_agent.py | Adds hosted-session-id extraction and promotes it into conversation_id during response/chunk parsing. |
| python/packages/foundry/tests/foundry/test_foundry_agent.py | Adds tests covering first-turn session ID promotion and streaming/non-streaming suppression behavior. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 3
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
There was a problem hiding this comment.
🟡 Not ready to approve
The intended precedence behavior (agent_session_id over session.id) is implemented but not currently covered by tests, leaving a key behavioral contract insufficiently protected against regression.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
Suppressed comments (2)
python/packages/foundry/tests/foundry/test_foundry_agent.py:889
- This streaming parametrized test doesn’t cover the case where both agent_session_id and session.id are present (with differing values) to validate the intended precedence of agent_session_id.
[
SimpleNamespace(agent_session_id="agent-session-123"),
SimpleNamespace(session=SimpleNamespace(id="agent-session-123")),
],
python/packages/foundry/tests/foundry/test_foundry_agent.py:812
- The precedence rule (agent_session_id should win over session.id when both are present) is implemented in _get_foundry_agent_session_id but isn’t covered by this parametrized test, so a regression could go unnoticed.
This issue also appears on line 886 of the same file.
[
SimpleNamespace(agent_session_id="agent-session-123"),
SimpleNamespace(session=SimpleNamespace(id="agent-session-123")),
],
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
There was a problem hiding this comment.
🟢 Ready to approve
The change is localized to Foundry parsing, aligns with existing store/continuation semantics in the OpenAI client, and is covered by targeted new unit tests for both non-streaming and streaming paths.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
Motivation & Context
Fixes #7503.
Foundry hosted agents return a durable hosted session handle (
agent_session_id, orsession.idon some payload shapes). The core Agent Framework session update path already persistsChatResponse.conversation_idintosession.service_session_id, and_prepare_optionsalready sends a hosted session ID back asextra_body.agent_session_id.The missing piece was the first-turn Foundry parser boundary: when no hosted session ID was sent in the request yet, the parser could leave the transient Responses API ID as
conversation_idinstead of promoting the durable hosted agent session handle.Description & Review Guide
agent_session_idorsession.idfrom the raw Foundry response payload.conversation_idfor first-turn non-streaming responses and streaming response events.store=Falsesemantics by not promoting hosted session IDs when response storage is explicitly disabled.session.service_session_idwith the durable Foundry session handle, allowing follow-up turns to reuse the same hosted runtime session through the existingextra_body.agent_session_idpath.agent_session_idshould take precedence oversession.idfor these Foundry payloads.event.response, as this patch does.Validation:
uv run pytest packages/foundry/tests/foundry/test_foundry_agent.py -k "hosted_agent_session_id or suppresses_conversation_id_for_agent_sessions"uv run pytest packages/foundry/tests/foundry/test_foundry_agent.pyuv run poe test -P foundryuv run poe syntaxuv run poe --directory packages/foundry syntaxuv run poe --directory packages/foundry pyrightuv run poe --directory packages/foundry buildI also attempted
uv run poe check; it passed workspace syntax and reached type checking, includingpackages/foundry, then failed in unrelatedpackages/labandpackages/coreoptional-dependency imports in this fresh container environment (orjson,pyarrow,graphviz, OpenTelemetry OTLP exporters, and related Lab-only dependencies).Related Issue
Fixes #7503
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.