Foundry separates user identity from sandbox isolation
The September 22 Microsoft Agent Framework post, by Roger Barreto and Tao Chen, documents two controls that application developers must keep separate. User isolation identifies the user represented by a request. Hosted-session isolation identifies the VM-isolated environment in which an agent executes and retains files.
Foundry can resolve either value, or an application can supply it. For a direct caller, the service derives user identity from the caller’s Microsoft Entra token. For an application serving its own authenticated users, a trusted middle-tier service can provide a delegated identity. Separately, Foundry can allocate a hosted session when a request arrives, or the application can select an existing session by its agent_session_id.
The independence of those controls is the central architectural point. Selecting a user establishes whose request the platform is handling; selecting a session establishes which sandbox receives it. An application that deliberately directs two delegated users into the same session has selected a shared execution environment, even if those requests carry different user identities.
Microsoft’s hosted-agent documentation describes each session as a VM-isolated sandbox with persistent storage under $HOME and /files. The service can stop its compute when idle and restore saved state when the session resumes. The isolation boundary described here is between sessions: it does not create another VM boundary between users whom the application places inside one session.
Three kinds of continuity need separate treatment
There is a third concept alongside identity and sandbox placement: conversation history. A conversation contains messages, tool calls, and responses. A hosted session contains sandbox compute and persisted files. Microsoft’s session-management documentation explicitly says that reusing agent_session_id does not, by itself, replay earlier messages to the model.
| Control or object | What it identifies | What an application uses it for |
|---|---|---|
| The caller’s Entra identity or a delegated user identity | The user represented by the request | Applying the service’s user-scoping behavior |
agent_session_id | A particular hosted sandbox | Reusing uploaded files and persisted working state |
previous_response_id or a Responses conversation identifier | Conversation continuity | Carrying messages and tool-call history across turns |
An Agent Framework AgentSession object | Framework-side session state | Retaining values that subsequent framework calls send to Foundry |
These distinctions explain two failure modes that can otherwise look contradictory. An agent can return to the correct filesystem without receiving its previous conversational context. Conversely, a Responses request can continue a response chain while landing in a new sandbox if the caller has not also preserved the required session binding.
A Responses conversation object provides a documented convenience: Foundry automatically associates a stable hosted session with that conversation. That reduces the amount of session tracking the client must perform. It does not make conversation history and sandbox storage the same resource; it supplies a binding between them.
For an application that analyzes uploaded documents, the distinction determines what “continue” actually means. Continuing the chat requires conversation continuity. Continuing work on files requires sandbox continuity. If the application needs both, its request path must preserve both, either explicitly or through the documented conversation binding.
Separate sessions remain the default privacy choice
Microsoft’s per-user isolation guidance describes direct callers receiving identity-scoped sessions by default. Each session has its own private $HOME filesystem, and ordinary caller-scoped access does not expose another user’s conversations or sessions. This is the straightforward model for an agent endpoint shared by multiple people who should retain separate workspaces.
The delegated model gives the application more responsibility. Microsoft explicitly warns that the platform does not fence one delegated end user from another inside a session selected by the application. Its recommendation is to give each user a distinct session ID unless shared state is intentional.
That warning limits how developers should read the September 22 pooling example. Microsoft says response chains remain private by user while the sandbox filesystem remains shared. Those are different protections over different resources. A private conversation does not establish that every file a tool can open in the selected sandbox belongs only to that conversation’s user.
The useful decision is therefore concrete: choose separate hosted sessions when users require separate sandbox files, and use shared sessions only when the application has deliberately accepted and designed for shared session-scoped state. A distinct identity header alone cannot supply the missing filesystem boundary.
Delegated Foundry identity makes the middle tier responsible for trust
For direct access, Foundry already has an authenticated identity to work with: the Microsoft Entra identity on the request. Applications that authenticate their own customers need another arrangement. Microsoft documents a trusted middle tier that authenticates the application user, maps that user to a stable identifier, and forwards that identifier to Foundry.
The request header is:
x-ms-user-identity: <stable-end-user-id>
Foundry and Agent Framework treat this identifier as an opaque value. They do not establish the application’s user mapping for it. Microsoft’s guidance gives examples of applications using Google, GitHub, or a custom identity provider, but the same responsibility remains with the middle tier: the forwarded value must represent the user whom the application actually authenticated.
The identifier must contain between 1 and 256 characters. Microsoft permits letters, digits, and the characters ., _, :, -, and @; values outside the documented format are rejected. The guidance also says identifiers should be stable, unique, and hard to guess.
Stability has an operational purpose. Reusing the same value allows subsequent requests to return to the same user scope. Uniqueness has a security purpose: the application must not map different authenticated users onto one value unintentionally. Microsoft’s example of a tenant-scoped user ID is relevant to applications whose user identifiers are only unique within an individual tenant.
The identity header requires a specific permission
Sending a header is not enough to authorize delegation. The calling service identity must hold this data-plane permission:
Microsoft.CognitiveServices/accounts/AIServices/agents/endpoints/UserIdentityImpersonation/action
Microsoft’s per-user isolation documentation says this permission is absent from built-in roles. It must be granted explicitly through a custom role assigned to the trusted middle-tier service identity. A caller that sends x-ms-user-identity without the permission receives HTTP 403.
There is also a documented change that existing deployments should notice: the broad Microsoft.CognitiveServices/* data action previously covered this permission, but no longer grants it. A service that relied on that coverage needs the explicit delegation action. The September 22 post does not establish when that permission change took effect, so it should not be treated as a change introduced on the post’s publication date.
The security consequence of granting the action is substantial. Microsoft says a service holding it can act on behalf of any end user. Assigning the role therefore means trusting the service’s authentication, identity mapping, and request construction—not merely allowing it to invoke an agent.
The exact custom-role definition and assignment commands are not included in the available guidance excerpts. The established requirement is nevertheless specific: grant the named data action to the middle-tier identity through a custom role. Substituting a broader built-in role is not the documented remedy for a delegation-related 403.
The browser must not choose the delegated identity
Microsoft’s instruction is explicit: derive x-ms-user-identity from an authenticated, server-side identity. Do not accept its value directly from a browser or another untrusted client. Otherwise, a caller could substitute another user’s identifier and potentially access that user’s data.
This is where the application’s authorization boundary sits. Foundry receives a request from a service trusted to delegate identity; the middle tier must ensure that its claim about the end user is correct. A syntactically valid header proves neither that the browser owns the identifier nor that the user is entitled to the selected session.
Session selection needs equally careful treatment. Microsoft’s warning that delegated users can enter application-created sessions means the middle tier must maintain the intended association between authenticated users and hosted-session IDs. Identity mapping and sandbox routing are two parts of the same application request, even though Foundry exposes them as independent controls.
If the service has delegation permission but omits the header, Foundry scopes the request to the service’s own identity. The documented behavior is a fallback to non-delegated service scope, not automatic inference of the application user. A missing header can therefore change the request’s identity without producing the same error as an unauthorized header.
For developers, the diagnostic difference matters. A 403 on a request carrying the header points toward the explicit delegation permission. A successful request that behaves as the service rather than the end user points toward the identity value being absent or incorrectly propagated. Treating both cases simply as “authentication failed” loses the distinction the platform exposes.
Shared pools preserve an application-owned boundary
In Microsoft’s pooled design, the middle tier maps users to a bounded set of hosted-session IDs and sends the delegated identity on each request. That permits intentional reuse of a smaller set of workspaces. It also means that several users can encounter the same sandbox filesystem.
The September 22 post suggests using both agent_session_id and user identity when partitioning application-owned files, database rows, and caches. This supplies two useful dimensions: which workspace holds the data, and which user owns it. A session ID alone cannot distinguish users inside a shared session.
That partitioning remains application logic. It should not be described as another VM security boundary or as proof that arbitrary code in a shared sandbox cannot reach other files there. The platform’s documented session boundary remains the sandbox itself; the application is responsible for how shared data inside that boundary is handled.
The evidence supports pooling as a design option, not a universal optimization. Microsoft has not supplied comparative cost or latency measurements here. Developers can assess whether bounded allocation suits their workload, but should not trade away separate sandboxes on the assumption that this announcement establishes a quantified performance benefit.
Agent Framework’s.NET and Python APIs retain different request state
Microsoft’s examples show the same Foundry model through two framework interfaces, with an important difference in identity handling. In.NET, the delegated identity is stored with the Agent Framework session. In the Python interface shown, the identity is supplied on each invocation.
The snippets below are integration fragments, not complete deployment programs. They assume an existing configured agent client, authenticated application users, and—when delegation is used—the explicit impersonation permission. Session-precreation examples also assume a configured Foundry project client and an existing agent name and version.
These prerequisites matter because framework-side state does not replace Foundry-side authorization. Creating an AgentSession object cannot grant the application delegation rights, authenticate an end user, or establish that a selected shared sandbox is appropriate for that user.
.NET keeps the delegated identity with the framework session
Microsoft’s.NET example uses CreateFoundryHostedAgentSessionAsync with the userIdentity argument:
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Foundry;
ChatClientAgentSession userConversationSession =
await agent.CreateFoundryHostedAgentSessionAsync(
userIdentity: userIdentity);
await agent.RunAsync(
"Analyze the uploaded files.",
userConversationSession);
string? delegatedUserIdentity =
userConversationSession.FoundryHostedAgentUserIdentity;
Agent Framework stores the delegated identity on the session. Reusing or restoring that session sends the same identity on subsequent runs, according to Microsoft’s September 22 post. The exposed FoundryHostedAgentUserIdentity property lets application code read the value associated with it.
The practical implication follows directly from that persistence: restoring a framework session also restores its identity association. An application must select the framework session that belongs to the authenticated user it intends to represent. Treating a previously populated session object as an interchangeable container would overlook state that affects later requests.
The helper’s name also needs careful reading. Microsoft says the Agent Framework object does not itself create the remote hosted session. With no hosted-session ID attached, the service creates the remote session on the first invocation and returns its identifier.
That separates two events which can otherwise be confused during debugging: creating local framework state and allocating remote sandbox state. A successful call that constructs a framework session is not, on its own, evidence that a Foundry sandbox has already been allocated or that files can already be uploaded to it.
Python forwards delegated identity with each invocation
Microsoft’s Python example attaches the identity through client_kwargs and an extra request header:
await agent.run(
"Analyze the uploaded files.",
session=user_conversation_session,
client_kwargs={
"extra_headers": {
"x-ms-user-identity": user_identity,
}
},
)
The current interface shown forwards that value per call. Developers should not assume the.NET behavior—retaining the delegated identity on the framework session—also applies to this Python example. The published Python invocation explicitly supplies the header.
For a multi-turn workflow, every delegated call must carry the intended identity through the documented request path. The service’s missing-header behavior still applies: an authorized middle tier that omits x-ms-user-identity makes a request scoped to its own service identity.
The difference is particularly relevant when application code has multiple invocation paths. An initial document-analysis call and a later follow-up both need the correct identity. Retaining the same Python session object handles session-related state shown in Microsoft’s examples; it does not justify dropping the separately supplied delegated-identity header.
These examples describe pre-release APIs as published on September 22. Microsoft has not identified a stable Agent Framework hosting-package release in this announcement. Teams using these interfaces should distinguish the service’s general availability from the maturity of the SDK surface they are compiling or importing.
Precreating a hosted session gives files somewhere to go
An application can let Foundry allocate a session on demand. Alternatively, it can create the remote hosted session through the Foundry project client before invoking the agent. Microsoft identifies advance file upload, explicit lifecycle management, stable workload placement, and bounded session pools as reasons to choose the latter.
The.NET creation example is:
using Azure.AI.Projects;
using Azure.AI.Projects.Agents;
ProjectAgentSession foundryHostedSession =
await projectClient.AgentAdministrationClient.CreateSessionAsync(
agentName,
new VersionRefIndicator(agentVersion));
string foundryHostedSessionId =
foundryHostedSession.AgentSessionId;
The returned ID refers to the service-created resource. It can then be attached to a framework session using the documented hostedSessionId argument:
ChatClientAgentSession session =
await agent.CreateFoundryHostedAgentSessionAsync(
hostedSessionId: foundryHostedSessionId);
await agent.RunAsync("Analyze the uploaded files.", session);
string? resolvedFoundryHostedSessionId =
session.FoundryHostedAgentSessionId;
This fragment illustrates sandbox selection. It does not, by itself, add delegated identity; a middle-tier application using delegation must also supply the documented userIdentity value. Keeping those concerns explicit prevents a session-routing example from being mistaken for a complete user-isolation implementation.
The corresponding Python creation path uses the project client’s create_session method:
from azure.ai.projects.models import VersionRefIndicator
foundry_hosted_session = await project_client.agents.create_session(
agent_name,
version_indicator=VersionRefIndicator(
agent_version=agent_version,
),
)
foundry_hosted_session_id = (
foundry_hosted_session.agent_session_id
)
Agent Framework’s Python session stores that identifier under a named state key:
from agent_framework import AgentSession
from agent_framework.foundry import (
FOUNDRY_HOSTED_AGENT_SESSION_ID_KEY,
)
session = AgentSession()
session.state[
FOUNDRY_HOSTED_AGENT_SESSION_ID_KEY
] = foundry_hosted_session_id
await agent.run(
"Analyze the uploaded files.",
session=session,
)
resolved_session_id = session.state[
FOUNDRY_HOSTED_AGENT_SESSION_ID_KEY
]
Again, this is the session-binding portion of the integration. For delegated calls, the Python invocation also needs the identity header shown earlier. Supplying a hosted-session ID does not replace that header, and supplying the header does not choose a sandbox.
For on-demand allocation, Microsoft’s examples omit the existing hosted-session ID. Foundry creates the remote session at invocation time, and Agent Framework retains the returned value. Later calls through that framework session can then return to the same persisted files and working state.
Precreation and on-demand allocation therefore lead to the same kind of hosted resource through different lifecycle choices. Precreation establishes the destination before execution, which is useful when files must arrive first. On-demand creation defers allocation until work actually reaches the agent.
Responses and Invocations bind Foundry sessions differently
The Foundry session-management documentation describes two invocation protocols, and they place the hosted-session identifier in different parts of a request. This is an operational detail with visible consequences: an identifier sent in the wrong place may reach container code without controlling the sandbox that Foundry selected.
For the Responses protocol, agent_session_id belongs in the request body. A Responses conversation identifier can instead provide the automatic session binding described earlier. For the Invocations protocol, the session identifier belongs in the query string.
| Protocol | Documented session-binding location | Conversation-history behavior |
|---|---|---|
| Responses | The request-body field agent_session_id, or a conversation that automatically binds a session | Foundry supports history through response chaining or a conversation object |
| Invocations | The query parameter agent_session_id | Container code manages the history or state its agent needs |
For Invocations, Microsoft is unusually explicit about the wrong alternatives. Body fields named agent_session_id or session_id, and headers such as x-agent-session-id, are forwarded to the container but do not influence sandbox routing. Seeing the expected value inside application code is therefore insufficient proof that the platform routed to that session.
This explains why missing files can be a routing problem rather than a persistence problem. If a later invocation reaches a newly allocated sandbox, files from the previous session are not the files of the current workspace. The first check is whether the intended session ID reached the protocol-specific routing location.
Response history alone does not generally select the sandbox
Microsoft’s general Responses guidance separates previous_response_id from agent_session_id. The previous response identifier threads the conversation. When files or $HOME state must be reused, the documented approach also includes the hosted-session ID.
A conceptual Responses follow-up therefore carries two different references:
{
"input": "Continue analyzing the uploaded files.",
"agent_session_id": "<session-id-from-first-response>",
"previous_response_id": "<id-from-first-response>"
}
The two values solve different continuity problems. The response reference carries conversational context; the session reference selects the environment containing the uploaded files. Neither should be silently substituted for the other.
There is one discrepancy within Microsoft’s session-management page worth making visible. Its general instructions say invoke endpoints do not infer the session from previous_response_id alone. A.NET example on that same page says that using PreviousResponseId routes the call to the same session, but the displayed example does not explicitly pass a hosted-session ID.
The available evidence does not explain that difference. It would be unsafe to generalize the.NET example into a protocol-wide guarantee. For file-dependent workflows, the explicit session-binding rules and Agent Framework’s documented attached-session-ID behavior provide the clear basis for implementation; the deployed session’s identity should then be checked.
A conversation object can manage the binding
The alternative Responses workflow creates a conversation object and passes its identifier on subsequent requests. Microsoft says the platform stores the message history under that conversation ID and automatically associates a stable agent_session_id with it.
This is useful when a conversation and its workspace should advance together. The client does not have to manually attach the session ID to every Responses request using that conversation. The convenience is narrower than saying “all chat history automatically restores files”: it depends on the documented conversation mechanism.
An application that uses previous_response_id instead still needs to account for the separate session binding when persisted files matter. An application that intentionally wants stateless invocations can let calls receive fresh sessions. The appropriate choice follows from whether subsequent turns require the previous workspace.
Invocations has a different contract. Foundry does not store conversation history for that protocol; the container is responsible for the state the agent needs across turns. A stable hosted session can preserve filesystem state, but it does not add Responses-style conversation management to an Invocations container.
The response format also varies. Microsoft’s samples and containers built with the AgentServer Invocations SDK use a Server-Sent Events stream whose terminal done event carries a session_id. A custom container can return other formats, so that parsing procedure must not be treated as universal for every Invocations implementation.
Foundry persistence survives idle compute, within a defined lifecycle
Hosted-session reuse has a lifecycle beyond the duration of one model response. Microsoft’s session-management documentation says sessions persist for up to 30 days. It separately defines an idle timeout that controls when sandbox compute is deprovisioned and state is saved.
Those are different clocks. Reaching the idle timeout does not mean the application should automatically discard the session ID and create a replacement. Foundry can provision compute again and restore saved state when the existing session is referenced.
The documented idle-timeout range is 120 to 3,600 seconds, or two to 60 minutes. The default is 900 seconds, or 15 minutes. These values apply to the agent version’s session configuration rather than serving as a per-invocation conversation setting.
Microsoft’s hosted-agent description calls this scale-to-zero with stateful resume. That supports the practical expectation that a session can outlive its currently running compute. It does not establish a measured cold-start latency, nor does the material provide a benchmark comparing separate sessions with shared pools.
Changing the timeout requires a new agent version
Microsoft documents the Azure Developer CLI configuration under the hosted service in azure.yaml:
services:
my-agent:
host: azure.ai.agent
kind: hosted
sessionConfiguration:
idleTimeoutSeconds: 120
The corresponding deployment command is:
azd deploy
The Foundry agents extension maps sessionConfiguration.idleTimeoutSeconds to the hosted agent version’s session_configuration.idle_timeout_seconds property. Microsoft says this applies to both code and container deployment modes.
The 120-second minimum requires azure.ai.agents extension version 1.0.0-beta.14 or later. The documented extension installation or update command is:
azd ext install azure.ai.agents
Omitting sessionConfiguration leaves the property out of the request and allows the service to use its 900-second default. To change the timeout, Microsoft says to create another agent version with the new value. The setting applies to sessions created for that version; the documentation does not establish that changing it rewrites the behavior of existing sessions.
The Python SDK and REST API also expose session configuration during version creation. Microsoft’s session-management page says the.NET SDK’s HostedAgentDefinition does not yet expose the corresponding property, so developers using.NET must use one of the supported configuration paths rather than inventing an equivalent.NET property.
That gap is a concrete example of why service availability and SDK maturity need separate evaluation. The service can support a capability before every language’s typed management interface exposes it. The correct implementation choice is determined by the documented interface, not by assuming feature parity.
Persistent files do not imply indefinite retention
“Up to 30 days” is a lifecycle limit, not a promise of unlimited workspace retention. The supplied documentation does not establish the exact expiry calculation or a recovery procedure after expiry. Applications should therefore avoid presenting hosted-session persistence as indefinite storage.
The persistence described is also specific: $HOME, uploaded files, and saved session state that the platform restores. It should not be expanded into a promise that arbitrary in-memory process state remains continuously alive while compute is deprovisioned.
For workflow design, that means using the hosted session for its documented purpose: retaining the working environment across turns and idle periods. A session ID remains a reference to that environment within the service’s lifecycle, rather than becoming a permanent application record simply because it can be stored in a database.
The independent controls allow an application to retain a stable user identity while choosing new sessions for different workloads. They also allow multiple conversations to target the same existing workspace. Those are supported routing choices, but neither extends the documented lifetime of the hosted resource.
Deployed Foundry tests must verify identity and session routing together
Microsoft’s isolation guidance provides a straightforward verification procedure, but it must run against a deployed hosted agent. Local execution does not enforce the same isolation behavior. Agent Framework’s hosting documentation likewise says Foundry supplies caller and call context in the hosted environment, while local applications must provide their own identity and state controls when needed.
For the current model, the deployment also needs container protocol 2.0.0. Microsoft’s per-user isolation documentation says protocol 1.0.0, which used caller-supplied isolation keys, is no longer supported and requests to agents still using it are blocked.
The documented minimum AgentServer versions are Python azure-ai-agentserver-core 2.0.0b7 and.NET Azure.AI.AgentServer.Core 1.0.0-beta.26, or later versions. Earlier versions use protocol 1.0.0, according to Microsoft’s guidance. These are AgentServer requirements; they are not version numbers for every Agent Framework package involved in the application.
Microsoft’s May 6 deployment post described per-session VM isolation and the earlier use of isolation keys. The current guidance makes identity derivation and delegated user identity the relevant model for protocol 2.0.0. Developers updating an older implementation need to account for that documented before-and-after rather than merely copying a newer invocation snippet into an unchanged container deployment.
Verify the default separate-session design first
The documented test requires a deployed agent, authenticated callers, and the relevant project permissions. For delegated requests, the calling middle tier also needs the explicit UserIdentityImpersonation action. Microsoft’s CLI invocation path uses the signed-in identity; its guidance directs delegated identity tests through the service’s REST or SDK path.
The basic procedure is:
- Invoke the deployed agent as one identity and record the returned
agent_session_id. - Invoke it as a second identity, using either another signed-in caller or another server-derived delegated identity.
- Confirm that the two identities receive different session IDs for the separate-session design.
- List sessions in each caller-scoped context and confirm that the results are restricted to the intended identity.
- Use Microsoft’s note-taking sample, if testing that sample deployment, to verify that notes stored under
$HOMEland in separate session files.
The expected result is more than two successful responses. The session IDs should demonstrate separate routing, and the file behavior should demonstrate that each user’s workspace is separate. Microsoft’s sample makes that visible through notes that only the corresponding identity can list or download through the Session Files API.
The same success criteria do not describe an intentionally pooled design. If the middle tier deliberately chooses one session for several users, matching session IDs are expected. The application then needs to evaluate its shared-state behavior against the platform’s warning that those users can see session-scoped data.
Administrative access adds another scope distinction. Microsoft’s documentation says an administrator or automation holding the Foundry User role on the project can list and manage sessions across identities. An administrative listing is therefore not equivalent to the ordinary caller-scoped view used to demonstrate end-user separation.
The role names may also look different in existing environments. Microsoft says Foundry User was previously named Azure AI User, alongside related role renames, with role IDs and core permissions unchanged. The display-name transition should not be mistaken for a new grant of delegation rights: the impersonation action still requires its explicit custom-role assignment.
Diagnose failures by the boundary that failed
A failed deployment, a rejected identity header, and an agent that cannot find an uploaded file are different problems. Microsoft’s documented symptoms provide a way to separate them without weakening authorization or changing unrelated settings.
| Symptom | Documented explanation or relevant check | Supported response |
|---|---|---|
A request with x-ms-user-identity returns 403. | The caller may lack the explicit impersonation action. | Assign the required data action through a custom role to the trusted service identity. |
Session access returns 403 or session_not_accessible. | The session may belong to a different identity. | Use the identity that created the session, or authorized administrative access where appropriate. |
| A delegated service request behaves as the service itself. | Omitting the identity header scopes the request to the service. | Check that the documented invocation path supplies the intended server-derived identity. |
| An Invocations call reaches a workspace without the expected files. | A session ID in a body field or header does not control routing. | Put the intended ID in the documented query parameter. |
| A Responses follow-up has conversation context but lacks workspace files. | Response chaining and session binding are separate. | Preserve the hosted-session binding as well as conversation continuity. |
| Local execution does not demonstrate per-user isolation. | Local mode lacks the hosted isolation behavior. | Perform isolation verification against the deployed agent. |
| An older hosted agent has requests blocked. | Container protocol 1.0.0 is unsupported. | Upgrade to protocol 2.0.0 with a supporting AgentServer SDK. |
The table identifies checks, not proof that every matching symptom has one cause. The permission-related 403 and the identity-related 403 are already distinct in Microsoft’s own guidance. Looking at whether the request carries delegated identity and which session it targets helps preserve that distinction.
No rollback to container protocol 1.0.0 is a supported escape route in this material. Microsoft says requests to that protocol are blocked. Similarly, removing the identity header to make a delegated request succeed changes the request’s scope to the service; it does not repair end-user delegation.
Choose separate Foundry sessions unless shared state is intentional
Teams building private per-user agents should begin with distinct hosted-session IDs and retain the correct user identity throughout the request path. That uses the platform’s documented default separation and avoids taking responsibility for shared sandbox data before the application actually needs that design.
Teams that already use a trusted middle tier should review two mappings: authenticated user to delegated identity, and intended workload to hosted-session ID. The.NET and Python differences make this a language-specific review. In.NET, restored framework sessions carry the stored delegated identity; in the shown Python API, the invocation supplies it each time.
Pooling remains available for applications that deliberately share session-scoped resources. Its adoption should be justified by the workload and its data model, rather than an assumption that user-scoped response chains also isolate files. The evidence establishes the supported architecture but does not quantify a financial or performance advantage.
For existing deployments, the immediate priority is compatibility and permission correctness. An older isolation-key implementation, a service relying on wildcard delegation coverage, and a Python call path that drops its identity header require different changes. None is resolved merely by knowing that hosted agents are generally available.
- Keep separate
agent_session_idvalues for users who require separate sandbox files; different delegated identities alone do not provide that filesystem boundary. - Derive
x-ms-user-identityfrom authenticated server-side state and grant its explicit impersonation action only to a trusted middle-tier service. - Preserve conversation continuity and sandbox continuity separately, unless using the documented Responses conversation binding that manages their association.
- Check the actual SDK behavior in each language:.NET retains delegated identity with the framework session, while the published Python interface forwards it per invocation.
- Verify container protocol
2.0.0, the documented AgentServer minimum versions, and isolation behavior against a deployed agent rather than relying on local execution. - Treat session pooling and the up-to-30-day persistence lifecycle as explicit application design choices, with shared-state handling and retention expectations defined accordingly.
Foundry’s September guidance gives developers a precise way to reason about hosted agents: identity determines whom a request represents, while session selection determines where its code and files run. Keeping those decisions separate allows useful flexibility without overstating the protection of either control. For production applications, the consequential next step is to verify that the deployed service routes each authenticated user to the intended workspace—and to make every shared workspace a deliberate choice.