mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
feature/python-hosting
2155 Commits
-
Evan Mattson ·
2026-05-12 15:27:13 +09:00 -
Trigger issue triage on bug-labeled issues (#5763)
* Trigger issue triage on bug-labeled issues instead of manual dispatch * Address PR feedback: scope concurrency cancellation to bug-label events
Evan Mattson ·
2026-05-12 13:07:17 +09:00 -
Python: [BREAKING] Migrate agent-framework-a2a to a2a-sdk v1.0 (#5752)
* Python: Migrate agent-framework-a2a to a2a-sdk v1.0 Upgrade the a2a-sdk dependency from v0.3.x to v1.0.0 and migrate all source, tests, samples, and documentation to the v1.0 API. Key changes: - Dependency: a2a-sdk>=1.0.0,<2 (was >=0.3.5,<0.3.24) - Types are now protobuf-based: Part replaces TextPart/FilePart/DataPart - Enums use SCREAMING_SNAKE_CASE (e.g. TaskState.TASK_STATE_COMPLETED) - Roles: Role.ROLE_AGENT, Role.ROLE_USER - Client: SendMessageRequest wrapper, subscribe() replaces resubscribe() - Server: A2AStarletteApplication replaced by Starlette + route factories - DefaultRequestHandler now requires agent_card parameter - TaskUpdater: final parameter removed, add_artifact gains last_chunk - AgentCard.url removed; use supported_interfaces with AgentInterface - Stream yields StreamResponse with WhichOneof('payload') Closes #5661 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: validate fallback URL, remove unused task_id vars - Raise ValueError with clear message when transport negotiation fails and no fallback URL is available (neither url arg nor supported_interfaces) - Remove unused task_id local in status_update branch - Inline artifact_event.task_id directly in artifact_update branch Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>Giles Odigwe ·
2026-05-11 22:46:12 +00:00 -
.NET: DevUI: add configurable access controls for the DevUI HTTP surface (#5739)
* .NET: DevUI: add configurable access controls for the DevUI HTTP surface * .NET: DevUI: address review and fix dotnet format - Restore parameterless AddDevUI overloads for binary compatibility on IServiceCollection and IHostApplicationBuilder. - Keep /meta outside the auth-filtered group so the frontend can discover whether a bearer token is required before prompting for one. Surface the actual requirement via MetaResponse.auth_required. - Invoke DevUIOptions.ConfigureEndpoints before mapping protected endpoints so RouteGroupBuilder conventions (RequireAuthorization, rate limiting) reliably apply. - Treat a null RemoteIpAddress as non-loopback in DevUIAuthFilter; tests now set IPAddress.Loopback explicitly when exercising the loopback path. - Add a DEVUI_AUTH_TOKEN env-var fallback test and a /meta-public test. - Fix dotnet format: add UTF-8 BOM to new files, simplify a cref in DevUIOptions, and drop an unused using in the new test. * .NET: DevUI: add missing authRequired param XML tag * .NET: DevUI tests: set loopback/AllowRemoteAccess for null-RemoteIp default DevUIIntegrationTests use the default TestServer which leaves RemoteIpAddress null. With the new conservative loopback default those tests now hit 403; set AllowRemoteAccess on the option since those tests are not exercising access control. Also add the missing SimulateRemoteIp call in the wrong-bearer test. * .NET: DevUI tests: capture DEVUI_AUTH_TOKEN before parallel tests can see it The env-var test was leaking DEVUI_AUTH_TOKEN into parallel DevUIIntegrationTests, intermittently causing their requests to be rejected as 401. Eagerly resolve the singleton DevUIAuthFilter so its constructor captures the token, then restore the env var before any HTTP requests run.
Evan Mattson ·
2026-05-11 22:45:41 +00:00 -
.NET: Remove Foundry Toolbox server-side tools support (#5753)
* .NET: Remove Foundry Toolbox server-side tools support Mirrors the Python cleanup in microsoft/agent-framework#5671. Passing toolbox tools as server-side Responses tools is not the experience we want to support; the hosted-agent MCP toolbox path (HostedMcpToolboxAITool + FoundryToolboxService) remains the supported way to consume Foundry Toolboxes. Removed: - FoundryToolbox static class (GetToolboxVersionAsync / GetToolsAsync / ToAITools / SanitizeAndConvert) - AIProjectClient.GetToolboxToolsAsync extension - Agent_Step25_ToolboxServerSideTools sample (+ slnx entry) - FoundryToolboxTests, TestDataUtil, HttpHandlerAssert, and the toolbox JSON fixtures only those tests referenced - ToolboxHostedAgentTests and ToolboxHostedAgentFixture; the "toolbox" switch arm + CreateToolboxAgent helper in TestContainer; matching README scenario row and bootstrap script entry Kept (MCP path, unchanged): - HostedMcpToolboxAITool, FoundryAITool.CreateHostedMcpToolbox, FoundryAIToolExtensions.CreateHostedMcpToolbox(ToolboxRecord/Version) - FoundryToolboxService, AddFoundryToolboxes, marker injection in AgentFrameworkResponseHandler, InputConverter.ReadMcpToolboxMarkers - Hosted-Toolbox sample, McpToolbox* tests, FoundryToolboxServiceTests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Add Foundry Toolbox MCP sample (Agent_Step25_FoundryToolboxMcp) Adds a non-hosted-agent equivalent of the Python foundry_chat_client_with_toolbox.py sample. The agent connects to a Foundry Toolbox's MCP endpoint via Streamable HTTP, injects a fresh Azure AI bearer token on every request, and discovers the toolbox's tools at runtime via McpClient.ListToolsAsync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Tighten Agent_Step25_FoundryToolboxMcp README/Program comments Drop 'non-hosted agent' framing from README (this sample isn't related to hosted agents) and remove narrative comparison to server-side tools from the Program.cs header comment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Drop python sample reference from Agent_Step25 README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Drop incorrect .NET 10 prereq from Agent_Step25 README Toolboxes don't require .NET 10 (Microsoft.Agents.AI.Foundry targets net8.0+); the parent AgentsWithFoundry README already lists the sample SDK prereq. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Toolsets api-version in Agent_Step25 example endpoint Use 2025-05-01-preview to match FoundryToolboxOptions.ApiVersion. The placeholder 'v1' is not accepted by the Toolsets endpoint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ben Thomas ·
2026-05-11 22:05:14 +00:00 -
.NET: Fix/per service input persistence on stream error (#5744)
* .NET: Persist input messages on streaming errors in PerServiceCallChatHistoryPersistingChatClient When the underlying chat service emits an in-stream error (for example a `response.error` SSE event from the OpenAI Responses API on rate limit), the OpenAI client surfaces it as an `ErrorContent` update and ends the stream without throwing. Previously, `PerServiceCallChatHistoryPersistingChatClient` only persisted history when the streaming loop completed successfully and `NotifyProvidersOfNewMessagesAsync` was called at the end. On the in-stream-error path, the input messages handed to that iteration - typically `FunctionResultContent` produced by `FunctionInvokingChatClient` in the previous iteration - were never persisted. The next run would replay session history with a dangling `FunctionCallContent` and the service would reject the request with `No tool output found for function call <id>`. This change: - Adds a `PersistInputOnErrorAsync` helper that persists the input messages (with no response messages) so function-call/function-result pairings are not split across failures. - Calls the helper from every error path: pre-loop enumerator creation, the first `MoveNextAsync`, the in-loop `MoveNextAsync`, and a new `finally` that handles abnormal iterator disposal. - After the streaming loop, scans the assembled response for any `ErrorContent` and, if present, persists the input, notifies providers of failure, and throws `InvalidOperationException` so the error is surfaced to the caller instead of silently corrupting history. - Hardens `InMemoryChatHistoryProvider.StoreChatHistoryAsync` to treat a null `RequestMessages` as empty, since the new error path can invoke it with no response messages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix dropped FunctionResultContent on streaming pipeline early-disposal When a consumer of ChatClientAgent.RunStreamingAsync stops iterating early (e.g. ToolApprovalAgent yields the approval request and then `yield break`), the framework cascades DisposeAsync down the stream. C# async iterators do not auto-dispose IAsyncDisposable locals, so the inner enumerator returned by IChatClient.GetStreamingResponseAsync(...).GetAsyncEnumerator(ct) was left suspended. That suspended FunctionInvokingChatClient downstream, which suspended PerServiceCallChatHistoryPersistingChatClient at its `yield return`, so its finally block never ran and the in-flight FunctionResultContent for the just-completed tool call was not persisted to chat history. The next turn then loaded a session that contained a FunctionCallContent with no matching FunctionResultContent and the model returned HTTP 400 `No tool output found for function call`. Fixes: * ChatClientAgent.RunStreamingAsync: wrap the iteration in try/finally that disposes the inner enumerator. Disposal now cascades through the pipeline and PerService's finally runs on early exit. * PerServiceCallChatHistoryPersistingChatClient: in the streaming path, snapshot input messages with `messages.ToList()` (the caller, FICC, reuses a single mutable buffer across iterations and may mutate it before our finally / error path persists), wrap GetAsyncEnumerator, the first MoveNextAsync, and in-loop MoveNextAsync in try/catch each calling PersistInputOnErrorAsync + NotifyProvidersOfFailureAsync, and add a finally that calls PersistInputOnErrorAsync when the loop did not exit normally so per-iteration FRCs are persisted on early disposal as well as on errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Add tests for PerService streaming error/dispose persistence paths Adds five regression tests covering the new error-path persistence in PerServiceCallChatHistoryPersistingChatClient.GetStreamingResponseInnerAsync: - Persists input messages when GetStreamingResponseAsync throws synchronously. - Persists input messages when the first MoveNextAsync throws. - Persists input messages when a mid-stream MoveNextAsync throws. - Persists input messages when the consumer abandons enumeration early (the ToolApprovalAgent yield-break / disposal-cascade case). - Throws and persists input when the stream emits an in-band ErrorContent. All 66 tests in the class pass on net10.0 and net472. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Address PR feedback on PerService streaming error persistence Two follow-ups from PR #5744 review: 1. Prevent duplicate persistence on the in-loop MoveNextAsync catch path. The inner catch persists input messages, then rethrows, which propagates through the surrounding try/finally where loopExitedNormally is still false, causing the finally to persist again. Introduced an inputPersisted flag that the inner catch sets after persisting; the finally now skips when inputPersisted is true. 2. Use the caller's CancellationToken in the abnormal-exit finally instead of CancellationToken.None, so cleanup remains responsive to cancellation. Fall back to CancellationToken.None only when the caller's token is already canceled (otherwise the persist call would observe the cancellation, throw, and mask the original early-exit reason). Tightened all five new streaming-error tests from Times.AtLeastOnce to Times.Once on the input-persistence matcher to regression-guard against duplicate persistence. All 66 tests in the class still pass (net10.0 + net472). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Scope PerService streaming changes to cooperative early-exit only Per discussion on PR #5744, scope this PR back to fix only the original ToolApprovalAgent dropped-FunctionResultContent bug and address the enumerator-disposal review comment. Specifically: - Remove input-message persistence from the GetAsyncEnumerator and MoveNextAsync error paths. Routing failed service calls through the success notification channel was breaking the provider contract; we will instead rely on inner-agent retries for transient errors. Failure paths still call NotifyProvidersOfFailureAsync as before. - Remove the in-stream ErrorContent detection block (same rationale). - Keep the try/finally that calls the (now narrower) early-exit input notification on cooperative disposal (e.g. ToolApprovalAgent yield break). A new serviceErrorOccurred flag ensures we do NOT renotify on exception paths. - Always DisposeAsync the underlying enumerator on every exit path, addressing the copilot-reviewer comment about leaked HTTP/streams. - Rename PersistInputOnErrorAsync -> NotifyProvidersOfEarlyExitInputAsync to better reflect what it does and when it runs (rogerbarreto nit). - Apply rogerbarreto nit on InMemoryChatHistoryProvider null-coalescing. - Drop the four tests that covered the removed error-path behavior; keep RunStreamingAsync_PersistsInputMessages_WhenConsumerAbandons EnumerationAsync (regression guard for the cooperative-pause path). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ben Thomas ·
2026-05-11 20:28:14 +00:00 -
.NET: Hosted Agents - RAG Sample with Azure AI Search (#5693) (#5701)
* .NET: Hosted Agents - RAG Sample with Azure AI Search (#5693) Adds a Hosted-AzureSearchRag sample plus a live Foundry.Hosting integration test scenario backed by a real Azure AI Search index. Sample (Hosted-AzureSearchRag): keyword-only Azure AI Search via SearchClient adapter into TextSearchProvider, scope-aware DevTemporaryTokenCredential consuming AZURE_BEARER_TOKEN_FOUNDRY + AZURE_BEARER_TOKEN_SEARCH for local Docker, Dockerfile + contributor Dockerfile mirroring Hosted-TextRag. Integration test: AzureSearchRagHostedAgentFixture extends the PR #5598 HostedAgentFixture with the new azure-search-rag scenario branch in the shared test container; AzureSearchRagHostedAgentTests asserts the model returns canary tokens (TR-CANARY-7821, SHIP-CANARY-4493) that exist only in the seeded documents - real proof the agent grounded its answer in retrieved content rather than training data. * Address PR 5701 Copilot review feedback - Sample README: drop stale 'bootstraps the index on first run' line; index is pre-provisioned out of band - Sample + TestContainer search adapters: propagate CancellationToken to await foreach via .WithCancellation()
Roger Barreto ·
2026-05-11 13:59:42 +00:00 -
Simplify ClientHeadersScope, drop redundant using/Dispose (#5676)
Wesley pointed out (with a clean demo) that AsyncLocal<T> mutations made inside an awaited async method do not leak back to the caller after the method returns - the runtime restores the caller's view automatically. ClientHeadersAgent.RunCoreAsync and RunCoreStreamingAsync are the only callers of the scope, both are async methods awaited by their callers, so the explicit using/Dispose pattern was doing work the runtime already does for us. * ClientHeadersScope collapsed to a single Current { get; set; } property over an AsyncLocal<IReadOnlyDictionary<string,string>?>. Drops Push, the Scope struct, and Dispose. XML doc explains the AsyncLocal natural- restoration semantics so the design intent is self-documenting. * ClientHeadersAgent uses a direct ClientHeadersScope.Current = snapshot before delegating. Drops the local RunAsyncCoreAsync helper and the snapshot-passed-as-parameter dance. * Test 10 renamed to ClientHeadersScope_IsAsyncLocalIsolatedAndAutoRestoresAsync; drops the LIFO claim, keeps the parallel-isolation assertion, and adds a Wesley-style 'set inside async, caller sees null on return' assertion. * Test 12 switches from using ClientHeadersScope.Push to direct Current = ... with try/finally for test isolation. Snapshot deep-copy in TrySnapshot stays - it defends against caller mutating the source Dictionary mid-run, which is independent of the AsyncLocal restoration mechanism.Roger Barreto ·
2026-05-11 13:38:14 +00:00 -
.NET: Hosted-Files sample + AgentSessionFiles SDK companion + integration test (#5698)
* .NET: Add Hosted-Files sample + alpha AgentSessionFiles SDK companion + integration test Closes #5691 - Hosted-Files server sample (mirrors python 06_files): 3 local tools reading the per-session \C:\Users\rbarreto sandbox volume. - SessionFilesClient REPL companion: code-first equivalent of zd ai agent files upload using the alpha Azure.AI.Projects.AgentSessionFiles SDK (upload/ls/download/rm + session lifecycle with isolation key). - session-files scenario added to the Foundry.Hosting.IntegrationTests multi-scenario harness (PR #5598): SessionFilesHostedAgentFixture + SessionFilesHostedAgentTests.UploadAndAgentReadsFileAsync, end-to-end validating upload then agent-reads-file (agent_session_id pinned via CreateResponseOptions.Patch). Bundled testdata is linked from the sample so there is a single source of truth. * .NET: Hosted-Files: REPL companion now demonstrates file-as-knowledge end-to-end Adds an 'ask <prompt>' command to SessionFilesClient that pins agent_session_id (via CreateResponseOptions.Patch) so the agent invoked from the REPL reads files this REPL just uploaded. Surfaces the file content as agent knowledge in the same in-process loop instead of telling the user to shell out to azd ai agent invoke. * .NET: Reshape Hosted-Files sample - bake files into image, SessionFilesClient becomes thin chat REPL The previous SessionFilesClient leaned on the alpha AgentSessionFiles SDK to upload files at runtime, which made it diverge from the canonical Using-Samples shape (SimpleAgent / SimpleInvocationsAgent: tiny chat REPLs). This change: - Bakes the sample resources/ directory into the published output via a Content Include in HostedFiles.csproj. Inside the container the files live at /app/resources/. Two local function tools (ListFiles, ReadFile) surface them to the model. - Reshapes SessionFilesClient as a thin FoundryAgent chat REPL, identical shape to SimpleAgent. AGENT_ENDPOINT + AGENT_NAME, that is it. - Demo flow: user asks 'Give me the total revenue in the contoso file' and the agent answers with the figure read from its bundled file. Validated end-to-end locally against Hosted-Files on http://localhost:60419. - Bypasses SampleEnvironment alias on optional env vars to avoid stdin prompts when running unattended. The Foundry.Hosting.IntegrationTests session-files scenario continues to validate the alpha AgentSessionFiles SDK end-to-end (upload + agent reads from session HOME) and is unchanged. * .NET: Foundry.Hosting.IntegrationTests TestContainer - constrain session-files tools to $HOME Addresses the path-traversal review comment on the session-files scenario: ResolveSessionPath in TestContainer used to allow absolute paths and .. traversals, which (when chained with indirect prompt injection in an uploaded file) would let the model read or list arbitrary container files via the ReadFile / ListFiles tools. Mirrors the canonicalize + StartsWith(home) pattern from the framework's own FileSystemAgentFileStore.ResolveSafePath: rejects rooted paths, calls Path.GetFullPath, and verifies the result stays under $HOME, throwing ArgumentException otherwise. The Hosted-Files sample is already safe (uses Path.GetFileName which strips any directory component) so no change there. The integration test continues to upload and read 'contoso_q1_2026_report.txt', a single relative filename which passes the new validation unchanged. * .NET: SessionFilesHostedAgentTests - shrink to alpha SDK round-trip The previous test attempted to pin agent_session_id into the /responses payload via JsonPatch so the agent would read the file uploaded through AgentSessionFiles. The Foundry alpha service now consistently rejects the explicit-session-id pin with HTTP 400 conflict on /responses, regardless of whether the session was pre-created via AgentAdministrationClient or left to be auto-provisioned, so the agent leg of the test is no longer reachable from the SDK surface. Reshape the test to exercise what the alpha SDK actually guarantees: create session, upload, list (assert presence + size), download (assert deterministic token), delete (assert removed), cleanup. Everything stays inside Azure.AI.Projects.Agents.AgentSessionFiles. Verified live against tao-foundry-prj: UploadListDownloadAndDeleteAsync passed in 30s. Full Foundry.Hosting.IntegrationTests run: 25 total, 6 passed, 19 skipped (existing placeholders), 0 failed. * .NET: SessionFilesHostedAgentTests - rewrite as upload-then-FoundryAgent.RunAsync e2e Per review feedback the integration test must validate the hosted agent itself: client uploads a file via the alpha AgentSessionFiles SDK, then FoundryAgent.RunAsync invokes the deployed agent and the agent's container-side ReadFile tool surfaces the uploaded file content into the response. Test flow: 1. agent.RunAsync(warmup) - platform provisions a per-session container. 2. AgentAdministrationClient.GetSessionsAsync(latest) - resolve the just-provisioned agent_session_id. 3. AgentSessionFiles.UploadSessionFileAsync - upload contoso file to that session, asserts BytesWritten + GetSessionFiles listing. 4. agent.RunAsync(real prompt, options=PreviousResponseId chain) - chained to warmup so the platform routes back to the same container. 5. Assert response contains '1,482.6' (deterministic token from file). 6. Best-effort cleanup. The test is annotated with [Fact(Skip=...)] right now: the Foundry alpha service consistently returns HTTP 400 conflict on /responses requests that link to a prior session via previous_response_id, conversation_id, or agent_session_id pinning - verified across multiple retries with multiple chaining strategies. Without that link we cannot route the second invocation to the same container the file was uploaded to. When the platform regression is resolved, removing the Skip will exercise the full flow. Full Foundry.Hosting.IntegrationTests run with this change: 25 total, 5 passed, 20 skipped (existing placeholders + this one), 0 failed. * .NET: SessionFilesHostedAgentTests - end-to-end upload-then-FoundryAgent.RunAsync now passes The blocker was a routing problem combined with a platform race: 1. Routing two /responses calls to the same per-session container. - agent_session_id pin in body -> 400 (platform treats it as create) - conversation_id created at project root -> 404 at agent endpoint - previous_response_id chain -> different session The working answer is to create the conversation on a per-agent ProjectOpenAIClient (AgentName option, URL becomes /agents/{name}/endpoint/protocols/openai/conversations) and pass that conversation_id on both calls. Both then resolve to the SAME x-agent-session-id (verified by capturing the response header). 2. Race after AgentSessionFiles upload. The upload mutates session/ conversation revision; a /responses call issued immediately after 400-conflicts with 'modified concurrently. Please retry.' Bounded exponential retry handles it (5 attempts, 2*attempt seconds). Test flow: 1. Create per-agent OpenAI client + ProjectConversationsClient + ProjectResponsesClient. 2. CreateProjectConversationAsync on the per-agent client. 3. Warm-up agent.RunAsync(prompt, ChatOptions { ConversationId = ... }) - captures x-agent-session-id from the response header via a custom pipeline policy. 4. AgentSessionFiles.UploadSessionFileAsync to that session id. 5. ProjectResponsesClient.CreateResponseAsync (raw, retry-on-conflict) with the same conversation_id -> routes back to the same container. 6. Assert response contains '1,482.6' (deterministic token from file). 7. Cleanup: delete file, leave session for TTL. Verified live against tao-foundry-prj: UploadedFile_IsReadByHostedAgentAsync passed in 24.9s. Full Foundry.Hosting.IntegrationTests run: 25 total, 6 passed, 19 skipped (existing placeholders), 0 failed. * .NET: address Copilot PR review findings - agent.manifest.yaml: description + tags now reflect bundled-files agent (image-baked /app/resources), not the obsolete session-sandbox tools the prior shape claimed. - SessionFilesHostedAgentTests: wrap test body in try/finally to call DeleteConversationAsync on the conversation we created (matches HappyPathHostedAgentTests pattern; prevents conversation leakage across runs). - ResponseHeaderCapturePolicy: drop unused LastRequestBody capture left over from diagnosis. Test still passes live (40s). * .NET: Hosted-Files: split into bundled vs session-file tool pairs The previous Hosted-Files agent only exposed bundled (image-baked) file knowledge. The platform also surfaces session-uploaded files at \C:\Users\rbarreto inside the per-session container per container-image-spec.md line 172 (verified live by SessionFilesHostedAgentTests). The sample now teaches both patterns. Two distinct tool pairs, each scoped to its own root: Bundled (image-baked): ListBundledFiles, ReadBundledFile -> /app/resources/ (BUNDLED_FILES_DIR override) Session-uploaded (\C:\Users\rbarreto): ListSessionFiles, ReadSessionFile -> \C:\Users\rbarreto (default /home/session per container spec) Security model -- distinct tools, distinct sandboxes: - Tool input is a fileName, not a path. Schema-level: model cannot request directories or traversals. - Path.GetFileName(input) strips any directory components. - Path.GetFullPath + StartsWith(root) check rejects anything outside the tool's root, mirroring FileSystemAgentFileStore.ResolveSafePath. - Read-only, non-recursive listing. No glob, no '..'. - Failures non-revealing: 'File <name> not found in <scope>.' The two roots are physically isolated (image-baked vs platform-mounted per-session volume). A bundled-root tool can never reach a session file and vice-versa, even if the implementation has a bug. README updated to document both flows, the security pattern, and cite the container-image-spec.md line 172 contract for \C:\Users\rbarreto. Live IT SessionFilesHostedAgentTests.UploadedFile_IsReadByHostedAgentAsync re-passed in 42s after the change (TestContainer is unchanged; the sample-agent split does not affect the IT). * .NET: Hosted-Files README - fix broken relative link to IT (4..5 dots)
Roger Barreto ·
2026-05-11 11:56:58 +00:00 -
.NET: Foundry.Hosting IT - eliminate MSBuild parallel-output races (#5725)
* .NET: Foundry.Hosted IT - fix MSBuild parallel-output races Two surgical changes inside the dotnet-foundry-hosted-it job: 1. Replace dotnet build <slnx> -f net10.0 with dotnet build <test.csproj>. The test csproj pins TargetFrameworks=net10.0 and its ProjectReference closure gives MSBuild a single-rooted graph, eliminating the duplicate inner-builds that race on bin/obj. Drops the two New-FilteredSolution.ps1 steps. 2. In it-build-image.ps1, drop the -UsePrebuiltProjectReferences switch and always pass --no-dependencies to dotnet publish. Publish now resolves TestContainer's framework refs by reading prebuilt DLLs and never re-touches them. Replaces the partial-mitigation in PR #5689 with a structural fix. Local validation confirmed published Foundry.dll has identical mtime and bytes as the prebuild output. * .NET: dotnet test - use --project flag for Microsoft Testing Platform
Roger Barreto ·
2026-05-11 09:39:13 +00:00 -
.NET: Add IChatMessageInjector for message injection during function loop (#5679)
* Adding the ability to inject messages during the function call loop * Split message injection functionality * Remove interface, since it is not required not that we split the chat client. * Address conversation id propogation * Fix formatting issue
westey ·
2026-05-08 17:16:03 +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 -
westey ·
2026-05-08 09:28:35 +00:00 -
Jacob Alber ·
2026-05-08 00:17:44 +00:00 -
Python: bump package versions for 1.3.0 release (#5706)
* Python: bump package versions for 1.3.0 release MINOR bump on the released cohort (agent-framework, agent-framework-core, agent-framework-openai, agent-framework-foundry: 1.2.2 -> 1.3.0). All 22 beta packages stamp 1.0.0b260507 and all 3 alpha packages stamp 1.0.0a260507 per the lockstep convention. Date stamp reflects 2026-05-07 Pacific. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review: bump foundry_local openai floor, fix devui orchestrations pin, clarify breaking scope - foundry_local: bump agent-framework-openai lower bound from >=1.1.0 to >=1.3.0 - devui: update stale agent-framework-orchestrations dev pin from 1.0.0b260402 to 1.0.0b260507 - CHANGELOG: clarify [BREAKING] applies to experimental skills API only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revert devui orchestrations pin to 1.0.0b260402 to avoid breaking DevUI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Giles Odigwe ·
2026-05-08 08:57:02 +09:00 -
.NET: Fix function_call_output.output to be a JSON string on the wire (#5705)
* Fix function_call_output.output to be a JSON string on the wire OutputConverter was passing the JSON serialization of complex tool results (e.g. List<TodoItem>) directly into OutputItemFunctionToolCallOutput via BinaryData.FromString. The Responses SDK treats that BinaryData as the *raw JSON value* for the field, so non-string results landed on the wire as an unquoted JSON array (e.g. `"output":[{...}]`) instead of a JSON string. The OpenAI Responses spec requires `function_call_output.output` to be a JSON string. The strict-parsing OpenAI .NET client (FunctionCallOutputResponseItem) consequently failed when threading a follow-up turn that replayed such an item, with: `The JSON value could not be converted... requires an element of type 'String', but the target element has type 'Array'`. Always wrap the payload as a JSON string literal: - string s -> JSON-encode s (quoted, with escapes) - object o -> JSON-serialize o, then JSON-encode the resulting text Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR feedback: JsonElement special-case, symmetric inbound unwrap, tests OutputConverter: extract EncodeFunctionResultAsJsonStringPayload helper that special-cases JsonElement / JsonDocument so a string-kind element does not get double-encoded into "\"value\"". Other JsonElement kinds (object/array/number/bool) round-trip via GetRawText() and are then JSON-string-wrapped, matching the spec. InputConverter: symmetric DecodeFunctionResultPayload added to ConvertFunctionCallOutput and ConvertFunctionToolCallOutput so previously-stored function_call_output items replayed via previous_response_id unwrap back to the original tool result text instead of leaking the JSON-encoded form into FunctionResultContent.Result. Legacy non-conforming raw-JSON-value payloads pass through unchanged. Tests: - Replace ConvertUpdatesToEventsAsync_FunctionResultStringPayload_EmittedAsRawTextAsync with EmittedAsJsonStringAsync asserting the new wire contract ("sunny" -> "\"sunny\""). - Add coverage for object payloads, JsonElement string kind (no double-encoding), and JsonElement array kind (JSON-stringified). - Add InputConverter round-trip tests for spec-compliant JSON-string payloads and legacy raw-JSON-array payloads. All 663 tests pass on net8/net9/net10. Verified end-to-end against the local hosted-harness sample: T1-T4 (incl. TodoList tool replay across turns) all succeed with no SDK parse errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>Ben Thomas ·
2026-05-07 23:27:57 +00:00 -
.NET: Mark Magentic Orchestration Experimental (#5704)
* fix: Mark Magentic Orchestration Experimental * Apply [Experimental] to all public Magentic types and suppress MAAIW001 in project Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/957a07c1-a805-40eb-989d-bd3425d4c0af Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com>
Jacob Alber ·
2026-05-07 22:54:01 +00:00 -
Python: Upgrade github-copilot-sdk to v1.0.0b2 with new features (#5665)
* Upgrade github-copilot-sdk to v1.0.0b1 and implement new features - Bump github-copilot-sdk dependency from 0.2.1 to 1.0.0b1 - Fix breaking type renames: ErrorClass -> ToolExecutionCompleteError, Result -> ToolExecutionCompleteResult - Add instruction_directories support in GitHubCopilotOptions (session-level) - Add copilot_home support in GitHubCopilotSettings (client-level) - Add sample: github_copilot_with_instruction_directories.py - Update README with new env var and sample entry - Add 8 new unit tests covering the new features (103 total, 96% coverage) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * mypy fix * small fix * Address PR feedback: fix resume path, remove copilot_home from Options, bump to beta.2 - Forward runtime_options through _resume_session (fixes silent drop of instruction_directories/model/etc on resumed sessions) - Remove copilot_home from GitHubCopilotOptions (client-level setting only consumed at startup, not per-call) - Bump github-copilot-sdk from 1.0.0b1 to 1.0.0b2 - Add test for instruction_directories override on resumed sessions - Update existing resume test to match new _resume_session signature Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Giles Odigwe ·
2026-05-07 21:43:47 +00:00 -
Fix typo:sesionEleme -> sessionElement (#5674)
Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Hao-Xiong ·
2026-05-07 21:05:41 +00:00 -
fix(security): non-thread-safe sequence number generation may cau (#5320)
`SequenceNumber.Increment()` uses `this._sequenceNumber++` without synchronization. In concurrent streaming scenarios, this can produce race conditions and inconsistent sequencing, which may break event ordering guarantees and potentially allow response-mixing or state confusion. Affected files: SequenceNumber.cs Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com> Co-authored-by: Jacob Alber <jaalber@microsoft.com>
tuanaiseo ·
2026-05-07 20:42:49 +00:00 -
.NET: Python: Add dotnet integration test report to CI (#5515)
* Add dotnet integration test report to CI - Add --report-junit flag to dotnet integration test step to generate JUnit XML alongside TRX, with explicit --results-directory to centralize output in IntegrationTestResults/ - Upload JUnit XML artifacts from each matrix leg (net10.0/ubuntu, net472/windows) as dotnet-test-results-{framework}-{os} - Add dotnet-integration-test-report job that downloads artifacts, runs the existing aggregate.py script, posts markdown to Job Summary, and saves trend history via actions/cache - Refactor aggregate.py to discover JUnit XML files recursively, supporting both pytest (pytest.xml) and xunit (*.junit.xml) layouts - Handle provider name derivation for dotnet artifact naming convention - Fix nodeid collision when same test runs under multiple frameworks by qualifying keys with provider when collisions are detected - Improve module extraction for dotnet C# classnames (recognizes IntegrationTests/UnitTests namespace segments) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: trigger dotnet CI for report validation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use .junit extension (not .junit.xml) for xunit v3 output xUnit v3 generates files with .junit extension, not .junit.xml. Update upload glob and aggregate.py discovery to match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use deterministic provider-qualified keys for dotnet tests Always prefix dotnet test keys with provider (e.g. net10.0 (ubuntu)::TestName) to ensure stable, comparable counts across runs regardless of file parse order. Also show Executed (passed+failed) instead of Total in summary table. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: match Python report summary format (Total, passed/total, etc.) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: split dotnet report into per-framework tables Dotnet tests run on multiple frameworks (net10.0, net472). Instead of one combined table with unstable totals, show separate sections per framework — each with its own summary row and per-test table. Python reports retain the original single-table format. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Re-enable 7 flaky dotnet integration tests with increased timeouts Increase timeouts to reduce timing-related flakiness in LLM-backed integration tests (issue #4971): - ExternalClientTests: 60s -> 120s default timeout - SamplesValidationBase: 60s -> 120s default timeout - ConsoleAppSamplesValidation: 90s -> 150s for long-running tests - AzureFunctions SamplesValidation: 2min -> 3min orchestration timeout, 60s -> 90s per-step WaitForConditionAsync timeouts Remove all Skip=Flaky annotations and unused SkipFlakyTimingTest constants. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Re-skip LLM non-determinism flaky tests, keep timeout fixes Re-skip SingleAgentOrchestrationHITLSampleValidationAsync and LongRunningToolsSampleValidationAsync - these fail due to LLM producing extra review notifications, not timeouts. Updated skip reasons to accurately describe the root cause. Reverted unnecessary timeout change on the skipped LongRunningTools test. The remaining 5 re-enabled tests with timeout increases are stable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Enable Anthropic integration tests in CI Replace hardcoded skip with conditional skip pattern (matching CopilotStudio approach): tests gracefully skip when ANTHROPIC_API_KEY is missing, and run when present. Changes: - AnthropicChatCompletionFixture: try/catch in InitializeAsync with Assert.Skip on missing config (replaces hardcoded SkipReason) - AnthropicSkillsIntegrationTests: same pattern per test method - dotnet-build-and-test.yml: wire up ANTHROPIC_API_KEY, ANTHROPIC_CHAT_MODEL_NAME, and ANTHROPIC_REASONING_MODEL_NAME env vars to the integration test step Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix missing System using in AnthropicSkillsIntegrationTests Add 'using System;' for InvalidOperationException in try/catch blocks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Skip flaky SingleAgentOrchestrationChainingSampleValidationAsync LLM non-determinism causes Assert.NotNull failures on orchestration results. Skip until test logic is hardened against non-deterministic LLM responses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Re-enable HITL and LongRunningTools tests with timeout and flexibility fixes - Remove Skip attribute from SingleAgentOrchestrationHITLSampleValidationAsync - Remove Skip attribute from LongRunningToolsSampleValidationAsync - Increase timeout from 120s/90s to 180s to accommodate 2+ LLM round-trips - Replace rigid 2-cycle assertion with flexible approval logic that handles extra review cycles from LLM non-determinism Fixes the two failure modes identified in #4971: 1. Timeout: 120s/90s was insufficient for multiple LLM calls under CI load 2. Extra notifications: Assert.Fail on 3rd+ review cycle was too rigid Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Increase AzureFunctions LongRunningTools test timeouts from 90s to 180s The LongRunningToolsSampleValidationAsync test in the AzureFunctions integration tests was failing in CI with TimeoutException at the 'Content published notification is logged' step. The 90-second timeouts are too tight for CI environments where LLM calls and orchestration overhead can be slow. Increased all three WaitForConditionAsync timeouts from 90s to 180s: - Waiting for human feedback notification - Waiting for publish notification (the step that was failing) - Waiting for orchestration completion Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Merge main and fix dotnet report path after flaky_report rename Merge upstream/main which renamed scripts/flaky_report/ to scripts/integration_test_report/ (from Python PR #5454). Update the dotnet-build-and-test workflow to reference the new path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add RetryFact to DurableTask and AzureFunctions integration tests These tests interact with LLMs via stdin/stdout (DurableTask) or HTTP (AzureFunctions) and are inherently non-deterministic. Unlike the Python side which uses pytest-retry, the dotnet tests had no retry mechanism and a single transient failure would fail the entire CI run. Changes: - Switch [Fact] to [RetryFact(2, 5000)] on all LLM-dependent tests across ConsoleAppSamplesValidation, ExternalClientTests, WorkflowConsoleAppSamplesValidation, and AzureFunctions SamplesValidation - Add re-prompt mechanism to LongRunningToolsSampleValidationAsync: if the LLM doesn't invoke the tool within 60s, re-send the prompt (up to 2 retries) instead of burning the full timeout - Reduce LongRunningTools timeout from 240s to 180s (re-prompt makes the extra buffer unnecessary) - Leave simple/deterministic tests as [Fact] (SingleAgent, unit tests) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add persist-credentials: false to Integration Test Report checkout step Matches the convention used by other checkout steps in this workflow to avoid leaving GITHUB_TOKEN credentials in the local git config. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * small fixes * disable anthropic failing tests --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>Giles Odigwe ·
2026-05-07 20:39:32 +00:00 -
Python: Add ClassSkill for class-based skill definitions (#5678)
* Python: Add ClassSkill for class-based skill definitions Add ClassSkill abstract base class with decorator-based resource and script discovery, porting .NET's AgentClassSkill (PRs #5027 and #5183) to Python. - Add ClassSkill(Skill, ABC) with instructions abstract property, cached content/resources/scripts properties - Add @ClassSkill.resource and @ClassSkill.script static method decorators for auto-discovery of methods and properties - Extract _build_skill_content() and _create_resource_element() shared helpers from InlineSkill for reuse - Add _discover_marked_members() for scanning class hierarchies - Add _make_method_name() for Python-to-skill name conversion - Add class_based_skill sample (UnitConverterSkill) - Update mixed_skills sample with TemperatureConverterSkill - Add 58 new tests covering ClassSkill, decorator discovery, property resources, inheritance, kwargs forwarding, and duplicate detection - Export ClassSkill from agent_framework public API Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: replace try/except/continue with assignment to satisfy bandit B112 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * address PR review feedback - Walk cls.__mro__ in _discover_marked_members for inherited property resources - Use inspect.getattr_static for MRO-aware is_property check - Return defensive copies from resources/scripts properties - Raise TypeError on wrong decorator stacking order (@resource above @property) - Log warning instead of silently swallowing descriptor errors during discovery - Validate explicit name= at decoration time via _validate_member_name - Add tests for all of the above Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix temperature converter skill: make resource necessary for script Refactor TemperatureConverterSkill so the agent must read the formulas resource (factor/offset) before calling the script, aligning with the volume-converter pattern. - Resource: numeric factor/offset table instead of symbolic formulas - Script: generic linear transform (value * factor + offset) - Instructions: updated to reflect new workflow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SergeyMenshykh ·
2026-05-07 19:39:12 +00:00 -
.NET: Foundry.Hosting IT: avoid MSB3026 in publish; fix telemetry UT flake (#5689)
CI publish step: gate the BuildProjectReferences=false fast-path on an explicit -UsePrebuiltProjectReferences switch (passed by the workflow) instead of marker detection. Adds a preflight error when stale obj/Release/net10.0 outputs would cause CS0579, with actionable recovery instructions. Telemetry UT flake: AgentFrameworkResponseHandlerTelemetryTests was using a plain List<Activity> for OTel's InMemoryExporter. The exporter writes from background Activity completion callbacks while parallel tests on the same global ActivitySource feed every listener, racing against the assertion's enumeration and throwing 'Collection was modified'. Replaced with a small thread-safe ConcurrentActivityList that locks add/enumerate and returns a snapshot for assertions.
Roger Barreto ·
2026-05-07 18:54:46 +00:00 -
.NET: feat: Implement Magentic Orchestration for .NET (#5595)
* feat: Implement Magentic Orchestration for .NET * fixup: Update for review comments * fix: Fix FenceJsonRegexPattern * fix: Format * fix: Updates for PR feedback * fix: Add missing serialized types to source gen for trimming * fix: Address PR Comments
Jacob Alber ·
2026-05-07 18:36:15 +00:00 -
Python: Fix
MCPStreamableHTTPToolleakingasyncio.CancelledErrorwhen MCP server is unreachable (#5687)* fix: wrap asyncio.CancelledError in ToolException in _connect_on_owner (#5667) asyncio.CancelledError is a BaseException (not Exception) in Python 3.8+. When an MCP server is unreachable, the MCP library's internal anyio task group raises CancelledError, which escaped all three 'except Exception' handlers in _connect_on_owner(). This propagated through _run_lifecycle_owner -> _run_on_lifecycle_owner -> connect -> __aenter__, bypassing user except Exception blocks entirely. Fix: change the three except-Exception clauses in _connect_on_owner to 'except (Exception, asyncio.CancelledError)' so spurious CancelledErrors from the MCP transport layer are caught and wrapped in ToolException, consistent with the method's documented contract. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(mcp): propagate genuine task CancelledError in connect() (#5667) On Python >= 3.11, check task.cancelling() > 0 before wrapping CancelledError as ToolException in the three except blocks inside _connect_on_owner(). When the current task is being cancelled by its caller, the CancelledError now propagates after cleanup, consistent with the existing pattern at _mcp.py:560-564 and _runner.py:115-120. On Python < 3.11 task.cancelling() is unavailable, so MCP-internal CancelledErrors still cannot be reliably distinguished from caller-driven cancellation; they continue to be wrapped as ToolException with a comment documenting the trade-off. Tests: - Add cleanup assertion to transport-creation CancelledError test - Add MCPStdioTool variants exercising the 'command' message branches for both transport-creation and initialize CancelledError paths - Add Python 3.11+-gated tests verifying genuine task cancellation propagates (and still cleans up) for transport and initialize stages Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(mcp): log CancelledError with exc_info before wrapping in ToolException (#5667) CancelledError inherits from BaseException (not Exception) on Python >= 3.8, so the 'inner_exception=ex if isinstance(ex, Exception) else None' guard always yields None for CancelledError. This means ToolException.__init__ calls logger.log(level, message, exc_info=None), dropping the traceback. Add an explicit logger.debug(error_msg, exc_info=ex) before each raise ToolException(...) in the three CancelledError handlers so the full traceback is preserved in debug logs when MCP-internal cancellation is wrapped rather than propagated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback for #5667: Python: [Bug]: Error Handling Issue regarding Python MCPStreamableHTTPTool Class * refactor(_mcp): extract cancellation helper, fix session error msg and exc_info - Extract _should_propagate_cancelled_error() helper to eliminate duplicated genuine-cancellation detection logic across the three connect() except blocks - Fix session-creation ToolException message to include exception details (e.g. 'Failed to create MCP session: <ex>') matching the transport and initialize failure paths - Change exc_info=ex to exc_info=True in all three logger.debug() calls for idiomatic logging - Add tests for _should_propagate_cancelled_error helper - Add regression test asserting session error message includes exception text - Add test verifying logger.debug is called with exc_info=True Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: factor out _close_and_check_cancelled helper in _connect_on_owner Addresses review comment on PR #5687: 1. Add _close_and_check_cancelled() helper method that combines _safe_close_exit_stack() + _should_propagate_cancelled_error() into a single await-able call. This eliminates the duplicated close-then-check pattern that appeared identically in all three connect phases (transport, session, initialize), reducing future drift risk. 2. Comments 2 and 3 (missing {ex} in session error message and non-idiomatic exc_info=ex) were already addressed in the current code: all error messages include {ex} and all logger.debug calls use exc_info=True. 3. Add test_connect_genuine_cancellation_during_session_creation_propagates to cover the previously untested genuine-cancellation path in the session-creation phase (transport and initialize phases already had tests). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback for #5667: review comment fixes --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evan Mattson ·
2026-05-07 17:58:30 +00:00 -
.NET: feat: Update Github Copilot SDK to 1.0.0-beta.2 (#5699)
* feat: Update Github Copilot SDK to 1.0.0-beta.2 * Fix formatting Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: Update for breaking changes in Github.Copilot.SDK * fix sample project * fix: whitespace formatting --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Jacob Alber ·
2026-05-07 19:15:10 +01:00 -
Python: Add
base_urlparameter toAnthropicClientandRawAnthropicClient(#5685)* feat(anthropic): add base_url parameter to AnthropicClient and RawAnthropicClient Add base_url support to AnthropicSettings TypedDict, RawAnthropicClient, and AnthropicClient so users can point the client at Foundry or other Anthropic-compatible endpoints without having to construct AsyncAnthropic manually. - Add base_url field to AnthropicSettings (resolved from ANTHROPIC_BASE_URL env var) - Add base_url parameter to RawAnthropicClient.__init__ and pass it to AsyncAnthropic - Add base_url parameter to AnthropicClient.__init__ and forward to super - Add unit tests for base_url on both client classes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Add `base_url` parameter to `AnthropicClient` and `RawAnthropicClient` Fixes #5683 * test: add ANTHROPIC_BASE_URL env fallback tests for issue #5683 Add unit tests verifying that both AnthropicClient and RawAnthropicClient pick up base_url from the ANTHROPIC_BASE_URL environment variable via load_settings when base_url is not passed explicitly as a constructor arg. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(anthropic): explicit base_url kwarg beats ANTHROPIC_BASE_URL env var (#5683) Add regression tests asserting that when both ANTHROPIC_BASE_URL is set in the environment *and* an explicit base_url kwarg is passed to AnthropicClient / RawAnthropicClient, the explicit kwarg wins. This closes the priority-ordering contract (explicit arg > env var) that the existing tests left implicit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evan Mattson ·
2026-05-07 17:57:09 +00:00 -
.NET: Support reasoning events in AGUI (#4953)
* Support reasoning * MEAI gives the same MessageId for reasoning and text content because they are part of the same logical model response. Create a new GUID for reasoning messages to be consistent with AGUI protocol and establish no link between reasoning and text messages * When a frontend AG-UI client sends conversation history back in a subsequent POST, any accumulated role: "reasoning" messages fail deserialization in AGUIMessageJsonConverter because the role wasn't handled - causing the request to fail. This adds AGUIReasoningMessage with Content and EncryptedValue properties, registers it in the JSON converter and serializer context, and converts it to TextReasoningContent (with ProtectedData) in AsChatMessages. * Added MapReasoningMessage - converts a ChatMessage containing TextReasoningContent to AGUIReasoningMessage for c# client * review * Support reasoning * MEAI gives the same MessageId for reasoning and text content because they are part of the same logical model response. Create a new GUID for reasoning messages to be consistent with AGUI protocol and establish no link between reasoning and text messages * When a frontend AG-UI client sends conversation history back in a subsequent POST, any accumulated role: "reasoning" messages fail deserialization in AGUIMessageJsonConverter because the role wasn't handled - causing the request to fail. This adds AGUIReasoningMessage with Content and EncryptedValue properties, registers it in the JSON converter and serializer context, and converts it to TextReasoningContent (with ProtectedData) in AsChatMessages. * Added MapReasoningMessage - converts a ChatMessage containing TextReasoningContent to AGUIReasoningMessage for c# client * review * dotnet format * Replace hardcoded string with constant Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Jeffin SIby ·
2026-05-07 15:09:04 +00:00 -
Python: Add support for function approval flow in Foundry hosted agent (#5666)
* Add support for function approval flow in Foundry hosted agent * Address comments * Address comments * Address comments
Tao Chen ·
2026-05-07 14:55:26 +00:00 -
Python: Core: notify agent of external AgentModeProvider mode changes (#5650)
When the operating mode is changed externally (e.g. via a slash-command handler calling set_agent_mode), the agent's chat history still shows the prior set_mode tool call near the end. Updating only the system instructions is insufficient — models tend to anchor on the recent tool call and ignore the new mode. Mirror the .NET AgentModeProvider behavior: when set_agent_mode detects an actual mode change, record the previous mode in provider state. On the next before_run, the provider pops that flag and injects a user-role notification message announcing the switch, so the most recent context unambiguously reflects the current mode. The agent-driven set_mode tool path bypasses this so it does not trigger a redundant notification on its own change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eduard van Valkenburg ·
2026-05-07 02:58:38 +00:00 -
.NET: Issue 5662 (#5668)
* Fix dangling function_call on approval response in Foundry hosting (#5662) Make the wire<->AF approval translation in Microsoft.Agents.AI.Foundry.Hosting lossless so the resume turn pairs function_call/function_call_output correctly. Root cause: InputConverter.ConvertMcpApprovalResponse rebuilt FunctionCallContent with CallId set to the FICC-composed AF request id (ficc_<callId>) and Name hardcoded to 'mcp_approval'. This (a) broke Azure Conversations pairing because the persisted function_call had CallId <callId> without prefix, and (b) made FICC unable to invoke the original tool by name on resume. Fix: ToolApprovalIdMap now records the original FunctionCallContent (CallId, Name, Arguments) keyed by wire id at outbound time. InputConverter reconstructs the original FCC on inbound, falling back to the legacy placeholder when no mapping exists. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Suppress orphan function_call items at the wire (#5662) Foundry-Hosting's OutputConverter was emitting FunctionCallContent as wire `function_call` items while dropping the paired FunctionResultContent. The result: every auto-invoked tool call left an orphan `function_call` in the response store. The next turn (chained via previous_response_id or via a workflow that yields after one turn under externalLoop) reloaded that history and submitted it to Azure Conversations, which rejected it with HTTP 400 `No tool output found for function call ...`. Function call/result pairs are entirely internal to the agent's tool-calling loop and have no place on the wire. Approval-required calls already surface separately via ToolApprovalRequestContent → mcp_approval_request, so dropping FCC is safe. FCC's message-close behavior is preserved so pre-tool text doesn't accidentally concatenate with post-tool text under the same MessageId. Existing OutputConverter tests asserting FCC wire emission are updated to assert suppression. Verified end-to-end against the declarative-workflow-menu external_loop bench: three-turn previous_response_id chain (menu → carbonara price → EXIT) now completes, where it previously failed at turn 2 with HTTP 400. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fail fast when no approval mapping is recorded (#5662) The previous best-effort placeholder fallback in InputConverter.ConvertMcpApprovalResponse couldn't actually round-trip — it just delayed and obscured the failure as an HTTP 400 deep inside the agent loop. Throw InvalidOperationException with the wire id and a clear cause hint instead so the failure is local and actionable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Trim narrative comments and exception message (#5662) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Defer FunctionCallContent emission until matched FunctionResultContent (#5662) Replace blanket FCC suppression with deferred emission. FunctionCallContent is buffered (name + serialized arguments) keyed by CallId; the function_call and function_call_output wire items are only flushed once the matching FunctionResultContent arrives. - Auto-invoked FCC/FRC pairs surface as paired wire items so Azure's stored conversation has matched call+output and previous_response_id resume works (closes the orphan-function_call symptom from #5662). - Orphan FCCs (e.g. workflow paused at a checkpoint mid-tool-loop) are dropped so they never poison the response store. - Approval flows are unchanged: TARC still emits mcp_approval_request and the post-approval FRC has no buffered FCC to pair with so it is dropped; the approval round-trip handles its own pairing via mcp_approval_*. - Leaves the door open for future client-side function calling: that pattern would surface an FCC without an FRC, would need to opt out of buffering, but the wire shape is already correct. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Emit FunctionCallContent and FunctionResultContent directly (option B) Replace the deferred-emission/buffer-and-drop strategy with direct emission of both function_call and function_call_output wire items. Rationale: a lone FunctionCallContent in OutputConverter's input can mean two semantically different things, and only the caller knows which: - Auto-invoke (FICC response surface): always paired with a matching FRC; both halves should appear on the wire as historical record. - HITL / port-pause request (typed RequestPort<FunctionCallContent,...> or workflow synthesizing a request): a lone FCC IS the wire signal that the caller must resume by supplying a function_call_output. Buffering+dropping orphans silently swallows the second case. Emitting both directly is the only correct shape for OpenAI Responses semantics. The InputConverter already accepts function_call_output and mcp_approval_response on resume, so the round-trip works for both kinds. The approval-flow round-trip fixes (ToolApprovalIdMap rich ApprovalEntry, fail-fast on missing mapping in ConvertMcpApprovalResponse) remain intact. Tests: updated 7 OutputConverter tests + 1 OutputConverterWorkflow test that asserted the old buffer/drop semantics; all 227 tests pass. Refs #5662 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5668 review feedback on TryLoadMap Stop swallowing JsonException in ToolApprovalIdMap.TryLoadMap. The catch block recovered to an empty map and a stale comment claimed the caller would gracefully degrade via a 'wire-id fallback path' — but that path no longer exists: InputConverter.ConvertMcpApprovalResponse fails fast when no entry is found. Letting the JsonException propagate produces an error message that points at the actual cause (a state-bag format incompatibility), instead of converting it into a confusing 'no approval mapping recorded' InvalidOperationException one stack frame later. Refs #5662, PR #5668 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5668 review feedback round 2 - OutputConverter FRC: emit string results as raw text (no JSON-quoting), matching the wire contract for function_call_output.output. - OutputConverter FCC: validate non-empty CallId before closing the in-flight text message, so a skipped FCC no longer breaks output-item boundaries. - ToolApprovalIdMap.Record: take pre-serialized arguments JSON (string) and primitive callId/name. Drops [RequiresUnreferencedCode]/[RequiresDynamicCode] so trim/AOT warnings stop propagating to call sites. - ToolApprovalIdMap.Record: no-op when callId or name is empty. - Tests: dedup duplicate ConvertItemsToMessages_McpApprovalResponse no-mapping test; add coverage for empty-CallId boundary, raw-string FRC payload, and Record empty-key no-op. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ben Thomas ·
2026-05-07 00:30:41 +00:00 -
Python: Remove bespoke Foundry toolbox helpers; standardize on MCP for toolbox consumption (#5671)
* Remove Foundry toolbox helpers; standardize on MCP for toolbox consumption - Remove RawFoundryChatClient.get_toolbox() and its fetch_toolbox import - Remove fetch_toolbox, select_toolbox_tools, get_toolbox_tool_name, get_toolbox_tool_type, FoundryHostedToolType, ToolboxToolSelectionInput from agent_framework_foundry._tools - Remove ExperimentalFeature.TOOLBOXES from _feature_stage.py (no consumers) - Drop toolbox re-exports from agent_framework_foundry/__init__.py and agent_framework.foundry namespace - Update _sanitize_foundry_response_tool docstring to remove toolbox framing; sanitization logic itself is unchanged - Update _agent.py docstring: 'toolbox-fetched MCP' → 'hosted MCP' - Delete tests/test_toolbox.py (all tests covered removed helpers) - Update test_foundry_chat_client.py: rename/redoc tests that mentioned toolbox but test sanitization that remains - Delete foundry_chat_client_with_toolbox.py (bespoke toolbox API sample) - Delete foundry_toolbox_context_provider.py (relied on select_toolbox_tools) - Rename foundry_chat_client_with_toolbox_mcp.py → foundry_chat_client_with_toolbox.py (canonical MCP pattern) - Rewrite 04_foundry_toolbox/main.py to use MCPStreamableHTTPTool - Update provider/README, context_providers/README, 04_foundry_toolbox/README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(samples): update 06_files sample to consume toolbox via MCP (#5670) Replace removed get_toolbox/select_toolbox_tools APIs with MCPStreamableHTTPTool, using allowed_tools=["code_interpreter"] to select only the code interpreter from the toolbox endpoint. Update .env.example and README to use FOUNDRY_TOOLBOX_ENDPOINT instead of TOOLBOX_NAME. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(foundry): remove non-existent toolbox helper APIs from README (#5670) Remove the 'fetch, optionally filter, and pass tools directly' pattern from the FoundryChatClient toolbox documentation, as select_toolbox_tools and get_toolbox were removed. Only the MCP endpoint pattern is documented. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(foundry): remove residual toolbox docstring references and reproduction report Remove REPRODUCTION_REPORT.md (workflow artifact that should not be committed), and update two remaining docstring references that still said 'toolbox reads' /'toolbox definition' after the toolbox helpers were removed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Remove bespoke Foundry toolbox helpers; standardize on MCP for toolbox consumption Fixes #5670 * fix(#5670): resolve toolbox endpoint from TOOLBOX_NAME fallback; add namespace regression tests - Add _resolve_toolbox_endpoint() helper in 04_foundry_toolbox/main.py and 06_files/main.py that prefers FOUNDRY_TOOLBOX_ENDPOINT but falls back to deriving the MCP URL from FOUNDRY_PROJECT_ENDPOINT + TOOLBOX_NAME — fixing the startup KeyError when agents are deployed via azd provision (which injects TOOLBOX_NAME, not FOUNDRY_TOOLBOX_ENDPOINT). - Update 04_foundry_toolbox/.env.example to use FOUNDRY_TOOLBOX_ENDPOINT (consistent with 06_files). - Add TOOLBOX_NAME env var to 06_files/agent.yaml so deployed agents have it available for the fallback derivation. - Update both READMEs to document the two ways to supply the toolbox endpoint. - Add test_foundry_namespace_no_longer_exposes_toolbox_helpers() with negative assertions for FoundryHostedToolType, get_toolbox_tool_name, get_toolbox_tool_type, and select_toolbox_tools — guarding against accidental re-introduction of removed symbols. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(samples): fail fast on empty FOUNDRY_TOOLBOX_ENDPOINT; add unit tests Addresses review feedback for #5670: - In _resolve_toolbox_endpoint() (04_foundry_toolbox/main.py and 06_files/main.py) change the walrus-operator check from a truthy test to an explicit 'is not None' guard. An explicitly set empty string now raises ValueError immediately with a clear message instead of silently falling through to the fallback URL construction. - Add tests/samples/hosting/test_toolbox_endpoint.py covering both sample modules: (a) FOUNDRY_TOOLBOX_ENDPOINT set → returned as-is (b) FOUNDRY_TOOLBOX_ENDPOINT set to empty string → ValueError (c) fallback constructs URL from FOUNDRY_PROJECT_ENDPOINT + TOOLBOX_NAME, stripping trailing slashes (d) neither variable group set → KeyError Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback: remove extraneous test and docstring content - Remove test_foundry_namespace_no_longer_exposes_toolbox_helpers (no longer warranted) - Remove docstring from _agent.py _prepare_tools_for_openai (extraneous) - Trim _chat_client.py _prepare_tools_for_openai docstring to one-liner (toolbox references no longer relevant) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove remaining extraneous docstring from RawFoundryChatClient._prepare_tools_for_openai Address review comment on PR #5671: reviewer noted the description isn't warranted now that toolbox helpers have been removed. Matches the pattern in RawFoundryAgentChatClient which has no docstring. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evan Mattson ·
2026-05-06 23:56:16 +00:00 -
.NET: Add Foundry.Hosting.IntegrationTests (#5598)
* Foundry.Hosting.IntegrationTests: scaffold project, fixtures, and 24 tests Add a new integration test project for Foundry hosted agents alongside the existing Foundry.IntegrationTests project. The project provisions a real Foundry hosted agent per scenario via AgentAdministrationClient.CreateAgentVersionAsync, points it at a single test container image (built and pushed out of band by scripts/it-build-image.ps1 in a follow up commit), and exercises the agent through AIProjectClient.AsAIAgent. Six scenario fixtures are introduced, each pointing at the same image but selecting behavior via the IT_SCENARIO environment variable on the HostedAgentDefinition: - HappyPathHostedAgentFixture (round trip, multi turn, stored=false flag) - ToolCallingHostedAgentFixture (server side AIFunctions) - ToolCallingApprovalHostedAgentFixture (approval flow) - ToolboxHostedAgentFixture (Foundry toolbox) - McpToolboxHostedAgentFixture (MCP backed toolbox) - CustomStorageHostedAgentFixture (custom storage provider) 24 tests across 6 test classes are scaffolded. All are tagged Skip pending the test container build and the end to end smoke iteration in follow up commits. Once the container is in place the Skip annotations can be removed scenario by scenario. Adds an IT_HOSTED_AGENT_IMAGE constant to the shared TestSettings so every IT project agrees on the env var name the build script emits. * Foundry.Hosting.IntegrationTests: add TestContainer, build script, slnx, README Adds the rest of the integration test infrastructure on top of the previous scaffolding commit: * Foundry.Hosting.IntegrationTests.TestContainer csproj and Program.cs implementing the multi scenario container (one image, IT_SCENARIO env var dispatches between happy-path, tool-calling, tool-calling-approval, toolbox, mcp-toolbox, and custom-storage). The toolbox, mcp-toolbox, and custom-storage branches are placeholders pending API surface stabilization. * Dockerfile and dockerignore in the test container project, using the contributor pattern matching the investigation work (host side dotnet publish, container only does COPY out/). * scripts/it-build-image.ps1 with mandatory Registry parameter (no hardcoded ACR), content hashed tags so unchanged source results in a no op push, and emits IT_HOSTED_AGENT_IMAGE for shells and CI to consume. * slnx entry for both new projects. * README in the IT project covering env vars, image build, scenario table, and current placeholder status. Steps still pending: end to end smoke (step 5) and CI workflow integration (step 6) require a live Foundry deployment and ACR push, so they land in follow up commits. * Foundry.Hosting.IntegrationTests: address PR 5598 review feedback Fix issues raised by Copilot review: * it-build-image.ps1: hash file contents, not the path list, so any source edit produces a fresh tag. Normalize Registry input by stripping scheme and trailing slash before deriving the ACR short name. Validate the short name is non empty. * HostedAgentFixture: route GetAgentAsync through _adminClient (which has the FoundryFeaturesPolicy attached) instead of through _projectClient.AgentAdministrationClient (which does not). * HostedAgentFixture FoundryFeaturesPolicy: replace Headers.Add with Remove plus Add so retries cannot accumulate duplicate headers. * HappyPath, ToolCalling, ToolCallingApproval, CustomStorage tests: create the AgentSession before turn 1 and reuse it for both turns. The previous pattern created the session after turn 1 so turn 2 had no link to turn 1, defeating the multi turn assertion. * .NET: Foundry.Hosting.IntegrationTests: constrain to net10.0 + dotnet format autofix - Set <TargetFrameworks>net10.0</TargetFrameworks>: the project references both Microsoft.Agents.AI.Foundry.Hosting (net8/9/10 only) and AgentConformance.IntegrationTests (net10.0;net472 — inherits the tests-default TFM list). The intersection is net10.0; the previous $(TargetFrameworksCore) triple caused NU1702 + System.Text.Json version conflicts on the net8.0/net9.0 builds because AgentConformance had no matching asset. - Apply `dotnet format` autofix on the test files (IDE0005, IDE0009, IDE0032, IMPORTS). * .NET: Foundry.Hosting.IntegrationTests.TestContainer/Program.cs: add UTF-8 BOM CI's check-format requires charset=utf-8-bom per .editorconfig. * Foundry.Hosting IntegrationTests: wire end-to-end CI flow against hosted agents Make the integration tests usable end-to-end against a live Foundry deployment, including a per-run rebuild of the test container so framework code changes are exercised. Fixture (HostedAgentFixture.cs) * Switch from per-run unique agent names to stable scenario-keyed names (it-happy-path, it-tool-calling, ...). The agent's managed identity carries the Azure AI User role on the project scope, which is required for inbound inference; deleting the agent recycles the MI and breaks that role assignment, so we keep the agent across runs and only churn versions. * Add IT_RUN_ID env var to defeat Foundry's content-addressed version dedup; otherwise a rerun just receives the existing version and Dispose deletes it. * PATCH the per-agent endpoint with AgentEndpointConfig (Responses protocol, version selector at 100% to the new version). Without this, /agents/{name}/endpoint/protocols/ openai/responses returns HTTP 400. * Build a per-agent ProjectOpenAIClient (not the cached projectClient.ProjectOpenAIClient, which is bound to the project-level URL); set AgentName in options so the URL routes through the agent endpoint, and add the Foundry-Features header to the inference pipeline. * Use Versions (which serializes to container_protocol_versions) instead of the deprecated ProtocolVersions; the server now rejects the legacy field. * On Dispose, delete only the version this fixture created. Never delete the agent. Tests * Tag every HostedAgentTests class with [Trait("Category", "FoundryHostedAgents")] so the CI workflow can route them to a separate Foundry project than the rest of the integration suite. CI workflow (.github/workflows/dotnet-build-and-test.yml) * Add a foundryHosting paths-filter covering Microsoft.Agents.AI.Foundry.Hosting and its in-repo dependency chain (Foundry, Agents.AI, Agents.AI.Abstractions), the test container, the test fixture, Directory.Packages.props, the build script, and this workflow file. Skip the costly hosted-agent steps when none of those changed. * Add "Build and push Foundry Hosted Agents test container" step that invokes scripts/it-build-image.ps1 against vars.IT_HOSTED_AGENT_REGISTRY and pipes the resulting IT_HOSTED_AGENT_IMAGE=<tag> into GITHUB_ENV. * Add "Run Foundry Hosted Agents Integration Tests" step that filters in only the new trait, with AZURE_AI_PROJECT_ENDPOINT/AZURE_AI_MODEL_DEPLOYMENT_NAME pointed at IT_HOSTED_AGENT_PROJECT_ENDPOINT/IT_HOSTED_AGENT_MODEL_DEPLOYMENT_NAME (Tao project, East US 2; the SK IT project's region does not yet support hosted agents preview). * Exclude the new trait from the existing "Run Integration Tests" step. * TEMP: drop the != 'pull_request' guard on the new steps and on Azure CLI Login when the paths-filter triggers, so PR #5598 can validate the wiring before promoting to merge queue only. Restore the original guard after one green PR run. Build script (scripts/it-build-image.ps1) * Hash now spans TestContainer source AND its referenced framework projects so any framework code change forces a fresh tag and a real docker push; the previous TestContainer-only hash silently reused stale images on framework edits. Bootstrap script (dotnet/tests/Foundry.Hosting.IntegrationTests/scripts/it-bootstrap-agents.ps1) * New idempotent script that creates the six stable scenario agents and grants Azure AI User on the project scope to each agent's MI. Run once per Foundry project. Includes AAD-graph propagation retries because newly created MIs take time to appear there. README (dotnet/tests/Foundry.Hosting.IntegrationTests/README.md) * Document the bootstrap prerequisite, the regional caveat (East US 2 is the only region we have validated; East US returned "Unsupported region" at the time of writing), the per-run image rebuild, and the CI wiring including the SP RBAC requirements. SDK pin (TEMP) * Bump Microsoft.Agents.AI.Foundry.Hosting's Azure.AI.Projects VersionOverride to 2.1.0-alpha.20260505.1 from the azure-sdk public daily feed (added to nuget.config). This release is the first that builds the per-agent inference URL as /agents/{name}/endpoint/protocols/openai (the 2.1.0-beta.1 release builds .../openai/openai/v1, which the server rejects). Revert both the feed and the override once the URL fix lands in a stable Azure.AI.Projects release. * Foundry.Hosting IntegrationTests: revert alpha SDK pin; move endpoint PATCH to bootstrap The alpha SDK pin (Azure.AI.Projects 2.1.0-alpha.20260505.1 from the azure-sdk public daily feed) was needed only for the URL routing fix and the strongly-typed AgentEndpointConfig/PatchAgentOptions wrapper. We do not need either right now: the fixture stays compatible with the public 2.1.0-beta.1 by moving the one-time endpoint PATCH to the bootstrap script (it sets version_selector to FixedRatio @latest, so each new fixture run becomes the served version automatically without a per-run PATCH from the test code). The hosted-agent invocation path will start working end-to-end once the URL routing fix lands in a stable Azure.AI.Projects release; until then the tests stay [Fact(Skip = ...)] as documented. * Revert dotnet/nuget.config: drop the azure-sdk-for-net public feed. * Revert Microsoft.Agents.AI.Foundry.Hosting.csproj VersionOverride to 2.1.0-beta.1. * Revert Microsoft.Agents.AI.Foundry.UnitTests and Microsoft.Agents.AI.Foundry.Hosting.UnitTests Azure.AI.Projects pin (they had been bumped to align Azure.Core 1.54 transitive). * Drop the AgentEndpointConfig PATCH block from HostedAgentFixture.cs (the type is alpha-only). Replace with a comment pointing at the bootstrap script. * Bootstrap script (it-bootstrap-agents.ps1) now also PATCHes each agent's endpoint with version_selector=@latest if not already set. Idempotent. * Foundry.Hosting IntegrationTests: drop accidentally committed filtered.slnx * Foundry.Hosting IntegrationTests: revert TEMP PR override on Azure CLI Login + IT steps The previous attempt to validate the new hosted-agent IT wiring on PR #5598 failed because the PR is from a fork (rogerbarreto/agent-framework-public). GitHub never passes environment secrets to fork PRs regardless of event-name guards on individual steps, so 'azure/login@v2' fails with 'client-id and tenant-id are not supplied'. Restore the original github.event_name != 'pull_request' guard. The new steps will execute on push to main and on merge_group runs. * Foundry.Hosting IntegrationTests: invoke build-and-push script with absolute path The pwsh shell on the GitHub Actions runner couldn't resolve ./scripts/it-build-image.ps1 when the step had no working-directory set; the step inherits the runner's PWD which is not always the repo root after preceding steps. Use github.workspace explicitly to remove the ambiguity. * Foundry.Hosting IntegrationTests: move it-build-image.ps1 inside the IT project tree The previous location at scripts/it-build-image.ps1 lived outside the sparse-checkout paths the workflow uses (.github, dotnet, python, declarative-agents), so the runner never had the file when the new step tried to invoke it. Move the script next to its sibling it-bootstrap-agents.ps1 inside the IT project tree, and anchor its relative paths to the repo root via so callers can invoke it from any PWD. * Move scripts/it-build-image.ps1 -> dotnet/tests/Foundry.Hosting.IntegrationTests/scripts/it-build-image.ps1 * Add Push-Location to the resolved repo root inside the script (Pop-Location in finally) so the existing relative paths (TestContainerProject, hashed src dirs) keep working no matter where the script is invoked from. * Update the workflow path filter and the step's invocation path to the new location. * Foundry.Hosting IntegrationTests: enable 5 HappyPath tests on the live Foundry endpoint The fixture already constructs ProjectOpenAIClient via the per-agent path that beta.1 supports (new ProjectOpenAIClient(uri, cred, opts { AgentName })), so no SDK pin bump is required to run the smoke tests end-to-end. Un-skip the 5 tests that pass against the live test container. Tests un-skipped (verified passing locally against tao-foundry-prj): * RunAsync_ReturnsNonEmptyTextAsync * RunStreamingAsync_YieldsAtLeastOneUpdateAsync * MultiTurn_WithPreviousResponseId_PreservesContextAsync * StoredFalse_Baseline_DoesNotPersistResponseAsync * Instructions_FromContainerDefinition_AreObeyedAsync Tests still skipped with a more specific reason (4 of 9 in HappyPath plus all ToolCalling*, McpToolbox, Toolbox, CustomStorage) because the test container does not yet emit usable response_id / conversation_id chains, and the placeholder scenarios are not implemented in the test container's Program.cs. These are test container limitations, not infra bugs, and can be un-skipped as the container surfaces stabilize. * Foundry.Hosting IntegrationTests: extract hosted IT into parallel job, add Workflows dep Address Wesley's review feedback on PR #5598: 1. Pull Foundry hosted-agent IT into its own dotnet-foundry-hosted-it job that runs in parallel to dotnet-build and dotnet-test. Same path-filter gate keeps it skipped on unrelated edits. Builds only the filtered solution containing Foundry.Hosting.IntegrationTests and src deps. dotnet-build-and-test-check now waits on it too. 2. Add Microsoft.Agents.AI.Workflows to the foundryHosting paths-filter and to hashedDirs in it-build-image.ps1 since Foundry.Hosting transitively depends on it. TFM constraint on the IT csproj stays at net10.0 because AgentConformance.IntegrationTests targets net10/net472 and is consumed by ~12 other IT projects on net472. --------- Co-authored-by: Roger Barreto <rbarreto@microsoft.com>Roger Barreto ·
2026-05-06 16:08:15 +00:00 -
.NET: Fix flaky declarative test (#5669)
* Fix flaky declarative test * Addressed host gating and guid parsing concerns in test file.
Peter Ibekwe ·
2026-05-06 15:07:23 +00:00 -
.NET: Bump MEAI to 10.5.1 and add Foundry per-call x-client header support (#5652)
* Bump MEAI to 10.5.1 and add per-call x-client header support Replaces the brittle UserAgentResponsesClient subclass with a clean per-call x-client-* header pipeline built on the new Microsoft.Extensions.AI 10.5.1 OpenAIRequestPolicies hook. Public surface (Microsoft.Agents.AI.Foundry, [Experimental(MAAI001)]): * chatOptions.WithClientHeader(name, value) and .WithClientHeaders(IEnumerable) validate the x-client- prefix (case-insensitive), apply all-or-nothing on bulk, and throw InvalidOperationException on foreign-typed slot collision * myAgent.AsBuilder().UseClientHeaders().Build() opts a customer-built agent into the pipeline; idempotent via agent.GetService<ClientHeadersAgent>() * Foundry-built agents (FoundryAgent.Create*) pre-wire automatically Internals: * ClientHeadersAgent decorator snapshots the dict at scope-push time so concurrent runs sharing a ChatOptions reference do not leak headers * ClientHeadersScope is an AsyncLocal<IReadOnlyDictionary<string,string>?> with LIFO push/dispose semantics * ClientHeadersPolicy singleton stamps headers via Headers.Set so per-call values overwrite any same-name header from earlier policies and so duplicate registration is value-stable * OpenAIRequestPoliciesReflection dedups against MEAI's private _entries field and falls back to AddPolicy on any reflection failure; a CI test asserts the field shape on every MEAI bump Hosting cleanup: * Deleted UserAgentResponsesClient and its dummy throwing pipeline * HostedAgentUserAgentPolicy is now registered via OpenAIRequestPolicies in FoundryHostingExtensions.TryApplyUserAgent Tests: * 19 new unit tests in ClientHeadersExtensionsTests.cs covering validation, AsyncLocal isolation, snapshot semantics, end-to-end wire stamping, and shared-chat-client dedup * Updated OpenTelemetryAgentTests for MEAI 10.5.1 changes to web_search serialization and the reduced tool definition payload when sensitive data capture is disabled Microsoft.Extensions.Compliance.Abstractions stays at 10.5.0 because no 10.5.1 release exists on nuget.org. * Address PR review: pre-wire AsAIAgent path and dedup TryApplyUserAgent * FoundryAgent: extract WireClientHeaders helper and call it from the internal (AIProjectClient, ChatClientAgent) constructor used by AzureAIProjectChatClientExtensions.AsAIAgent so those Foundry-built agents also pre-wire the x-client header pipeline. * Foundry.Hosting TryApplyUserAgent: dedup HostedAgentUserAgentPolicy registration per OpenAIRequestPolicies instance via ConditionalWeakTable so per-request resolution does not grow the policy list unboundedly on singleton agents. * Add tests covering AsAIAgent pre-wire and TryApplyUserAgent dedup Backs the PR review fixes from
a4c8f91with regression tests: * ClientHeadersExtensionsTests: AsAIAgent_FoundryAgent_HasPreWiredClientHeadersAgent asserts the FoundryAgent built via AzureAIProjectChatClientExtensions.AsAIAgent contains a ClientHeadersAgent in its delegating chain (catches future regressions of the bypass). * ClientHeadersExtensionsTests: FoundryAgent_PublicConstructor_HasPreWiredClientHeadersAgent covers the public constructor path the same way. * ClientHeadersExtensionsTests: UseClientHeaders_RepeatedRegistrations_OnSameChatClient_OnlyRegistersOnce invokes UseClientHeaders 25 times on a shared chat client and asserts via reflection that OpenAIRequestPolicies._entries length is exactly 1. * HostedTryApplyUserAgentDedupTests: two tests asserting FoundryHostingExtensions.TryApplyUserAgent stays at one entry per OpenAIRequestPolicies instance after 50 calls on the same agent and across distinct agents on different chat clients. * Move tests next to their SUT Removes the dedicated HostedTryApplyUserAgentDedupTests.cs test class. Tests are co-located with the SUT they exercise: * FoundryAgentTests.cs gains the Constructor_PreWiresClientHeadersAgent and Constructor_FromAsAIAgentExtension_PreWiresClientHeadersAgent cases, since FoundryAgent is the SUT for the pre-wire behavior. * HostedOutboundUserAgentTests.cs gains the two TryApplyUserAgent dedup cases, since FoundryHostingExtensions.TryApplyUserAgent is the SUT it already covers. * ClientHeadersExtensionsTests.cs keeps only the UseClientHeaders_RepeatedRegistrations_OnSameChatClient_OnlyRegistersOnce case, which exercises the public ClientHeadersExtensions surface. * Remove redundant WithCancellation on inner streaming call ct is already passed to InnerAgent.RunStreamingAsync, so .WithCancellation(ct) on the resulting IAsyncEnumerable is a no-op. Caught by Sergey on PR review. * Address PR review: surface downstream MEAI experimental ID * Add AIOpenAIRequestPolicies = MEAIExperiments alias to DiagnosticIds.Experiments (matches the existing AIResponseContinuations, AIMcpServers, AIFunctionApprovals pattern). * Mark public ClientHeadersExtensions with [Experimental(AIOpenAIRequestPolicies)] instead of AgentsAIExperiments. Consumers now see the MEAI001 warning, surfacing the dependency on MEAI's experimental OpenAIRequestPolicies hook. * Mark internal OpenAIRequestPoliciesReflection with the same alias to suppress warnings at the source rather than via project-wide NoWarn. * Remove MEAI001 from Foundry csproj NoWarn (kept on Foundry.Hosting where pre-PR usages remain). * Clarify ClientHeadersScope XML doc: AsyncLocal flows values forward but does NOT auto-restore on method return; explicit using/Dispose is what gives stack-style LIFO semantics.Roger Barreto ·
2026-05-06 14:43:08 +00:00 -
Python: [Breaking] Restructure agent skills to use multi-source architecture (#5584)
* migrate skills to multi source architecture * Fix ruff lint errors in skills module (ASYNC240, SIM108, E501) - Use anyio.Path for async file I/O in _FileSkillResource.read() - Use noqa: ASYNC240 for pure string os.path calls in async context - Restore pre-commit if/else pattern in InlineSkillScript.run() - Break long lines to fit 120-char limit in _skills.py and test_skills.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: collapse multi-line lambdas to single lines to fix pyright errors The pyright ignore comments only suppress errors on the same line, so multi-line lambdas left arguments on continuation lines uncovered. Collapse both lambdas to single lines matching the existing load_skill lambda pattern. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: replace untyped lambdas with typed inner functions to fix pyright errors Python lambdas cannot have type annotations, so pyright reports reportUnknownLambdaType and reportUnknownArgumentType errors that cannot be suppressed with inline ignore comments. Replace the lambdas for read_skill_resource and run_skill_script with typed inner async functions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address PR review feedback on docs and prompt template - Update with_prompt_template() docstring to document the {resource_instructions} placeholder requirement - Remove stray backslashes after {resource_instructions} and {runner_instructions} in DEFAULT_SKILLS_INSTRUCTION_PROMPT - Update subprocess_script_runner docstring to reflect FileSkillScript.full_path usage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: replace dict[str, Skill] with Sequence[Skill] in SkillsProvider Replace internal dict-based skills storage with Sequence[Skill] to eliminate silent duplicate overwrites and simplify the code. Add _find_skill helper for case-insensitive linear lookup. Also fix pyright errors in tests by adding isinstance assertions before accessing .function on SkillResource/SkillScript base types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: add read-time resource path validation in _FileSkillsSource Move security validation (path-traversal and symlink guards) for file-based skill resources into _FileSkillsSource, restoring the read-time checks that existed in main via _read_file_skill_resource. - Add _get_validated_resource_path static method on _FileSkillsSource that validates containment, existence, and symlink safety - _FileSkillsSource.get_skills() validates resource paths at discovery time via _get_validated_resource_path before passing to _FileSkillResource - Move _normalize_resource_path, _is_path_within_directory, and _has_symlink_in_path from module-level into _FileSkillsSource as static methods (only used there) - _FileSkillResource remains a simple path-to-content reader - Add tests for _get_validated_resource_path security checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: reject str/Path in SkillsProvider constructor to prevent str-as-Sequence ambiguity Since str is a Sequence, passing a path string to the source parameter would silently be treated as a sequence of characters instead of a file source. Add an explicit TypeError with a helpful message pointing callers to SkillsProvider.from_paths(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5584 review feedback - Remove .NET reference from _FileSkillResource docstring - Fix inconsistent resource name example (references/FAQ.md -> references/FAQ) - Simplify SkillsProvider usage in code_defined_skill sample (pass single skill directly) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * remove skillsproviderbuilder * Update python/packages/core/agent_framework/_skills.py Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com> * fix: remove dead code and fix sync function call in InlineSkillResource.read() - Change await self.function() to self.function() for sync functions without **kwargs; async results are handled by inspect.isawaitable() - Remove unreachable raise ValueError since __init__ already validates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * remove full_path unnecessary property * replace anyio with asyncio.to_thread for file I/O in _FileSkillResource Replace anyio.Path usage with asyncio.to_thread + pathlib.Path since anyio is not a direct dependency of core (transitive via mcp). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * simplify awaitable check to return directly Use 'return await result' instead of assigning then returning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * address PR review feedback for skills refactoring - Replace anyio with asyncio.to_thread + pathlib.Path for file I/O - Simplify awaitable check to return directly - Remove unnecessary function None guard in InlineSkillResource.read() - Add assert for type narrowing on self.function Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * address PR review feedback for skills refactoring - Replace anyio with asyncio.to_thread + pathlib.Path for file I/O - Simplify awaitable checks to return directly - Remove unnecessary function None guard in InlineSkillResource.read() - Use typing.cast instead of assert for type narrowing - Add caching behavior note to SkillsProvider docstring Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: move name/description from abstract properties to Skill.__init__ Replace abstract properties for name and description on the Skill ABC with a base __init__ that validates and stores them as regular attributes. This simplifies custom Skill subclasses (only content remains abstract) and centralizes validation in the base class, consistent with SkillResource and SkillScript base classes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
SergeyMenshykh ·
2026-05-06 09:45:06 +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 -
Python: Add Python parity for InvokeMcpTool in declarative workflow (#5630)
* Add Python parity for HttpRequestAction in declarative workflow * Ran pyupgrade and pright to fix CI issues * Fix conversation ID dot parsing for http executor * Removed unnecessary export command * Initial implementation of invoke mcp tool in python * Update sample to support require approval to be toggled by environment variable. * Fix cache and PR comments * Update python/samples/03-workflows/declarative/invoke_mcp_tool/main.py Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com> --------- Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
Peter Ibekwe ·
2026-05-05 20:16:03 +00:00 -
Python: fix(bedrock): don't send toolChoice when no tools are configured (#5172)
* fix(bedrock): don't send toolChoice when no tools are configured BedrockChatClient was sending toolConfig.toolChoice even when no tools were configured (tools=None). AWS Bedrock requires toolConfig.tools to be present whenever toolChoice is specified, causing a 400 validation error. Only set toolChoice when tool_config has a 'tools' key present. Fixes #5165 Signed-off-by: bahtya <bahtyar153@qq.com> * test: add tests for toolChoice without tools - test_prepare_options_tool_choice_auto_without_tools_omits_tool_config - test_prepare_options_tool_choice_required_without_tools_omits_tool_config Verifies that toolConfig is omitted when tool_choice is set but no tools are provided, preventing ParamValidationError from Bedrock. * fix: address maintainer feedback — remove stray test file, raise ValueError for required without tools 1. Remove test_addition.py — stray duplicate of tests already in python/packages/bedrock/tests/test_bedrock_client.py, missing all necessary imports and would fail with NameError. 2. Change tool_choice='required' handling to raise ValueError when no tools are configured instead of silently falling through. Using 'required' without tools is a logical contradiction — the model must invoke a tool but none exist — so surfacing this as a ValueError helps callers catch the misconfiguration early. 3. Update the corresponding test to expect ValueError instead of silently omitted toolConfig. --------- Signed-off-by: bahtya <bahtyar153@qq.com>
bahtyar ·
2026-05-05 19:15:37 +00:00 -
Python: information-flow control prompt injection defense (#5331)
* Python: Information-flow control based prompt injection defense (#5024) * fides integration * documentation * documentation * documentation * human-approval on policy violation * numenous hyena 'works' * IFC based implementation * minor edits in documentation * rebasing the branch and running the email example * Add security tests for IFC middleware * Fix Role.TOOL NameError in approval handling * tiered labelling scheme * 3 tier labelling scheme in middleware * Adapt security middleware to list[Content] tool results * Refactor SecureAgentConfig as context provider and address Copilot review comments * Update FIDES docs to reflect context provider pattern and update code for ContextProvider rename * Fix security examples: use OpenAIChatClient instead of non-existent AzureOpenAIChatClient * Address PR review: consolidate security modules, remove ContentLineage, update docs * remove unrelated files * remove comment from _tools.py and rename decision file * Fix CI failures: Bandit B110, broken md links, hosted approval passthrough * apply template to decision doc 0024 * minor fixes to decision doc 0024 --------- Co-authored-by: Aashish <t-akolluri@microsoft.com> * Python: follow up FIDES security flow (#5330) * Python: follow up FIDES security flow Refine the secure approval path, mark the security classes with the FIDES experimental feature label, and clean up the related docs/tests. Also fix workspace-level validation regressions uncovered while running the full Python check suite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: remove FIDES GitHub MCP sample Drop the GitHub MCP security sample from the FIDES follow-up branch while keeping the remaining security docs and samples intact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: fix paths and update FIDES implementation (#5352) * Python: updated import naming and comment from review (#5421) * updated import naming and comment from review * Add approval replay None call-id test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Address PR 5331 comments and track sesssion while calling Agent in email_security_example (#5446) * Address PR review: fix paths and update FIDES implementation * Address PR comments and add session tracking in email example in samples * Fix session creation and resolve merge conflict in docstring example * Resolve merge conflict in docstring example * Python: add test for empty-message pruning in approval result replacement (#5617) Adds test coverage for the second-pass logic in `_replace_approval_contents_with_results` that removes messages whose `contents` list becomes empty after first-pass content removal. Addresses review comment on PR #5331: https://github.com/microsoft/agent-framework/pull/5331#discussion_r3129039445 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: shrutitople <shruti.tople@gmail.com> Co-authored-by: Aashish <t-akolluri@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eduard van Valkenburg ·
2026-05-05 18:08:08 +00:00 -
.NET: Fix YAML block scalar parsing for file skills (#5610)
* Fix YAML block scalar parsing for file skills * Address block scalar parsing review feedback
Teja Kusireddy ·
2026-05-05 16:32:05 +00:00 -
.NET: Fix QuestionExecutor looping after GotoAction re-entry in declarative workflows (#5635)
* Fix QuestionExecutor looping after GotoAction re-entry in declarative workflows * Addressed failing integration test and promptcount
Peter Ibekwe ·
2026-05-05 15:53:31 +00:00 -
Jacob Alber ·
2026-05-05 15:45:49 +00:00 -
fix: JSON Serialization issue with MultiPartyConversation (#5653)
When MultiPartyConversation gets saved during checkpointing, the data for the chat history is not persisted, resulting in failures to deserialize after. The fix is to make the history visible to the source generated serialization code.
Jacob Alber ·
2026-05-05 15:36:05 +00:00 -
.NET: Improve Todo multithreading and inject todos into message list (#5655)
* Improve Todo multithreading and inject todos into message list * Address PR comments
westey ·
2026-05-05 15:21:51 +00:00 -
.NET: Add allow listing for WebBrowsingTool (#5605)
* Add allow listing for WebBrowsingTool * Address PR comments.
westey ·
2026-05-05 15:20:55 +00:00 -
.NET: feat: Implement message filtering to exclude non-portable content typ… (#5410)
* feat: Implement message filtering to exclude non-portable content types before forwarding Co-authored-by: Copilot <copilot@github.com> * Added unit tests to cover forwarded message filtering within AI Agent executors Co-authored-by: Copilot <copilot@github.com> * Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: Disable forwarding of incoming messages in AIAgentHostExecutor tests Co-authored-by: Copilot <copilot@github.com> --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Taylor Rockey ·
2026-05-05 14:43:45 +00:00 -
.NET: Add Microsoft.Agents.AI.Hyperlight package for CodeAct integration (.NET) (#5329)
* Add Microsoft.Agents.AI.Hyperlight package for CodeAct integration Introduces a new Microsoft.Agents.AI.Hyperlight package that enables CodeAct-style sandboxed code execution via Hyperlight (hyperlight-sandbox .NET SDK, PR #46) for .NET agents, following the docs/features/code_act/dotnet-implementation.md design and the Python agent_framework_hyperlight reference. Highlights: - HyperlightCodeActProvider (AIContextProvider): injects an execute_code tool and CodeAct guidance per invocation; single-instance-per-agent via a fixed StateKeys value; supports multiple provider-owned tools (exposed inside the sandbox via call_tool), file mounts, and an outbound domain allow-list; snapshot/restore per run. - HyperlightExecuteCodeFunction: standalone AIFunction for manual/static wiring when the sandbox configuration is fixed. - Approval model via CodeActApprovalMode (AlwaysRequire / NeverRequire) with propagation from ApprovalRequiredAIFunction-wrapped tools. - Unit tests (instruction builder, tool bridge, approval computation, provider CRUD, ProvideAIContextAsync snapshot isolation and approval wrapping). - Env-gated integration test (HYPERLIGHT_PYTHON_GUEST_PATH). - Three samples under samples/02-agents/AgentWithCodeAct (interpreter, tool-enabled, manual wiring). Build is not yet runnable: requires .NET SDK 10.0.200 and the not-yet-published HyperlightSandbox.Api 0.1.0-preview NuGet package. Package is marked IsPackable=false until the dependency is available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5329 review feedback for Hyperlight CodeAct provider - A. Build-breakers: drop unused usings, override test TargetFrameworks off net472, drop redundant Microsoft.Extensions.AI.Abstractions PackageRef. - B. API: keep CRUD but rebuild sandbox when config fingerprint changes; add HyperlightCodeActProviderOptions.CreateForWasm/CreateForJavaScript factory methods (Backend/ModulePath now read-only); rename WorkspaceRoot to HostInputDirectory; convert AllowedDomain & FileMount from record to sealed class; drop ToolBridge.Unwrap (ApprovalRequiredAIFunction is invocable as-is). - C. ToolBridge: collapse SerializeResult switch; add comment explaining AOT-driven choice to keep JsonNode.Parse over typed Deserialize. - D. InstructionBuilder: drop language-specific 'Python code' phrasing; strip host filesystem paths from execute_code description. - E. Style polish: ternary expression-body for ComputeApprovalRequired, .Where(x is not null), .ToList() over .ToArray() in IReadOnlyList returns. - F. Samples: add guest-module / KVM-WHP build instructions to Step01; note future Excel-upload sample in Step02. Also adds SandboxExecutorTests covering the new RunSnapshot.ComputeFingerprint used for sandbox-rebuild detection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align Hyperlight package id and JS warm-up with merged upstream SDK The .NET SDK in hyperlight-dev/hyperlight-sandbox PR #46 has merged. The published package id is Hyperlight.HyperlightSandbox.Api (the bare HyperlightSandbox.Api remains the assembly/namespace) and the reference CodeExecutionTool uses 'void 0;' as the JavaScript warm-up no-op. Update the package reference, project comment, README, and SandboxExecutor warm-up accordingly. No functional change beyond that — all other public APIs we depend on (SandboxBuilder.With*, Sandbox.Run/RegisterToolAsync/AllowDomain/Snapshot/ Restore, ExecutionResult, SandboxBackend) match the merged shape. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump Hyperlight package to 0.4.0 and fix build/test issues Hyperlight.HyperlightSandbox.Api 0.4.0 is now published on nuget.org. Bump the version reference and address the analyzer/runtime issues that surfaced once restore could complete: - Add HyperlightJsonContext source-generated JsonSerializerContext for the execute_code result + tool error envelopes; route arbitrary AIFunction results through AIJsonUtilities.DefaultOptions to keep IsAotCompatible=true. - Replace explicit ObjectDisposedException throws with ObjectDisposedException.ThrowIf (CA1513). - Use HyperlightSandbox.Api.SandboxBackend in cref docs to disambiguate. - Update tests to match AIContext.Tools being IEnumerable<AITool>, drop ConfigureAwait(false) in xUnit test methods (xUnit1030), use collection expressions for AllowedDomain methods. - Add 'using OpenAI.Chat;' to all three samples so AsAIAgent resolves. - Verified: dotnet build of all four hyperlight projects + samples succeeds on net8/9/10; dotnet test for the unit tests passes 32/32 on net10.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CI check failures: file encoding (UTF-8 BOM + LF) and broken markdown link - Convert all new .cs/.csproj files to UTF-8 with BOM and LF line endings to satisfy the dotnet/.editorconfig charset/end_of_line settings enforced by check-format. - Drop unused System.Collections.Generic using in HyperlightCodeActProviderTests. - Add missing using Microsoft.Extensions.AI in CodeActApprovalMode.cs and shorten ApprovalRequiredAIFunction cref (IDE0001). - Fix broken README link to docs/decisions/0024-codeact-integration.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: AIFunction inheritance, packaging, GetService approval check - HyperlightExecuteCodeFunction now inherits AIFunction directly. The AsAIFunction() indirection is gone; instances are accepted anywhere an AIFunction is. Approval requirement is surfaced via GetService<ApprovalRequiredAIFunction>() which lazily exposes a wrapping ApprovalRequiredAIFunction proxy when the effective ApprovalMode/tool stack requires it. - ComputeApprovalRequired now uses GetService<ApprovalRequiredAIFunction>() so approval-required tools nested anywhere in the AITool decorator stack are detected (not just the top-most class). - csproj: drop IsPackable=false (ready to release with the published Hyperlight.HyperlightSandbox.Api 0.4.0 dependency); add PackageReadmeFile and pack README.md at the package root, matching the pattern used by Aspire.Hosting.AgentFramework.DevUI / Microsoft.Agents.AI.DurableTask. - Update Step03 sample and README wording to reflect direct AIFunction usage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eduard van Valkenburg ·
2026-05-05 12:56:24 +00:00 -
Python: Core: add experimental session-mode harness context provider (#5611)
* Python: Core: add experimental session-mode harness context provider Introduces the _harness namespace and the first context provider: SessionModeContextProvider, with get_session_mode / set_session_mode helpers and a DEFAULT_MODE_SOURCE_ID constant. Behind @experimental(ExperimentalFeature.HARNESS). Also folds in a small _sessions.py cleanup (try/except ImportError -> contextlib.suppress) touched while developing the harness. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Core: align session-mode harness with .NET AgentModeProvider Mirror the default mode descriptions and instruction template used by the .NET AgentModeProvider so the cross-language harness UX is consistent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Core: address review feedback on session-mode harness - json.dumps tool outputs to stay valid for arbitrary mode names - normalize configured mode keys (lower+strip) so custom-cased configs work - raise TypeError instead of silently replacing non-dict session state - mark get_session_mode/set_session_mode as @experimental(HARNESS) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Core: rename SessionModeContextProvider to AgentModeProvider Match the .NET AgentModeProvider class name for cross-language consistency. Helpers renamed accordingly: get_session_mode -> get_agent_mode, set_session_mode -> set_agent_mode. The default source_id is now "agent_mode". Construction pattern stays Pythonic (kwargs, not an options object). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Core: address AgentModeProvider review feedback - default_mode now defaults to None and falls back to the first configured mode, decoupling the kwarg from the built-in 'plan'/'execute' set. - get_agent_mode catches ValueError when a previously persisted mode is no longer in available_modes and resets to the default mode (matching the non-string recovery branch). Added regression coverage for both behaviors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eduard van Valkenburg ·
2026-05-05 10:09:19 +00:00 -
Python: Fix hyperlight WasmSandbox cross-thread Drop and harden hosted-agent sample (#5603)
* update hyperlight to beta and move samples, add hosted agent sample * Python: Fix hyperlight WasmSandbox cross-thread Drop and harden sample Root cause: when a worker-side closure raised, the exception's __traceback__ retained frame locals that included the partially constructed PyO3 sandbox. Future.result() re-raised that exception on the caller thread, and when the caller's exception was eventually GC'd the frame locals were released off-thread, dec_ref'ing the unsendable sandbox from the wrong thread and tripping the PyO3 panic '_native_wasm::WasmSandbox is unsendable, but is being dropped on another thread'. Fix: * Add _SandboxWorker._run_on_worker which catches every exception on the worker, drops __traceback__ there, deletes the original exception, and re-raises a fresh instance on the caller thread. initialize and execute route through it; dispose keeps its bare-submit semantics. * Add an opt-in diagnostic module _drop_diagnostic (no-op unless HYPERLIGHT_TRACE_DROPS=1) that installs a sys.unraisablehook and dumps owner-thread + per-thread stacks on any future cross-thread unsendable Drop. Useful for triaging similar PyO3 regressions. * Tests: cross-thread invocation, traceback-leak isolation, _SandboxEntry attribute-shape check, and a stale-reference stress test driven through asyncio.to_thread. Sample (samples/04-hosting/foundry-hosted-agents/responses/06_hyperlight_codeact): * Dockerfile installs agent-framework-* from in-tree source with python/ as build context so unreleased fixes can be validated end-to-end. * call_server.py pins the Responses API version. * main.py enables include_detailed_errors=True so future tool failures surface the actual exception text instead of a bare 'Error: Function failed.' string. * README.md documents the in-tree-package build and the Hyperlight hypervisor requirement (/dev/kvm on Linux, MSHV on Windows). Hosted environments without hypervisor passthrough surface 'No Hypervisor was found for Sandbox'; this is a hosting constraint, not a hyperlight bug. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: remove _drop_diagnostic from hyperlight package The diagnostic module was useful while bisecting the cross-thread Drop bug, but it is no longer needed now that _SandboxWorker._run_on_worker prevents the panic at the source. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: address PR review feedback on hyperlight - Use lazy agent_framework.hyperlight import in sample main.py. - Env-driven endpoint (FOUNDRY_AGENT_ENDPOINT) in call_server.py; remove personal URLs. - Align agent.yaml model deployment with manifest (gpt-4.1-mini). - Tighten Dockerfile requirements guard; drop dangling deploy.ps1 reference. - Preserve exception args when sanitizing tracebacks in _run_on_worker. - Add public _SandboxWorker.is_alive(); update test to avoid private attr. - Add namespace coverage tests for agent_framework.hyperlight lazy loader. - Add prominent note: Foundry hosted-agent runtime does not yet support Hyperlight (no hypervisor exposed); container works locally with /dev/kvm. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: bump hyperlight-sandbox dependencies to 0.4.x Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: renumber hyperlight codeact sample to 08 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Coerce worker exception args to strings for cross-thread safety Stringify exc.args on the worker thread before propagating, so any PyO3 unsendable object captured in args (e.g. via a caller-supplied callback or underlying SDK) cannot be Dropped on the calling thread. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * moved sample --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eduard van Valkenburg ·
2026-05-05 10:06:16 +00:00