mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
feature/python-hosting
433 Commits
-
.NET: Add additional openai specific error observers and move them to openai project (#6004)
* Add additional openai specific error observers and move them to openai project * Address PR comments
westey ·
2026-05-21 13:54:47 +00:00 -
.NET: Add background agents support to HarnessAgent (#5977)
* Add background agents support to HarnessAgent * Add unit tests * Address PR comments
westey ·
2026-05-21 10:57:06 +00:00 -
.NET: Reduce re-rendering in harness console (#5953)
* Reduce re-rendering in harness console * Address PR comments * Fix broken merge
westey ·
2026-05-19 19:10:57 +00:00 -
.NET: Harness code act skill sample (#5930)
* Add sample that shows code execution and skills together * Use nuget for python module path * Update readme. * Fix formatting. * Reduce flashing in rendering. * Improve screen clearing for Powershell * Add a couple of small UX fixes
westey ·
2026-05-19 15:49:03 +00:00 -
westey ·
2026-05-19 15:32:14 +00:00 -
.NET: Bump Azure.AI.Projects to 2.1.0-beta.2 and add agent-endpoint AsAIAgent path (#5899)
* .NET: Bump Azure.AI.Projects to 2.1.0-beta.2 and add agent-endpoint AsAIAgent path Bumps Azure.AI.Projects to 2.1.0-beta.2 with the matching transitive pins (Azure.Core 1.55.0, System.ClientModel 1.11.0). Foundry agent endpoint plumbing: * FoundryAgent now routes the agent-endpoint constructor through the new GetProjectResponsesClientForAgentEndpoint helper. * Adds an internal FoundryAgent ctor that takes an existing AIProjectClient plus a parsed agent endpoint so the public extension does not need to construct a second project client. * Adds public AIProjectClient.AsAIAgent(Uri agentEndpoint, ...) extension. This is the path consumer samples are expected to use for hosted agents because version selection happens server-side. * Trims the dangling "If you want to construct a FoundryAgent against a project endpoint..." sentence from ParseAgentEndpoint. Unit tests: * Four new tests in AzureAIProjectChatClientExtensionsTests cover the AIProjectClient.AsAIAgent(Uri agentEndpoint, ...) overload. 263/263 pass. Consumer samples (Using-Samples): * SimpleAgent and SessionFilesClient now read AZURE_AI_PROJECT_ENDPOINT and AZURE_AI_AGENT_NAME (both required, throw on missing), derive the agent endpoint with new Uri($"{projectEndpoint}/agents/{agentName}/endpoint/protocols/openai"), then call aiProjectClient.AsAIAgent(agentEndpoint, ...). * SessionFilesClient README updated. Contributor samples (responses/*): * New HostedContributorRouteExtensions.MapDevTemporaryLocalAgentEndpoint() wildcard route extension so localhost contributor servers accept the per-agent OpenAI endpoint shape the production Hosted runtime exposes. * All 11 contributor Program.cs files call MapDevTemporaryLocalAgentEndpoint() with a contributor-only warning comment. * Hosted-Files and Hosted-AzureSearchRag were importing Hosted_Shared_Contributor_Setup but never calling AddDevTemporaryLocalContributorSetup(). Both now call it so HostedSessionIsolationKeyProvider resolves correctly in dev. * Hosted-AzureSearchRag, Hosted-Files, Hosted-MemoryAgent csprojs drop stale VersionOverride="2.1.0-beta.1" pins. * Hosted-AzureSearchRag and Hosted-Files csprojs add ProjectReference to Hosted_Shared_Contributor_Setup. * Hosted-Observability/.dockerignore removed the out/ exclusion that was blocking COPY out/ . in Dockerfile.contributor. Verified: * Full solution-scoped build of changed projects: green. * Scoped CI-parity dotnet format via WSL2 + Docker (mcr.microsoft.com/dotnet/sdk:10.0) over every changed csproj: clean. * Foundry unit tests: 263/263. * Contributor docker smoke for 8 hosted samples (publish + docker build + docker run + curl POST to the wildcard route): HTTP 200 / 500 with route matched. * End-to-end smoke against the real Azure Foundry project with a fresh bearer token: Hosted-Files contributor container served HTTP 200, the agent invoked ListBundledFiles, and returned the expected file name. * Address PR review: forward pipeline settings; add UTs - CreateProjectClientOptions also carries RetryPolicy, NetworkTimeout, ClientLoggingOptions, MessageLoggingPolicy (was Transport+UserAgentApplicationId only). - Make CreateProjectClientOptions internal so tests can verify the copy directly. - Add AsAIAgent(Uri) UTs covering tools forwarding to inner ChatOptions and null tools handling. - Add CreateProjectClientOptions UTs covering null caller and full pipeline-settings copy.Roger Barreto ·
2026-05-18 20:20:56 +00:00 -
.NET: Add ability to export/import sessions in harness console (#5920)
* Add ability to export/import sessions in harness console * Address PR comments
westey ·
2026-05-18 18:44:50 +00:00 -
.NET: Add otel file logging and switch samples to projects client with store=true (#5924)
* Add otel file logging and switch samples to projects client with store=true * Fix formatting and remove rogue file
westey ·
2026-05-18 17:39:29 +00:00 -
.NET: Require TODO finish reason and rename SubAgents to BackgroundAgents (#5902)
* Require TODO finish reason and rename SubAgents to BackgroundAgents * Address PR comments
westey ·
2026-05-18 15:37:25 +00:00 -
.NET: Adding default providers and tools to HarnessAgent (#5896)
* Adding default providers and tools to HarnessAgent * Address PR comments * Add further comments to clarify certain setings. * Apply suggestion from @SergeyMenshykh Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> --------- Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
westey ·
2026-05-18 10:07:16 +00:00 -
.NET: Add observer for OpenAIWebSearch (#5894)
* Add observer for OpenAIWebSearch * Update reference in comment * Use types where possible.
westey ·
2026-05-15 17:30:01 +00:00 -
.NET: Add Hosted-MemoryAgent sample with isolation key plumbing (#5692) (#5702)
* .NET: Add Hosted-MemoryAgent sample with isolation key plumbing (#5692) Adds HostedSessionContext + HostedSessionIsolationKeyProvider in Microsoft.Agents.AI.Foundry.Hosting so AIContextProviders (notably FoundryMemoryProvider) can scope per user via the platform's x-agent-user-isolation-key / x-agent-chat-isolation-key headers. - New types: HostedSessionContext (sealed), HostedSessionContextExtensions (public Get, internal Set), abstract HostedSessionIsolationKeyProvider (async), internal PlatformHostedSessionIsolationKeyProvider mapping ResponseContext.Isolation. - AgentFrameworkResponseHandler now resolves the provider, tags fresh sessions, and validates resumed sessions against the live request (strict 403 'Hosted session identity context mismatch' on any mismatch; 500 on null keys). - New shared sample project Hosted_Shared_Contributor_Setup hosts DevTemporaryTokenCredential and DevTemporaryLocalSessionIsolationKeyProvider plus AddDevTemporaryLocalContributorSetup. All 9 existing responses samples migrated to consume it so local runs keep working under the strict isolation contract. - New Hosted-MemoryAgent sample: travel assistant wired through FoundryMemoryProvider with stateInitializer reading session.GetHostedContext().UserId. Includes Dockerfile, smoke.ps1, agent.yaml/manifest. - New IT scenario 'memory' in Foundry.Hosting.IntegrationTests + MemoryHostedAgentFixture + MemoryHostedAgentTests. Verified end to end against the tao Foundry project. - ADR 0026 captures the design tree. * Address PR review feedback - Dockerfile: add header noting it targets NuGet builds; contributors must use Dockerfile.contributor for ProjectReference source builds. - PlatformHostedSessionIsolationKeyProvider: doc said 'returns context with empty values'; corrected to 'returns null' which the handler treats as 500. - FakeHostedSessionIsolationKeyProvider: doc clarifies that null configurations are allowed for testing the handler error path. - HostedSessionContextExtensions.SetHostedContext: enforce write-once with InvalidOperationException; doc + xml exception updated. - AgentFrameworkResponseHandler: cache PlatformHostedSessionIsolationKeyProvider as static readonly to avoid per-request allocation. - MemoryHostedAgentTests: tighten waits from 20s to 5s (FoundryMemoryProvider defaults UpdateDelay=0; ingestion ~3s). - Sample Program.cs imports reordered to satisfy IDE0005. * Add HostedFoundryMemoryProviderScopes built-in helpers (#5692) Addresses review feedback from @lokitoth on Hosted-MemoryAgent/Program.cs:54. - New HostedFoundryMemoryProviderScopes static class with PerUser, PerChat, PerUserAndChat factories returning Func<AgentSession?, FoundryMemoryProvider.State>. - All helpers throw InvalidOperationException when GetHostedContext() is null, with a message pointing at writing a custom stateInitializer for non-hosted scenarios. - New HostedFoundryMemoryScope enum and AddHostedFoundryMemoryProvider DI extension (two overloads: explicit AIProjectClient and DI-resolved). Singleton lifetime. Default scope = PerUser. - Hosted-MemoryAgent sample and the memory IT scenario container both swap their inline lambdas for HostedFoundryMemoryProviderScopes.PerUser(). - 14 new unit tests (241/241 hosting unit tests pass). * Replace HostedFoundryMemoryScope enum with Func<...> parameter (#5692) Address PR review feedback from @westey-m: enums are a breaking-change hazard when extended, and the enum was redundant with the existing HostedFoundryMemoryProviderScopes static class. - Delete HostedFoundryMemoryScope.cs. - AddHostedFoundryMemoryProvider DI extensions now take Func<AgentSession?, FoundryMemoryProvider.State>? stateInitializer = null. When null, default to HostedFoundryMemoryProviderScopes.PerUser(). - Callers pick a built-in helper (PerUser/PerChat/PerUserAndChat) or pass a custom delegate. New built-ins are a single static method addition with zero impact on existing callers. - Tests updated; 244/244 hosting unit tests pass. * Fix isolation context resume for externally-created conversations (#5692) Branch on the session's existing hosted-context (not on conversation_id presence) so a conversation provisioned externally (e.g. via conversations.CreateProjectConversationAsync) is treated as fresh on first hosted-agent request and stamped, rather than rejected with 403 hosted_session_identity_mismatch. Strict equality is preserved on real resume of an already-stamped session. Also tighten dotnet/global.json to version 10.0.204 + rollForward latestPatch so local builds match the CI Docker image SDK and avoid 10.0.300 dotnet format stripping required usings. * Revert global.json SDK pin to upstream (#5692) The 10.0.204 + latestPatch pin from the previous commit broke the dotnet-format CI job (hostfxr_resolve_sdk2 could not find a compatible SDK in the mcr.microsoft.com/dotnet/sdk:10.0 image). Restore upstream 10.0.200 + minor; local Release builds with SDK 10.0.300 should set GITHUB_ACTIONS=true to bypass the auto-format-on-build target.
Roger Barreto ·
2026-05-15 05:42:12 +00:00 -
.NET: Add sample for invoking Foundry Toolbox tools from declarative workflows (#5829)
* Add sample for invoking Foundry Toolbox tools from declarative workflows * Addressed initial PR comments.
Peter Ibekwe ·
2026-05-14 15:30:48 +00:00 -
.NET: Harness console refactoring (#5811)
* Restructure harness console so that reactive app is the entry point * Further refactoring to split tool formatters, improve UX, make console configurable and fix bugs * Address PR comments. * UX tweak * Fix streaming text bug * Address PR comments.
westey ·
2026-05-14 15:22:11 +00:00 -
.NET: feat(evals): add ground_truth/expected_output support for workflow evaluation (#5755)
* .NET: feat(evals): add ground_truth/expected_output support for workflow eval Brings .NET to parity with Python PR #5234 for issue #5135: - Add expectedOutput parameter to Run.EvaluateAsync (workflow) and stamp on the overall EvalItem.ExpectedOutput. - Map EvalItem.ExpectedOutput -> ground_truth in the Foundry JSONL payload, item_schema, and data_mapping for similarity. - Add GroundTruthEvaluators set (currently builtin.similarity) and a FindMissingGroundTruthEvaluators helper. - Fail fast with InvalidOperationException when a ground-truth evaluator is selected but no item provides an ExpectedOutput, instead of surfacing a remote provider error. - Add tests in FoundryEvalConverterTests and WorkflowEvaluationTests. - Add Evaluation_WorkflowExpectedOutputs sample (workflow + Foundry similarity). Fixes microsoft/agent-framework#5135 (.NET side). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review: relax BuildOverallItem events to IReadOnlyList<WorkflowEvent> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Sample: disable per-agent breakdown when using reference-based evaluator Per-agent EvalItems are intentionally left without ExpectedOutput, so the new fail-fast validation in FoundryEvals would throw when Similarity is invoked for per-agent items. Pass includePerAgent: false in the workflow + similarity sample, and document this gotcha in the EvaluateAsync XML doc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix BuildOverallItem: fall back to last ExecutorCompletedEvent AgentResponseEvent is only emitted when AIAgentHostOptions.EmitAgentResponseEvents is enabled, which is not the default for WorkflowBuilder(agent).AddEdge(...). When it is absent, fall back to the last non-internal ExecutorCompletedEvent whose Data is an AgentResponse / ChatMessage / string so the overall EvalItem (and any expectedOutput) is produced. Without this, samples wired up the standard way returned 0 evaluation items. Update test to cover the fallback path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Sample: enable EmitAgentResponseEvents; eval throws clear error when no overall response found Root cause of '0 results': AIAgentHostExecutor only emits AgentResponseEvent when AIAgentHostOptions.EmitAgentResponseEvents is true (default false). For ordinary AIAgent executors the runtime's ExecutorCompletedEvent.Data is null, so the prior fallback couldn't find a final response either. Sample now builds executors with EmitAgentResponseEvents=true via BindAsExecutor(hostOptions). EvaluateAsync now throws InvalidOperationException with a remediation hint when the user supplies expectedOutput but no overall final response can be located, instead of silently returning 0/0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Guard against null sample/error/usage/datasource_item in ParseDetailedItem Foundry eval responses can have these properties present with JSON null or non-object values, which caused JsonElement.TryGetProperty to throw 'requires Object, has Null'. Check ValueKind == Object before drilling in. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: reorder expectedOutput, tighten ground-truth check, add fail-fast test * WorkflowEvaluationExtensions.EvaluateAsync: move 'expectedOutput' to after 'splitter' so the original positional contract of (splitter, cancellationToken) is preserved for existing callers. * FoundryEvals: require ALL items to carry ExpectedOutput when a ground-truth evaluator is selected (e.g. similarity), not just any. Reference-based evaluators score per-item, so a single missing GT would still surface as a provider-side validation error. Updated fail-fast message accordingly. * WorkflowEvaluationTests: add EvaluateAsync_WithExpectedOutputButNoFinalResponse_ThrowsAsync to verify the InvalidOperationException is thrown (and that the message mentions EmitAgentResponseEvents). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fail-fast on missing overall item regardless of expectedOutput; harden BuildOverallItem default * EvaluateAsync now throws InvalidOperationException whenever 'includeOverall' is requested but BuildOverallItem cannot produce an item, instead of only when 'expectedOutput' is supplied. Same misconfiguration (agents not bound with EmitAgentResponseEvents) used to silently return empty results — now it surfaces a clear, actionable error in both cases. * BuildOverallItem switch default now throws instead of returning null. The preceding for-loop already constrains Data to AgentResponse/ChatMessage/ string, so reaching default would indicate a contract drift; throw to make the bug visible. * Test renamed and broadened to verify the throw fires without expectedOutput. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <25218250+alliscode@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ben Thomas ·
2026-05-13 19:03:27 +00:00 -
Fixing FoundryToolboxMcp sample to use created toolbox. (#5786)
Co-authored-by: alliscode <bentho@microsoft.com>
Ben Thomas ·
2026-05-13 16:53:16 +00:00 -
.NET: Add harness agent package (#5782)
* Add harness agent package * Fix formatting. * Fix formatting. * Update release filter * Address PR comments.
westey ·
2026-05-13 10:58:05 +00:00 -
.NET: Fix OpenAIResponsesAgentClient to include agentName in endpoint path (#5748)
* Fix OpenAIResponsesAgentClient endpoint to include agentName in path (#5324) The sample OpenAIResponsesAgentClient used '/v1/' as the endpoint, which routes to the multi-agent endpoint requiring agent.name in the request body. However, AsIChatClient(agentName) maps agentName to the model field, not agent.name, causing HTTP 400 errors on OpenAI-compatible endpoints. Changed the endpoint to '/{agentName}/v1/' to match the pattern used by OpenAIChatCompletionsAgentClient, routing to the single-agent endpoint where no agent.name body field is needed. Added regression test verifying that the model field alone is insufficient for agent resolution on the multi-agent endpoint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback for #5324 - URL-escape agentName in OpenAIResponsesAgentClient endpoint path to handle reserved characters safely - Add per-agent MapOpenAIResponses() calls in AgentHost so the sample host serves the /{agentName}/v1/responses routes the client now targets - Replace brittle Assert.Contains("agent.name") assertions with stable machine-readable error code assertion ("missing_required_parameter") Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address additional review feedback for #5324 - Apply Uri.EscapeDataString to OpenAIChatCompletionsAgentClient endpoint for consistency with OpenAIResponsesAgentClient - Map OpenAI Responses and ChatCompletions endpoints for all builder-based agents (chemist, mathematician, literator, science workflows) so every discoverable agent is reachable via the single-agent endpoint path 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>
Giles Odigwe ·
2026-05-12 17:16:47 +00:00 -
.NET: Feat/dotnet shell tool (#5604)
* feat(dotnet): add Microsoft.Agents.AI.Tools.Shell with LocalShellTool Ports Python LocalShellTool to .NET as a new package (net8/9/10). - Microsoft.Agents.AI.Tools.Shell: LocalShellTool, ShellPolicy (deny-list guardrail), ShellResolver (cross-OS pwsh/powershell/cmd vs bash/sh), ShellResult with head+tail truncation, timeout + process-tree kill, AsAIFunction with required-by-default human approval gate. - Persistent mode via ShellSession (sentinel protocol over pwsh/bash). - acknowledgeUnsafe parity gate matches the Python implementation. - Auto-injected platform context in the AIFunction description so the LLM sees the active OS and shell at tool-discovery time. - 17 xunit.v3 tests cover policy allow/deny, echo roundtrip, exit codes, timeout/kill, AsAIFunction shape + approval wrapping, persistent cwd/env carry-over, head+tail truncation, sentinel race. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(shell): close Python parity gaps for LocalShellTool Closes the .NET vs Python parity gaps identified in the competitive eval: - Default mode flipped to ShellMode.Persistent (matches Python). Every call now reuses a long-lived shell so cd/exports/functions persist; pass mode: ShellMode.Stateless to opt out. - New IShellExecutor interface — pluggable backend so future DockerShellTool / Hyperlight / SSH executors don't fork the framework. LocalShellTool implements it. - Workdir confinement: confineWorkingDirectory (default true) re-anchors every persistent-mode command back to workingDirectory so a wandering cd in one call doesn't leak to the next. Mirrors Python _maybe_reanchor. - Graceful interrupt on timeout: ShellSession sends SIGINT (POSIX) or Ctrl+C-on-stdin (Windows) before falling back to a hard close+respawn. Successfully-interrupted commands return exit 124 + TimedOut=true while preserving session state for the next call. - cleanEnvironment opt-in: when true, only PATH/HOME/USER/USERNAME/ USERPROFILE/SystemRoot/TEMP/TMP plus user-supplied vars are visible. - shellArgv: IReadOnlyList<string> override accepted alongside the string shell binary param (mutually exclusive). Lets advanced callers inject flags like --rcfile or --login. - Typed exceptions ShellTimeoutException and ShellExecutionException replace InvalidOperationException for launch / liveness failures. Tests: 17 -> 23. New cases cover persistent-default ctor, mutually- exclusive shell/shellArgv, confined re-anchor, confine-disabled leak, clean-env strip, and IShellExecutor implementation. All green on net10.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(shell): add DockerShellTool sandboxed shell tier Ports the Python DockerShellTool to .NET. Mirrors the public surface of LocalShellTool but executes commands inside an isolated container, where the container is the security boundary. Stateless and persistent modes both supported; persistent mode reuses ShellSession by launching 'docker exec -i <ctr> bash --noprofile --norc' as the long-lived REPL, so the sentinel protocol works unchanged. Defaults chosen for safety: - --network none, --user 65534:65534 (nobody), --read-only root - --cap-drop=ALL, --security-opt=no-new-privileges - 512m memory cap, pids-limit 256, --tmpfs /tmp - Optional host workdir mount, ro by default Public surface: - DockerShellTool ctor with image/container_name/mode/host_workdir/ workdir/network/memory/pids_limit/user/read_only_root/extra_run_args/ environment/policy/timeout/max_output_bytes/on_command/docker_binary - StartAsync, CloseAsync, RunAsync, AsAIFunction, IShellExecutor impl - IsAvailableAsync(binary) probe - Static argv builders (BuildRunArgv, BuildExecArgv) — pure, side- effect free, so unit tests don't need a Docker daemon AsAIFunction defaults to requireApproval: false (the container IS the boundary). LocalShellTool keeps the opposite default. Tests: 23 -> 35. 12 new tests cover argv builders, env/extra-args/host- workdir flags, exec interactive vs stateless, container name uniqueness, IShellExecutor implementation, AsAIFunction approval defaults, and IsAvailableAsync false-path. None require Docker. Multi-TFM build (net8/9/10) green. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(shell): add DockerShellTool integration tests Adds 9 end-to-end tests that exercise DockerShellTool against a live Docker (or Podman) daemon. Tests are tagged [Trait("Category", "Integration")] and auto-skip via Assert.Skip when no daemon is available, so they are CI-safe. Coverage: - IsAvailableAsync probe - Persistent mode basic command + state preservation across calls - --network none blocks outbound DNS - --read-only root prevents writes outside /tmp; /tmp tmpfs is writable - --user 65534:65534 (nobody) is in effect - Stateless mode: env vars do not leak across calls - HostWorkdir bind-mount + read-only enforcement - Environment variables passed via -e Tests use debian:stable-slim (alpine ships only busybox sh, which ShellSession persistent bash REPL cannot drive). Run locally: dotnet test --filter "Category=Integration" or filter by class on the test exe directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * style(shell): apply dotnet format pass - Whitespace and code-style fixes from `dotnet format` across both projects - Convert all new files to UTF-8 with BOM and LF line endings (repo convention) - Rename ShellSession statics to s_ prefix (IDE1006) - Add Async suffix to async test methods (IDE1006) No behavioral changes. All 44 tests still pass on net10.0; multi-TFM build (net8/net9/net10) green. `dotnet format --verify-no-changes` now reports clean for both projects. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(shell): add DockerShellTool walkthrough with sequence diagrams Explains the mental model (we shell out to the docker CLI; we never speak the engine API), the hardened docker run argv, persistent vs stateless lifecycles with mermaid sequence diagrams, the full agent-to-bash call ladder, and the failure modes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * PR 5604 review fixes (group a): libc DllImport, namespace cleanup, policy-msg dedup Three quick-win review comments on PR #5604: 1. ShellSession: the libc `killpg` P/Invoke was annotated with `DllImportSearchPath.System32`, a Windows-only loader hint that does nothing for libc.so on POSIX. Switched to `SafeDirectories` (CA5392 /CA5393 clean) and added a comment noting the call site is gated to non-Windows. 2. DockerShellToolTests: replaced the fully-qualified `Extensions.AI.ApprovalRequiredAIFunction` with a `using Microsoft.Extensions.AI;` import and the bare type name, matching `LocalShellToolTests`. 3. LocalShellTool / DockerShellTool: `AsAIFunction`'s catch block was producing a doubled "Command blocked by policy: Command rejected by policy: ..." prefix because the `ShellPolicyException` message already starts with "Command rejected by policy". Now we return `ex.Message` directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * PR 5604 review fix (group b): add ShellKind.Sh for /bin/sh fallback Review comment (#3): when /bin/bash is missing the resolver fell back to /bin/sh but tagged it as ShellKind.Bash, so the launcher passed bash-only flags --noprofile --norc to dash/ash/busybox, which interpret them as positional script names. Fix: * Added ShellKind.Sh for minimal POSIX shells (sh, dash, ash, busybox). * /bin/sh fallback is now tagged Sh. * ClassifyKind maps "SH" / "DASH" / "ASH" / "BUSYBOX" binary names to Sh. * StatelessArgvForCommand emits just `-c <command>` for Sh (no bash-only flags); PersistentArgv emits no flags at all. * LocalShellTool's system-prompt builder describes Sh distinctly and warns the model away from bash-only constructs. Tests: ShellResolverTests covers Sh/Bash classification through the observable argv output (14 new theory cases). Total: 58/58. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * PR 5604 review fix (group d): honor timeout=null, add DefaultTimeout Review comment (#5): both LocalShellTool and DockerShellTool documented `timeout: null` as "disables timeouts" but the constructor coerced null to 30 seconds, making the documented disable mechanism unreachable through the public API. Fix: * Drop the `?? TimeSpan.FromSeconds(30)` coercion in both ctors. `_timeout` now faithfully reflects what the caller passed (null = disabled). The downstream CTS-construction sites already short-circuit on null, so no other code changes are required. * Add `public static readonly TimeSpan DefaultTimeout` (30 s) on both tools so callers who want a bounded timeout can opt in explicitly. Tests: * New `RunAsync_NullTimeout_DoesNotTimeOutAsync` confirms a quick command runs to completion when the caller passes `timeout: null`. * New `DefaultTimeout_IsThirtySeconds` documents the constant. Behavioral note: this is a deliberate change-of-default. Callers that previously omitted `timeout` and relied on the implicit 30 s now get "no timeout". They should pass `LocalShellTool.DefaultTimeout` or `DockerShellTool.DefaultTimeout` explicitly to preserve the prior behavior. Tests: 60/60 (44 baseline + 14 resolver + 2 new timeout tests). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * PR 5604 review fix (group e): smart requireApproval default for DockerShellTool Review comment (#6, design): requireApproval: false baked in a safety decision the type cannot prove on its own. Callers can weaken any isolation knob (network, user, readOnlyRoot, mount, extraRunArgs) and still get an unapproved tool by default. Fix: * New public IsHardenedConfiguration property returns true iff the effective config matches the safe defaults: network=="none", non-root user, read-only root, host mount (if any) read-only, no extra run args. * AsAIFunction's requireApproval parameter is now bool? defaulting to null. When null, approval is enabled iff IsHardenedConfiguration is false. Pass false explicitly to opt out, or true to force. * docker-shell-tool.md updated with the new approval matrix. Tests: 4 new theory cases + 2 facts cover hardened-default, relaxed-network, root-user, writable-root, extraRunArgs, and explicit-opt-out branches. Total: 66/66. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * PR 5604 review fix (group c): wrap POSIX shell in setsid for correct killpg Review comment (#1): killpg(proc.Id, SIGINT) only behaves like a process-group signal when proc.Id IS a process group id. Since the .NET launcher does not call setsid() / setpgid() itself, the spawned shell inherits the agent host's process group — so killpg targeted the wrong group and the cancel signal could leak to the agent. Fix: * On non-Windows, EnsureStartedAsync probes for setsid (well-known paths first, then PATH). When found it wraps the shell launch as `setsid <shell> <args...>` so the spawned shell becomes a session leader (PID == PGID). * A new _isSessionLeader flag tracks whether the wrap succeeded. * InterruptCurrentCommandAsync only calls killpg when _isSessionLeader is true. Without setsid, killpg on an unsuited PID could signal the agent itself, so we skip the fast path and let the caller's hard close-and-respawn handle the timeout. * Windows behaviour is unchanged (Ctrl+C-via-stdin to pwsh). No public-API changes; existing tests cover the interrupt path and all 66/66 still pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .Net: DockerShellTool design + caller-cancel container leak fixes (PR #5604) Addresses three Copilot review findings on PR #5604. Design (group f): * StartAsync: change inner ResolvedShell from ShellKind.Bash to ShellKind.Sh. BuildExecArgv() already includes `--noprofile --norc` in ExtraArgv; Bash's PersistentArgv() was appending those flags a second time, yielding `bash --noprofile --norc --noprofile --norc`. Sh's PersistentArgv() returns Array.Empty so ExtraArgv is forwarded unchanged. * BuildExecArgv: remove the dead `interactive: false` branch and the `interactive` parameter. The `false` path produced an unusable argv ending in `-c` with no command and was never invoked internally (stateless mode uses BuildRunArgvStateless). Updated tests and docs/docker-shell-tool.md sequence diagram. Reliability (group g): * RunStatelessAsync: add a second `catch (OperationCanceledException)` guarded on `cancellationToken.IsCancellationRequested` that issues `docker kill --signal KILL <perCallName>` before rethrowing. Previously, caller-driven cancellation bypassed the timeout-only catch and propagated without killing the container; because `--rm` only fires when PID 1 exits, the container ran indefinitely. Extracted the kill-by-name logic into a `BestEffortKillContainerAsync` helper shared by both the timeout and caller-cancel paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .Net: Fill PR #5604 test coverage gaps for Shell tools Addresses the test-coverage findings in the latest Copilot review. * ShellResultTests (new): direct branch coverage for ShellResult.FormatForModel() — empty stdout, non-empty stderr, truncated, timed-out, success, and the truncated-with-empty-stdout edge where the marker is intentionally suppressed. This method's string is what the language model sees, so it benefits from explicit unit-level coverage independent of integration tests. * ShellSessionTests (new): direct unit tests for the internal TruncateHeadTail head-tail truncation utility — under-cap (no truncation), exactly at cap (no truncation), over-cap (truncated with marker, both head and tail preserved), and empty-string. Reachable via InternalsVisibleTo. * LocalShellToolTests: Theory test exercising 8 representative patterns from ShellPolicy.DefaultDenyList (rm -rf /, mkfs.ext4, curl|sh, wget|sh, Remove-Item /, shutdown, reboot, Format-Volume) to catch deny-list regex regressions; previously only 1/16 was tested. * LocalShellToolTests: explicit stderr-capture assertion (echo to stderr → result.Stderr contains the message). Stderr capture was not directly asserted anywhere in the suite. * DockerShellToolTests: RunAsync_RejectedCommand throws ShellCommandRejectedException. The Docker-side policy check is a pure-logic path that runs before any docker invocation, so this test covers the rejection branch without needing a Docker daemon. Total: 66 -> 85 tests, all passing on net10.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(dotnet/shell): add ShellEnvironmentProvider for OS-aware shell instructions Pairs LocalShellTool/DockerShellTool with an AIContextProvider that probes the live shell once per session (OS, family, version, CWD, configurable CLI versions) and injects authoritative instructions so the agent uses platform-native idioms (PowerShell vs POSIX). Fixes the class of bugs where the model emits 'VAR=value' / '/tmp' / '$VAR' on a Windows PowerShell session. - ShellEnvironmentProvider/Snapshot/Options public surface in the existing Microsoft.Agents.AI.Tools.Shell package (one new project reference to Microsoft.Agents.AI.Abstractions). - Probes go through the same IShellExecutor that runs agent commands, so they respect the configured policy and (for DockerShellTool) the container boundary. - 8 unit tests covering snapshot capture, default formatter idioms, missing-tool handling, custom formatter override, and refresh. - Agent_Step21_ShellWithEnvironment sample replays the DEMO_TOKEN cross-call scenario using a persistent local shell. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(dotnet/shell): address PR review feedback round 3 - ShellEnvironmentProvider.cs split into one-type-per-file (ShellFamily, ShellEnvironmentSnapshot, ShellEnvironmentProviderOptions, plus the provider class) to match FoundryMemoryProvider/AgentSkillsProvider layout. - csproj: drop IsPackable=false (package will publish on merge), add IsReleased=true and disable package validation baseline (first release), use TargetFrameworksCore, add InjectSharedDiagnosticIds and InjectExperimentalAttributeOnLegacy to align with shipping packages. - Sample: refactor to demonstrate stateless mode first (independent read-only commands), then persistent mode (state carried across calls, e.g. DEMO_TOKEN). Strip narrative/historical comments. - Move docker-shell-tool.md out of the package — that doc lives in the docs repo (semantic-kernel-pr/agent-framework, branch feat/dotnet-shell-tool). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5604 round 4 review feedback - Sample (Agent_Step21_ShellWithEnvironment): add prominent WARNING block noting LocalShellTool runs real commands on the host. Restructure sample to demonstrate stateless mode first (cd does not carry across calls) then persistent mode (cd and env vars persist), motivating when to pick each. - DockerShellTool class XML doc: reframe as a best-effort baseline rather than a security guarantee; list mitigations users should still apply. - DockerShellTool ShellKind.Sh comment: rephrase as forward-looking design rationale (avoid duplicate --noprofile/--norc if Bash is reintroduced) instead of bug-history narrative. - DockerShellTool.IsHardenedConfiguration / AsAIFunction XML docs: clarify these are configuration-shape checks and convenience defaults, not security guarantees. - Drop IDisposable from LocalShellTool and DockerShellTool. The previous sync Dispose() blocked on DisposeAsync().GetAwaiter().GetResult() with a VSTHRD002 suppression, which is fragile under sync contexts. Both tools now expose IAsyncDisposable only; tests updated to await using. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Async suffix to async test methods to satisfy IDE1006 Fixes check-format CI failure on PR #5604. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CPU busy-spin in WaitForSentinelAsync When new bytes arrived in the stdout read loop, the producer called TrySetResult on _stdoutSignal but did not replace it with a fresh TCS. A consumer looping inside WaitForSentinelAsync would then re-read the same already-completed TCS, causing WaitAsync(100ms) to return synchronously every iteration — a tight busy-spin that pinned a core until the sentinel arrived or the timeout fired. Swap the signal before completing the old one so the next consumer iteration observes a fresh (uncompleted) TCS, matching the pattern already used in ReadExitCodeAsync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove unused onCommand audit hook from shell tools The Action<string> onCommand callback was a redundant audit-logging seam: no production callers, no Python parity, and the framework already provides function-invocation middleware for cross-cutting concerns at the AIFunction layer. Removing the parameter from LocalShellTool and DockerShellTool keeps the public surface lean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align Shell csproj with Foundry.Hosting preview-package conventions - Add RootNamespace - Move Title/Description into the primary PropertyGroup with TargetFrameworks/VersionSuffix to match the Foundry.Hosting layout - Drop IsReleased (preview packages do not set it) - Drop UTF-8 BOM Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Document why ShellEnvironmentProvider uses Instructions, not Messages Expand the class XML doc to record the design rationale: the shell environment is stable runtime metadata, not per-turn retrieval, so it belongs in AIContext.Instructions (matching AgentSkillsProvider). Messages is reserved for retrieval payloads (TextSearchProvider, ChatHistoryMemoryProvider). System-role placement also has higher steering weight and benefits from prompt caching in major providers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify which probe failures ShellEnvironmentProvider swallows Name the four exception types explicitly (timeout, policy rejection, spawn failure, cancellation) and note that all other exceptions propagate normally. Avoids the misleading impression that the provider is a blanket try/catch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Strip cross-language and bug-history narrative from shell tool comments Remove "hard-won" framing and explicit "Mirrors the Python ..." cross references from class XML docs and inline comments in ShellSession, DockerShellTool, and ShellResolver. Comments now describe current behavior without commentary on prior implementations or development history. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5604 round 5 review feedback - ShellResolver: classify only `bash` as ShellKind.Bash; sh/zsh/dash/ash/ksh/busybox now route through ShellKind.Sh so bash-only --noprofile/--norc flags are not emitted to shells that reject them. Update enum doc and tests. - ShellEnvironmentProvider.ProbeToolVersionAsync: validate the tool name against ^[A-Za-z0-9._-]+$ before interpolating into a shell command (prevents injection if ProbeTools is sourced from untrusted config). Fall back to stderr when stdout is empty so CLIs like java/older gcc still report a version. Drop misleading 'quoted' comment. - ShellSession.TruncateHeadTail: truncate by UTF-8 byte count on rune boundaries, honouring the documented maxOutputBytes contract for non-ASCII output. - ShellEnvironmentProviderTests: drop reflection on private _options; assert against the options instance the test already owns. Rename misnamed RefreshAsync test to reflect re-probing semantics. Add coverage for invalid tool names and stderr-only version output. - ShellSessionTests: add multi-byte UTF-8 truncation tests (byte-budget honoured, no rune split, no U+FFFD). - Move DockerShellToolIntegrationTests.cs from the unit test project into a new Microsoft.Agents.AI.Tools.Shell.IntegrationTests project so 'dotnet test' on the unit suite no longer requires a Docker daemon. Wire the new project into agent-framework-dotnet.slnx. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5604 round 6 review feedback - ShellSession.MaybeReanchor: switch from double-quoted to single-quoted literal-quoting per shell. Double quotes still expand $VAR, ``, and backticks in both PowerShell and POSIX, so a working directory containing shell metacharacters could trigger command substitution. Add QuotePowerShell (escape ' as '') and QuotePosix (close-and-reopen around ') helpers and route MaybeReanchor through them. Add tests covering ``, $VAR, backticks, and embedded single quotes. - ShellEnvironmentProvider.RunProbeAsync: narrow the OperationCanceledException filter to `when (!cancellationToken.IsCancellationRequested)` so caller-driven cancellation propagates instead of being silently converted to a null snapshot. Update the class XML doc to call out the distinction. Add tests for both paths (caller cancellation throws, probe-timeout returns null fields). - DockerShellTool.RunStatelessAsync / RunDockerCommandAsync: replace unbounded StringBuilder accumulators with a shared HeadTailBuffer (extracted from LocalShellTool into its own internal type). Caps memory at roughly maxOutputBytes regardless of how much output a command emits; drops the now-redundant trailing TruncateHeadTail call. RunDockerCommandAsync caps helper-command output at 1 MiB (defends against chatty docker pull progress streams). Add HeadTailBufferTests covering bounded behaviour over 10 MiB of streamed input. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5604 round 7 review feedback - HeadTailBuffer: switch to UTF-8 byte-aware truncation. The class previously capped on UTF-16 char count while callers pass _maxOutputBytes, so multi-byte output could exceed the budget and head/tail boundaries could split surrogate pairs into orphaned halves. Now tracks UTF-8 byte counts and treats each rune as an indivisible unit (encode -> bytes -> head/tail), guaranteeing the final string round-trips through UTF-8 and never contains an unpaired surrogate. The truncation marker now reads `bytes` instead of `chars` to match. - ShellEnvironmentProvider: clear cached _snapshotTask on failure. Previously a faulted/cancelled first probe permanently poisoned the provider — every later ProvideAIContextAsync await replayed the same exception. Now the failed task is cleared via a CompareExchange so the next caller starts a fresh probe. Tests: added rune-boundary coverage for HeadTailBuffer, plus two regression tests for poison-recovery (executor-throw and caller-cancellation paths). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5604 round 8 review feedback - HeadTailBuffer odd-cap data loss: previously _halfCap = cap / 2 was used as both the head fill bound and the tail eviction threshold, so an odd cap (e.g. cap=5 -> halfCap=2) would silently drop a byte while ToFinalString still reported truncated == false. Split into _headCap = cap / 2 and _tailCap = cap - _headCap so head + tail budgets always sum to exactly cap; any input whose UTF-8 size is <= cap now round-trips losslessly. - ShellSession.TakePrefixByBytes unpaired-high-surrogate: the prefix walker advanced 2 chars whenever it saw a high surrogate, without verifying that the next char was actually a low surrogate. Mirrored the pair check from TakeSuffixByBytes so unpaired surrogates are treated as a single (invalid) BMP char and the encoder substitutes U+FFFD as it would anywhere else. - Centralize clean-environment preserved-vars list. The {PATH, HOME, USER, USERNAME, USERPROFILE, SystemRoot, TEMP, TMP} allowlist was duplicated in LocalShellTool (stateless launch) and ShellSession (persistent startup), so adding a new variable required touching both. Extracted into CleanEnvironmentHelper.PreservedVariables / ApplyPreserved; both call sites collapse to a single line. Tests: HeadTailBuffer round-trip-at-odd-cap regression, ShellSession unpaired- surrogate test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5604 round 9 review feedback - ShellSession.TruncateHeadTail odd-cap budget: same fix applied to HeadTailBuffer last round but missed here. Use headCap = cap/2 + tailCap = cap - headCap so the head/tail budgets sum to exactly cap. - Replace TakePrefixByBytes / TakeSuffixByBytes Encoder.Convert loops with rune iteration. The old code ignored Encoder.charsUsed and trusted the caller's hand-rolled surrogate-pair detection, which made the byte count fragile around unpaired surrogates. EnumerateRunes + Utf8SequenceLength is stateless and self-evidently correct. - ShellEnvironmentProvider.ProbeAsync now skips case-insensitive duplicates in the user-supplied ProbeTools list. Previously {\"git\",\"GIT\"} would probe twice and rely on insertion order to determine the kept value. - DockerShellToolTests.AsAIFunction_RelaxedConfig_DefaultsToApprovalGated: removed unused trailing ool _ parameter and matching InlineData column. Tests: added duplicate-ProbeTools regression test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5604 round 10 review feedback * ShellSession.ReadLoopAsync: replace per-byte buf.Add(chunk[i]) loop with a single buf.AddRange(new ArraySegment<byte>(chunk, 0, n)) bulk copy on the read hot path. * ShellPolicy: compile allow-list patterns with RegexOptions.IgnoreCase, matching the deny-list and avoiding case-mismatch surprises. * LocalShellToolTests.RunAsync_NonZeroExit: drop the redundant ternary that selected between two identical 'exit 7' literals. * DockerShellToolIntegrationTests.NetworkNone: fix the comment to reference 'getent' (matching the actual command) instead of the stale 'wget' phrasing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(dotnet): address PR #5604 round-3 review feedback - Rename LocalShellTool/DockerShellTool -> LocalShellExecutor/DockerShellExecutor - Rename IShellExecutor.StartAsync/CloseAsync -> InitializeAsync/ShutdownAsync - Rename ShellDecision -> ShellPolicyOutcome - Rename CleanEnvironmentHelper.ApplyPreserved -> EnvironmentSanitizer.RemoveNonPreserved - Convert ShellRequest/ShellPolicyOutcome from record struct to plain readonly struct (with IEquatable<T>) - Split ShellMode, ShellTimeoutException, ShellExecutionException into their own files - Add DockerNetworkMode static class with None/Bridge/Host constants - Convert DockerShellExecutor memory parameter from string to long? memoryBytes - Use Throw.IfNull(image) in DockerShellExecutor ctor - Make ShellResolver.EnvVarName public const - Inline-comment each DefaultDenyList regex; document allow-precedence-over-deny on ShellPolicy.Evaluate Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(dotnet): address PR #5604 round-3 follow-up nits - DockerShellExecutor / LocalShellExecutor: drop redundant IAsyncDisposable from class declarations (IShellExecutor : IAsyncDisposable already covers it) - DockerShellExecutor: scope DefaultImage / DefaultContainerUser / DefaultNetwork / DefaultMemoryBytes / DefaultPidsLimit / DefaultContainerWorkdir to internal (only used as parameter defaults; tests have InternalsVisibleTo) - DockerShellExecutor.RunAsync: blank line after the null-guard block (style consistency) - csproj: move <Title>/<Description> below the nuget-package.props import so they are not overwritten by the shared defaults; refresh wording to match new executor names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor shell tool: abstract ShellExecutor, options classes, ContainerUser record Round-3 review responses for PR #5604: * Replace IShellExecutor interface with abstract ShellExecutor base class so the surface can be extended without breaking implementers (review feedback from @westey-m). * Drop ShutdownAsync from the executor surface; DisposeAsync is the canonical teardown (review feedback from @SergeyMenshykh). * Replace the long parameter lists on Local/DockerShellExecutor constructors with LocalShellExecutorOptions and DockerShellExecutorOptions classes so adding new knobs is no longer a breaking change (review feedback from @SergeyMenshykh). * Introduce ContainerUser(Uid, Gid) record in place of a 'uid:gid' string for the Docker user, with Default and Root statics (review feedback from @lokitoth). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove IsHardenedConfiguration; AsAIFunction defaults to approval-gated Addresses PR #5604 review thread AZpMj. The IsHardenedConfiguration property was a configuration-shape check, not a security guarantee, and using it to auto-disable approval gating gave false confidence. - Delete IsHardenedConfiguration property. - AsAIFunction(requireApproval: null) now always wraps in ApprovalRequiredAIFunction; callers must explicitly pass false to opt out. - Update class- and method-level XML docs to drop hardened-attestation language and call out approval gating as the primary safety control. - Drop two hardening-assertion tests and the relaxed-config theory; add one test asserting null requireApproval is approval-gated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace ShellExecutionException/ShellTimeoutException with standard exceptions Addresses PR #5604 review threads AaqVP and Aasod. The custom exception types added no behavior beyond the base type — only a different name — so callers gain nothing from them. - Delete ShellExecutionException.cs and ShellTimeoutException.cs. - Process spawn failures (LocalShellExecutor, DockerShellExecutor) and broken-pipe to a long-lived shell (ShellSession) now throw IOException, which is the natural .NET shape for these failures. - ShellTimeoutException was declared but never thrown; the only in-process timeout path uses the OperationCanceledException raised by the linked CancellationTokenSource. The catch-and-swallow in ShellEnvironmentProvider now matches IOException + TimeoutException. - Update XML doc comments accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove ShellPolicy.DefaultDenyList; default policy is empty Addresses PR #5604 review thread AY7Ba. A regex deny-list is bypassed in seconds by hex escapes ($(echo -e "\x72\x6D")), command substitution ($(base64 -d <<<...)), and envvar splicing ($(A=r B=m; echo $A$B)). No major agent framework uses regex matching as a primary control; AutoGen explicitly removed theirs in v2. The real defenses are approval gating (default) and the Docker sandbox tier. - Delete DefaultDenyList property from ShellPolicy. - ShellPolicy(denyList: null) now means an empty deny-list. - Rewrite ShellPolicy class XML docs to frame as a UX pre-filter for operator-supplied patterns, not as a security control. - Update LocalShellExecutorOptions/DockerShellExecutorOptions Policy docs to match. - Tests that exercise the deny-list mechanism now supply patterns explicitly, mirroring real operator usage. - Add Policy_DefaultConstruction_AllowsAnyNonEmptyCommand test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Document single-session ownership for persistent shell mode Several PR #5604 review threads (notably AaQh2) raised that the persistent shell experience has no concurrency story. The framework's actual design is "one executor per conversation" — there is no per-caller isolation — but that contract was only stated briefly on ShellExecutor and not at all on the types and properties developers reach for first. Strengthen the docs in the places a user is most likely to land: - ShellMode.Persistent: explicit single-session-ownership paragraph (state visible across calls, single pipe, no isolation, one per session). - ShellExecutor: rewrite the Concurrency paragraph to enumerate what leaks (cwd, env, history, background jobs) and call out DI scoping. - LocalShellExecutor: new Single-session-ownership paragraph mirroring the executor-level contract and pointing at Stateless mode as the escape hatch. - DockerShellExecutor: same, framed around the container + bash REPL the persistent-mode executor owns end-to-end. - ShellSession: add a Single-owner paragraph on the type docs and a comment on _runLock clarifying that it serializes the owner's calls, not multiple tenants. - LocalShellExecutorOptions.Mode / DockerShellExecutorOptions.Mode: per-property note pointing at the executor remarks. Docs-only; src builds clean with zero warnings, zero 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-12 16:17:49 +00:00 -
.NET: Refactor harness console rendering (#5751)
* Refactor harness console rendering * Fix formatting issues * Address PR comments
westey ·
2026-05-12 15:13:53 +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: 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 -
.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: 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 -
Fix typo:sesionEleme -> sessionElement (#5674)
Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Hao-Xiong ·
2026-05-07 21:05:41 +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 -
.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 -
.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: 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 -
.NET: Harness Feature branch (#5310)
* .NET: Add a TODO AIContextProvider (#5233) * Add a TODO AIContextProvider * Add unit tests * Address PR comments * Address PR comments * Fix test after removing one tool * .NET: Add a ModeProvider for managing agent modes (#5247) * Add a ModeProvider for managing agent modes * Fix typo * Fix typo * Fix typo * Address PR comments * .NET: Add sample to show how to build a harness (#5268) * Add sample to show how to build a harness * Improve sample * Sample max output tokens and model * Fix encoding * Fix model name in readme * Address PR comments * .NET: Add context window size compaction strategy for harness (#5304) * Add context window size compaction strategy for harness * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Address PR comments --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * .NET: Add a file memory provider (#5315) * Add a file memory provider * Address PR comments * Fix review comments. * Add additional unit tests * Addressing PR comments. * .NET: Harness: Improve prompts and add FileSystem store (#5365) * Harness: Improve prompts and add FileSystem store * Address PR comments * .NET: Harness: Improve path validation (#5404) * Harness: Improve path validation * Address PR comments * .NET: Add always approve helpers, improve sample and fix bug (#5451) * Add always approve helpers, improve sample and fix bug * Address PR comments * .NET: Make Todo, Mode and FileMemory providers more configurable (#5477) * Make Todo, Mode and FileMemory providers more configurable * Address PR comments. * .NET: Add subagents provider and sample (#5518) * Add subagents provider and sample * Addressing PR comments. * .NET: Harness filememory index plus instructions consistency (#5540) * Add FileMemoryProvider index and improve instruction consistency * Address PR comments. * Address PR comments * Address PR comments. * Apply suggestion from @rogerbarreto Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> --------- Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> * .NET: Refactor harness console to be more extensible and easy to understand with better UX (#5573) * Refactor harness console to be more extensible and easy to understand with better UX. * Fix formatting issues. * Allow multiple clarifications in one response * Address PR comments * .NET: Add FileAccessProvdider and concurrency fix for FileMemoryProvider (#5583) * Add FileAccessProvdider and concurrency fix for FileMemoryProvider * Address PR comments --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
westey ·
2026-05-01 10:52:38 +00:00 -
.NET: Add declarative HttpRequestAction sample (#5572)
* Add declarative HttpRequestAction support to workflows * Clean up response body for diagnostics and fix tests. * Fix merge with main. * Remove redundant fallback for request content headers. * Add declarative InvokeHttpRequest sample * Fix solution file and update sample yaml comments * Add final newline to sample class to fix formatting failure
Peter Ibekwe ·
2026-04-29 19:19:31 +00:00 -
.NET: [Breaking] Support string[] arguments for file-based skill scripts (#5475)
* support arguments of string[] shape for file-based skill scripts * suppress breaking changes errors * address feedback * remove unnecessary usung directive
SergeyMenshykh ·
2026-04-27 15:37:10 +00:00 -
.NET: Support returning durable workflow results from HTTP trigger endpoint (#5321)
* Adding support for "wait for response" when invoking workflow http endpoint. * update changelog. * PR comment fixes. * Address PR review feedback. - Return 404 Not Found when no orchestration with the given ID exists - Return 200 OK for failed workflows (the HTTP operation succeeded; the workflow outcome is conveyed via the response body) - Rename 'status' to 'workflowStatus' in WorkflowRunResponse to avoid inconsistency with AgentRunSuccessResponse which uses integer status - Add optional 'error' field (omitted from JSON when null) to WorkflowRunResponse for failed workflow details
Shyju Krishnankutty ·
2026-04-25 00:55:28 +00:00 -
.NET: Bump OpenTelemetry packages to 1.15.3 (#5478)
* Bump OpenTelemetry packages to 1.15.3 to fix known vulnerabilities Update OpenTelemetry packages from 1.15.0 to 1.15.3 in Directory.Packages.props to resolve NU1902 warnings-as-errors for CVEs GHSA-g94r-2vxg-569j, GHSA-mr8r-92fq-pj8p, and GHSA-q834-8qmm-v933. Add explicit PackageReference for OpenTelemetry.Exporter.OpenTelemetryProtocol in Foundry.Hosting and OpenTelemetry.Api + OpenTelemetry.Exporter.OpenTelemetryProtocol in Hosted-Invocations-EchoAgent to override transitive 1.15.0 resolution in projects with CentralPackageTransitivePinningEnabled=false. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump OpenTelemetry Extensions and Instrumentation packages to 1.15.x Align the full OpenTelemetry package set to the 1.15.x family: - OpenTelemetry.Extensions.Hosting: 1.14.0 -> 1.15.3 - OpenTelemetry.Instrumentation.AspNetCore: 1.14.0 -> 1.15.2 - OpenTelemetry.Instrumentation.Http: 1.14.0 -> 1.15.1 - OpenTelemetry.Instrumentation.Runtime: 1.14.0 -> 1.15.1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SergeyMenshykh ·
2026-04-24 21:56:30 +00:00 -
.NET: dotnet: Add server-side Foundry Toolbox support and fix SDK beta.4 br… (#5450)
* dotnet: Add server-side Foundry Toolbox support and fix SDK beta.4 breaking changes Add FoundryToolbox and AIProjectClient extensions to Microsoft.Agents.AI.Foundry.Hosting for server-side toolbox tool integration matching Python's FoundryChatClient.get_toolbox() pattern. Tools are fetched from the Foundry project SDK and passed as server-side tools in the Responses API request. New files: - FoundryToolbox.cs: Core implementation using AgentAdministrationClient SDK - AIProjectClientToolboxExtensions.cs: Extension methods on AIProjectClient - Agent_Step25_ToolboxServerSideTools sample with create helper and combine flow - 19 unit tests covering param validation, conversion, sanitization, and extensions SDK breaking changes (Azure.AI.AgentServer.Responses beta.3 -> beta.4): - FunctionToolCallOutputResource renamed to OutputItemFunctionToolCallOutput - AzureAIAgentServerResponsesModelFactory made internal, replaced with direct constructors - ResponseUsage constructor now requires non-null token details parameters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: reuse endpoint variable in CreateSampleToolboxAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: pass endpoint through static local functions to avoid capture Static local functions cannot capture top-level variables. Thread the endpoint parameter through Main, CombineToolboxes, and CreateSampleToolboxAsync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: remove unused projectClient param from CreateSampleToolboxAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Removing GetToolbocVersion. * Removing tests for GetToolboxVersion * fix: map cached/reasoning token counts in ConvertUsage instead of hardcoding zeros Extract InputTokenDetails.CachedTokenCount and OutputTokenDetails.ReasoningTokenCount from UsageDetails.AdditionalCounts, matching the pattern in AgentResponseExtensions. Also accumulate detail counts when merging with existing usage. 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> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
Ben Thomas ·
2026-04-23 18:52:03 +00:00 -
.NET: Add dynamic tool expansion sample (#5425)
* Add dynamic tool expansion sample * Address PR comments * Remove tool names from tool call response to avoid confusing LLM
westey ·
2026-04-23 15:10:57 +00:00 -
.NET: [Breaking] Migrate A2A agent and hosting to A2A SDK v1 (#5423)
* update a2a agent to the latest a2a sdk (#5257) * Move A2A samples from 04-hosting to 02-agents (#5267) Move the A2A sample projects (A2AAgent_AsFunctionTools and A2AAgent_PollingForTaskCompletion) from samples/04-hosting/A2A/ to samples/02-agents/A2A/ to better align with the sample directory structure. Update solution file and samples README accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Fix stream reconnection for A2AAgent (#5275) * Add SSE stream reconnection support to A2AAgent Implement automatic reconnection for SSE streams that disconnect mid-task, using the Last-Event-ID header to resume from where the stream left off. Changes: - Add InvokeStreamingWithReconnectAsync method to A2AAgent with configurable max retries and delay between attempts - Add new log messages for reconnection events - Add A2AAgent_StreamReconnection sample demonstrating the feature - Update existing polling sample to use simplified SendMessageAsync API - Add unit tests for stream reconnection logic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * address comments * Address PR review feedback - Dispose SSE enumerator before GetTaskAsync fallback to release HTTP connection - Wrap StreamWriter in using blocks with leaveOpen:true and explicit UTF-8 encoding - Print update.Text instead of update object in stream reconnection sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Use IA2AClientFactory to create A2AClient (#5277) * Refactor A2A extensions to use IA2AClientFactory and add ProtocolSelection sample - Update A2AAgentCardExtensions to accept IA2AClientFactory instead of A2AClientOptions - Update A2ACardResolverExtensions to accept IA2AClientFactory - Update A2AClientExtensions to accept IA2AClientFactory - Update A2AAgent to use IA2AClientFactory for client creation - Add A2AAgent_ProtocolSelection sample demonstrating protocol selection - Add comprehensive unit tests for all changes - Update README files with new sample reference Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Reorder params: options before loggerFactory in A2A extensions Move A2AClientOptions parameter before ILoggerFactory in AsAIAgent and GetAIAgentAsync extension methods to follow the repo convention of keeping LoggerFactory and CancellationToken as the last parameters. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Migrate A2A hosting to A2A SDK v1 (#5363) * .NET: Migrate A2A hosting to A2A SDK v1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * remove unused agent card --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Split A2A endpoint mapping into protocol-specific methods (#5413) * .NET: Refactor A2A hosting registration into A2AServerServiceCollectionExtensions - Rename A2AHostingOptions to A2AServerRegistrationOptions - Move server registration logic from A2AEndpointRouteBuilderExtensions and AIAgentExtensions into new A2AServerServiceCollectionExtensions - Remove A2AProtocolBinding and AIAgentExtensions (consolidated) - Update samples and tests to use the new registration API Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * address copilot comments --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove unnecessary using directive in AgentWebChat.AgentHost Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * restore AsyncEnumerable package version * address copilot initial feedback * address automated code review and formatting issues * fix formatting issues * Add DI wiring verification tests for AddA2AServer Add three tests to A2AServerServiceCollectionExtensionsTests that verify custom keyed services are actually wired through to the A2AServer, not just that the server resolves non-null: - Custom IAgentHandler: verifies the keyed handler is invoked when processing a SendMessageRequest instead of the default A2AAgentHandler. - Custom AgentSessionStore (no handler): verifies the keyed session store's GetSessionAsync is called during request processing when no custom handler is registered. - Default stores end-to-end: verifies the InMemoryAgentSessionStore and InMemoryTaskStore defaults successfully process a request. Uses a new CreateAgentMockForRequests helper that includes SerializeSessionCoreAsync setup needed by InMemoryAgentSessionStore. All tests call A2AServer.SendMessageAsync directly (no HTTP layer needed) and use CancellationToken timeouts to guard against hangs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SergeyMenshykh ·
2026-04-23 07:53:00 +00:00 -
.NET [WIP] Foundry Hosted Agents Support (#5312)
* Add Azure AI Foundry Responses hosting adapter Implement Microsoft.Agents.AI.Hosting.AzureAIResponses to host agent-framework AIAgents and workflows within Azure Foundry as hosted agents via the Azure.AI.AgentServer.Responses SDK. - AgentFrameworkResponseHandler: bridges ResponseHandler to AIAgent execution - InputConverter: converts Responses API inputs/history to MEAI ChatMessage - OutputConverter: converts agent response updates to SSE event stream - ServiceCollectionExtensions: DI registration helpers - 336 unit tests across net8.0/net9.0/net10.0 (112 per TFM) - ResponseStreamValidator: SSE protocol validation tool for samples - FoundryResponsesHosting sample app Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump System.ClientModel to 1.10.0 for Azure.Core 1.52.0 compat Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clean up tests and sample formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update Azure.AI.AgentServer packages to 1.0.0-alpha.20260401.5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hosted package version suffix (0.9.0-hosted) to distinguish from mainline Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move Foundry Responses hosting into Microsoft.Agents.AI.Foundry package Move source and test files from the standalone Hosting.AzureAIResponses project into the Foundry package under a Hosting/ subfolder. This consolidates the Foundry-specific hosting adapter into the main Foundry package. - Source: Microsoft.Agents.AI.Foundry.Hosting namespace - Tests: merged into Foundry.UnitTests/Hosting/ - Conditionally compiled for .NETCoreApp TFMs only (net8.0+) - Deleted standalone Hosting.AzureAIResponses project and test project - Updated sample and solution references Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump package version to 0.9.0-hosted.260402.2 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump OpenTelemetry packages to fix NU1109 downgrade errors - OpenTelemetry/Api/Exporter.Console/Exporter.InMemory: 1.13.1 -> 1.15.0 - OpenTelemetry.Exporter.OpenTelemetryProtocol: already 1.15.0 - OpenTelemetry.Extensions.Hosting: already 1.14.0 - OpenTelemetry.Instrumentation.AspNetCore/Http: already 1.14.0 - OpenTelemetry.Instrumentation.Runtime: 1.13.0 -> 1.14.0 - Azure.Monitor.OpenTelemetry.Exporter: 1.4.0 -> 1.5.0 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CA1873: guard LogWarning with IsEnabled check Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix model override bug and add client REPL sample - InputConverter: stop propagating request.Model to ChatOptions.ModelId Hosted agents use their own model; client-provided model values like 'hosted-agent' were being passed through and causing server errors. - Add FoundryResponsesRepl sample: interactive CLI client that connects to a Foundry Responses endpoint using ResponsesClient.AsAIAgent() - Bump package version to 0.9.0-hosted.260403.1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Catch agent errors and emit response.failed with real error message Previously, unhandled exceptions from agent execution would bubble up to the SDK orchestrator, which emits a generic 'An internal server error occurred.' message — hiding the actual cause (e.g., 401 auth failures, model not found, etc.). Now AgentFrameworkResponseHandler catches non-cancellation exceptions and emits a proper response.failed event containing the real error message, making it visible to clients and in logs. OperationCanceledException still propagates for proper cancellation handling by the SDK. Also bumps package version to 0.9.0-hosted.260403.2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Renaming and merging hosting extensions. (#5091) * Rename AddAgentFrameworkHandler to AddFoundryResponses and add MapFoundryResponses - Rename extension methods: AddAgentFrameworkHandler -> AddFoundryResponses, MapAgentFrameworkHandler -> MapFoundryResponses - AddFoundryResponses now calls AddResponsesServer() internally - Add MapFoundryResponses() extension on IEndpointRouteBuilder - Update sample and tests to use new API names - Remove redundant AddResponsesServer() and /ready endpoint from sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fixing numbering in sample. --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address breaking changes in 260408 * Bump hosted internal package version * Add UserAgent middleware tests for Foundry hosting * Hosting Samples update * Hosting Samples update * Hosting Samples update * Hosting Samples update * ChatClientAgent working * Adding SessionStorage and SessionManagement, improving samples to align Consumption vs Hosting * Using updates * Update chat client agent for contributor and devs * Foundry Agent Hosting * Address text rag sample working * Version bump * Adding LocalTools + Workflow samples * Removing extra using samples * Add Hosted-McpTools sample with dual MCP pattern Demonstrates two MCP integration layers in a single hosted agent: - Client-side MCP: McpClient connects to Microsoft Learn, agent handles tool invocations locally (docs_search, code_sample_search, docs_fetch) - Server-side MCP: HostedMcpServerTool delegates tool discovery and invocation to the LLM provider (Responses API), no local connection Includes DevTemporaryTokenCredential for Docker local debugging, Dockerfile.contributor for ProjectReference builds, and the openai/v1 route mapping for AIProjectClient compatibility in Development mode. * .NET: Bump Azure.AI.AgentServer packages to 1.0.0-beta.1/beta.21 and fix br… (#5287) * Bump Azure.AI.AgentServer packages to 1.0.0-beta.1/beta.21 and fix breaking API changes - Azure.AI.AgentServer.Core: 1.0.0-beta.11 -> 1.0.0-beta.21 - Azure.AI.AgentServer.Invocations: 1.0.0-alpha.20260408.4 -> 1.0.0-beta.1 - Azure.AI.AgentServer.Responses: 1.0.0-alpha.20260408.4 -> 1.0.0-beta.1 - Azure.Identity: 1.20.0 -> 1.21.0 (transitive requirement) - Azure.Core: 1.52.0 -> 1.53.0 (transitive requirement) - Remove azure-sdk-for-net dev feed (packages now on nuget.org) - Fix OutputConverter for new builder API (auto-tracked children, split EmitTextDone/EmitDone) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fixing small issues. --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Azure AI Foundry Responses hosting adapter Implement Microsoft.Agents.AI.Hosting.AzureAIResponses to host agent-framework AIAgents and workflows within Azure Foundry as hosted agents via the Azure.AI.AgentServer.Responses SDK. - AgentFrameworkResponseHandler: bridges ResponseHandler to AIAgent execution - InputConverter: converts Responses API inputs/history to MEAI ChatMessage - OutputConverter: converts agent response updates to SSE event stream - ServiceCollectionExtensions: DI registration helpers - 336 unit tests across net8.0/net9.0/net10.0 (112 per TFM) - ResponseStreamValidator: SSE protocol validation tool for samples - FoundryResponsesHosting sample app Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump System.ClientModel to 1.10.0 for Azure.Core 1.52.0 compat Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clean up tests and sample formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update Azure.AI.AgentServer packages to 1.0.0-alpha.20260401.5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add hosted package version suffix (0.9.0-hosted) to distinguish from mainline Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move Foundry Responses hosting into Microsoft.Agents.AI.Foundry package Move source and test files from the standalone Hosting.AzureAIResponses project into the Foundry package under a Hosting/ subfolder. This consolidates the Foundry-specific hosting adapter into the main Foundry package. - Source: Microsoft.Agents.AI.Foundry.Hosting namespace - Tests: merged into Foundry.UnitTests/Hosting/ - Conditionally compiled for .NETCoreApp TFMs only (net8.0+) - Deleted standalone Hosting.AzureAIResponses project and test project - Updated sample and solution references Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump package version to 0.9.0-hosted.260402.2 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump OpenTelemetry packages to fix NU1109 downgrade errors - OpenTelemetry/Api/Exporter.Console/Exporter.InMemory: 1.13.1 -> 1.15.0 - OpenTelemetry.Exporter.OpenTelemetryProtocol: already 1.15.0 - OpenTelemetry.Extensions.Hosting: already 1.14.0 - OpenTelemetry.Instrumentation.AspNetCore/Http: already 1.14.0 - OpenTelemetry.Instrumentation.Runtime: 1.13.0 -> 1.14.0 - Azure.Monitor.OpenTelemetry.Exporter: 1.4.0 -> 1.5.0 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CA1873: guard LogWarning with IsEnabled check Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix model override bug and add client REPL sample - InputConverter: stop propagating request.Model to ChatOptions.ModelId Hosted agents use their own model; client-provided model values like 'hosted-agent' were being passed through and causing server errors. - Add FoundryResponsesRepl sample: interactive CLI client that connects to a Foundry Responses endpoint using ResponsesClient.AsAIAgent() - Bump package version to 0.9.0-hosted.260403.1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Catch agent errors and emit response.failed with real error message Previously, unhandled exceptions from agent execution would bubble up to the SDK orchestrator, which emits a generic 'An internal server error occurred.' message — hiding the actual cause (e.g., 401 auth failures, model not found, etc.). Now AgentFrameworkResponseHandler catches non-cancellation exceptions and emits a proper response.failed event containing the real error message, making it visible to clients and in logs. OperationCanceledException still propagates for proper cancellation handling by the SDK. Also bumps package version to 0.9.0-hosted.260403.2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Renaming and merging hosting extensions. (#5091) * Rename AddAgentFrameworkHandler to AddFoundryResponses and add MapFoundryResponses - Rename extension methods: AddAgentFrameworkHandler -> AddFoundryResponses, MapAgentFrameworkHandler -> MapFoundryResponses - AddFoundryResponses now calls AddResponsesServer() internally - Add MapFoundryResponses() extension on IEndpointRouteBuilder - Update sample and tests to use new API names - Remove redundant AddResponsesServer() and /ready endpoint from sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fixing numbering in sample. --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address breaking changes in 260408 * Bump hosted internal package version * Add UserAgent middleware tests for Foundry hosting * Hosting Samples update * Hosting Samples update * Hosting Samples update * Hosting Samples update * ChatClientAgent working * Adding SessionStorage and SessionManagement, improving samples to align Consumption vs Hosting * Using updates * Update chat client agent for contributor and devs * Foundry Agent Hosting * Address text rag sample working * Version bump * Adding LocalTools + Workflow samples * Removing extra using samples * Add Hosted-McpTools sample with dual MCP pattern Demonstrates two MCP integration layers in a single hosted agent: - Client-side MCP: McpClient connects to Microsoft Learn, agent handles tool invocations locally (docs_search, code_sample_search, docs_fetch) - Server-side MCP: HostedMcpServerTool delegates tool discovery and invocation to the LLM provider (Responses API), no local connection Includes DevTemporaryTokenCredential for Docker local debugging, Dockerfile.contributor for ProjectReference builds, and the openai/v1 route mapping for AIProjectClient compatibility in Development mode. * Bump Azure.AI.AgentServer packages to 1.0.0-beta.1/beta.21 and fix breaking API changes - Azure.AI.AgentServer.Core: 1.0.0-beta.11 -> 1.0.0-beta.21 - Azure.AI.AgentServer.Invocations: 1.0.0-alpha.20260408.4 -> 1.0.0-beta.1 - Azure.AI.AgentServer.Responses: 1.0.0-alpha.20260408.4 -> 1.0.0-beta.1 - Azure.Identity: 1.20.0 -> 1.21.0 (transitive requirement) - Azure.Core: 1.52.0 -> 1.53.0 (transitive requirement) - Remove azure-sdk-for-net dev feed (packages now on nuget.org) - Fix OutputConverter for new builder API (auto-tracked children, split EmitTextDone/EmitDone) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fixing small issues. * Fix IDE0009: add 'this' qualification in DevTemporaryTokenCredential Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix IDE0009: add 'this' qualification in all HostedAgentsV2 samples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CHARSET: add UTF-8 BOM to Hosted-LocalTools and Hosted-Workflows Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix dotnet format: add Async suffix to test methods (IDE1006), fix encoding and style Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Register AgentSessionStore in test DI setups Add InMemoryAgentSessionStore registration to all ServiceCollection setups in AgentFrameworkResponseHandlerTests and WorkflowIntegrationTests. This is needed after the AgentSessionStore infrastructure was introduced in the responses-hosting feature. Tests still have NotImplementedException stubs for CreateSessionCoreAsync which will be fixed when the session infrastructure is fully available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Invocations protocol samples (hosted echo agent + client) (#5278) Add Hosted-Invocations-EchoAgent: a minimal echo agent hosted via the Invocations protocol (POST /invocations) using AddInvocationsServer and MapInvocationsServer, bridged to an Agent Framework AIAgent through a custom InvocationHandler. Add SimpleInvocationsAgent: a console REPL client that wraps HttpClient calls to the /invocations endpoint in a custom InvocationsAIAgent, demonstrating programmatic consumption of the Invocations protocol. Both samples default to port 8088 for consistency with other hosted agent samples. * Restructure FoundryHostedAgents samples into invocations/ and responses/ Align dotnet hosted agent samples with the Python side (PR #5281) by reorganizing the directory structure: - Remove HostedAgentsV1 entirely (old API pattern) - Split HostedAgentsV2 into invocations/ and responses/ based on protocol - Move Using-Samples accordingly (SimpleAgent to responses, SimpleInvocationsAgent to invocations) - Update slnx with new project paths and add previously missing invocations projects - Update README cd paths from HostedAgentsV2 to invocations or responses - Rename .env.local to .env.example to match Python naming convention - Fix format violations in newly included invocations projects * Remove launchSettings, use .env for port configuration - Delete all launchSettings.json files (port 8088 now comes from ASPNETCORE_URLS in .env) - Add DotNetEnv to Hosted-Invocations-EchoAgent so it loads .env like the responses samples - Create .env.example for EchoAgent with ASPNETCORE_URLS and ASPNETCORE_ENVIRONMENT - Add AGENT_NAME to ChatClientAgent and FoundryAgent .env.example (required by those samples) - Add AZURE_BEARER_TOKEN=DefaultAzureCredential to all .env.example files - Update DevTemporaryTokenCredential in all 6 samples to treat the sentinel value as unavailable, allowing ChainedTokenCredential to fall through to DefaultAzureCredential - Update EchoAgent README with Configuration section * Use placeholder for AGENT_NAME in Hosted-FoundryAgent .env.example * Move FoundryResponsesHosting to responses/Hosted-WorkflowHandoff, use GetResponsesClient * Rename Hosted-Workflows to Hosted-Workflow-Simple, Hosted-WorkflowHandoff to Hosted-Workflow-Handoff * Remove FoundryResponsesRepl and empty FoundryResponsesHosting directory * Add Dockerfiles, README, agent yamls and bearer token support to Hosted-Workflow-Handoff - Add Dockerfile and Dockerfile.contributor for Docker-based testing - Add agent.yaml and agent.manifest.yaml with triage-workflow as primary agent - Add README.md following sibling pattern, noting Azure OpenAI vs Foundry endpoint - Add DevTemporaryTokenCredential and ChainedTokenCredential for Docker auth - Register triage-workflow as non-keyed default so azd invoke works without model - Update .env.example with AZURE_BEARER_TOKEN sentinel - Add .gitignore to 04-hosting to suppress VS-generated launchSettings.json - Fix docker run image name in Hosted-Workflow-Simple README * Fix AgentFrameworkResponseHandlerTests: implement session methods in test mock agents * .NET: Auto-instrument resolved AIAgents with OpenTelemetry for Foundry Hosted Agents (#5316) * Auto-instrument resolved AIAgents with OpenTelemetry using Core ResponsesSourceName * Add OTel telemetry capture tests for Foundry hosted agent handler * Net: Prepare Foundry Preview Release (#5336) * Prepare Foundry preview release 1.2.0-preview.* Bump VersionPrefix to 1.2.0 and update the preview stamp date. Invert packaging opt-in so only the Foundry preview set produces NuGet packages: - Microsoft.Agents.AI.Abstractions - Microsoft.Agents.AI - Microsoft.Agents.AI.Workflows - Microsoft.Agents.AI.Workflows.Generators - Microsoft.Agents.AI.Foundry Flip IsReleased=false on the preview set so they pick up the -preview.YYMMDD.N suffix. Gate GeneratePackageOnBuild on IsPackable=true. Remove the global IsPackable=true from nuget-package.props so the repo-level default (false) applies to everything else. * Lower preview VersionPrefix to 0.0.1 Retroactive preview publish: bump VersionPrefix and GitTag from 1.2.0 to 0.0.1 so the 5 Foundry preview packages emit as 0.0.1-preview.260417.1. * Net: Publish all packages as 0.0.1-preview.260417.2 (#5341) Revises the Foundry pre-release approach to publish ALL normally packable src projects as preview packages stamped 0.0.1-preview.260417.2, including projects previously flagged IsReleased=true or with a non-default VersionSuffix (rc/alpha). nuget-package.props: - Collapse the four conditional PackageVersion expressions (IsReleaseCandidate, VersionSuffix, default preview, IsReleased stable) into a single unconditional 0.0.1-preview.260417.2. On this preview-only branch every package ships with the same pre-release stamp regardless of per-project flags. - Restore the global IsPackable=true default (offsetting the repo-wide IsPackable=false in Directory.Build.props). Projects that opt out (Mem0, Declarative) already set IsPackable=false AFTER importing this file so they remain non-packable. - Remove the IsReleased-gated EnablePackageValidation line. Package validation does not apply to a 0.0.1 preview. csproj reverts (Abstractions, Agents.AI, Workflows, Workflows.Generators, Foundry): - Revert the IsPackable=true opt-in block introduced in #5336 (now redundant since the props default is true again). - Restore IsReleased=true to its pre-PR value. The setting is now a no-op because the props no longer branches on it. * Bump preview version to 260420.1 and fix AgentServer package deps (#5367) - Bump PackageVersion to 0.0.1-preview.260420.1 - Bump Azure.AI.AgentServer.Core beta.21 -> beta.22 (required by Azure.AI.AgentServer.Responses beta.3) - Replace AgentHostTelemetry.ResponsesSourceName with local constant (type made internal in AgentServer.Core beta.22) Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Hosted agents toolbox support (#5368) * feat: Add Foundry Toolbox (MCP) support to AgentFrameworkResponseHandler Adds support for Foundry Toolsets MCP proxy integration in the hosted agent response handler. Toolsets connect at startup via IHostedService, gating the readiness probe per spec §3.1. MCP tools are injected into every request's ChatOptions and OAuth consent errors (-32006) are intercepted and surfaced as mcp_approval_request + incomplete SSE events. New files: - FoundryToolboxOptions.cs: configuration POCO for toolset names and API version - FoundryToolboxBearerTokenHandler.cs: DelegatingHandler with Azure Bearer token auth, Foundry-Features header injection, and 3x exponential backoff on 429/5xx - McpConsentContext.cs: AsyncLocal-based per-request consent state shared between the tool wrapper and the response handler - ConsentAwareMcpClientTool.cs: AIFunction wrapper that catches -32006 errors and signals consent via shared state and linked CancellationTokenSource - FoundryToolboxService.cs: IHostedService that creates McpClient per toolset at startup and exposes cached tools Modified files: - AgentFrameworkResponseHandler.cs: injects toolbox tools into ChatOptions, sets up linked CTS consent interception, emits mcp_approval_request on -32006 - ServiceCollectionExtensions.cs: adds AddFoundryToolboxes(params string[]) extension - Microsoft.Agents.AI.Foundry.csproj: adds ModelContextProtocol and Azure.Identity dependencies under NETCoreApp condition Sample: - Hosted-Toolbox: minimal hosted agent sample using AddFoundryToolboxes * Rename toolset to toolbox in user-facing API; rename ConsentAwareMcpClientTool to ConsentAwareMcpClientAIFunction * Add HostedMcpToolboxAITool for client-selectable Foundry toolboxes Introduces HostedMcpToolboxAITool, a marker tool subclassing HostedMcpServerTool that rides the OpenAI Responses 'mcp' wire format to let clients request a specific Foundry toolbox per request. - New FoundryAITool.CreateHostedMcpToolbox(name, version?) factory. - FoundryToolboxOptions.StrictMode (default true) rejects unregistered toolboxes; set to false to allow lazy-open on first use. - FoundryToolboxService.GetToolboxToolsAsync(name, version?) resolves cached or lazy-opened MCP tools. - AgentFrameworkResponseHandler parses request.Tools for foundry-toolbox://name[?version=v] markers and injects resolved tools per request, merging with pre-registered ones. - Unit tests for marker parsing and strict-mode resolution. * Bump Azure.AI.Projects to 2.1.0-alpha; add ToolboxRecord/ToolboxVersion factory overloads + tests * Fix PR review issues: retry off-by-one, URI encoding, docs, tests, build - Fix off-by-one in FoundryToolboxBearerTokenHandler retry loop (4 attempts → 3) - URI-encode version parameter in HostedMcpToolboxAITool.BuildAddress - Add XML doc clarifying version pinning is reserved for future use - Add comment clarifying AddHostedService deduplication safety - Fix DevTemporaryTokenCredential expiry to use DateTimeOffset.MaxValue - Fix AgentCard ambiguity in A2AServer sample with using alias - Add 18 new unit tests for retry handler and ReadMcpToolboxMarkers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Hosted agent adapter (#5371) * Bump preview version to 260420.1 and fix AgentServer package deps - Bump PackageVersion to 0.0.1-preview.260420.1 - Bump Azure.AI.AgentServer.Core beta.21 -> beta.22 (required by Azure.AI.AgentServer.Responses beta.3) - Replace AgentHostTelemetry.ResponsesSourceName with local constant (type made internal in AgentServer.Core beta.22) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CA1873: guard LogError with IsEnabled check in FoundryToolboxService Wrap the LogError call with an IsEnabled(LogLevel.Error) guard to satisfy the CA1873 analyzer rule which flags potentially expensive argument evaluation when logging is disabled. 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> * .NET: Hosted agent adapter (#5374) * Bump preview version to 260420.1 and fix AgentServer package deps - Bump PackageVersion to 0.0.1-preview.260420.1 - Bump Azure.AI.AgentServer.Core beta.21 -> beta.22 (required by Azure.AI.AgentServer.Responses beta.3) - Replace AgentHostTelemetry.ResponsesSourceName with local constant (type made internal in AgentServer.Core beta.22) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CA1873: guard LogError with IsEnabled check in FoundryToolboxService Wrap the LogError call with an IsEnabled(LogLevel.Error) guard to satisfy the CA1873 analyzer rule which flags potentially expensive argument evaluation when logging is disabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bumping NuGet version --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * .NET: Hosted agent adapter (#5406) * Bump preview version to 260420.1 and fix AgentServer package deps - Bump PackageVersion to 0.0.1-preview.260420.1 - Bump Azure.AI.AgentServer.Core beta.21 -> beta.22 (required by Azure.AI.AgentServer.Responses beta.3) - Replace AgentHostTelemetry.ResponsesSourceName with local constant (type made internal in AgentServer.Core beta.22) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CA1873: guard LogError with IsEnabled check in FoundryToolboxService Wrap the LogError call with an IsEnabled(LogLevel.Error) guard to satisfy the CA1873 analyzer rule which flags potentially expensive argument evaluation when logging is disabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bumping NuGet version * Restore conditional versioning, remove dev feed, bump Azure.AI.Projects to beta.1 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> * Hosted agent adapter (#5408) * Bump preview version to 260420.1 and fix AgentServer package deps - Bump PackageVersion to 0.0.1-preview.260420.1 - Bump Azure.AI.AgentServer.Core beta.21 -> beta.22 (required by Azure.AI.AgentServer.Responses beta.3) - Replace AgentHostTelemetry.ResponsesSourceName with local constant (type made internal in AgentServer.Core beta.22) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CA1873: guard LogError with IsEnabled check in FoundryToolboxService Wrap the LogError call with an IsEnabled(LogLevel.Error) guard to satisfy the CA1873 analyzer rule which flags potentially expensive argument evaluation when logging is disabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bumping NuGet version * Restore conditional versioning, remove dev feed, bump Azure.AI.Projects to beta.1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #5312 review comments - Add comment explaining NU1903 suppression (Microsoft.Bcl.Memory transitive vuln) - Remove NU1903 from sample/test projects where not needed - Fix Dockerfile ENTRYPOINT mismatch in Hosted-Workflow-Simple - Align agent name to 'hosted-workflow-simple' in agent.yaml and README - Fix Hosted-McpTools README: replace GitHub PAT refs with Microsoft Learn - Fix session persistence: only persist when client provides conversation ID - Upgrade IsNullOrEmpty to IsNullOrWhiteSpace for session ID checks 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> * Split Foundry into stable V1 and preview Hosting package Extract hosted agent functionality from Microsoft.Agents.AI.Foundry into a new Microsoft.Agents.AI.Foundry.Hosting preview package. This resolves NU5104 build errors caused by the stable Foundry package depending on prerelease Azure SDK packages (Azure.AI.AgentServer.Responses, Azure.AI.Projects beta). Changes: - Create Microsoft.Agents.AI.Foundry.Hosting with VersionSuffix=preview, targeting .NET Core only (net8.0/9.0/10.0) - Move all Hosting/ source files to the new project - Move ToolboxRecord/ToolboxVersion overloads to FoundryAIToolExtensions - Revert Azure.AI.Projects to 2.0.0 in Directory.Packages.props; Hosting uses VersionOverride for 2.1.0-beta.1 - Clean V1 Foundry csproj: remove beta deps, ASP.NET Core ref, hosting conditionals - Update 8 hosted agent sample projects to reference Foundry.Hosting - Split unit tests: ToolboxRecord/ToolboxVersion tests moved to Hosting/ - Add Foundry.Hosting to solution file Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review comments: experimental attrs, doc fixes, token propagation - Add [Experimental(OPENAI001)] to all 7 public Hosting types per reviewer request - Fix McpConsentContext XML doc: 'Thread-static' -> 'Async-local' (AsyncLocal flows with ExecutionContext, not thread-static) - Expand UserAgentMiddleware test regex to match prerelease versions (e.g. 1.0.0-rc.4) - Propagate CancellationToken in AgentFrameworkResponseHandler session save Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove unnecessary MEAI001 suppression from stable Foundry package MEAI001 was a leftover from when Hosting code lived in the same project. The stable V1 Foundry package builds clean without it, and suppressing experimental diagnostics in a released package can hide unintentional exposure of experimental APIs to consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Foundry.Hosting to release solution filter 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> Co-authored-by: Ben Thomas <ben.thomas@microsoft.com>
Roger Barreto ·
2026-04-21 20:25:10 +00:00 -
.NET: Features/3768-devui-aspire-integration (#3771)
* adds devui integration and samples * adds unit tests for devui integration * fix: correct formatting of copyright notice in unit test files * fixes formatting issues * fixes build for net8 target * fixes formatting errors on test apphost * adds copyright notice to multiple files and removes unnecessary using directives * Update dotnet/aspire-integration/Aspire.Hosting.AgentFramework.DevUI/DevUIAggregatorHostedService.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/aspire-integration/Aspire.Hosting.AgentFramework.DevUI/DevUIAggregatorHostedService.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/tests/Aspire.Hosting.AgentFramework.DevUI.UnitTests/Aspire.Hosting.AgentFramework.DevUI.UnitTests.csproj Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/samples/DevUIIntegration/DevUIIntegration.AppHost/DevUIIntegration.AppHost.csproj Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/aspire-integration/Aspire.Hosting.AgentFramework.DevUI/DevUIAggregatorHostedService.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Refactor project files to use TargetFrameworks instead of TargetFramework for multi-targeting support; add optional port property to DevUIResource class. * Add unit tests for DevUIAggregatorHostedService; refactor project files for TargetFrameworks support * Refactor project files to use TargetFrameworks for multi-targeting support in DevUIIntegration samples * Remove unnecessary using directive for Aspire.Hosting in DevUIAggregatorHostedServiceTests * merge * fixes Conversation routing for non-first backends * add documentation for devui integration sample * update project references in solution file for improved integration * fixes package versions post merge * move Aspire.Hosting.AgentFramework.DevUI to dotnet/src Move the project from aspire-integration/ to src/ to be consistent with the location of all other projects in the repo. * move DevUI sample to samples/05-end-to-end/DevUIAspireIntegration Move the sample from samples/DevUIIntegration/ to samples/05-end-to-end/DevUIAspireIntegration/ to match the location of other end-to-end samples. * remove unnecessary net472 framework condition from sample csproj files These projects only target net10.0, so the Condition="'$(TargetFramework)' != 'net472'" on ItemGroup is unnecessary. * update sample model name from gpt-4.1 to gpt-5.4 Use a more up-to-date model name in the DevUI integration samples. * Revert "remove unnecessary net472 framework condition from sample csproj files" This reverts commit
08cf41253b. * fix: use TargetFrameworks to override multi-targeting from Directory.Build.props The parent Directory.Build.props sets TargetFrameworks to net10.0;net472, which overrides the singular TargetFramework in each csproj. Use the plural TargetFrameworks property set to net10.0 only to properly override it, and remove the now-unnecessary net472 condition on ItemGroup. * fixes aspire config * fix: update Microsoft.Extensions packages to version 10.0.1 * Address Copilot review feedback on DevUI Aspire integration - Fix request body dropping in ProxyConversationsAsync: always read the body when ContentLength > 0 before routing, then pass it through to all proxy calls (previously null was passed when backend was resolved from query param or conversation map) - Fix resource leak: dispose aggregator on startup failure in catch block - Fix XML docs: accurately describe embedded resource serving behavior - Remove reflection from DevUIResourceTests (InternalsVisibleTo already set) - Make sensitive telemetry conditional on Development environment in samples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: update chat client version to gpt41 in both EditorAgent and WriterAgent --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>Tommaso Stocchi ·
2026-04-20 11:12:54 +00:00 -
.NET: Add Code Interpreter container file download samples (#5014)
* Add Code Interpreter container file download samples (#3081) - Add Agent_OpenAI_Step06_CodeInterpreterFileDownload (Public OpenAI) - Add Agent_Step24_CodeInterpreterFileDownload (Microsoft Foundry) - Both samples demonstrate downloading cfile_/cntr_ container files via ContainerClient instead of the standard Files API - Update solution file and parent READMEs * Address review feedback: flatten nested foreach loops using SelectMany Addresses https://github.com/microsoft/agent-framework/pull/5014#discussion_r3046908449 and https://github.com/microsoft/agent-framework/pull/5014#discussion_r3046920209 --------- Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Co-authored-by: rogerbarreto <rogerbarreto@users.noreply.github.com>
chetantoshniwal ·
2026-04-17 16:55:03 +00:00 -
.NET: Add error checking to workflow samples (#5175)
* Initial plan * Add WorkflowErrorEvent and ExecutorFailedEvent error checking to all workflow samples Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/c5d77400-d7ed-4fbe-9103-f5d74aabcf2b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Fix if/else if consistency for error event handlers per code review feedback Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/c5d77400-d7ed-4fbe-9103-f5d74aabcf2b Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * Address PR comments * fixup: PR comments --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Copilot ·
2026-04-16 20:03:16 +00:00 -
.NET: Add Handoff sample (#5245)
* feat: Add Handoff sample * docs: Add Handoff sample to readme
Jacob Alber ·
2026-04-16 20:02:31 +00:00 -
.NET: Foundry Evals integration for .NET (#4914)
* Foundry Evals integration for .NET - Core evaluation framework: EvalItem, LocalEvaluator, FunctionEvaluator, EvalChecks - IAgentEvaluator interface with MeaiEvaluatorAdapter bridge - AgentEvaluationExtensions for agent.EvaluateAsync() overloads - FoundryEvals wrapping MEAI quality/safety evaluators - ConversationSplitters (LastTurn, Full) and IConversationSplitter - EvalItem.PerTurnItems() for multi-turn decomposition - HasImageContent for multimodal content detection - WorkflowEvaluationExtensions for per-agent workflow evaluation - 7 eval samples mirroring Python parity: 02-agents/Evaluation: SimpleEval, ExpectedOutputs, Multimodal 03-workflows/Evaluation: WorkflowEval 05-end-to-end/Evaluation: FoundryQuality, MixedProviders, ConversationSplits - Comprehensive unit tests (1958 passing) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rewrite FoundryEvals to use real Foundry Evals API Replace MEAI evaluator shim with actual OpenAI EvaluationClient protocol methods. FoundryEvals now creates eval definitions, submits runs, polls for completion, and fetches per-item results server-side. - New constructor: FoundryEvals(AIProjectClient, model, evaluators) - Add FoundryEvalConverter for MEAI ChatMessage -> Foundry JSON format - Add EvalId, RunId, ReportUrl to AgentEvaluationResults - All 20 built-in evaluator constants now work (agent, tool, quality, safety) - Remove Microsoft.Extensions.AI.Evaluation.Quality/Safety dependencies - Update all samples for new constructor (no more ChatConfiguration) - Replace BuildEvaluators tests with ResolveEvaluator tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add response output to CustomEvals and ExpectedOutputs samples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review: pagination, validation, error handling, tests FoundryEvals fixes: - Add pagination for output items (has_more/after cursor) - Add guard clauses for pollIntervalSeconds/timeoutSeconds <= 0 - Fix double TryGetProperty for passed field parsing - Throw on all-tool-evaluators with no tool definitions - Fix XML doc (default 300s, not 180s) New tests (30 added, 1989 total): - EvalChecks: NonEmpty, ContainsExpected (pass/fail/skip/case), HasImageContent, ToolCallsPresent - FoundryEvalConverter: ConvertMessage (text, image, function call, function results fan-out, empty fallback, mixed content), ConvertEvalItem, BuildTestingCriteria (quality/agent/tool/groundedness data mappings), BuildItemSchema Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix review: null-refs, Data.ToString() bug, ContainsExpected, add tests - Fix NullReferenceException in sample Response display (pattern matching) - Fix WorkflowEvaluationExtensions Data?.ToString() producing type names instead of message text (pattern-match ChatMessage/AgentResponse/list) - Change EvalChecks.ContainsExpected to return Passed=false when no ExpectedOutput (was silently passing, masking misconfiguration) - Add EvalItem constructor tests with LastTurn/Full/null splitters - Add FoundryEvalConverter.ConvertMessage DataContent (base64 image) test - Add ExtractAgentData tests with ChatMessage, list, and AgentResponse data Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix review: conversation fidelity, eval caching, fallback tests - WorkflowEvaluationExtensions: preserve full response messages (tool calls, intermediate) instead of synthetic 2-message conversation. Cast completed Data to AgentResponse and use Messages when available, fallback to text. - FoundryEvals: cache evalId per schema shape (hasContext, hasTools) so subsequent EvaluateAsync calls create runs under the same eval definition. - MeaiEvaluatorAdapter: code already correctly passes queryMessages (not full conversation) to IEvaluator — no change needed, verified by inspection. - Add tests: AgentResponse full messages preservation, unknown object ToString() fallback for ExtractAgentData. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename AzureAI→Foundry: move eval files, update references - Move FoundryEvals.cs and FoundryEvalConverter.cs from Microsoft.Agents.AI.AzureAI to Microsoft.Agents.AI.Foundry - Update namespace from AzureAI to Foundry in both files - Add explicit usings required by Foundry project (no implicit usings) - Move FoundryEvalConverter tests to Foundry.UnitTests project (avoids ReplacingRedactor type conflict from dual project refs) - Update all sample csproj references and using statements - Remove Foundry project reference from AI UnitTests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * PR review round 4: wire up tool extraction, remove eval cache, fix null safety - BuildEvalItem: extract tools from agent via GetService<ChatOptions>() into EvalItem.Tools (Python parity) - FoundryEvals: remove eval ID cache - each call creates fresh definition (matches Python behavior) - FoundryEvals: replace null-forgiving operators with descriptive InvalidOperationException - MixedProviders sample: remove unnecessary explicit PackageReferences (transitively provided) - FoundryEvalConverter: document that tool results take precedence over text content - Add LocalEvaluator zero-checks test documenting 0 metrics = failed behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python-dotnet parity: 9 feature gaps filled New checks: - ToolCallArgsMatch() — verify tool call names + argument subset match - ToolCalledCheck(ToolCalledMode.Any, ...) — match any of the specified tools - ToolCalledMode enum (All/Any) FoundryEvals enhancements: - Default evaluators now [Relevance, Coherence, TaskAdherence] (was Relevance, Coherence) - Auto-add ToolCallAccuracy when items have tool definitions - EvaluateTracesAsync — evaluate by response_ids, trace_ids, or agent_id - EvaluateFoundryTargetAsync — evaluate deployed Foundry targets Result type enrichment: - AgentEvaluationResults: added Status, Error, PerEvaluator, DetailedItems - New EvalItemResult/EvalScoreResult/PerEvaluatorResult types - FoundryEvals populates all new fields from API responses Workflow fix: - Skip internal executors (_*, input-conversation, end-conversation, end) Tests: 8 new tests covering ToolCallArgsMatch, ToolCalledMode.Any, internal executor filtering Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add MeaiEvaluatorAdapter and PerTurnItems edge case tests - 3 tests for MeaiEvaluatorAdapter: query message forwarding, synthetic response fallback, multiple items aggregation - 3 tests for EvalItem.PerTurnItems: empty conversation, no user messages, system+assistant only - StubEvaluator and StubChatClient test helpers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Blocking link check for outdated package in DevUI. * Replace Dictionary<string, object> payloads with typed wire models Introduce internal FoundryEvalWireModels.cs with compile-time-safe types for the OpenAI Evals API wire format. The OpenAI .NET SDK (2.9.1) only provides protocol-level methods with BinaryContent/ClientResult — no typed request models. These internal models replace scattered dictionary literals with [JsonPropertyName]-annotated classes, giving: - Compile-time safety (typos become build errors) - Single point of change when the API evolves - IntelliSense discoverability - Cleaner serialization via JsonPolymorphic for content items Models: WireContentItem hierarchy (text, image, tool_call, tool_result), WireMessage, WireEvalItemPayload, WireTestingCriterion, WireItemSchema, WireCreateEvalRequest, WireCreateRunRequest, and data source variants. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Skip metric when Foundry returns neither score nor passed When an evaluator returns no score and no passed value, the previous code created BooleanMetric(name, false), which falsely failed items via ItemPassed. Now we skip the MEAI metric entirely for indeterminate results — the raw data remains available in DetailedItems for diagnostics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR #4914 review comments: fix tool evaluator bug and add tests - Fix duplicate ToolCallAccuracy: resolve evaluator names before checking against ToolEvaluators set (Comment 2) - Make FilterToolEvaluators internal for testability; add tests for the ArgumentException edge case when all evaluators are tool-type (Comment 3) - Add CancellationToken test for LocalEvaluator (Comment 4) - Add EvaluateAsync integration test on Run with sequential workflow and per-agent SubResults verification (Comment 5) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address Peter's review comments on PR #4914 - Add trailing newline to Evaluation_FoundryQuality.csproj (Comment 6) - Make evaluator name lookups case-insensitive: switch BuiltinEvaluators, ToolEvaluators, AgentEvaluators, and ResolveEvaluator's StartsWith check from Ordinal to OrdinalIgnoreCase (Comment 7) - Add Trace.TraceWarning when Foundry returns fewer results than submitted items, indicating expected vs actual count before padding (Comment 8) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Microsoft.Extensions.AI.Evaluation packages to Directory.Packages.props These were removed in #5269 as unused, but are needed by the Foundry and core evaluation integration added in this PR. 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-04-16 19:40:07 +00:00 -
.NET: Update AGUI service to support session storage (#5193)
* Update AGUI service to support session storage * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Address PR comments --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
westey ·
2026-04-13 18:03:51 +00:00 -
.NET: Support reflection for discovery of resources and scripts in class-based skills (#5183)
* support reflection for discovery of resources and scripts in class-based skills * fix format issues * refactor samples to use reflection * Validate resource member signatures during discovery Add discovery-time validation in AgentClassSkill.DiscoverResources() to fail fast when [AgentSkillResource] is applied to members with incompatible signatures: - Reject indexer properties (getter has parameters) - Reject methods with parameters other than IServiceProvider or CancellationToken Throws InvalidOperationException with actionable error messages instead of allowing silent runtime failures when ReadAsync invokes the AIFunction with no named arguments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * prevent duplicates --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SergeyMenshykh ·
2026-04-10 11:56:28 +01:00 -
.NET: Update models used in dotnet samples to gpt-5.4-mini (#5080)
* Update models used in dotnet samples to gpt-5.4-mini * Fix additional missed sample
westey ·
2026-04-07 15:34:00 +00:00 -
.NET: fix: Concurrent Workflow Sample (#5090)
* fix: Concurrent Workflow Sample * Switch to using Azure AI Projects APIs * Remove agent streaming outputs by changing emitEvents to false on TurnToken * Disable forwarding input from agent host executors * Make output format more legible * refactor: Update Concurrent sample to use message delivery event callback
Jacob Alber ·
2026-04-07 14:28:21 +00:00 -
Fix and simplify ComputerUse sample (#5075)
* fix the computer use sample * rollback changes to the search state enum * address review comments * address review comments
SergeyMenshykh ·
2026-04-07 12:29:31 +00:00