Python: Extend hosted session scoping to approval handling#6594
Python: Extend hosted session scoping to approval handling#6594eavanvalkenburg wants to merge 9 commits into
Conversation
Refine session scoping behavior across Python hosting adapters and cover the updated persistence paths with regression tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the hosted-session marker away from checkpoint file scans and reject whitespace-only ownership keys. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve Foundry Hosting workflow handler conflicts after upstream response-failure handling changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Avoid a known Windows Python 3.10 Hyperlight sandbox initialization failure in the real-sandbox event-loop responsiveness test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the provider/protocol shape with a sync-or-async callable resolver while keeping HostedSessionContext as the value object. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bind Foundry Hosting MCP approval save/load to the resolved hosted session identity, reusing the HostedSessionContext resolver and strict_session_isolation introduced in microsoft#6536. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Python Test Coverage Report •
Python Unit Test Overview
|
|||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Pull request overview
This PR extends the Python “hosted session scoping” work (stacked on #6536) so Foundry Hosting binds MCP approval handles to the same per-session identity boundaries used for hosted workflow checkpoints, improving multi-user isolation and preventing cross-session approval replay. It also clarifies/extends AG-UI snapshot-scope behavior so the resolver scopes the in-memory workflow cache even when snapshot persistence is disabled.
Changes:
- Add a hosted session identity model/resolver and thread the derived isolation key through approval save/load and approval response conversion to prevent cross-isolation redemption.
- Stamp workflow checkpoint directories with the hosted session context and reject resume/write when identity is missing/mismatched (plus tests to cover these cases).
- Update AG-UI endpoint behavior/docs/tests so
snapshot_scope_resolveralso scopes in-memory workflow instances even without a snapshot store.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| python/packages/hyperlight/tests/hyperlight/test_hyperlight_codeact.py | Skips a flaky Windows/Py3.10 integration test path for Hyperlight async threading. |
| python/packages/foundry_hosting/agent_framework_foundry_hosting/_responses.py | Implements hosted session context resolution/stamping and binds approval storage/redemption to a per-session isolation key. |
| python/packages/foundry_hosting/agent_framework_foundry_hosting/init.py | Exposes HostedSessionContext and HostedSessionContextResolver as public API exports. |
| python/packages/foundry_hosting/tests/test_responses.py | Adds regression tests for approval isolation binding and hosted session context stamping/mismatch enforcement. |
| python/packages/foundry_hosting/README.md | Documents strict hosted session isolation for checkpoints and approval-handle binding guidance. |
| python/packages/ag-ui/agent_framework_ag_ui/_endpoint.py | Applies snapshot_scope_resolver even without snapshot persistence (for scoping in-memory workflow cache). |
| python/packages/ag-ui/agent_framework_ag_ui/_workflow.py | Clarifies that snapshot scope is the isolation boundary for both snapshots and in-memory workflow instances. |
| python/packages/ag-ui/tests/ag_ui/test_endpoint.py | Adds coverage ensuring workflow-factory cache is scoped by resolver even without a snapshot store. |
| python/packages/ag-ui/README.md | Documents that snapshot scope resolver also scopes the in-memory workflow cache in multi-user deployments. |
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 86%
✓ Correctness
The PR correctly extends hosted session scoping to approval handling. The isolation binding logic in both InMemory and FileBased storage is sound, the checkpoint stamping uses exclusive-create to handle races, and the legacy entry rejection in FileBasedFunctionAprovalStorage is correct. One efficiency issue: the hosted session context resolver is invoked twice with identical arguments in _handle_inner_workflow — once for approval binding (line 723) and again for checkpoint stamping (line 781, which internally calls the same resolver via _resolve_hosted_session_context_optional). This doubles the cost for async resolvers that perform I/O and could theoretically yield inconsistent results with a non-deterministic resolver.
✓ Security Reliability
This PR extends hosted session scoping to approval handling, binding MCP approval handles to the caller's identity (CWE-863) and validating checkpoint ownership. The security implementation is sound: approval storage correctly uses isolation key matching, file-based context stamping uses exclusive create (O_CREAT|O_EXCL) to prevent races, legacy entries are rejected, and the default strict mode enforces identity resolution. The
_hosted_session_keyfunction usesjson.dumpsfor safe composite key derivation, preventing delimiter injection. No high-severity security or reliability issues were found. One low-severity efficiency concern exists: the user-provided hosted session context resolver is invoked twice per workflow request (once for approval isolation binding, once for checkpoint validation), which doubles latency for network-backed resolvers and could theoretically yield inconsistent results if the resolver is non-deterministic.
✓ Test Coverage
The PR adds comprehensive test coverage for the new approval isolation binding and hosted session context features. The core isolation logic in
_item_to_messageand both storage implementations (InMemoryFunctionApprovalStorage,FileBasedFunctionApprovalStorage) are well tested with cross-isolation rejection, strict mode enforcement, and legacy entry handling. The workflow handler integration tests cover cross-user rejection, unstamped checkpoints, and non-strict fallback. However, the_output_item_to_messagefunction has identical isolation plumbing (isolation_key,require_isolation) that is only exercised with default (None) values — the isolation-specific tests all go through_item_to_messageonly.
✓ Design Approach
I found one blocking design regression and one narrower API-coupling issue. In Foundry Hosting, the new strict approval-isolation path now breaks the default local/non-Foundry approval round-trip for plain agents, but the updated tests hide that by always injecting a fake hosted-session resolver. In AG-UI, the endpoint now resolves snapshot scope on every request even when the runner cannot use that value, which turns an optional scoping hook into an unnecessary request requirement for fixed-workflow endpoints.
Automated review by eavanvalkenburg's agents
Approvals bind to whatever hosted session identity is resolved (None when no isolation headers are present) and only reject redemption on identity mismatch. Removes the strict require_isolation gate so approval-gated flows work the same with or without isolation mode. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Validates that a ResponsesHostServer built with no injected identity resolver (and no ResponseContext.isolation) saves and redeems an MCP approval across two turns, guarding the default local behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Motivation & Context
This change extends the hosted session scoping work in #6536 so that Foundry Hosting handles per-session state more consistently across multi-user and local scenarios. It aligns approval handling with the same session-ownership boundaries used for hosted workflow checkpoints, so related hosted state behaves predictably.
This PR is stacked on #6536 and depends on the
HostedSessionContext/ resolver primitives it introduces; it should merge after #6536.Description & Review Guide
HostedSessionContext,hosted_session_context_resolver, andstrict_session_isolationhooks from Python: Improve hosted session scoping #6536 rather than introducing a parallel mechanism.Related Issue
No issue. Follow-up to / stacked on #6536.
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.