- 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>
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.
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
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.
* 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.
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>
- 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>
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>
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>
* feat: Refactor Handoff Orchestration and add HITL support
* Change HandoffAgentExecutor to use factory-based instantiation
* Extract shared request collection logic in AIAgentUnservicedRequestsCollector
* Refactor HandoffAgentExecutor to use the "ContinueTurn" pattern as in AIAgentHostExecutor
* fix: Remove '$' from exception strings
Rename authored identifiers, XML docs, log messages, and comments
from 'folder' to 'directory' across the file skills codebase for
consistency with the agentskills.io specification and .NET conventions.
Public API changes (experimental):
- ScriptFolders → ScriptDirectories
- ResourceFolders → ResourceDirectories
.NET BCL API calls (Directory.Exists, Path.GetDirectoryName, etc.)
were already using 'directory' and are unchanged.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* 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>
* .NET: Add JsonSerializerOptions support to programmatic skill APIs
Allow callers to pass custom JsonSerializerOptions when creating inline
resources and scripts via AgentInlineSkill, AgentClassSkill,
AgentInlineSkillResource, and AgentInlineSkillScript. A skill-level
default can be set on AgentInlineSkill and overridden per-resource/
script call.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update dotnet/tests/Microsoft.Agents.AI.UnitTests/AgentSkills/TestSkillTypes.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Adds a public CreateSessionAsync(string conversationId, CancellationToken)
method to FoundryAgent that delegates to the inner ChatClientAgent,
allowing users to create sessions with existing server-side conversation IDs.
Fixes#5138
* add class-based skills
* address formating issues
* Remove generated filtered-unit.slnx and add to .gitignore
The filtered solution file is generated dynamically by
eng/scripts/New-FilteredSolution.ps1 during CI. Checking it in
risks it becoming stale and out-of-sync with the real solution.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove generated filtered-unit.slnx and add to .gitignore
The filtered solution file is generated dynamically by
eng/scripts/New-FilteredSolution.ps1 during CI. Checking it in
risks it becoming stale and out-of-sync with the real solution.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* discover scripts and resource from folders defined in spec
* Remove Step05 and Step06 DI skill samples
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* address review comments
* fix build error
* Fix mixed path separators in skill folder discovery on .NET Framework
Path.Combine with forward-slash folder names (e.g. "scripts/f1") produces
mixed separators on Windows, causing the StartsWith containment check to
fail against Path.GetFullPath-resolved file paths. Wrap in Path.GetFullPath
to canonicalize separators before the containment comparison.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* address comment
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Improve workflow unit tests
* Update test name prefix for clarity.
* Update tests to surface any errors.
* fix check-point restore-time race in off-thread workflow event stream
* add class-based skills
* address formating issues
* Remove generated filtered-unit.slnx and add to .gitignore
The filtered solution file is generated dynamically by
eng/scripts/New-FilteredSolution.ps1 during CI. Checking it in
risks it becoming stale and out-of-sync with the real solution.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove generated filtered-unit.slnx and add to .gitignore
The filtered solution file is generated dynamically by
eng/scripts/New-FilteredSolution.ps1 during CI. Checking it in
risks it becoming stale and out-of-sync with the real solution.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* consolidate DI samples into one
* fix file encoding
* suppress compatibility warning
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: Remove Timeout from InputWait in StreamingRunEventStream
* fix: Race condition when the workflow executes to halt before TakeEventStream
* test: Make the OffThread Delay test more nimble
* fix: Remove slight window where runStatus could be stale
* Update Foundry Responses as ChatClientAgent
* Migrate obsolete AzureAI integration tests to versioned agent pattern
Replace obsolete CreateAIAgentAsync/GetAIAgentAsync calls with
Agents.CreateAgentVersionAsync() + AsAIAgent(AgentVersion) in all
AzureAI integration tests.
- Rename AIProjectClient* test files to FoundryVersionedAgent*
- Register AIFunction tools in PromptAgentDefinition.Tools for
server-side visibility via AsOpenAIResponseTool()
- Skip structured output tests (AzureAIProjectChatClient clears
ResponseFormat for versioned agents)
- Remove all [Obsolete] attributes and #pragma warning disable CS0618
* Merge FoundryMemory package into AzureAI under Memory/ folder
Move all FoundryMemory source, unit tests, and integration tests into
the Microsoft.Agents.AI.AzureAI package. Change namespace from
Microsoft.Agents.AI.FoundryMemory to Microsoft.Agents.AI.AzureAI.
- Add [Experimental] to FoundryMemoryProviderOptions and Scope
- Rename internal AIProjectClientExtensions to MemoryStoreExtensions
- Update AzureAI .csproj with Compliance.Abstractions, Redaction
- Remove FoundryMemory from solution and release filter
- Update sample to reference AzureAI instead of FoundryMemory
- Delete old Microsoft.Agents.AI.FoundryMemory project and tests
* Add EnsureMemoryStoreCreatedAsync and memory existence checks to integration tests
- Ensure memory store is created before testing memory operations
- Add AZURE_AI_EMBEDDING_DEPLOYMENT_NAME config setting
- Assert memories exist in store via SearchMemoriesAsync before cleanup
- Verify scope isolation with direct memory store queries
* Fix and rename AzureAI unit tests for RAPI vs Versioned clarity
- Rename AsAIAgentAsync_* to AsAIAgent_* (drop Async from method group)
- Add _Rapi_ prefix to non-versioned (Responses API) tests
- Add _Versioned_ prefix to versioned agent tests where needed
- Fix RAPI tests: assert GetService<AIProjectClient>() is null
- Fix Versioned tests: assert IsType<FoundryAgent> and
GetService<AIProjectClient>() returns the client instance
- Fix UserAgent header tests: proper HTTP handler routing
- Fix ChatClient_UsesDefaultConversationIdAsync test setup
- All 153 unit tests pass with 0 failures
* Rename Microsoft.Agents.AI.AzureAI to Microsoft.Agents.AI.Foundry
Rename the project, namespace, folder, and all references from
Microsoft.Agents.AI.AzureAI to Microsoft.Agents.AI.Foundry.
Also rename Workflows.Declarative.AzureAI to .Foundry.
- Rename src, unit test, integration test, and workflow folders
- Update namespaces in all source and test .cs files
- Update ProjectReferences in ~47 sample and test .csproj files
- Update solution files (.slnx, .slnf)
- Update sample using statements
- Update READMEs, SKILL.md, ADRs in docs/
- Disable package validation baseline for renamed packages
- Fix UTF-8 BOM encoding on all affected .cs files
- AzureAI.Persistent left completely unchanged
* Fix format: remove ImplicitUsings, add explicit usings, fix BOM encoding
- Remove ImplicitUsings=enable from Foundry csproj to resolve IDE0005
on shared ReplacingRedactor.cs
- Add explicit System usings to all source files that relied on them
- Sort usings alphabetically per editorconfig rules
- Fix UTF-8 BOM on 12 sample Program.cs files
- Rename Azure AI Foundry Agents to Microsoft Foundry Agents in docs
* Fix RequestInfoEvent lost when resuming workflow from checkpoint
* Fix streaming run double disposal in tests and lockstep republishing before Started event is emitted.
* Fix bug to remove messages after sending to avoid losing messages on send failure.
* Fix declarative test harness
* Add API breaking change validation for RC packages
Enable .NET Package Validation for release candidate packages to detect
API breaking changes in CI. This follows the same pattern used by
Semantic Kernel, centralized through nuget-package.props.
Changes:
- Enable EnablePackageValidation for IsReleaseCandidate packages
- Update PackageValidationBaselineVersion to 1.0.0-rc4 (latest published)
- Generate CompatibilitySuppressions.xml for existing known API changes
in 5 packages (AI, AzureAI, OpenAI, Workflows, Workflows.Declarative.AzureAI)
- Opt out Workflows.Declarative.Mcp (not yet published to NuGet)
- Add breaking changes guidance to CONTRIBUTING.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR review feedback
- Remove unnecessary empty PackageValidationBaselineVersion override
in Workflows.Declarative.Mcp.csproj (EnablePackageValidation=false
is sufficient)
- Tighten CONTRIBUTING.md wording to clarify opt-out possibility
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Enable package validation for GA packages (no VersionSuffix)
Expand the EnablePackageValidation condition to also cover future GA
packages that have no VersionSuffix, not just RC packages.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix EnablePackageValidation GA condition to check PackageVersion
The previous condition VersionSuffix=='' matched all packages (preview
included) since VersionSuffix defaults to empty. Now uses two separate
conditions: one for RC, one for true GA (PackageVersion == VersionPrefix).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add IsGeneralAvailable flag for package validation
Replace fragile PackageVersion condition with explicit IsGeneralAvailable
property, following the same per-project self-declaration pattern as
IsReleaseCandidate.
- Directory.Build.props: Add IsGeneralAvailable=false default
- nuget-package.props: EnablePackageValidation on RC OR GA
- CONTRIBUTING.md: Update docs to mention both flags
When packages go GA, they set IsGeneralAvailable=true in their .csproj.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Rename IsGeneralAvailable to IsGenerallyAvailable
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>