Skip to content

feat(agent-framework): Add Purview policy enforcement and pin compatible package versions#274

Open
Rishabh4275 wants to merge 3 commits intomicrosoft:mainfrom
Rishabh4275:main
Open

feat(agent-framework): Add Purview policy enforcement and pin compatible package versions#274
Rishabh4275 wants to merge 3 commits intomicrosoft:mainfrom
Rishabh4275:main

Conversation

@Rishabh4275
Copy link
Copy Markdown

@Rishabh4275 Rishabh4275 commented Apr 14, 2026

Summary

Adds optional Microsoft Purview policy enforcement to the Agent Framework samples (Python and .NET) and migrates both samples to the latest Agent Framework SDKs.

.NET (dotnet/agent-framework/sample-agent/)

SDK & runtime upgrades

  • Target framework upgraded net8.0net10.0.
  • Microsoft.Agents.AI upgraded 1.0.0-preview.251113.11.3.0 (stable).
  • Azure.Identity upgraded 1.17.01.21.0.
  • New dependency: Microsoft.Agents.AI.Purview 1.3.*-*.

Migration to the 1.3.0 agent API (Agent/MyAgent.cs)

  • Switched from the options-based ChatClientAgent(ChatClientAgentOptions) constructor to the new (chatClient, instructions, name, description, tools) constructor.
  • Migrated AgentThreadAgentSession (GetNewThread / DeserializeThreadCreateSessionAsync / DeserializeSessionAsync / SerializeSessionAsync). The thread-management helper is now GetConversationSessionAsync.
  • Dropped the ChatMessageStoreFactory + MessageCountingChatReducer(10) setup — chat history is now managed by the new AgentSession API.

Purview integration

  • New file: PurviewUserIdStampingClient.cs — a DelegatingChatClient that stamps every ChatRole.User message with AdditionalProperties["userId"] before it reaches the Purview middleware. Required because ClientSecretCredential is an app-level token from which Purview cannot infer the user.
  • Program.csWithPurview() is added to the IChatClient pipeline using ClientSecretCredential. Opt-in: only enabled when Purview:ClientAppId, AppName, TenantId, and ClientSecret are all set; gracefully skipped otherwise.
  • appsettings.json / appsettings.Playground.json — added a Purview section (ClientAppId, AppName, TenantId, ClientSecret, UserId).

Streaming + thread-history fixes for Purview-blocked turns (Agent/MyAgent.cs)

  • Streaming handler no longer filters on ChatRole.Assistant. Purview emits its block message as a System / Tool chunk; the previous filter silently swallowed it. All non-empty text chunks are now forwarded.
  • Conversation thread state is snapshotted before the run and restored if no assistant chunk was streamed (i.e. Purview blocked the turn). This prevents the blocked prompt from being baked into history and re-blocked on every subsequent turn.
  • Added a friendly fallback ("No response was produced for that request...") when the SDK streams nothing at all, instead of letting EndStreamAsync throw a bare exception to the user.

Python (python/agent-framework/sample-agent/)

Chat client switch (agent.py, AGENT-CODE-WALKTHROUGH.md)

  • Migrated from agent_framework.azure.AzureOpenAIChatClientagent_framework.openai.OpenAIChatClient configured for Azure (azure_endpoint, api_version).
    • Avoids a AzureOpenAIChatClient -> /openai/deployments/... API surface mismatch with the latest Azure OpenAI v1 endpoint, which only accepts api-version=preview on /openai/v1/responses.
  • Migrated from ChatAgentAgent (the renamed top-level class in current agent-framework).
  • Supports both API key and AzureCliCredential auth, selected by presence of AZURE_OPENAI_API_KEY.

Purview integration (agent.py)

  • New _build_purview_middleware() wires PurviewPolicyMiddleware into the Agent at creation time.
  • Opt-in: only enabled when PURVIEW_CLIENT_APP_ID is set; logs "ℹ️ Purview not configured" and continues without it otherwise.
  • Three auth modes (priority order): client secret → certificate → interactive browser.
  • process_user_message now wraps the user input in a Message with additional_properties={"user_id": ...}. The user id is resolved from the activity's aad_object_id if it's a valid UUID, falling back to PURVIEW_DEFAULT_USER_ID (covers Agents Playground, which sends synthetic non-GUID user ids).
  • New _valid_guid() helper validates user-id strings before they're sent to Purview.

DISABLE_MCP escape hatch (agent.py, .env.template)

  • setup_mcp_servers() now honors DISABLE_MCP=true and skips MCP tool registration entirely. Useful for local Agents Playground runs where the cloud MCP servers reject requests because the playground has no real M365 tenant context.

Dependencies (pyproject.toml)

  • Added agent-framework (top-level package, required for the renamed Agent class).
  • Added agent-framework-purview (Purview middleware).

Configuration template (.env.template)

  • New Purview Policy Enforcement section documenting all PURVIEW_* env vars and the three auth modes.
  • New DISABLE_MCP toggle with a comment explaining when to use it.

How to test

Python

  1. pip install -e . (or uv pip install --prerelease=allow -e .) in python/agent-framework/sample-agent/.
  2. Without Purview: leave PURVIEW_CLIENT_APP_ID empty → agent boots and logs "ℹ️ Purview not configured".
  3. With Purview: set PURVIEW_CLIENT_APP_ID, PURVIEW_CLIENT_SECRET, PURVIEW_TENANT_ID → agent logs "✅ Purview policy middleware enabled" and Purview is consulted on every turn.
  4. Playground: set DISABLE_MCP=true to skip MCP registration.

.NET

  1. Build: dotnet build dotnet/agent-framework/sample-agent/AgentFrameworkSampleAgent.csproj (requires .NET 10 SDK).
  2. Set ASPNETCORE_ENVIRONMENT=Playground and fill in appsettings.Playground.json.
  3. Run: dotnet run --project dotnet/agent-framework/sample-agent/AgentFrameworkSampleAgent.csproj.
  4. Without Purview: leave Purview values as "---" → agent runs without the middleware.
  5. With Purview: fill in all five Purview fields → blocked prompts surface "Prompt blocked by policies" to the user, and a normal follow-up message proceeds without being poisoned by the blocked turn.

@Rishabh4275 Rishabh4275 requested a review from a team as a code owner April 14, 2026 22:34
Copilot AI review requested due to automatic review settings April 14, 2026 22:34
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

Note

Copilot was unable to run its full agentic suite in this review.

Adds optional Microsoft Purview policy enforcement to the Python Agent Framework sample while pinning SDK package versions to a known-compatible set to prevent upstream import/rename breakages.

Changes:

  • Pin agent-framework-* and microsoft_agents_a365_* dependencies to specific compatible versions and document why.
  • Add opt-in Purview policy middleware initialization with multiple auth modes.
  • Attach a resolved AAD user GUID to each message via ChatMessage.additional_properties for Purview evaluation.

Reviewed changes

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

File Description
python/agent-framework/sample-agent/pyproject.toml Pins Agent Framework + A365 SDK versions and adds rationale/comments for the constraints.
python/agent-framework/sample-agent/agent.py Adds Purview middleware setup and passes a validated user GUID in message metadata.
python/agent-framework/sample-agent/.env.template Documents and templates Purview configuration and supported auth modes.

Comment thread python/agent-framework/sample-agent/agent.py Outdated
Comment thread python/agent-framework/sample-agent/agent.py Outdated
Comment thread python/agent-framework/sample-agent/agent.py Outdated
Comment thread python/agent-framework/sample-agent/.env.template Outdated
@Rishabh4275 Rishabh4275 changed the title feat(python/agent-framework): Add Purview policy enforcement and pin compatible package versions feat(agent-framework): Add Purview policy enforcement and pin compatible package versions Apr 15, 2026
@Rishabh4275 Rishabh4275 force-pushed the main branch 4 times, most recently from 16579ff to 1b27609 Compare April 29, 2026 06:36
@Rishabh4275 Rishabh4275 force-pushed the main branch 2 times, most recently from a75c615 to a7b2125 Compare April 29, 2026 20:16
@Rishabh4275 Rishabh4275 force-pushed the main branch 2 times, most recently from 6d7d125 to 7b81d5d Compare April 29, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants