mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
feature/python-hosting
4 Commits
-
.NET: Bump Azure.AI.Projects to 2.1.0-beta.2 and add agent-endpoint AsAIAgent path (#5899)
* .NET: Bump Azure.AI.Projects to 2.1.0-beta.2 and add agent-endpoint AsAIAgent path Bumps Azure.AI.Projects to 2.1.0-beta.2 with the matching transitive pins (Azure.Core 1.55.0, System.ClientModel 1.11.0). Foundry agent endpoint plumbing: * FoundryAgent now routes the agent-endpoint constructor through the new GetProjectResponsesClientForAgentEndpoint helper. * Adds an internal FoundryAgent ctor that takes an existing AIProjectClient plus a parsed agent endpoint so the public extension does not need to construct a second project client. * Adds public AIProjectClient.AsAIAgent(Uri agentEndpoint, ...) extension. This is the path consumer samples are expected to use for hosted agents because version selection happens server-side. * Trims the dangling "If you want to construct a FoundryAgent against a project endpoint..." sentence from ParseAgentEndpoint. Unit tests: * Four new tests in AzureAIProjectChatClientExtensionsTests cover the AIProjectClient.AsAIAgent(Uri agentEndpoint, ...) overload. 263/263 pass. Consumer samples (Using-Samples): * SimpleAgent and SessionFilesClient now read AZURE_AI_PROJECT_ENDPOINT and AZURE_AI_AGENT_NAME (both required, throw on missing), derive the agent endpoint with new Uri($"{projectEndpoint}/agents/{agentName}/endpoint/protocols/openai"), then call aiProjectClient.AsAIAgent(agentEndpoint, ...). * SessionFilesClient README updated. Contributor samples (responses/*): * New HostedContributorRouteExtensions.MapDevTemporaryLocalAgentEndpoint() wildcard route extension so localhost contributor servers accept the per-agent OpenAI endpoint shape the production Hosted runtime exposes. * All 11 contributor Program.cs files call MapDevTemporaryLocalAgentEndpoint() with a contributor-only warning comment. * Hosted-Files and Hosted-AzureSearchRag were importing Hosted_Shared_Contributor_Setup but never calling AddDevTemporaryLocalContributorSetup(). Both now call it so HostedSessionIsolationKeyProvider resolves correctly in dev. * Hosted-AzureSearchRag, Hosted-Files, Hosted-MemoryAgent csprojs drop stale VersionOverride="2.1.0-beta.1" pins. * Hosted-AzureSearchRag and Hosted-Files csprojs add ProjectReference to Hosted_Shared_Contributor_Setup. * Hosted-Observability/.dockerignore removed the out/ exclusion that was blocking COPY out/ . in Dockerfile.contributor. Verified: * Full solution-scoped build of changed projects: green. * Scoped CI-parity dotnet format via WSL2 + Docker (mcr.microsoft.com/dotnet/sdk:10.0) over every changed csproj: clean. * Foundry unit tests: 263/263. * Contributor docker smoke for 8 hosted samples (publish + docker build + docker run + curl POST to the wildcard route): HTTP 200 / 500 with route matched. * End-to-end smoke against the real Azure Foundry project with a fresh bearer token: Hosted-Files contributor container served HTTP 200, the agent invoked ListBundledFiles, and returned the expected file name. * Address PR review: forward pipeline settings; add UTs - CreateProjectClientOptions also carries RetryPolicy, NetworkTimeout, ClientLoggingOptions, MessageLoggingPolicy (was Transport+UserAgentApplicationId only). - Make CreateProjectClientOptions internal so tests can verify the copy directly. - Add AsAIAgent(Uri) UTs covering tools forwarding to inner ChatOptions and null tools handling. - Add CreateProjectClientOptions UTs covering null caller and full pipeline-settings copy.Roger Barreto ·
2026-05-18 20:20:56 +00:00 -
.NET: Add Hosted-MemoryAgent sample with isolation key plumbing (#5692) (#5702)
* .NET: Add Hosted-MemoryAgent sample with isolation key plumbing (#5692) Adds HostedSessionContext + HostedSessionIsolationKeyProvider in Microsoft.Agents.AI.Foundry.Hosting so AIContextProviders (notably FoundryMemoryProvider) can scope per user via the platform's x-agent-user-isolation-key / x-agent-chat-isolation-key headers. - New types: HostedSessionContext (sealed), HostedSessionContextExtensions (public Get, internal Set), abstract HostedSessionIsolationKeyProvider (async), internal PlatformHostedSessionIsolationKeyProvider mapping ResponseContext.Isolation. - AgentFrameworkResponseHandler now resolves the provider, tags fresh sessions, and validates resumed sessions against the live request (strict 403 'Hosted session identity context mismatch' on any mismatch; 500 on null keys). - New shared sample project Hosted_Shared_Contributor_Setup hosts DevTemporaryTokenCredential and DevTemporaryLocalSessionIsolationKeyProvider plus AddDevTemporaryLocalContributorSetup. All 9 existing responses samples migrated to consume it so local runs keep working under the strict isolation contract. - New Hosted-MemoryAgent sample: travel assistant wired through FoundryMemoryProvider with stateInitializer reading session.GetHostedContext().UserId. Includes Dockerfile, smoke.ps1, agent.yaml/manifest. - New IT scenario 'memory' in Foundry.Hosting.IntegrationTests + MemoryHostedAgentFixture + MemoryHostedAgentTests. Verified end to end against the tao Foundry project. - ADR 0026 captures the design tree. * Address PR review feedback - Dockerfile: add header noting it targets NuGet builds; contributors must use Dockerfile.contributor for ProjectReference source builds. - PlatformHostedSessionIsolationKeyProvider: doc said 'returns context with empty values'; corrected to 'returns null' which the handler treats as 500. - FakeHostedSessionIsolationKeyProvider: doc clarifies that null configurations are allowed for testing the handler error path. - HostedSessionContextExtensions.SetHostedContext: enforce write-once with InvalidOperationException; doc + xml exception updated. - AgentFrameworkResponseHandler: cache PlatformHostedSessionIsolationKeyProvider as static readonly to avoid per-request allocation. - MemoryHostedAgentTests: tighten waits from 20s to 5s (FoundryMemoryProvider defaults UpdateDelay=0; ingestion ~3s). - Sample Program.cs imports reordered to satisfy IDE0005. * Add HostedFoundryMemoryProviderScopes built-in helpers (#5692) Addresses review feedback from @lokitoth on Hosted-MemoryAgent/Program.cs:54. - New HostedFoundryMemoryProviderScopes static class with PerUser, PerChat, PerUserAndChat factories returning Func<AgentSession?, FoundryMemoryProvider.State>. - All helpers throw InvalidOperationException when GetHostedContext() is null, with a message pointing at writing a custom stateInitializer for non-hosted scenarios. - New HostedFoundryMemoryScope enum and AddHostedFoundryMemoryProvider DI extension (two overloads: explicit AIProjectClient and DI-resolved). Singleton lifetime. Default scope = PerUser. - Hosted-MemoryAgent sample and the memory IT scenario container both swap their inline lambdas for HostedFoundryMemoryProviderScopes.PerUser(). - 14 new unit tests (241/241 hosting unit tests pass). * Replace HostedFoundryMemoryScope enum with Func<...> parameter (#5692) Address PR review feedback from @westey-m: enums are a breaking-change hazard when extended, and the enum was redundant with the existing HostedFoundryMemoryProviderScopes static class. - Delete HostedFoundryMemoryScope.cs. - AddHostedFoundryMemoryProvider DI extensions now take Func<AgentSession?, FoundryMemoryProvider.State>? stateInitializer = null. When null, default to HostedFoundryMemoryProviderScopes.PerUser(). - Callers pick a built-in helper (PerUser/PerChat/PerUserAndChat) or pass a custom delegate. New built-ins are a single static method addition with zero impact on existing callers. - Tests updated; 244/244 hosting unit tests pass. * Fix isolation context resume for externally-created conversations (#5692) Branch on the session's existing hosted-context (not on conversation_id presence) so a conversation provisioned externally (e.g. via conversations.CreateProjectConversationAsync) is treated as fresh on first hosted-agent request and stamped, rather than rejected with 403 hosted_session_identity_mismatch. Strict equality is preserved on real resume of an already-stamped session. Also tighten dotnet/global.json to version 10.0.204 + rollForward latestPatch so local builds match the CI Docker image SDK and avoid 10.0.300 dotnet format stripping required usings. * Revert global.json SDK pin to upstream (#5692) The 10.0.204 + latestPatch pin from the previous commit broke the dotnet-format CI job (hostfxr_resolve_sdk2 could not find a compatible SDK in the mcr.microsoft.com/dotnet/sdk:10.0 image). Restore upstream 10.0.200 + minor; local Release builds with SDK 10.0.300 should set GITHUB_ACTIONS=true to bypass the auto-format-on-build target.
Roger Barreto ·
2026-05-15 05:42:12 +00:00 -
.NET: Update FoundryAgent to address HostedAgents strict URL routing (#5677)
* .NET: Foundry agent-endpoint constructor uses ProjectOpenAIClient directly to fix hosted-agent URL routing Fixes the experimental FoundryAgent(Uri agentEndpoint, AuthenticationTokenProvider, ...) constructor so it actually works against Foundry hosted agents. The previous implementation routed through AzureAIProjectChatClient, which internally called aiProjectClient.GetProjectOpenAIClient().GetProjectResponsesClientForAgent(...). For an agent-endpoint URL of the canonical shape https://<host>/api/projects/<project>/agents/<agentName>/endpoint/protocols/openai the chain produced POST https://<host>/api/projects/<project>/openai/v1/responses (project-level path, no /agents/ segment). The Foundry service rejects this with HTTP 400 "Hosted agents can only be called through the agent endpoint: .../agents/<agentName>/endpoint/protocols/openai/responses". The constructor also extracted the agent name via agentEndpoint.Segments[^1].TrimEnd('/'), which returns "openai" (the last segment), not the agent name. What changed - Public ctor signature: clientOptions parameter type changed from AIProjectClientOptions? to ProjectOpenAIClientOptions?. The constructor is fundamentally building a ProjectOpenAIClient; accepting AIProjectClientOptions was a leaky abstraction whose translation silently dropped any pipeline policies the caller added via AddPolicy(...). With the direct type, caller policies pass through to the per-agent traffic verbatim. - Per-agent client construction: `new ProjectOpenAIClient(BearerTokenPolicy, ProjectOpenAIClientOptions)` with Endpoint and AgentName set, then `GetProjectResponsesClient().AsIChatClient()`. The SDK auto-appends ?api-version=v1 when AgentName is set. - New private static ParseAgentEndpoint helper: single source of truth for both agent-name extraction and project-root derivation. Tolerates trailing slash, case variants on /agents/ and the suffix segment, strips query/fragment, and throws ArgumentException with paramName=nameof(agentEndpoint) for malformed input. - Project-level client (used by CreateConversationSessionAsync) is built fresh from the derived project root with primitive properties copied (RetryPolicy/NetworkTimeout/Transport/UserAgentApplicationId) plus MEAI UA. - New GetService<ProjectOpenAIClient>() entry alongside the existing GetService<AIProjectClient>() (the latter returns null in agent-endpoint mode since no AIProjectClient is constructed on that path). - Endpoint and AgentName on caller-supplied ProjectOpenAIClientOptions are overridden by values derived from agentEndpoint. Compatibility - FoundryAgent is [Experimental(OPENAI001)]. No GA surface touched. The Foundry project does not maintain PublicAPI.*.txt baselines so there is no shipped baseline to update. - The Microsoft.Agents.AI.Foundry csproj pins Azure.AI.Projects to VersionOverride 2.1.0-beta.1 (matching what the IT and hosting projects already use); the central pin in Directory.Packages.props stays at 2.0.0. - WireClientHeaders from PR #5652 is invoked on the agent-endpoint path so per-call x-client-* headers behave identically across both ctors. Tests - 23 new unit tests in FoundryAgentTests.cs: - 12 for the agent-endpoint constructor (URL routing for non-streaming and streaming, conversations URL shape, MEAI UA stamping, caller-policy passthrough on the per-agent pipeline, Endpoint/AgentName override semantics, GetService matrix, ProjectOpenAIClient propagation, UserAgentApplicationId propagation, null-arg validation, ID/Name slug) - 9 for ParseAgentEndpoint (standard shape, trailing slash, casing, sovereign-cloud host without /api/projects/ literal prefix, special chars in agent name, query/fragment stripping, three negative cases) - 2 null-arg tests for the public ctor - All 250 Microsoft.Agents.AI.Foundry.UnitTests pass (was 221 baseline plus 29 from PR #5652 plus 23 new in this PR equals 273; pre-existing tests collapsed by the rebase merge keep the total at 250). - All 225 Microsoft.Agents.AI.Foundry.Hosting.UnitTests pass; no behavioral change to the hosting layer. - dotnet build clean across net8/9/10/netstandard2.0/net472 with TreatWarningsAsErrors=true. - dotnet format --verify-no-changes clean for the touched src and test projects. * .NET: Bump central Azure.AI.Projects pin to 2.1.0-beta.1 and flip Microsoft.Agents.AI.Foundry to preview Required to fix the NU1109 downgrade chain that broke CI on the agent-endpoint constructor rewire (#5677). Microsoft.Agents.AI.Foundry now depends on ProjectOpenAIClientOptions.AgentName and the (AuthenticationPolicy, options) constructor that only exist in Azure.AI.Projects 2.1.0-beta.1. Changes: * Directory.Packages.props: Azure.AI.Projects 2.0.0 -> 2.1.0-beta.1. * Microsoft.Agents.AI.Foundry.csproj: drop IsReleased=true so the package ships as preview (matches the beta SDK we now depend on). Add a comment noting the flip is temporary and should revert once Azure.AI.Projects ships a stable 2.1.0. * Drop redundant VersionOverride="2.1.0-beta.1" from the 10 csprojs that had it as a workaround; the central pin now suffices. Verified: * dotnet build agent-framework-dotnet.slnx --warnaserror clean across all TFMs. * Microsoft.Agents.AI.Foundry.UnitTests 250/250 pass. * Microsoft.Agents.AI.Foundry.Hosting.UnitTests 211/211 pass. * dotnet format --verify-no-changes clean for the touched src and test projects.Roger Barreto ·
2026-05-08 14:46:52 +00:00 -
.NET: Add hosted agent observability sample (#5660)
* .Net: Add hosted agent observability sample Mirrors the Python sample added in #5608 for Foundry hosted agents. The .NET hosting library already wires OpenTelemetry automatically via Microsoft.Agents.AI.Foundry.Hosting (ApplyOpenTelemetry) plus Azure.AI.AgentServer.Core's AddAgentHostTelemetry, so no framework changes are needed. The sample is documentation plus a runnable artifact that produces an interesting span tree (invoke_agent / agent_invoke / chat / execute_tool). Adds Hosted-Observability under FoundryHostedAgents/responses with two small tools (GetCurrentLocation, GetWeather), agent.yaml / agent.manifest.yaml declaring OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT (the .NET equivalent of Python's ENABLE_SENSITIVE_DATA), Dockerfile + Dockerfile.contributor, .env.example and README explaining the .NET vs Python defaults. Project added to agent-framework-dotnet.slnx. * Address PR feedback: use Random.Shared and add .dockerignore
Roger Barreto ·
2026-05-06 08:33:16 +00:00