.NET: Preserve hosted session key boundaries - #8263
Conversation
Signed-off-by: Ricky-7-Yan <2314530442@qq.com>
There was a problem hiding this comment.
🟢 Approval recommended
The implementations preserve identifier boundaries and existing null, empty, and local-mode behavior with focused regression coverage.
Pull request overview
Preserves hosted session isolation by replacing ambiguous delimiter-based keys with boundary-safe representations.
Changes:
- Serializes Python hosted identifiers as compact JSON arrays.
- Uses a typed composite key for the .NET in-memory store.
- Adds regression tests for collision isolation and session continuity.
File summaries
| File | Description |
|---|---|
python/samples/04-hosting/foundry-hosted-agents/invocations/break_glass/main.py |
Updates the sample’s hosted session key format. |
python/packages/foundry_hosting/tests/test_invocations.py |
Tests collision isolation and repeated-session reuse. |
python/packages/foundry_hosting/agent_framework_foundry_hosting/_invocations.py |
Generates unambiguous hosted partition keys. |
dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/InMemoryAgentSessionStoreTests.cs |
Verifies composite identifier boundaries. |
dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/InMemoryAgentSessionStore.cs |
Replaces concatenated keys with a typed record key. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Vincent Biret (baywet)
left a comment
There was a problem hiding this comment.
Thanks for the contribution!
(to other reviewers, I've only reviewed the dotnet side of things)
| "Please ensure that the request is coming from a valid Foundry platform service." | ||
| ) | ||
| return f"{context.session_id}:{context.user_id}" | ||
| return json.dumps([context.session_id, context.user_id], separators=(",", ":")) |
There was a problem hiding this comment.
this is a wasteful way of creating this string, something like:
| return json.dumps([context.session_id, context.user_id], separators=(",", ":")) | |
| return f"[{context.session_id},{context.user_id}]" |
does the same, without importing json unnecessarily.
There was a problem hiding this comment.
Retained JSON serialization: opaque identifier strings need preserved component boundaries and escaping; direct interpolation is not equivalent. Added delimiter/escaping, streaming, and session-continuity coverage in 4451e8f.
There was a problem hiding this comment.
could we the list directly then?
There was a problem hiding this comment.
Not with the current contract: _partition_key() feeds both self._sessions: dict[str, AgentSession] (a list would be unhashable) and AgentSession(session_id=...), whose public session_id type is str | None. Keeping the boundary-safe pair as a compact JSON string preserves that opaque-string contract. We could instead use a tuple only for the internal dict and encode separately for AgentSession, but that would add a second key representation and broaden this fix.
Cover identifier boundaries, escaping, streaming, and session reuse. Fix missing test imports and document opaque hosted identifiers. Refs microsoft#8251 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 165465df-61e4-45eb-a147-08b425b4f5bd
Use tuple lookups in the session harness to avoid serialization and throwaway session construction on cache hits. Preserve existing JSON session identifiers by encoding only when a session is created. Refs microsoft#8251
Motivation & Context Hosted session stores must preserve the boundaries between agent, user, and conversation identifiers. Delimiter-based string keys allow distinct identifier tuples containing
:to collapse to the same cache entry, which can mix session state across requests. ### Description & Review Guide - What are the major changes? Python Invocations hosting now serializes hosted session/user identifiers as a compact JSON array, including the standalone break-glass example. The .NET Foundry in-memory store now uses a strongly typed composite key. Focused regression tests cover distinct colliding tuples and repeated-request continuity. - What is the impact of these changes? Distinct hosted identifier combinations remain isolated while existing local-mode keys and same-tuple session reuse stay unchanged. - What do you want reviewers to focus on? Please review the hosted key representation and the compatibility of null/empty agent and user components in the .NET store. ### Related Issue Fixes #8251 ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] All unit tests pass, and I have added new tests where possible - [x] The PR follows the Contribution Guidelines - [x] This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above). - [x] This is not a breaking change. If it is a breaking change, add thebreaking 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.