* .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>
_prepare_options() now removes tools, tool_choice, and parallel_tool_calls
from run_options after injecting agent_reference. The Foundry API rejects
requests containing both fields. FunctionTools are still invoked client-side
by the function invocation layer.
Fixes#5087
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
* Guard against empty text in _parse_structured_response_value (#5145)
When using response_format with background=True (Responses API), polling
an in-progress response produces empty text. _parse_structured_response_value
unconditionally passed this to model_validate_json/json.loads, causing
ValidationError or JSONDecodeError.
Add an early return of None when text is empty, matching the existing
guard for response_format=None. This allows .value to safely return None
for in-progress background responses.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Python: Fix `response_format` crash on background polling with empty text
Fixes#5145
---------
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eduard van Valkenburg
·
2026-04-07 22:26:03 +00:00
* Raise clear handler registration error for unresolved TypeVar (#4943)
Detect unresolved TypeVar in message parameter annotations during handler
registration in both _validate_handler_signature (Executor) and
_validate_function_signature (FunctionExecutor). Raises a ValueError with
an actionable message recommending @handler(input=..., output=...) or
@executor(input=..., output=...) instead of letting TypeVar leak through
to a confusing TypeCompatibilityError during workflow edge validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback for #4943: reorder checks and harden function executor
- Move TypeVar check before validate_workflow_context_annotation in
_executor.py so users see the more actionable error first
- Wrap get_type_hints in try/except in _function_executor.py matching
the defensive pattern in _executor.py
- Repurpose duplicate test to cover bounded TypeVar rejection
- Add test_function_executor_allows_concrete_types for test symmetry
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Narrow get_type_hints except clause and add missing tests (#4943)
- Narrow `except Exception` to `except (NameError, AttributeError, RecursionError)`
in both _executor.py and _function_executor.py so unexpected failures in
get_type_hints are not silently swallowed.
- Add test_handler_unresolvable_annotation_raises to test_function_executor_future.py
exercising the except branch of get_type_hints in the function executor path.
- Add test_function_executor_rejects_bounded_typevar_in_message_annotation to
test_function_executor.py for parity with the Executor bounded TypeVar test.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add error ordering test for TypeVar vs WorkflowContext priority (#4943)
Add test_handler_typevar_error_takes_priority_over_context_error to verify
that when a handler has both a TypeVar message and an unannotated ctx, the
TypeVar error is raised first (the more actionable issue).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Python: Fix image content serialization sending null file_id to Foundry API
Omit file_id from input_image dict when not present instead of including
it as null, which Azure AI Foundry's stricter schema validation rejects.
* Python: Fix Foundry API rejecting rich content in function_call_output
Azure AI Foundry does not support list-format output in function_call_output
items. Add SUPPORTS_RICH_FUNCTION_OUTPUT flag (default True) to
RawOpenAIChatClient, set to False in RawFoundryChatClient so Foundry
falls back to string output for tool results with images/files.
Also omit file_id from input_image dicts when not set, since Foundry
rejects explicit nulls.
* Python: Surface rich tool content as user message when Foundry lacks support
When SUPPORTS_RICH_FUNCTION_OUTPUT is False, image/file items from tool
results are injected as a follow-up user message so the model can still
process the visual content via Foundry's supported user message format.
* Xfail Foundry image integration test for the meantime
---------
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* 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
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>
* Add github actions workflow for verify-samples
* Make workflow run as part of PR (for now)
* Update workflow to remove pr trigger
* Address PR comments
* 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
* Fix GitHubCopilotAgent not calling context provider hooks (#3984)
GitHubCopilotAgent accepted context_providers in its constructor but
never called before_run()/after_run() on them in _run_impl() or
_stream_updates(), silently ignoring all context providers.
Add _run_before_providers() helper to create SessionContext and invoke
before_run on each provider. Both _run_impl() and _stream_updates() now
run the full provider lifecycle: before_run before sending the prompt
(with provider instructions prepended) and after_run after receiving the
response. This follows the same pattern used by A2AAgent.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Python: Fix GitHubCopilotAgent to invoke context provider before_run/after_run hooks
Fixes#3984
* fix(#3984): address review feedback for context provider integration
- Build prompt from session_context.get_messages(include_input=True) so
provider-injected context_messages are included in both non-streaming
and streaming paths (review comments #1, #2)
- Preserve timeout in opts (use get instead of pop) so providers can
observe it via context.options (review comment #3)
- Eliminate streaming double-buffer: move after_run invocation to a
ResponseStream result_hook (matching Agent class pattern) instead of
maintaining a separate updates list in the generator (review comment #4)
- Improve _run_before_providers docstring
Add tests for:
- Context messages included in prompt (non-streaming + streaming)
- Error path: after_run NOT called when send_and_wait/streaming raises
- Multiple providers: forward before_run, reverse after_run ordering
- BaseHistoryProvider with load_messages=False is skipped
- Streaming after_run response contains aggregated updates
- Streaming with no updates still sets empty response
- Timeout preserved in session context options for providers
Note: _run_before_providers remains on GitHubCopilotAgent for now. A
follow-up PR should extract it to BaseAgent so subclasses can reuse it
without duplicating the provider iteration logic.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback for #3984: Python: [Bug]: GitHubCopilotAgent Memory Example
* refactor(#3984): promote _run_before_providers to BaseAgent
Move _run_before_providers from GitHubCopilotAgent into BaseAgent,
mirroring the existing _run_after_providers helper. Agent's
_prepare_session_and_messages now delegates to the shared base method,
eliminating the near-duplicate provider iteration logic that could
drift as the provider contract evolves.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback for #3984: Python: [Bug]: GitHubCopilotAgent Memory Example
* revert: keep _run_before_providers in GitHubCopilotAgent only
Undo the promotion of _run_before_providers to BaseAgent. The method
stays in GitHubCopilotAgent where it is needed, and _agents.py
retains its original inline provider iteration in RawAgent.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: replace deprecated BaseContextProvider/BaseHistoryProvider with ContextProvider/HistoryProvider
Update imports and usages in GitHubCopilotAgent and its tests to use
the new non-deprecated class names from the core package.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address review feedback - reorder providers before session, wrap streaming after_run in try/except, assert after_run on skipped HistoryProvider
- Move _run_before_providers before _get_or_create_session so provider
contributions can affect session configuration
- Wrap _run_after_providers in try/except in streaming _after_run_hook
to prevent provider errors from replacing successful responses
- Add after_run assertion to test_history_provider_skip_when_load_messages_false
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>
Add deduplication to `prepend_instructions_to_messages()` to skip
instructions that are already present as leading messages with the
same role and text. This prevents duplicate system messages when
instructions are injected by multiple layers (e.g. Agent + chat client).
Fixes#5049
* 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
* Python: Fix broken samples and add missing READMEs
- simple_context_provider: move instructions kwarg into options dict
- suspend_resume_session: use OpenAIChatCompletionClient for in-memory demo
- foundry_chat_client_with_hosted_mcp: move store kwarg into options dict
- Add README.md for context_providers and conversations sample folders
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Python: Fix additional sample issues in context_providers
- mem0_basic: send preferences query before sleep so Mem0 can learn them,
print result from new session recall
- mem0_sessions: add session for multi-turn conversation in agent-scoped
example, remove user_id from agent-scoped provider (Mem0 API stores
memories without user_id when agent_id is provided), use single message
for storing preferences
- redis_basics: print retrieved context messages instead of raw object
- redis_sessions: add missing load_dotenv() call
- redis_basics/redis_sessions: fix docstrings referencing wrong client type
- azure_redis_conversation: replace duplicate copyright with load_dotenv()
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Python: Fix broken link in declarative README
openai_responses_agent.py was renamed to openai_agent.py
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Refactor Anthropic model option and provider clients
Rename the Anthropic client model option from model_id to model, add provider-specific Anthropic wrappers for Foundry, Bedrock, and Vertex, and expose them through the Anthropic, Foundry, Amazon, and Google namespaces. Update core option handling, docs, samples, and tests accordingly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix Anthropic skills sample typing
Cast the Anthropic beta client to Any in the skills sample so the pre-commit sample pyright check no longer fails on beta skills and files endpoints that are not exposed by the current SDK stubs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* undo sample mypy
* Retry CI after transient external failures
Retrigger PR validation after an unrelated Copilot review workflow SAML failure and a transient external tau2 git fetch failure in the Windows Python test setup.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback on model option merging
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address Anthropic compatibility review feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* moved all to `model`
* fixes for azure ai search
* Python: standardize remaining sample env var names
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Python: fix foundry-local pyright compatibility
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* updated env vars in cicd
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eduard van Valkenburg
·
2026-04-01 19:00:18 +00:00