* fix: resolve string annotations in FunctionExecutor
Enhance type hint validation in FunctionExecutor by importing `typing` and
using `get_type_hints` to correctly resolve annotations.
This fixes validation failures when `from __future__ import annotations`
is enabled, which stores annotations as strings.
Fixes#1808
* Update python/packages/core/tests/workflow/test_function_executor_future.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* ran pre commit
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Fix bug where ChatAgent system instructions were not captured in Langfuse
traces due to incorrect attribute access.
The observability code was attempting to retrieve instructions using
getattr(self, "instructions", None), but ChatAgent stores instructions
in self.chat_options.instructions. This caused system_instructions to
always be None in Langfuse traces.
Changed both _trace_agent_run and _trace_agent_run_stream functions
to correctly retrieve instructions from chat_options.instructions.
Fixes affect:
- Line 1123: _trace_agent_run (non-streaming)
- Line 1192: _trace_agent_run_stream (streaming)
2025-11-19 07:08:27 +00:00
Eduard van ValkenburgGitHubCopilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>eavanvalkenburgcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>CopilotVictor Dibia
Update XML documentation to clarify exception behavior.
See `ChatClientAgentThreadTests.SetConversationIdThrowsWhenMessageStoreIsSet` which already verifies this is the actual behavior.
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* Fix: Prevent duplicate MCP tools and prompts (#1876)
- Added deduplication logic in MCPTool.load_tools() method
- Added deduplication logic in MCPTool.load_prompts() method
- Track existing function names before loading from MCP server
- Skip tools/prompts that are already registered in _functions list
- Prevents 400 error from Azure AI Foundry caused by duplicate tool names
The issue occurred because load_tools() was being called multiple times
(during connect() and by notification handlers), causing tools to be
appended without duplicate checking.
Changes made:
1. In load_tools(): Added existing_names set to track registered functions
2. In load_tools(): Added check to skip tools already in existing_names
3. In load_prompts(): Applied same deduplication pattern
Testing:
- Created unit test verifying deduplication logic
- Confirmed duplicates are skipped correctly
- Confirmed new functions are added correctly
- Prevents duplicate tool names being sent to LLM
Fixes#1876
* Address review feedback: Prevent multiple calls to load_tools and load_prompts
- Added _tools_loaded and _prompts_loaded flags to MCPTool class
- Modified load_tools() to check if already loaded and return early
- Modified load_prompts() to check if already loaded and return early
- Moved test cases from test_mcp_fix.py to test_mcp.py
- Added tests for multiple call prevention
- Deleted separate test_mcp_fix.py file
Addresses review feedback from @eavanvalkenburg:
- Prevents accidental multiple calls to load_tools()
- Prevents accidental multiple calls to load_prompts()
- Test file now in proper location (test_mcp.py)
* Address review feedback: Move flag checks to connect() and remove comments
- Removed verbose comments from code
- Moved _tools_loaded and _prompts_loaded checks to connect() method
- Allows manual calls to load_tools() and load_prompts() for updates
- Updated tests to reflect new behavior
- connect() now prevents duplicate loading during connection
- Users can still manually call load_tools()/load_prompts() to refresh
Addresses feedback from @eavanvalkenburg
* Fix: Code quality and formatting issues
- Applied black formatting
- Fixed ruff linting issues
- All tests passing locally
* chore: Re-run uv lock per review request
* Apply pre-commit formatting: consolidate type annotations
- Consolidate multi-line type annotations to single line
- Remove unnecessary parentheses
- Apply ruff format and security checks
* Move Purview integration logic into middleware
* Improve error handling and user id management
* Rename purview package
* Handle 402s more explicitly; add Middleware generation methods; don't ignore exceptions
* Use DI container; pass scope id to PC
* Add protection scope caching
* Wrap more exceptions in PurviewClient
* Remove block check dedup; add tests
* Refactor PurviewWrapper intialization; Add unit tests
* Use different .Use method and add IDisposable stub
* Add background job processing for Purview
* Misc comment cleanup
* Apply copilot comments
* Fix formatting
* Formatting other files to fix pipeline
* Small updates to settings and exceptions
* Add README
* Move Purview sample
* Address review comments and update XML comments
* Newline after namespace
* Move public Purview classes to single namespace; Clean up csproj and slnx
* Commit the renames
* Remove unused openAI dependency
---------
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
* fix devui regression from #2021 where all input is stringified but devui HIL input does not handle stringified json strings correctly.
* update incorrect test
* add devui hil input tests
This commit fixes three issues in the security_filter_middleware:
1. Missing context.terminate flag - Without this, middleware continues processing after setting blocked response
2. No streaming support - When context.is_streaming is True, middleware now returns async generator with ChatResponseUpdate
3. Checks all messages - Changed to check only context.messages[-1] (most recent user message) instead of iterating through conversation history
Changes:
- Added AsyncIterable import
- Added ChatResponseUpdate and TextContent imports
- Modified security_filter_middleware to handle both streaming and non-streaming modes
- Added context.terminate = True to properly stop execution
- Changed message checking logic to only inspect the last user message
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
* Added changes (#1909)
* Python: [Feature Branch] Renamed Azure AI agent and small fixes (#1919)
* Renaming
* Small fixes
* Update python/packages/core/agent_framework/openai/_shared.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Small fix
* Python: [Feature Branch] Added use_latest_version parameter to AzureAIClient (#1959)
* Added use_latest_version parameter to AzureAIClient
* Added unit tests
* Update python/samples/getting_started/agents/azure_ai/azure_ai_use_latest_version.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update python/packages/azure-ai/agent_framework_azure_ai/_client.py
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
* Python: [Feature Branch] Structured Outputs and more examples for AzureAIClient (#1987)
* Small updates
* Added support for structured outputs
* Added code interpreter example
* More examples and fixes
* Added more examples and README
* Small fix
* Addressed PR feedback
* Removed optional ID from FunctionResultContent (#2011)
* Added hosted MCP support (#2018)
* Python: [Feature Branch] Fixed "store" parameter handling (#2069)
* Fixed store parameter handling
* Small fix
* Python: [Feature Branch] Added more examples and fixes for Azure AI agent (#2077)
* Updated azure-ai-projects package version
* Added an example of hosted MCP with approval required
* Updated code interpreter example
* Added file search example
* Update python/samples/getting_started/agents/azure_ai/azure_ai_with_file_search.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update python/samples/getting_started/agents/azure_ai/azure_ai_with_file_search.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Small fix
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Added handling for conversation_id (#2098)
* Merge from main
* Revert "Merge from main"
This reverts commit b8206a85d7.
* Python: [Feature Branch] Merge from main to Azure AI branch (#2111)
* Do not build DevUI assets during .NET project build (#2010)
* .NET: Add unit tests for declarative executor SetMultipleVariables (#2016)
* Add unit tests for create conversation executor
* Update indentation and comment typo.
* Added unit tests for declarative executor SetMultipleVariablesExecutor
* Updated comments and syntactic sugar
* Python: DevUI: Use metadata.entity_id instead of model field (#1984)
* DevUI: Use metadata.entity_id for agent/workflow name instead of model field
* OpenAI Responses: add explicit request validation
* Review feedback
* .NET: DevUI - Do not automatically add/map OpenAI services/endpoints (#2014)
* Don't add OpenAIResponses as part of Dev UI
You should be able to add and remove Dev UI without impacting your other production endpoints.
* Remove `AddDevUI()` and do not map OpenAI endpoints from `MapDevUI()`
* Fix comment wording
* Revise documentation
---------
Co-authored-by: Daniel Roth <daroth@microsoft.com>
* Python: DevUI: Add OpenAI Responses API proxy support + HIL for Workflows (#1737)
* DevUI: Add OpenAI Responses API proxy support with enhanced UI features
This commit adds support for proxying requests to OpenAI's Responses API,
allowing DevUI to route conversations to OpenAI models when configured to enable testing.
Backend changes:
- Add OpenAI proxy executor with conversation routing logic
- Enhance event mapper to support OpenAI Responses API format
- Extend server endpoints to handle OpenAI proxy mode
- Update models with OpenAI-specific response types
- Remove emojis from logging and CLI output for cleaner text
Frontend changes:
- Add settings modal with OpenAI proxy configuration UI
- Enhance agent and workflow views with improved state management
- Add new UI components (separator, switch) for settings
- Update debug panel with better event filtering
- Improve message renderers for OpenAI content types
- Update types and API client for OpenAI integration
* update ui, settings modal and workflow input form, add register cleanup hooks.
* add workflow HIL support, user mode, other fixes
* feat(devui): add human-in-the-loop (HIL) support with dynamic response schemas
Implement HIL workflow support allowing workflows to pause for user input
with dynamically generated JSON schemas based on response handler type hints.
Key Features:
- Automatic response schema extraction from @response_handler decorators
- Dynamic form generation in UI based on Pydantic/dataclass response types
- Checkpoint-based conversation storage for HIL requests/responses
- Resume workflow execution after user provides HIL response
Backend Changes:
- Add extract_response_type_from_executor() to introspect response handlers
- Enrich RequestInfoEvent with response_schema via _enrich_request_info_event_with_response_schema()
- Map RequestInfoEvent to response.input.requested OpenAI event format
- Store HIL responses in conversation history and restore checkpoints
Frontend Changes:
- Add HILInputModal component with SchemaFormRenderer for dynamic forms
- Support Pydantic BaseModel and dataclass response types
- Render enum fields as dropdowns, strings as text/textarea, numbers, booleans, arrays, objects
- Display original request context alongside response form
Testing:
- Add tests for checkpoint storage (test_checkpoints.py)
- Add schema generation tests for all input types (test_schema_generation.py)
- Validate end-to-end HIL flow with spam workflow sample
This enables workflows to seamlessly pause execution and request structured user input
with type-safe, validated forms generated automatically from response type annotations.
* improve HIL support, improve workflow execution view
* ui updates
* ui updates
* improve HIL for workflows, add auth and view modes
* update workflow
* security improvements , ui fixes
* fix mypy error
* update loading spinner in ui
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
* .NET: Remove launchSettings.json from .gitignore in dotnet/samples (#2006)
* Remove launchSettings.json from .gitignore in dotnet/samples
* Update dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Properties/launchSettings.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/AGUIClientServer/AGUIServer/Properties/launchSettings.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* DevUI: Serialize workflow input as string to maintain conformance with OpenAI Responses format (#2021)
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
* Add Microsoft Agent Framework logo to assets (#2007)
* Updated package versions (#2027)
* DevUI: Prevent line breaks within words in the agent view (#2024)
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
* .NET [AG-UI]: Adds support for shared state. (#1996)
* Product changes
* Tests
* Dojo project
* Cleanups
* Python: Fix underlying tool choice bug and all for return to previous Handoff subagent (#2037)
* Fix tool_choice override bug and add enable_return_to_previous support
* Add unit test for handoff checkpointing
* Handle tools when we have them
* added missing chatAgent params (#2044)
* .NET: fix ChatCompletions Tools serialization (#2043)
* fix serialization in chat completions on tools
* nit
* .NET: assign AgentCard's URL to mapped-endpoint if not defined explicitly (#2047)
* fix serialization in chat completions on tools
* nit
* write e2e test for agent card resolve + adjust behavior
* nit
* Version 1.0.0-preview.251110.1 (#2048)
* .NET: Remove moved OpenAPI sample and point to SK one. (#1997)
* Remove moved OpenAPI sample and point to SK one.
* Update dotnet/samples/GettingStarted/Agents/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Bump AWSSDK.Extensions.Bedrock.MEAI from 4.0.4.2 to 4.0.4.6 (#2031)
---
updated-dependencies:
- dependency-name: AWSSDK.Extensions.Bedrock.MEAI
dependency-version: 4.0.4.6
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* .NET: Separate all memory and rag samples into their own folders (#2000)
* Separate all memory and rag samples into their own folders
* Fix broken link.
* Python: .Net: Dotnet devui compatibility fixes (#2026)
* DevUI: Add OpenAI Responses API proxy support with enhanced UI features
This commit adds support for proxying requests to OpenAI's Responses API,
allowing DevUI to route conversations to OpenAI models when configured to enable testing.
Backend changes:
- Add OpenAI proxy executor with conversation routing logic
- Enhance event mapper to support OpenAI Responses API format
- Extend server endpoints to handle OpenAI proxy mode
- Update models with OpenAI-specific response types
- Remove emojis from logging and CLI output for cleaner text
Frontend changes:
- Add settings modal with OpenAI proxy configuration UI
- Enhance agent and workflow views with improved state management
- Add new UI components (separator, switch) for settings
- Update debug panel with better event filtering
- Improve message renderers for OpenAI content types
- Update types and API client for OpenAI integration
* update ui, settings modal and workflow input form, add register cleanup hooks.
* add workflow HIL support, user mode, other fixes
* feat(devui): add human-in-the-loop (HIL) support with dynamic response schemas
Implement HIL workflow support allowing workflows to pause for user input
with dynamically generated JSON schemas based on response handler type hints.
Key Features:
- Automatic response schema extraction from @response_handler decorators
- Dynamic form generation in UI based on Pydantic/dataclass response types
- Checkpoint-based conversation storage for HIL requests/responses
- Resume workflow execution after user provides HIL response
Backend Changes:
- Add extract_response_type_from_executor() to introspect response handlers
- Enrich RequestInfoEvent with response_schema via _enrich_request_info_event_with_response_schema()
- Map RequestInfoEvent to response.input.requested OpenAI event format
- Store HIL responses in conversation history and restore checkpoints
Frontend Changes:
- Add HILInputModal component with SchemaFormRenderer for dynamic forms
- Support Pydantic BaseModel and dataclass response types
- Render enum fields as dropdowns, strings as text/textarea, numbers, booleans, arrays, objects
- Display original request context alongside response form
Testing:
- Add tests for checkpoint storage (test_checkpoints.py)
- Add schema generation tests for all input types (test_schema_generation.py)
- Validate end-to-end HIL flow with spam workflow sample
This enables workflows to seamlessly pause execution and request structured user input
with type-safe, validated forms generated automatically from response type annotations.
* improve HIL support, improve workflow execution view
* ui updates
* ui updates
* improve HIL for workflows, add auth and view modes
* update workflow
* security improvements , ui fixes
* fix mypy error
* update loading spinner in ui
* DevUI: Serialize workflow input as string to maintain conformance with OpenAI Responses format
* Phase 1: Add /meta endpoint and fix workflow event naming for .NET DevUI compatibility
* additional fixes for .NET DevUI workflow visualization item ID tracking
**Problem:**
.NET DevUI was generating different item IDs for ExecutorInvokedEvent and
ExecutorCompletedEvent, causing only the first executor to highlight in the
workflow graph. Long executor names and error messages also broke UI layout.
**Changes:**
- Add ExecutorActionItemResource to match Python DevUI implementation
- Track item IDs per executor using dictionary in AgentRunResponseUpdateExtensions
- Reuse same item ID across invoked/completed/failed events for proper pairing
- Add truncateText() utility to workflow-utils.ts
- Truncate executor names to 35 chars in execution timeline
- Truncate error messages to 150 chars in workflow graph nodes
** Details:**
- ExecutorActionItemResource registered with JSON source generation context
- Dictionary cleaned up after executor completion/failure to prevent memory leaks
- Frontend item tracking by unique item.id supports multiple executor runs
- All changes follow existing codebase patterns and conventions
Tested with review-workflow showing correct executor highlighting and state
transitions for sequential and concurrent executors.
* format fixes, remove cors tests
* remove unecessary attributes
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
Co-authored-by: Reuben Bond <reuben.bond@gmail.com>
* DevUI: support having both an agent and a workflow with the same id in discovery (#2023)
* Python: Fix Model ID attribute not showing up in `invoke_agent` span (#2061)
* Best effort to surface the model id to invoke agent span
* Fix tests
* Fix tests
* Version 1.0.0-preview.251107.2 (#2065)
* Version 1.0.0-preview.251110.2 (#2067)
* Update README.md to change Grafana links to Azure portal links for dashboard access (#1983)
* .NET - Enable build & test on branch `feature-foundry-agents` (#2068)
* Tests good, mkay
* Update .github/workflows/dotnet-build-and-test.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Enable feature build pipelines
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
* Python: Add concrete AGUIChatClient (#2072)
* Add concrete AGUIChatClient
* Update logging docstrings and conventions
* PR feedback
* Updates to support client-side tool calls
* .NET: Move catalog samples to the HostedAgents folder (#2090)
* move catalog samples to the HostedAgents folder
* move the catalog samples' projects to the HostedAgents folder
* Bump OpenTelemetry.Instrumentation.Runtime from 1.12.0 to 1.13.0 (#1856)
---
updated-dependencies:
- dependency-name: OpenTelemetry.Instrumentation.Runtime
dependency-version: 1.13.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* .NET: Bump Microsoft.SemanticKernel.Agents.Abstractions from 1.66.0 to 1.67.0 (#1962)
* Bump Microsoft.SemanticKernel.Agents.Abstractions from 1.66.0 to 1.67.0
---
updated-dependencies:
- dependency-name: Microsoft.SemanticKernel.Agents.Abstractions
dependency-version: 1.67.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* .NET: Bump all Microsoft.SemanticKernel packages from 1.66.* to 1.67.* (#1969)
* Initial plan
* Update all Microsoft.SemanticKernel packages to 1.67.*
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
* Remove unrelated changes to package-lock.json and yarn.lock
Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
* .NET: fix: WorkflowAsAgent Sample (#1787)
* fix: WorkflowAsAgent Sample
* Also makes ChatForwardingExecutor public
* feat: Expand ChatForwardingExecutor handled types
Make ChatForwardingExecutor match the input types of ChatProtocolExecutor.
* fix: Update for the new AgentRunResponseUpdate merge logic
AIAgent always sends out List<ChatMessage> now.
* Updated (#2076)
* Bump vite in /python/samples/demos/chatkit-integration/frontend (#1918)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.9 to 7.1.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.1.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.12/packages/vite)
---
updated-dependencies:
- dependency-name: vite
dependency-version: 7.1.12
dependency-type: direct:development
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Bump Roslynator.Analyzers from 4.14.0 to 4.14.1 (#1857)
---
updated-dependencies:
- dependency-name: Roslynator.Analyzers
dependency-version: 4.14.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Bump MishaKav/pytest-coverage-comment from 1.1.57 to 1.1.59 (#2034)
Bumps [MishaKav/pytest-coverage-comment](https://github.com/mishakav/pytest-coverage-comment) from 1.1.57 to 1.1.59.
- [Release notes](https://github.com/mishakav/pytest-coverage-comment/releases)
- [Changelog](https://github.com/MishaKav/pytest-coverage-comment/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mishakav/pytest-coverage-comment/compare/v1.1.57...v1.1.59)
---
updated-dependencies:
- dependency-name: MishaKav/pytest-coverage-comment
dependency-version: 1.1.59
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* Python: Handle agent user input request in AgentExecutor (#2022)
* Handle agent user input request in AgentExecutor
* fix test
* Address comments
* Fix tests
* Fix tests
* Address comments
* Address comments
* Python: OpenAI Responses Image Generation Stream Support, Sample and Unit Tests (#1853)
* support for image gen streaming
* small fixes
* fixes
* added comment
* Python: Fix MCP Tool Parameter Descriptions Not Propagated to LLMs (#1978)
* mcp tool description fix
* small fix
* .NET: Allow extending agent run options via additional properties (#1872)
* Allow extending agent run options via additional properties
This mirrors the M.E.AI model in ChatOptions.AdditionalProperties which is very useful when building functionality pipelines.
Fixes https://github.com/microsoft/agent-framework/issues/1815
* Expand XML documentation
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add AdditionalProperties tests to AgentRunOptions
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
* Python: Use the last entry in the task history to avoid empty responses (#2101)
* Use the last entry in the task history to avoid empty responses
* History only contains Messages
* Updated package versions (#2104)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Reuben Bond <203839+ReubenBond@users.noreply.github.com>
Co-authored-by: Peter Ibekwe <109177538+peibekwe@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shawn Henry <sphenry@gmail.com>
Co-authored-by: Javier Calvarro Nelson <jacalvar@microsoft.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
Co-authored-by: Korolev Dmitry <deagle.gross@gmail.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Reuben Bond <reuben.bond@gmail.com>
Co-authored-by: Tao Chen <taochen@microsoft.com>
Co-authored-by: wuweng <wuweng@microsoft.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Co-authored-by: Giles Odigwe <79032838+giles17@users.noreply.github.com>
Co-authored-by: Daniel Cazzulino <daniel@cazzulino.com>
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
* Updated azure-ai-projects package version and small fixes (#2139)
* Python: [Feature Branch] Resolve CI issues (#2143)
* Small documentation and code fixes
* Small fix in documentation
* Addressed PR feedback
* Added AI Search example
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Co-authored-by: Reuben Bond <203839+ReubenBond@users.noreply.github.com>
Co-authored-by: Peter Ibekwe <109177538+peibekwe@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
Co-authored-by: Shawn Henry <sphenry@gmail.com>
Co-authored-by: Javier Calvarro Nelson <jacalvar@microsoft.com>
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
Co-authored-by: Korolev Dmitry <deagle.gross@gmail.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Reuben Bond <reuben.bond@gmail.com>
Co-authored-by: Tao Chen <taochen@microsoft.com>
Co-authored-by: wuweng <wuweng@microsoft.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Co-authored-by: Giles Odigwe <79032838+giles17@users.noreply.github.com>
Co-authored-by: Daniel Cazzulino <daniel@cazzulino.com>
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
* move catalog samples to the HostedAgents folder
* move the catalog samples' projects to the HostedAgents folder
* move deep research sample out of the HostedAgents folder
* fix: WorkflowAsAgent Sample
* Also makes ChatForwardingExecutor public
* feat: Expand ChatForwardingExecutor handled types
Make ChatForwardingExecutor match the input types of ChatProtocolExecutor.
* fix: Update for the new AgentRunResponseUpdate merge logic
AIAgent always sends out List<ChatMessage> now.
* DevUI: Add OpenAI Responses API proxy support with enhanced UI features
This commit adds support for proxying requests to OpenAI's Responses API,
allowing DevUI to route conversations to OpenAI models when configured to enable testing.
Backend changes:
- Add OpenAI proxy executor with conversation routing logic
- Enhance event mapper to support OpenAI Responses API format
- Extend server endpoints to handle OpenAI proxy mode
- Update models with OpenAI-specific response types
- Remove emojis from logging and CLI output for cleaner text
Frontend changes:
- Add settings modal with OpenAI proxy configuration UI
- Enhance agent and workflow views with improved state management
- Add new UI components (separator, switch) for settings
- Update debug panel with better event filtering
- Improve message renderers for OpenAI content types
- Update types and API client for OpenAI integration
* update ui, settings modal and workflow input form, add register cleanup hooks.
* add workflow HIL support, user mode, other fixes
* feat(devui): add human-in-the-loop (HIL) support with dynamic response schemas
Implement HIL workflow support allowing workflows to pause for user input
with dynamically generated JSON schemas based on response handler type hints.
Key Features:
- Automatic response schema extraction from @response_handler decorators
- Dynamic form generation in UI based on Pydantic/dataclass response types
- Checkpoint-based conversation storage for HIL requests/responses
- Resume workflow execution after user provides HIL response
Backend Changes:
- Add extract_response_type_from_executor() to introspect response handlers
- Enrich RequestInfoEvent with response_schema via _enrich_request_info_event_with_response_schema()
- Map RequestInfoEvent to response.input.requested OpenAI event format
- Store HIL responses in conversation history and restore checkpoints
Frontend Changes:
- Add HILInputModal component with SchemaFormRenderer for dynamic forms
- Support Pydantic BaseModel and dataclass response types
- Render enum fields as dropdowns, strings as text/textarea, numbers, booleans, arrays, objects
- Display original request context alongside response form
Testing:
- Add tests for checkpoint storage (test_checkpoints.py)
- Add schema generation tests for all input types (test_schema_generation.py)
- Validate end-to-end HIL flow with spam workflow sample
This enables workflows to seamlessly pause execution and request structured user input
with type-safe, validated forms generated automatically from response type annotations.
* improve HIL support, improve workflow execution view
* ui updates
* ui updates
* improve HIL for workflows, add auth and view modes
* update workflow
* security improvements , ui fixes
* fix mypy error
* update loading spinner in ui
* DevUI: Serialize workflow input as string to maintain conformance with OpenAI Responses format
* Phase 1: Add /meta endpoint and fix workflow event naming for .NET DevUI compatibility
* additional fixes for .NET DevUI workflow visualization item ID tracking
**Problem:**
.NET DevUI was generating different item IDs for ExecutorInvokedEvent and
ExecutorCompletedEvent, causing only the first executor to highlight in the
workflow graph. Long executor names and error messages also broke UI layout.
**Changes:**
- Add ExecutorActionItemResource to match Python DevUI implementation
- Track item IDs per executor using dictionary in AgentRunResponseUpdateExtensions
- Reuse same item ID across invoked/completed/failed events for proper pairing
- Add truncateText() utility to workflow-utils.ts
- Truncate executor names to 35 chars in execution timeline
- Truncate error messages to 150 chars in workflow graph nodes
** Details:**
- ExecutorActionItemResource registered with JSON source generation context
- Dictionary cleaned up after executor completion/failure to prevent memory leaks
- Frontend item tracking by unique item.id supports multiple executor runs
- All changes follow existing codebase patterns and conventions
Tested with review-workflow showing correct executor highlighting and state
transitions for sequential and concurrent executors.
* format fixes, remove cors tests
* remove unecessary attributes
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
Co-authored-by: Reuben Bond <reuben.bond@gmail.com>
* DevUI: Add OpenAI Responses API proxy support with enhanced UI features
This commit adds support for proxying requests to OpenAI's Responses API,
allowing DevUI to route conversations to OpenAI models when configured to enable testing.
Backend changes:
- Add OpenAI proxy executor with conversation routing logic
- Enhance event mapper to support OpenAI Responses API format
- Extend server endpoints to handle OpenAI proxy mode
- Update models with OpenAI-specific response types
- Remove emojis from logging and CLI output for cleaner text
Frontend changes:
- Add settings modal with OpenAI proxy configuration UI
- Enhance agent and workflow views with improved state management
- Add new UI components (separator, switch) for settings
- Update debug panel with better event filtering
- Improve message renderers for OpenAI content types
- Update types and API client for OpenAI integration
* update ui, settings modal and workflow input form, add register cleanup hooks.
* add workflow HIL support, user mode, other fixes
* feat(devui): add human-in-the-loop (HIL) support with dynamic response schemas
Implement HIL workflow support allowing workflows to pause for user input
with dynamically generated JSON schemas based on response handler type hints.
Key Features:
- Automatic response schema extraction from @response_handler decorators
- Dynamic form generation in UI based on Pydantic/dataclass response types
- Checkpoint-based conversation storage for HIL requests/responses
- Resume workflow execution after user provides HIL response
Backend Changes:
- Add extract_response_type_from_executor() to introspect response handlers
- Enrich RequestInfoEvent with response_schema via _enrich_request_info_event_with_response_schema()
- Map RequestInfoEvent to response.input.requested OpenAI event format
- Store HIL responses in conversation history and restore checkpoints
Frontend Changes:
- Add HILInputModal component with SchemaFormRenderer for dynamic forms
- Support Pydantic BaseModel and dataclass response types
- Render enum fields as dropdowns, strings as text/textarea, numbers, booleans, arrays, objects
- Display original request context alongside response form
Testing:
- Add tests for checkpoint storage (test_checkpoints.py)
- Add schema generation tests for all input types (test_schema_generation.py)
- Validate end-to-end HIL flow with spam workflow sample
This enables workflows to seamlessly pause execution and request structured user input
with type-safe, validated forms generated automatically from response type annotations.
* improve HIL support, improve workflow execution view
* ui updates
* ui updates
* improve HIL for workflows, add auth and view modes
* update workflow
* security improvements , ui fixes
* fix mypy error
* update loading spinner in ui
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
* Don't add OpenAIResponses as part of Dev UI
You should be able to add and remove Dev UI without impacting your other production endpoints.
* Remove `AddDevUI()` and do not map OpenAI endpoints from `MapDevUI()`
* Fix comment wording
* Revise documentation
---------
Co-authored-by: Daniel Roth <daroth@microsoft.com>
* Add unit tests for create conversation executor
* Update indentation and comment typo.
* Added unit tests for declarative executor SetMultipleVariablesExecutor
* Updated comments and syntactic sugar
* Add ChatHistoryMemoryProvider with unit tests
* Set new project to not packable.
* Fix bugs
* Add serialization support.
* Update dotnet/src/Microsoft.Agents.AI.VectorDataMemory/ChatHistoryMemoryProvider.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Remove unnecessary line
* Convert ChatHistoryMemoryProvider to use Dynamic collections.
* Sealing options and scope classes.
* Add sample, add scope to logs and improve scope validation
* Move ChatHistoryMemoryProvider to MAAI project.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix the ordering of chained resolvers in JsonSerializerOptions
We want the resolvers from AIJsonUtilities to be used before the ones from the source generator, in case the source generator emits its own copy in that assembly for the M.E.AI types.
* Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/src/Microsoft.Agents.AI/AgentJsonUtilities.cs
* Update dotnet/src/Microsoft.Agents.AI.Mem0/Mem0JsonUtilities.cs
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* Remove unused using directive in Mem0JsonUtilities
Removed unused using directive for Microsoft.Extensions.AI.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* fix: Workflow Validation
* adds orphan validation to workflow builder
* adds tests for workflow validation
* expands on the underlying reasoning why type validation is not supported
* fixup: CodeGen template
* [BREAKING] refactor: Normalize WorkflowBuilder APIs
* "partitioner" => "assigner"
* normalize ordering so sources always to the left of targets for edges
* normalize parameter ordering so sources and targets are always first arguments
* remove `params` (users should use collection expressions instead)
* refactor: Align name with Python
In #1551 we added a mechanism to open a Streaming workflow run without providing any input. This caused unintuitive behaviour when passing a string as input without providing a runId, resulting in the input being misinterpreted as the runId and the workflow not executing.
As well, the name caused confusion about why the Workflow was not running when using the input-less StreamAsync (since the Workflow cannot run without any messages to drive its execution).
* Removed automatic agent cleanup in AzureAIAgentClient
* Revert "Removed automatic agent cleanup in AzureAIAgentClient"
This reverts commit 89846c7212.
* Exposed boolean flag to control deletion behavior
* Update sample
* Initial plan
* Infrastructure setup
* Plan for minimal client
* Plan update
* Basic agentic chat
* cleanup
* Cleanups
* More cleanups
* Cleanups
* More cleanups
* Test plan
* Sample
* Fix streaming and error handling
* Fix notifications
* Cleanups
* cleanup sample
* Additional tests
* Additional tests
* Run dotnet format
* Remove unnecessary files
* Mark packages as non packable
* Fix build
* Address feedback
* Fix build
* Fix remaining warnings
* Feedback
* Feedback and cleanup
* Cleanup
* Cleanups
* Cleanups
* Cleanups
* Retrieve existing messages from the store to send them along the way and update the sample client
* Run dotnet format
* Add ADR for AG-UI
* Switch to use the SG and use a convention for run ids
* Cleanup MapAGUI API
* Fix formatting
* Fix solution
* Fix solution
* feat: Add ChatKit integration with a new frontend application
- Created a new frontend application using React and Vite for the ChatKit integration.
- Added essential files including package.json, vite.config.ts, and Tailwind CSS configuration.
- Implemented core components: App, Home, ChatKitPanel, ThemeToggle, and hooks for color scheme management.
- Established SQLite-based store implementation for ChatKit data persistence in store.py.
- Integrated theme toggling functionality for light and dark modes.
- Set up ESLint and TypeScript configurations for better development experience.
* git ignore
* fix mypy
* add mising file
* minimal frontend for chatkit sample
* update ignore files
* version
* set python version lowerbound on chatkit
* update project settings for chatkit
* update setup
* update setup
* update setup
* update setup
* weather widget
* add select city widget sample
* remove widget helper
* update chatkit to include file attachments and cover more thread item types
* update readme with mermaid diagram
* update diagram
* update instructions
* update chatkit dependency
* fix converter imports
* move to demos/
* move to demos/ -- rename references
* support multiple session instead of using global variable in sample
* support chunk streaming
* fix tests
* Update python/samples/demos/chatkit-integration/store.py
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
* use local host
---------
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
* Adding Sample for writer-critic workflow implemented using Worfklow, custom executors, agents, switch, custom states, different entry points for the executors.
* Update dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* using now structured output, with streaming for UX responsiveness.
* improved comments and order, so comments directly precede what they're describing
* fixing issue with internal class that the analyzer doesn't recognize that CriticDecision is instantiated, just indirectly via JSON deserialization
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* Port store for adding text to a vector store to AF
* Fix typo.
* Change TextSearchStore to sample, and add sample to use it and do rag with a custom schema
* Add more tests and fix broken ones
* Fix merge issue
* Fix sample after merge.
* Convert TextSearchStore to use Dynamic mode to be AOT compatible.
* Add some more clarification on when to use assistant messages in rag searches.
* Adding sample demonstrating hosted MCP with Responses
* Add mcp readme.md to slnx
* Update FoundryAgent sample to use MCP types from abstraction and to show how to do approval
* Fix param name after package update.
* Fix environment variable name for consistency
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add workflow as an agent with observability sample
* Address comment
* Fix formatting
* enable sensitive data
* enable sensitive data for sub agents
* adjust aggregator handlers
* initial version of anthropic connector
* updated implementation and added tests
* fix type and readme
* mypy fix and int tests enabled
* add integration test setup
* updated based on comments
* improved function result handling
* added extra unordered test
* updated from review
* fix tool choice handling
* same fix for chat client
* refactor: Unify ExecutorIsh and ExecutorRegistration => ExecutorBinding
* Switch to more modern Record type-tree for Sum Types
* Unify APIs for getting ExecutorBinding
* Fix an issue where workflows consisting entirely of cross-run shareable executors which are not instance-resettable do not properly clear state when running non-concurrently.
* feat: Simplify function-to-executor pattern
* refactor: Normalize API naming
* Propagate cancellation token down the stack
* Added unit tests to cover workflow cancellation scenarios
* Updated tests based on feedback to simplify assert.
* Create custom AsyncEnumrable to gracefully handle cancellation for Channel reader. Tailor cancellation tests to declarative scenarios.
* Update comment and naming for readability.
* Fixing minor stylistic recommendation.
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* ensure agent thread is part of checkpoint
* Update python/packages/core/agent_framework/_workflows/_agent_executor.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* remove data copying for server side thread.
* refine warning check
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix issue where AIContextProvider messages were not added to MessageStores
* Fix typos
* Update XML docs to reduce ambiguity.
* Update AIContext XML docs
* Fix merge issue
* Prototype: Add request_info API and @response_handler
* Add original_request as a parameter to the response handler
* Prototype: request interception in sub workflows
* Prototype: request interception in sub workflows 2
* WIP: Make checkpointing work
* checkpointing with sub workflow
* Fix function executor
* Allow sub-workflow to output directly
* Remove ReqeustInfoExecutor and related classes; Debugging checkpoint_with_human_in_the_loop
* Fix Handoff and sample
* fix pending requests in checkpoint
* Fix unit tests
* Fix formatting
* Resolve comments
* Address comment
* Add checkpoint tests
* Add tests
* misc
* fix mypy
* fix mypy
* Use request type as part of the key
* Log warning if there is not response handler for a request
* Update Internal edge group comments
* REcord message type in executor processing span
* Update sample
* Improve tests
* Add Rag AIContext Provider
* Fix issues
* Improve options naming based on PR feedback.
* Move Rag Provider to Data namespace
* Add Raw Representation to RagSearchResult
* Renaming RagProvider to TextSearchProvider
* Porting Mem0Provider to AF from SK
* Switch integration tests to manual
* Address issues
* Move Mem0Provider to separate project.
* Move integration tests to new project
* Address PR comments.
* Intro group chat and refactor magentic. Fix as_agent()
* Cleanup and improvements
* Add as_agent docstring clarification
* Standardize orchestration messages to use agent-style inputs.
* Simplify group chat constructs
* Further cleanup
* Add sk to af group chat migration sample. Update README.
* Improvements and simplifications
* consolidating shared orchestration logic
* Further clean up
* Add group chat sample
* Improve typing
* Fix test imports
* Fix readme links
* Cleanup per PR Feedback
Concurrent run support was recently added to workflows, but Orchestrations did not fully update to support it. A few executors were missing Cross-Run Shareable annotations, and the ConcurrentEnd executor needed to be factory-instantiated.
This also ports the fix for #1613 from #1637, to avoid waiting on that PR.
Checkpointing is used by the WorkflowHostAgent to be able to support resume from a provided thread. When a CheckpointManager is not specified, we use the InMemoryCheckpointManager and serialize its state into the thread's Serialize()ed JsonElement.
At some point InMemoryCheckpointManager became not serializable, breaking this behaviour. This change restores serializability, and adds a test.
* Improve conformance of OpenAI Responses API serving
* Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentRunResponseExtensions.cs
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentRunResponseExtensions.cs
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Sort packages
* Relax adherence where acceptable
* nit
* PromptCacheKey is not obsolete
* format
---------
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Add Handoff orchestration pattern support
* PR feedback
* Use AOAI client in samples
* Adjust to tool
* Handoff to sub-agent via ai function
* PR feedback
* More cleanup
* Improvements
* PR feedback cleanup
* Add handoff migration sample.
* Remove type ignore
* fix markdown link formatting
* Remove readme link for non-existent sample
* use extension methods from A2A package for converting between MEAI and A2A model classes.
* Update dotnet/tests/Microsoft.Agents.AI.A2A.UnitTests/A2AAgentTests.cs
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* remove unused using
---------
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Fix handoff function naming
We don't need the agent's name or a guid in the handoff name... we can just use simple numbering. There's a possibility that someone built an agent with a built-in function tool named "handoff_to_x"; if that turns out to be an issue, we could add back some longer bit of randomness.
* Update dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/HandoffAgentExecutor.cs
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Remove input type checking in favour of explicit `.DescribeProtocolAsync()` flow. Also removes `.AsAgentAsync()` as the validation happens at workflow run time. This makes it easier to use Workflows with DI without resorting to async-over-sync.
* Add support for getting and creating Assistant and Foundry agents with ChatClientAgentOptions
* Fix options cloning and agent creation
* Fix inconsistency
* Add support for mapping more tools and integration tests for ensuring CreateAIAgent works with those tools.
* Add support for additional openai tools with tests.
* Remove special casing for function tools, since it's either not supported yet, or requires a lot of code duplication.
* Removed unused using.
* Fix broken unit tests
* Change integration test to reduce flakiness.
* Add copilot instructions for c#
* Add some further improvements based on copilot suggestions.
* Update .github/copilot-instructions.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update C# sample code guidelines
Added a comment guideline for sample code in C#.
* Fix casing of Program.cs in instructions
* Update guidelines for coding standards and testing
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* unit test for using create agent option by constructor
* remove this for prevent duplicate when ChatClientAgentOption and ChatOption has same Instruction
* update unit test for ChatClientAgentOptions
* ensure function aproval is parsed correctly
* udpate ui, add deployment guide button, other debug panel fixes
* feat(devui): Implement lazy loading architecture with enhanced security and state management
Major architectural improvements to DevUI for better performance, security, and developer experience:
Performance & Architecture:
- Implement lazy loading for entity discovery - entities loaded on-demand instead of at startup
- Add hot reload capability for development workflow via new reload endpoint
- Reduce startup time and memory footprint by deferring module imports
Security Enhancements:
- Remove remote entity loading capabilities (POST /v1/entities/add, DELETE endpoints)
- DevUI now strictly local development tool - no remote code execution
- Add explicit security documentation and best practices in README
Frontend Improvements:
- Migrate to Zustand for centralized state management (replacing prop drilling)
- Add lightweight zero-dependency markdown renderer with code block copy support
- Improve gallery UX with setup instructions modal instead of direct URL loading
- Enhanced message UI with copy functionality and better token usage display
Testing & Quality:
- Expand test coverage for lazy loading, type detection, and cache invalidation
- Add comprehensive tests for new behaviors (+231 lines of test code)
- Improve type safety and documentation throughout
Breaking Changes:
- Remote entity loading via URLs is no longer supported
- Entities must be loaded from local filesystem only
* update ui issues, uupdate test descripion
* refactor: remove unused internals
* feat: Execution Mode for sharing a workflow among concurrent runs
* feat: Update WorkflowHostAgent to support concurrent execution
* Also update AsAgent APIs to support injecting a CheckpointManager and an IWorkflowExecutionEnvironment
* fix: Make Read logic consistent in DeclarativeWorkflowContext
WorkflowHostAgent was initially implemented before Checkpointing was available. This meant that in order to support resuming, the WorkflowHostAgent needed to keep the runs around, which broke it when stricter rules about concurrent sharing of workflows during execution were introduced.
This change updates the hosting logic to release the underlying StreamingRun when the RunStreamingAsync or RunAsync are invoked, in favour of keeping the checkpointing information in the WorkflowThread to enable resumption.
* Python: Fix AI Search Tool Sample and improve AI Search Exceptions
* Python: Fix AI Search Tool Test
---------
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
* Python: set role=tool when processing approval responses
* Python: set role=tool when processing approval responses
* Fix approval mode with OpenAIChatClient and threads: add approval requests to assistant message, fix deduplication/rejection call_id, filter approval content, add tests and example
* update test tools after change
* Rename _collect_approval_todos to _collect_approval_responses and filter empty call_ids
* sanitize agent name
* simplify
* Update dotnet/src/Microsoft.Agents.AI/AgentExtensions.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/src/Microsoft.Agents.AI/AgentExtensions.cs
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Update dotnet/src/Microsoft.Agents.AI/AgentExtensions.cs
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Update dotnet/tests/Microsoft.Agents.AI.UnitTests/AgentExtensionsTests.cs
Co-authored-by: Stephen Toub <stoub@microsoft.com>
* change regex to flag underscores as well so their sequence can be replaced with a single one.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
- Added ChatMessage[] handler to ConfigureRoutes to support array dispatch
- Workflow runtime can dispatch messages as either List<ChatMessage> or ChatMessage[]
- Added 10 comprehensive unit tests validating message routing behavior
- Tests ensure functionality and protect against future refactoring (issue #782)
- Updated code comments to reflect exact-type-matching requirement
Fixes issue where raw WorkflowBuilder with AIAgent nodes failed to receive
initial messages due to missing array type handler.
* add workflow edge data properties to the workflow.definition tag.
* use workflow info classes for workflow.definition tag value
* add unit test
* fix test
* fix formatting issue
* remove flaky unit test
* remove unused package dependency
* Python: DevUI - Internal Refactor, Conversations API support, and performance improvements
Comprehensive refactor of DevUI package including samples relocation,
frontend reorganization, OpenAI Conversations API support, and critical
performance and code quality improvements.
Key Changes:
Architecture & Organization
- Moved DevUI samples to python/samples/getting_started/devui/
- Consolidated with other framework samples for better discoverability
- Added .env.example files and comprehensive README
- Restructured frontend components into feature-based folders (agent, workflow, gallery, layout)
- Created new OpenAI-compliant message renderers (devui should render oai responses types primarily)
New Features
- Added _conversations.py (467 lines) - Full conversation storage abstraction, replaces the /threads endpoint to better match oai conversations api
- Implements OpenAI Conversations API for thread management, Supports in-memory and extensible storage backends
API Simplification
- Use 'model' field as entity_id (agent/workflow name) instead of extra_body
- Use standard OpenAI 'conversation' field for conversation context.
Performance & Quality Improvements
- Improved context management in MessageMapper with bounded memory (~500KB max)
- Implemented hybrid LRU + cleanup approach to prevent unbounded memory growth
- General QOL improvement - Eliminated ~150 lines of dead/duplicate code, Consolidated helper functions into _utils.py, Extracted magic numbers to module-level constants, Optimized conversation item lookups with index-based approach
Testing
- Added test_conversations.py (13 tests)
- Added test_performance_fixes.py (9 tests)
- Updated existing tests for code consolidation
- 53 tests passing
Impact: 76 files changed: +4,106 insertions, -2,373 deletions
All linting and formatting checks passing. No breaking changes - backward compatible.
Migration: Samples moved to python/samples/getting_started/devui/
* readme lint fixes
* initial support for function approval and minor ui fixes
* Update readme.md sample to show sample parameter values and make azure sdk pre-release
* Add clarifying comment about params.
* Switch sample to use the OpenAI SDK
* Add mapping for application media type in OpenAI responses client
* Enhance multimodal input samples: Add PDF testing functionality and fix image sample
* Standardize filename handling and add multimodal samples
- Standardized filename extraction logic between chat and responses clients
- Both clients now omit filename when not provided (no default fallback)
- Added Azure Responses API multimodal sample with PDF support
- Cleaned up Azure Chat sample to focus on supported features only
- Fixed test comment placement for better code documentation
- Updated README with clear API capability differences
* Enhance multimodal input samples with image and PDF handling
- Refactor image and PDF handling in `azure_chat_multimodal.py` and `openai_chat_multimodal.py` to use new utility functions.
- Add `load_sample_pdf` and `create_sample_image` functions for better test asset management.
- Remove redundant code for creating sample images and PDFs.
- Introduce a sample PDF file in `sample_assets` for testing purposes.
* Fix formatting in OpenAI chat client
---------
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
* refactor AgentExecutor, add output_response flag for switching on or off workflow output for each agent.
* introduce add_agent
* make default agent's streaming to false
* address comments
* fix test
* add is_streaming to RunnerContext and WorkflowContext
* fix add_agent return
* fix tests
* address comments
* resolve conflict
* update to address comments
* fix
* improve structured output for chat client agent
* add comment to the result property
* remove code duplication and add tests
* refactor the CreateAIAgent extension methods to return specific types, so consumers can avoid unnecessary downcasting.
* fix type and remove unused using.
* add ChatClientAgentRunResponse and move AgentRunResponse to the abstractions package to reuse later.
* seal ChatClientAgentRunResponse
* update xml comment
* remove funcitons from sample
* rename agent for streaming
* Fix bug where ChatClientAgent throws when providing a ChatMessageStore with a service that requries service storage
* Update dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* added a sample on integration of Azure OpenAI Responses Client with hosted Model Context Protocol (MCP)
* added additional comments mentioning that the Microsoft Learn MCP server can be replaced by any other desired MCP server
* corrected the MCP server type to local
* added a newline at the end
* Update python/samples/getting_started/agents/azure_openai/azure_responses_client_with_local_mcp.py
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
---------
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
* Updates to async run loop.
* fix: Workflow Onwership can be release by nonowner
* fix: Incorrect handling of blockOnPending in StreamingRun
Depending on whether we are running in streaming on non-streaming mode, we may be using the StreamingRun in different ways. Unfortunately, the only place we can really know what is the actual state of execution is in the RunEventStream implementations.
This resulted in blocking where blocking was unneeded and occasionally not-blocking when blocking was needed.
The fix is to move the logic of handling this blocking into RunEventStream implementations.
* fix: Fix cleanup on error and end run
This ensures we clean up the background resources correctly.
* fix: Ensure we let the run loop proceed when shutting down
* fix: Add timeout for Input Waiting
* fix: Make the samples properly clean up `Run`s and `StreamingRun`s
* fix: Simplify Declarative Workflow Run disposal pattern
* Also fixes missing .Disposal() in Integration tests
---------
Co-authored-by: Ben Thomas <ben.thomas@microsoft.com>
Capitalize instruction and relax assertion to accept any non-empty response instead of requiring exact text match. Fixes flaky test failures with reasoning models.
* Add dev containers
* Add workspace folder and cs dev extension
* Try other workspace folder format
* Add default solution.
* Move default solution to settings.json
* Fix repo open
* Remove duplicate python codespace and rename folder
* Add recommended C# extensions and a default build task
* Add vscode icons extension by default
* Add python setup and customizations, plus ai studio for all
* Add bash command
* Try running devsetup from workspace folder
* Remove echo and cd
* Change workspace mount
* Change dotnet workspace name
* Revert workspacemount addition
* Try workspace mount to root
* remove trailing slash
* Try workspacefolder with var
* Revert to original approach
* Modify dev containers to work in main repo.
* Remove trailing comma
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Add optional name and description fields to workflows in both Python and .NET implementations, matching the existing agent API pattern.
Python changes:
- Add name/description parameters to WorkflowBuilder.__init__
- Add name/description attributes to Workflow class
- Include name/description in to_dict() serialization
- Add WORKFLOW_NAME and WORKFLOW_DESCRIPTION OTEL attributes
- Add tests in test_serialization.py and test_workflow_observability.py
.NET changes:
- Add Name and Description properties to Workflow and Workflow<T>
- Add WithName() and WithDescription() fluent methods to WorkflowBuilder
- Add WorkflowName and WorkflowDescription OTEL tags
- Add test in WorkflowBuilderSmokeTests.cs
This enables applications like DevUI to display human-readable workflow names (e.g., 'Data Processing Pipeline') instead of auto-generated UUIDs (e.g., 'Workflow 50fdd917').
Fixes: #1181
* support for local function approval
* small fix
* fix mypy
* added bigger test scenario's for function calling and approvals
* updated lock
* updated return message for rejection
* fix test
* updated function result content handling
Should be `Agent2Agent Protocol` not `Agent-to-Agent` unless talking about general agent to agent communication
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* feat: Add support for Workflow-as-Executor
* Fixes routing of 'object' compile-typed variables to properly take in type information
* Fixes a concurrency issue in StepTracer
* fix: Make Subworkflow ExternalRequests work properly
* fix: Threading and Concurrency fixes; prep for OffThread Mode
* refactor: Remove dead code around OffStreamRunEventStream
Currently not used, and will be replaced with a rewrite when brought back, so having it in the change is not valuable.
* ci: Work around issues with dotnet-format not properly analyzing the source
* fix: Fix the logic of AsyncCoordinator and AsyncBarrier
* Prevent individual wait cancellations from canceling the entire barrier
* Propagate information about whether the wait was completed or cancelled, and whether any waiters were present when released
* fix: Remove superfluous acces to .Keys in InProcStepTracer
* refactor: Clean up AsyncCoordinator's use of AsyncBarrier
* Ignore null, timeout, status codes
* Only run when a markdown file is changed and run nightly
* Add markdown change
* Add run on link checker change and arbitrary change
* updated docstrings of all _files
* fix mypy
* fixed codeblocks in workflows and some other files
---------
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* Move the AsAIAgent extension methods to the correct class
* Fix format issue
* Disable unit test, see issue #1109
---------
Co-authored-by: Mark Wallace <markwallace@microsoft.com>
* Re-enable ImplicitUsings in samples and clean up NoWarns
* Fix dotnet format
* More dotnet format
* More dotnet format
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
We shouldn't be shipping any more dependencies on this package, as it's becoming legacy, replaced by System.Linq.AsyncEnumerable.
We'll eventually want to replace it with System.Linq.AsyncEnumerable in all tests/samples, too, but that's hard to do until SK updates to use S.L.AsyncEnumerable once its 10.0.0 version is released. I did remove the package reference from tests/samples where it's not needed.
* Use copilot to improve XML docs for M.Agents.AI{.Abstractions}
Asked copilot to help improve some of the docs, then I reviewed them.
I also cleaned up a few things along the way, like a couple of extension method types that should be combined.
* Update dotnet/src/Microsoft.Agents.AI.Abstractions/InMemoryChatMessageStore.cs
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
* Update README with links to video content. Include initial code samples as a quickstart.
* Include import
* Fix .net code
* Simplify sample
* Fix python spacing
* updates
* Remove .DS_Store file.
* Update M.A.AI.OpenAI implementations
- There was only a ChatClient-based agent. Add a Responses one, too.
- Fix the public extension methods to create OpenAI types even when not backed by the right OpenAI client.
- Add reusable AgentRunResponse{Update} to ChatResponse{Update} conversion routines that are then used by the OpenAI agents and elsewhere
* Address feedback
* Adding more test for workflow vizualization.
* Improving README for sample.
* More cleanup.
* Removing rendering of workflow visualization and adding basic support for mermaid format.
* Adding basic mermaid tests.
* Improving sample. Switching to another branch.
* About to merge from main.
* Formatting.
* More fromatting.
* Removng uneeded call to ToUpper.
* Adding README.
* Moving samples under workflow to workflows.
* Removing uneeded README for map-reduce sample.
* Addressing a SK bug where threads can't be reused + threads should be capture after the request, not created before
* Using storedenabled to align with AF default behavior
* Address copilot comment
* Address Azure + OpenAI remaining sample improvements
* Update OpenTelemetryAgent to latest spec
It was stale. Rather than try to keep it up-to-date manually, I've changed it to piggy back on OpenTelemetryChatClient, so that it inherits everything OpenTelemetryChatClient does and then augments it just with agent-specific tags.
* Address feedback / merge
This document provides comprehensive transparency information about Microsoft Agent Framework, including intended uses, limitations, evaluation methods, and responsible development practices.
* Make serialize methods sync and rename one to match others.
* Remove unnecessary async postfixes.
* Remove nullability of ChatMessageStore.Serialize return type, since the default JsonElement already represents an undefined json element.
* Fix unit test
* consolidate lab packages into a single one; update contribution guidelines
* update dep list
* add poe tasks; fix tests and lint erros
* add lab tests for CI
* fix test
* update root pyproject.toml
* Disallow execution of multiple workflows at once
* Define notion of executor Reset() to allow reuse of workflows with shared executor instances
* Switch to delivering all messages to a single executor sequentially, with executors running in parallel
* Added example with stateful middleware
* Added chat middleware
* Updated middleware example with override scenario
* Small revert
* Small fixes
* Added kwargs to context objects
* Added README
* Added function middleware to chat client
* Small refactoring
* Reverted example files
* Made MiddlewareWrapper generic
* Added Middleware exception
* Small refactoring
* Small fix
* Magentic checkpoint wip
* Magentic checkpoint updates
* Support checkpointing for magentic orchestration.
* Checkpointing for sub-workflows
* Use _execute_contexts instead of _pending_requests
* Remove unnecessary type ignores
* Support checkpoints for other orchestrations, refactor some code.
* Regenerate uv.lock
* Rename AI Agent packages to use Microsoft.Agents.AI
* Fix for build
* Fix formatting
* Fix formatting
* Ignore in VSTHRD200 in migration samples
* Ignore in VSTHRD200 in migration samples
* Add some missing projects and run format
* Fix build errors
* Address code review feedback
* Fix merge issues
---------
Co-authored-by: Mark Wallace <markwallace@microsoft.com>
* Further observability cleanup and update telemetry samples
* Add VS Code Extension config
* Fix unit tests
* Fix unit tests
* Add more comments
* Remove live metric
* removed intercepts_request and simplified how interception is handled
* parameterize SubWorkflowRequestInfo
* revert back the field rename of RequestResponse
* remove duplicate tests
* ignore type error
* remove SubWorkflowResponse
* Remove SubWorkflowRequestInfo and update RequestInfoMessage with source_executor_id for correlation
* feat: Make Executor id field mandatory
When checkpointing is involved, it is critical to keep executor ids consistent between runs, even when recreating a new object tree for the workflow.
The default id-setting mechanism generated a guid for part of the id, making it not work when restoring from a checkpoint.
This change prevents this situation from arising.
* feat: Enable running untyped Workflows
With the change to enable delay-instantiation of executors and support for async Executor factory methods, we must instantiate the starting executor to know what are the valid input types for the workflow.
To avoid forcing instantiation every time, and to better support workflows with multiple input types, we enable support for build and interacting with the base Workflow type without type annotations, and remove the requirement to know a valid input type when initiating a run.
* feat: Support Output from any executor and multiple outputs.
* Add AgentWorkflowBuilder group chat
And fix a variety of issues along the way:
- Use DateTime{Offset}.UtcNow rather than Now
- AIAgentHostExecutor shouldn't be publishing empty messages
- Sequential workflows should be flowing all history and not just the output from the previous agent as the input into the next agent
- Renamed some of the new agent workflow methods... still not super happy with the shape, though
- Simplified handoffs builder, e.g. using a hashset with a custom comparer instead of a dictionary
- Improved multi-service use by trying to change assistant->user role for messages created by other agents
- Changed MessageMerger to rely on M.E.AI's coalescing more and to avoid empty contents / text
- Ensured that messages from ChatClientAgent include MessageId and CreatedAt timestamps
- Avoided including instructions for agents in a handoff workflow that don't have any handoffs
- Removed the unnecessary end function in handoffs
- Improved naming of executors to include agent name for debuggability
- Use "N" formatting with Guid.ToString everywhere, to avoid the unnecessary extra dash character which is also not valid in various places (like function tool names)
- Replace `params T[]` with `params IEnumerable<T>` to make public APIs more flexible in what they consume
* Address feedback
- Fix unintentional provider change in sample
* Add GetService for AIContextProviders and ChatMessageStore
* Change styling and fix format issues
* Update sample code to allow for missing memory component.
* Improve type utils
* Add sample
* Add Union
* Add more test cases
* Add more test cases
* Fix RequestResponse typing to only coerce mapping original_request
---------
Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
* Subclass AgentThread so that different agents have their own threads with their own typed settings.
* Address PR comment.
* Add unit tests for base abstract threads
* Fix style warning
* Fix stlying
* FIx and suppress warnings as needed.
* Remove covariant thread response types and fix some styling.
* Remove unecessary json property name attributes and make OrchestratingAgentThread private
* Fix break from merge from main.
* Fix formatting
* Fix deserialization bug in Memory sample
* Remove thread deletion from basic samples.
* Remove public constructors for thread subclasses and add more factory methods to concrete agent types.
* Update AgentProxy thread constructors to be internal as well.
* Revert AgentProxyThread to internal
* Change AIContextProvider to internal set
* Change conversation id and message store properties to internal set
* Update styling.
* Seal various thread types.
* Add thread type check for thread deletion
* Fix tests after latest merge from main
* Add thread type checks for thread deletion.
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* update to packaging section
* added options
* clarification and typo
* updated python packaging guidance, moved discussion to appendix
* moved discussion into ADR
* updated folder strcutre
* Setting up
* Readme
* Add redis tests path to all-tests
* First pass integration
* Keep provider convention
* First pass integration
* add redis integration tests
* update README.md
* Add basic sample for redis integration
* Add partitioning, add partition-aware tests, improve sample script
* Fix code quality check
* Try to resolve pytest check
* Try to identify if pytest is the cause of failed checks
* Re-enable tests
* Rename redis test file
* Removing some tests to narrow down issue
* Revert, no difference
* Delete temp files
* Starting refactor of RedisProvider
* Build dynamic schema builder, still need to do dynamic embedding model config
* Add scope control
* Complete first pass functionality with OpenAI + HF vectors -> Tests, Samples, Demo to follow
* Fix code quality
* attempt to identify rootcause of failed test
* attempt to identify rootcause of failed test
* Attempt to resolve code quality fail
* Update pyproject.toml for foundry to pin azure-ai-projects == 1.1.0b3,azure-ai-agents == 1.2.0b3
* Add tests for redisprovider
* Remove invalid tests
* Add API key handling for openai vectorizer
* Update uv.locl
* Use master uv.lock
* Begin sample file, add lazy index creation, fix faulty override
* Index drop and reinit depends on drop_redis_index not overwrite
* Add samples, threading included, escaped queries, verify threading works, sample README.md
* Refactor filters
* Opinionated vars
* Allow filter expression combination
* Try inline stubs for mypy
* Address mypy errors
* Better docstrings, tweaks for feedback
* Tweak example 3 in redis_threads.py sample
* adjust confusing name
* Enrich docstrings
* Add descriptions and comments to samples, externalize vectorizer choice, remove nltk and sentencetransformers dependnecy
* Add descriptions and comments to samples, externalize vectorizer choice, remove nltk and sentencetransformers dependnecy
* Incorporate initial feedback from dmytrostruk
* Fix uv.lock
* Attempt to resolve conflict
* Use remote .tomls
* Sanity check
* fix tests
* Remove hardcoded API key from samples
* Fix incorrect env var
* Make add and redis_search private
* Fix tests relying on private funcs
* Expand tests
* Explainer comments to each test
* Add a 'get_conversation_history' function to RedisProvider - This just returns messages in sequential order. Added 'created_at_*' timestamps to facilitate sequential recovery. function has to be manually invoked by user
* Add agent-framework-redis to python/pyproject.toml
* Remove get_conversation_history
* improve redis context provider with pydantic techniques and safe index handling patterns
* add RedisChatMessageStore
* remove integration test :(
* fix mypy error
* Remove unused params
* Redo schema validation to be order-invariant, handle attrs (previously throwing errors due to strict ==)
* Expand explanation
* Add ChatMessageStore example
* Fix comments in redis_conversation.py
* Resolving uv.lock conflict, update to match main
* Fix test in redis provider
* Apply suggestion from @ekzhu
* Update python/packages/main/pyproject.toml
---------
Co-authored-by: Tyler Hutcherson <tyler.hutcherson@redis.com>
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* Fix options_dict handling in response client
* Update python/packages/main/agent_framework/openai/_responses_client.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update condition for storing chat options
Fixes issue where, when using server-side threads, AF would pass back the function call message due to store being in chat_options in kwargs, not at the kwargs level. Means the appending of only the tool execution result never happens.
Resulted in a "tool output not found error" as we replied with the call not the result first.
* Refactor chat_options access for clarity
* Refactor store option assignment in responses client
* Small fixes
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
* Initial middleware implementation
* Small fixes
* Small updates
* Small updates in samples
* Moved middleware functionality to decorator
* Removed obsolete file
* Renamed AgentInvocationContext to AzureRunContext
* Added unit tests
* Small settings update for test discovery in VS Code
* Added unit tests
* Reverted changes in environment settings
* Added context result override
* Renaming and updates to logic
* Added more samples
* Updated DEV_SETUP.md
* Addressed PR feedback
* Addressed PR feedback
* Removed unused parameter
* Small fix
* Small fix in telemetry logic
* Revert "Small fix in telemetry logic"
This reverts commit 6f82660d2d.
* Small fix
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* feat: Support Checkpoint Serialization
* Implements serialization roundtripping for checkpoints.
* Adds support for JSON serialization
* Adds FileSystem-based checkpoint persistence
* fix: Executor State does not deserialize correctly
The StateManager was not properly handling delay-deserialized values.
* Fix PortableValue handling in StateManager (this makes it delegate to PortableValue the uwnrapping)
* Fix UnitTest to actually test checkpoint serialization
* Additional review comment fixes
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* Adds Azure Monitor Entra ID authentication support
Enables token-based authentication for Application Insights by adding an optional credential parameter to telemetry setup functions.
* Fix linting errors
* Documentation: Add Entra ID authentication details to README for Application Insights
* Documentation: Add Entra ID authentication details to README for Application Insights
* Update python/packages/main/agent_framework/telemetry.py
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
* Update python/samples/getting_started/telemetry/README.md
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
* Update python/packages/main/agent_framework/telemetry.py
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
* Rename application_insights_credential to credential
---------
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
* Move workflow to main package
* Remove workflow specific unit test config
* Remove workflow-specific version info
* Revert unintended telemetry changes
* Removed the obsolete packages/workflow/tests target
* Rename dir workflow to _workflow
* Fix test imports
* Add AIContextProvider support
* Address feedback.
* Address PR comments.
* Switch to valuetask and remove parallel calls for AIContextProvider
* Remove Model from ModelInvokingAsync method name
* Remove agent thread id again and remove it from context provider interface
* Add AIContextProvider serialization support to AgentThread and update sample to show this feature
* Address PR comments
* Improve memory sample
* Update sample comment.
* Remove AggregateAIContextProvider for now since it makes too many assumptions. We can include it later as a sample if needed.
* Update AIContextProviders to have an Invoked method instead of MessagesAddingAsync.
* Remove unused using.
* Address PR comments.
* Address PR comment.
* Update comment.
* Update comment
* Address PR comments.
* Add support for the Sequential Builder. Add samples. Add tests
* AgentExecutor: always compute full convo during response
* Upgrade azure-ai-agents ToolOutput to FunctionToolOutput
* Explicit notes around allows types for custom agent executors
* Small fix in dotnet conformance tests
* Added CopilotStudioAgent implementation
* Added examples
* Updated package README
* Small fixes
* Small improvements
* Fixed dotnet tests
* Add unit tests
* Updated tests
* Small updates
* Small test fixes
* Revert "Small test fixes"
This reverts commit 983ac44a70.
* Small fixes in documentation
* Updated test configuration
* Revert "Updated test configuration"
This reverts commit 2a16fea815.
* Small fix
* Reverted TODO item
* Small suppressions
* More fixes
* Small fixes
* Fixed tests
* Removed disallow_any_unimported rule in all packages
* Fixes
* Change implementation to use AsFunctionTool extension method to create a function from an agent
* Update dotnet/tests/Microsoft.Extensions.AI.Agents.UnitTests/AgentExtensionsTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Address code review feedback and add a new sample
* Address some code review feedback
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update AIAgent,Run to take IEnumerable instead of IReadonlyCollection
* Address PR comment.
* Cast to IReadonlyCollection since this is typically all that is required to avoid unecessary allocation.
* Update OrchestratingAgent protected methods as well.
* feat: add OpenAI reasoning events support with comprehensive test coverage
- Implement reasoning event handling in OpenAI Responses client
* Add support for ResponseReasoningTextDeltaEvent
* Add support for ResponseReasoningTextDoneEvent
* Add support for ResponseReasoningSummaryTextDeltaEvent
* Add support for ResponseReasoningSummaryTextDoneEvent
* Map all reasoning events to TextReasoningContent objects
* Preserve metadata across reasoning events
- Add comprehensive test coverage (5 focused test functions)
* test_streaming_reasoning_text_delta_event
* test_streaming_reasoning_text_done_event
* test_streaming_reasoning_summary_text_delta_event
* test_streaming_reasoning_summary_text_done_event
* test_streaming_reasoning_events_preserve_metadata
- Add sample demonstrating reasoning functionality
* Shows how to enable reasoning in chat options
* Demonstrates accessing reasoning content from responses
- Code quality improvements
* Follow existing code patterns and style guidelines
* Organize imports properly
* Maintain backwards compatibility
* All tests pass and quality checks succeed
* fix: resolve type errors and cleanup unused imports after rebase
- Add proper hasattr checks for optional attributes in union types
- Remove unused OpenAI event type imports
- Fix line length formatting issues
- Ensure type safety when accessing content attributes
* Added context provider abstractions
* Added mem0 implementation
* Example and small fixes
* Added unit tests for agent
* Added unit tests for mem0 provider
* Updated README
* Small doc updates
* Update python/packages/mem0/agent_framework_mem0/_provider.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Small fixes in tests
* Renaming based on PR feedback
* Small fixes
* Added tests for AggregateContextProvider
* Small improvements
* More improvements based on PR feedback
* Small constant update
* Added more examples
* Added README for Mem0 examples
* Small updates to API
* Updated initialization logic
* Updates for context manager
* Updated Context class
* Dependency update
* Revert changes
* Fixed tests
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* test with stack and simplified names
* quick demo of agent decorator
* moved builder to protocol to enhance functionality
* undid chatclientAgent -> agent rename
* one more
* reverted AIAgent rename
* final reverts
* fixed foundry import
* revert changes
* streamlined otel and fcc decorators
* cleanup of telemetry
* further refinement
* lots of updates
* fixed typing
* fix for mypy
* added input and output atttributes
* fix import
* initial work on baking in otel
* major update to telemetry
* final fixes after rename
* fix
* fix test
* updated tests
* fix for tests
* fixes for tests
* updated based on comments
* removed agent decorator
* fix for Python: ServiceResponseException when using multiple tools
Fixes#649
* addressed comments
* fix tests
* fix tests
* fix tools tests
* fix for conversation_id in assistants client
* fix responses test
* fix tests and mypy
* updated test
* foundry fix
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* initial work on User Approval (and hosted mcp to validate)
* small update to the comments in the sample
* enable local MCP tools in chatClient get methods
* working streaming and improved setup
* fix for pyright
* updated create_approval -> create_response method
* added tests
* updated HostedMcpTool and addressed feedback
* update type name
* naming updates
* small docstring update
* mypy fix
* fixes and updates
* fixes for responses
* fix int tests
* removed broken tests
* updated test running
* removed specific content check on websearch
* increased timeout
* split slow foundry test
* don't parallel run samples
* add dist load to unit tests
---------
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* fix: MessageMerger crashes when there are no dangling messages
* refactor: Better logic for AgentId in Workflow-as-Agent
If the parent "agent" instance received an Id or Name when being instantiated, we should avoid stomping over it with the subagents' ids. But if there is no parent identifier, and only a single subagent yielded identified messages, pull that in.
* Add getting started samples that show how to call MCP tools
* Add getting started samples that show how to call MCP tools
* Update dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix README
* Address code review feedback
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update getting started with workflows sample structure and README
* Small updates
* Adjust getting started samples. Fix agent executor bug. Add workflow tests to unit test file.
* Fix resource links
* Update README with clearer setup instructions and direct links to getting started guides
* Update README.md
Co-authored-by: Tao Chen <taochen@microsoft.com>
---------
Co-authored-by: Tao Chen <taochen@microsoft.com>
When checkpointing we did not persist the set of instantiated executors. This means, in turn, when we restore from a checkpoint when using Resume(Stream) rather than restoring a checkpoint in the context of an already existing (Streaming)Run, the executors never got reinstantiated and there were no executors to notify that a state should be loaded.
The fix is to ensure we persist the list and reinstantiate the executors on rehydration.
* Also adds a rehydration restore test
* feat: Improve DevEx for simple Executors
* Add abstract types for executors that will only handle one type of message
* Add FunctionExecutor and configuration capability on delegates
* Add support for late-instantiated Executors
* refactor: Remove open-typed extension method
* refactor: Switch to TaskFactory pattern for async--from-sync
* docs: Update XML docs for publics and fix formatting
* refactor: Better naming for ExecutorIsh configuration methods
* docs: Fix typo in ExecutorIshConfigurationExtensions.ConfigureFactory
* Add PrPr welcome message and important notes to README
Enhanced the README with a comprehensive welcome message for the private preview, highlighting the multi-language framework capabilities and key features. Added important notes about package availability and the need to sync forks regularly for this active project.
* Update README to use 'clone' instead of 'fork and clone'
* Update README.md
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
---------
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* Added documentation how to run examples
* Small fix
* Update user-documentation-python/getting-started/running_examples.md
Co-authored-by: Tao Chen <taochen@microsoft.com>
* Small fix
---------
Co-authored-by: Tao Chen <taochen@microsoft.com>
* Add FunctionExecutor and @executor decorator
* refactor
* add single argument function
* fix test
* update example code
* add support for sync funciton
* start a new implementation based on .net
* add response handling
* update init files
* remove handling of WorkflowCompletedEvent
* clean up implemenation
* fix bug
* update tests for merge_updates
* WorkflowAgent validation
* add a sample and fix bug
* revert pre-commit config
* revert pre-commit
* add human in the loop sample
* add comment
* fix type issue in Executor
* fix type errors and rename Executor.type to Executor.type_ with field alias
* fix test
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* Organize the .Net samples
* Organize the .Net samples
* Merge latest from main
* Update sample to also include function calling telemetry (#577)
* Move package installation instructions to user-guide (#572)
* Move package installation instructions to user-guide
* Update user-documentation-dotnet/getting-started/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update docs/docs-templates/getting-started/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* .NET: Add SK-AF Migration Samples for Responses API. (#575)
* Responses wip
* Adding OpenAI Responses Migration samples
* Address all samples and code for Azure and OpenAI Responses Migration code
* Update dotnet/samples/SemanticKernelMigration/OpenAIResponses/Step02_ReasoningModel/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Organize the .Net samples
* Organize the .Net samples
* Merge latest from main
* Use Agent rather than AIAgent
* Rename agents getting started samples
* Use singular Agent
---------
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: FanIn Edge does not work
We were not creating the state for FanIn edge in EdgeMap correctly, leading to crashes. After fixing that, it turns out the logic in FanInEdgeRunner was only forwarding the last message, not all of them.
* fix: Remove duplicate code and fix typo
The previous fix for the aggregation in AIAgentHostExecutor has a bug wherein we only include the first update from a ChatMessage in the outgoing "collected" message.
The fix is to ensure we put the collected updates into the message before sending it out.
* Add more console based getting started samples
* Simplify function calling and approavls samples and some minor renaming based on PR feedback.
* Cover streaming with comments for aprovals sample.
* Remove extra line break.
* Update getting started samples list in readme.
* Address PR comments
* Address PR comments.
* Add a script to produce docs by language, and add multi-turn-conversation docs.
* Fix typo.
* Remove java pivots, move source templates and update comments.
* Add links to docs from root readme
The current implementation of AIAgentHostExecutor unwraps every incoming AgentRunResponseUpdate into a separate ChatMessage, amplifying the number of ChatMessages are actually generated, and yielding multiple messages with the same MessageId.
The fix is to aggregate by MesageId, with the expectation that agents do not interleave messages with differing ids, thus every new MessageId indicates a new ChatMessage and never an old one.
* workflow tracing design doc
* add tracing implementation for workflow
* fix bug caused by double wrapping of sub workflow request
* add unit tests for tracing
* add documentation for workflow tracing
* remove unnecessary file
* update aspire command
* fix tests
* proper serialization of subworkflows and add workflow.definition
* add serialization test
* fix subworkflow serialization
* workflow_id --> id
* update workflow sample to address comments
* update naming; use costant
* use NoOpTracer instead of nullcontext
* use span event instead of attribtutes for status
* fix typing
* add workflow.build span
* rename methods for clarity
* ensure all source trace contexts are propagated in fan in
* feat: Make WorkflowBuilder more intutitve
Right now Executorish binding has some unintutitive behaviour. When a user adds an eecutor with an id of an executor that already exists, we silently replace it, if the user provides it inside of add_edge. When a user introduces an executor via an unbound id, the user must bind it via BindExecutor, even though the registration is created implicitly when an edge id added.
The change will remove the invisible update in favor of a "best efforts" check of type and instance equality.
* Expand errors when rebinding to disallowed
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat: Implement Checkpointing API
* refactor: Normalzie Namespaces and break out multi-class files
* feat: Support checkpointing in AIAgentHostExecutor
* test: Representation tests
* feat: Add Step-level Tracing and WorkflowEvents
* feat: Add Checkpointing Sample and Smoke Test
* Fixes an issue where StateManager was not properly clearing the incoming queued updates.
* Fixes order of checkpointing and in-step event publication
* Adds import of RunContext state on LoadCheckpoint
* Add re-firing of events for unserviced ExternalRequests on Checkpoint load
* docs: Add documentation to publics
* Also adds documentation to ICheckpointManager which may go public
* refactor: Fix Union Aggregators and add Tests
* fix: Fix issues raised in PR comments and remove dead code
* Adding draft version of workflows design doc.
* Adding message flow diagrams and fixing group chat sample.
* Added sequence diagram for fan_in with WhenAny
* Updating workflows design
* clean up
* Clean up request & response contents
* Add more future enhacements
* message_handler -> handler
* remove mention of visual designer
* Minor updates and rename
* Name reformat
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Co-authored-by: Tao Chen <taochen@microsoft.com>
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* Adding design documents and data flow descriptions for sub-workflows
* Updating docs.
* Sub-workflow implementation #1. Stuck because of singleton RequestInfoExecutor, going to make a change to remove that restrivtion.
* Removed the singleton restriction on RequestInfoExecutor so enable sub-workflows.
* Scenarios seem to be working.
* Sample improved.
* going to have intern add generic response wrappers.
* Wrapped responses working.
* Non-hardcoded routing is working.
* Sample showing external approved and not approved.
* Cleaning up.
* Updating some samples and user guide.
* Removing old design doc.
* Cleaning up.
* Adding python-package-setup.md back.
* Update python/packages/workflow/agent_framework_workflow/_executor.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update python/packages/workflow/agent_framework_workflow/_validation.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Removing prints.
* Fixing lint and type issues.
* Fixing lint and type issues.
* Update python/packages/workflow/agent_framework_workflow/_executor.py
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* Adding type hints to intercepts decorator.
* Removing unused files.
* Fixing issue with sample 5 groupchat with hil.
* Removing redundent samples.
* Updates to ensure no conflicting request interceptors and to support a subflow with multiple requests in a single super step.
* Fixing pypi errors.
* clean up samples
* update samples to make it more clear
* warning for unhandled request info from sub workflow
* add logger info
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* Allows creation of ExternalRequest objects directly to control the requestId
* Allows receiving ExternalResponse objects rather than unwrapped Data
* Normalizing naming
* Refactor workflow to introduce EdgeRunner for edge execution.
* Fix edge cases
* Convert Workflow, Edge, EdgeGroup, and Executor into AFBaseModel to support object model serialization
* format
* remove accidental file
* fix typing
* Add type information to EdgeGroup and Executor subclasses
* fix format
* Add condition_name field to Edge
* Add new fields
* remove Optional
* Update
* feat: Host Workflow as AIAgent
* Also changes AIAgent-as-Executor to use streaming runs and streaming
events
* Also enables default setting for yielding events
* fix: Infinite loop in GenerateNewId()
* docs: Spelling
* test: Add Workflow-as-Agent sample and test
* Use generic for WorkflowContext and use its type parameters to indicate executor's output types
* Update
* Fix type errors and add in-line comments
* fix test
* type
* Fix executor type issues
* feat: Support Executor-targeted messages
This adds support for only sending a message to a given executor. Messages will still only route through connected edges.
* feat: Support sending all valid input types after starting a run
* feat: Normalize AIAgent-as-Executor Message Protocol to use MEAI types
* Introducing edge groups
* Add conditional and partitioning edge groups; next add samples and tests
* Add unit tests
* Add samples
* Address comments 1
* Address comments 2
* Update conditional edge group to take in cases and default
* Minor updates to sample
* Collapsing Paritioning Edge group and Conditional Edge group to source edge group
* Improve sample clarity
* Name consolidation
---------
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* Updates for message store support
* Added unit tests
* Added suspend-resume example
* Added example with custom chat message store
* Small fix
* Addressed PR feedback
* Renaming and documentation
* More renaming
* Addressed more PR feedback
* Small fixes in Foundry chat client and examples
* Small update
* Addressed PR feedback
* Increased timeout for Azure tests
* feat: Define Workflow and Executor APIs
* feat: Define IExecutionContext and Events
* feat: Simple Workflow Demos
* refactor: Move Workflows classes to separate assembly
* feat: Move FanOut/In to LowLevel API with new semantics
* feat: Implement Local Execution
* refactor: Assembly name .Workflow => .Workflows
* feat: Enable Default Message Handling
* also lifts Bind in MessageHandlerInfo to better be able to direclty invoke handlers (for AOT, later)
* feat: Implement StreamingHandle APIs
This allows the user to respond to WorkflowEvents with external messages, enabling HIL.
* feat: Add checks for duplicate edges and chain cycles
* feat: Add built-in WorkflowEvents
* refactor: Pull classes into own files
* refactor: Simplify Disposal pattern in Executor
* refactor: Break EdgeRunner file into per-type files
* refactor: Use Throw.IfNull()
* refactor: Remove AddLoop()
Per https://github.com/microsoft/agent-framework/pull/272#discussion_r2241739079 we decided this was not very useful.
* refactor: Normalize use of ValueTask
* fix: Build Break from removing .AddLoop
* refactor: Explicit routing and RouteBuilder
Split out reflection from MessageRouter implemention into build phase, enabling AOT compilation to drive RouteBuilding without reflection.
* test: Add Reflection/Invocation tests
* fix: Terminate on Completion event
* refactor: Update public API surface
* feat: Add support for external requests
* feat: Support hosting AIAgent instances in Workflows
* fix: Fix routing to go through Executor.ExecuteAsync
* test: Update samples for "must SendMessage" semantics
* Add invoking samples to unit tests to avoid future breaks
* fix: ExternalRequest should block Workflow completion
* feat: Normalize API surface against Python
* Also adds xmldoc to all public APIs
* refactor: Normalize UnitTest and Sample namespaces
* fix: Formatting
* refactor: Normalize project/folder names
* feat: Remove DynamicCodeExecution from ValueTaskTypeErasure
* fix: Fix ILTrim warnings
* docs: Add missing docs and fix typos
* feat: Hosted Agents should report Run events
* fix: Fix type propagation for ILTrim changes
* refactor: Simplify DynamicallyAccessedMembers annotations
* sample: Use static-Type construction of InputPort
* feat: Support non-Streaming Run Mode
* test: Add test for non-streaming execution
* refactor: Remove unused types
* refactor: Simplify Event and EdgeData type hierarchies
* feat: Add Switch (=Conditional Edge Group) control flow
* feat: Make .NET AutoSend the MessageHandler result
* feat: Implement State APIs
* refactor: Simplify public namespaces and code organization
* refactor: Reconcile .NET and Python names
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* mcp parts
* mcp parts 2
* removed structured output in favor of handling in chatresponse, mcp as AITool and running samples
* updated naming
* fixed test
2025-08-13 09:48:22 +00:00
2870 changed files with 360124 additions and 48073 deletions
All python code resides under the `python/` directory.
All C# code resides under the `dotnet/` directory.
The purpose of the code is to provide a framework for building AI agents.
When contributing to this repository, please follow these guidelines:
## C# Code Guidelines
Here are some general guidelines that apply to all code.
- The top of all *.cs files should have a copyright notice: `// Copyright (c) Microsoft. All rights reserved.`
- All public methods and classes should have XML documentation comments.
### C# Sample Code Guidelines
Sample code is located in the `dotnet/samples` directory.
When adding a new sample, follow these steps:
- The sample should be a standalone .net project in one of the subdirectories of the samples directory.
- The directory name should be the same as the project name.
- The directory should contain a README.md file that explains what the sample does and how to run it.
- The README.md file should follow the same format as other samples.
- The csproj file should match the directory name.
- The csproj file should be configured in the same way as other samples.
- The project should preferably contain a single Program.cs file that contains all the sample code.
- The sample should be added to the solution file in the samples directory.
- The sample should be tested to ensure it works as expected.
- A reference to the new samples should be added to the README.md file in the parent directory of the new sample.
The sample code should follow these guidelines:
- Configuration settings should be read from environment variables, e.g. `var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");`.
- Environment variables should use upper snake_case naming convention.
- Secrets should not be hardcoded in the code or committed to the repository.
- The code should be well-documented with comments explaining the purpose of each step.
- The code should be simple and to the point, avoiding unnecessary complexity.
- Prefer inline literals over constants for values that are not reused. For example, use `new ChatClientAgent(chatClient, instructions: "You are a helpful assistant.")` instead of defining a constant for "instructions".
- Ensure that all private classes are sealed
- Use the Async suffix on the name of all async methods that return a Task or ValueTask.
- Prefer defining variables using types rather than var, to help users understand the types involved.
- Follow the patterns in the samples in the same directories where new samples are being added.
- The structure of the sample should be as follows:
- The top of the Program.cs should have a copyright notice: `// Copyright (c) Microsoft. All rights reserved.`
- Then add a comment describing what the sample is demonstrating.
- Then add the necessary using statements.
- Then add the main code logic.
- Finally, add any helper methods or classes at the bottom of the file.
### C# Unit Test Guidelines
Unit tests are located in the `dotnet/tests` directory in projects with a `.UnitTests.csproj` suffix.
Unit tests should follow these guidelines:
- Use `this.` for accessing class members
- Add Arrange, Act and Assert comments for each test
- Ensure that all private classes, that are not subclassed, are sealed
- Use the Async suffix on the name of all async methods
- Use the Moq library for mocking objects where possible
- Validate that each test actually tests the target behavior, e.g. we should not have tests that creates a mock, calls the mock and then verifies that the mock was called, without the target code being involved. We also shouldn't have tests that test language features, e.g. something that the compiler would catch anyway.
- Avoid adding excessive comments to tests. Instead favour clear easy to understand code.
- Follow the patterns in the unit tests in the same project or classes to which new tests are being added
Below are some ways that you can get involved in the Agent Framework Community.
## Engage on GitHub
- [Discussions](https://github.com/microsoft/agent-framework/discussions): Ask questions, provide feedback and ideas to what you'd like to see from the Agent Framework.
- [Issues](https://github.com/microsoft/agent-framework/issues) - If you find a bug, unexpected behavior or have a feature request, please open an issue.
- [Pull Requests](https://github.com/microsoft/agent-framework/pulls) - We welcome contributions! Please see our [Contributing Guide](https://github.com/microsoft/agent-framework/blob/main/CONTRIBUTING.md)
We do our best to respond to each submission.
## Public Community Office Hours
We regularly have Community Office Hours that are open to the **public** to join.
Add Agent Framework events to your calendar. We are running two community calls to accommodate different time zones for Q&A Office Hours:
- **Americas & EMEA timezone:** Every Wednesday at 8:00 AM Pacific Time/17:00 CET. Adjusted for daylight savings. Join here: [AF-AG-SK-Americas-Europe-OfficeHours](https://aka.ms/sk-officehours).
- **Asia Pacific timezone:** The second Wednesday of every month at 4:00 PM Pacific Time Wednesday. In much of Asia this occurs on Thursday local time. Adjusted for daylight savings. Join here: [AF-AG-SK-APAC-OfficeHours](https://aka.ms/sk-apac-officehours).
If you are unable to make it live, all meetings will be recorded and posted online.
- Flexible Agent Framework: build, orchestrate, and deploy AI agents and multi-agent systems
- Multi-Agent Orchestration: Group chat, sequential, concurrent, and handoff patterns
- Plugin Ecosystem: Extend with native functions, OpenAPI, Model Context Protocol (MCP), and more
- LLM Support: OpenAI, Azure OpenAI, Azure AI Foundry, and more
- Runtime Support: In-process and distributed agent execution
- Multimodal: Text, vision, and function calling
- Cross-Platform: .NET and Python implementations
# Welcome to Microsoft Agent Framework!
Below are the basics for each language implementation. For more details on python see [here](./python/README.md) and for .NET see [here](./dotnet/README.md).
[](https://discord.gg/b5zjErwbQM)
Welcome to Microsoft's comprehensive multi-language framework for building, orchestrating, and deploying AI agents with support for both .NET and Python implementations. This framework provides everything from simple chat agents to complex multi-agent workflows with graph-based orchestration.
<p align="center">
<a href="https://www.youtube.com/watch?v=AAgdMhftj8w" title="Watch the full Agent Framework introduction (30 min)">
Watch the full Agent Framework introduction (30 min)
</a>
</p>
## 📋 Getting Started
### 📦 Installation
Python
```bash
pip install agent-framework --pre
# This will install all sub-packages, see `python/packages` for individual packages.
# It may take a minute on first install on Windows.
```
.NET
```bash
dotnet add package Microsoft.Agents.AI
```
### 📚 Documentation
- **[Overview](https://learn.microsoft.com/agent-framework/overview/agent-framework-overview)** - High level overview of the framework
- **[Quick Start](https://learn.microsoft.com/agent-framework/tutorials/quick-start)** - Get started with a simple agent
- **[Tutorials](https://learn.microsoft.com/agent-framework/tutorials/overview)** - Step by step tutorials
- **[User Guide](https://learn.microsoft.com/en-us/agent-framework/user-guide/overview)** - In-depth user guide for building agents and workflows
- **[Migration from Semantic Kernel](https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-semantic-kernel)** - Guide to migrate from Semantic Kernel
- **[Migration from AutoGen](https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-autogen)** - Guide to migrate from AutoGen
### ✨ **Highlights**
- **Graph-based Workflows**: Connect agents and deterministic functions using data flows with streaming, checkpointing, human-in-the-loop, and time-travel capabilities
If you use the Microsoft Agent Framework to build applications that operate with third-party servers or agents, you do so at your own risk. We recommend reviewing all data being shared with third-party servers or agents and being cognizant of third-party practices for retention and location of data. It is your responsibility to manage whether your data will flow outside of your organization's Azure compliance and geographic boundaries and any related implications.
# TODO: The maintainer of this repo has not yet edited this file
**REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project?
- **No CSS support:** Fill out this template with information about how to file issues and get help.
- **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps.
- **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide.
*Then remove this first heading from this SUPPORT.MD file before publishing your repo.*
# Support
## How to file issues and get help
@@ -16,9 +6,11 @@ This project uses GitHub Issues to track bugs and feature requests. Please searc
issues before filing new issues to avoid duplicates. For new issues, file your bug or
feature request as a new Issue.
For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE
FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER
CHANNEL. WHERE WILL YOU HELP PEOPLE?**.
For help and questions about using this project, please create a GitHub issue.
AI Support team will support Microsoft Agent Framework issues for customers under a **Unified support agreement when the issue arises from usage of Azure AI services** (Foundry Models, Foundry Agents etc.) in conjunction with the SDK. Conversely, if customer has any other / non unified support agreement and/or Agent Framework SDK is used in a way **not involving an Azure service**, it is treated as a purely open-source tool – Microsoft’s support organization will not handle it, and users should use GitHub or forums for assistance
For Copilot Studio SDK implementation issues, customers should use GitHub Issues for assistance, as outlined above. Conversely, for prerequisites managed within the Copilot Studio portal, customers can rely on the standard Microsoft Copilot Studio support channels.
Microsoft Agent Framework is a comprehensive multi-language (C#/.NET and Python) framework for building, orchestrating, and deploying AI agents and multi-agent workflows. The system takes user instructions and conversation inputs and produces intelligent responses through AI agents that can integrate with various LLM providers (OpenAI, Azure OpenAI, Azure AI Foundry). It provides both simple chat agents and complex multi-agent workflows with graph-based orchestration.
**What can Microsoft Agent Framework do?**
The framework offers:
- **Agent Creation**: Build AI agents with custom instructions and tools
- **Multi-Agent Orchestration**: Group chat, sequential, concurrent, and handoff patterns
- **Graph-based Workflows**: Connect agents and deterministic functions using data flows with streaming, checkpointing, time-travel, and Human-in-the-loop
- **Extensibility Framework**: Extend with native functions, A2A, Model Context Protocol (MCP)
- **LLM Integration**: Support for OpenAI, Azure OpenAI, Azure AI Foundry, and other providers
- **Runtime Support**: Both in-process and distributed agent execution
**What is/are Microsoft Agent Framework's intended use(s)?**
Intended uses include:
- **Enterprise AI Applications**: Building AI-powered business applications with multiple specialized agents
- **Multi-Agent Collaboration**: Coordinating multiple AI agents for complex tasks (e.g., content creation with writer/reviewer agents)
- **Workflow Automation**: Orchestrating AI agents and deterministic functions in business processes
**How was Microsoft Agent Framework evaluated? What metrics are used to measure performance?**
Microsoft Agent Framework is a development framework rather than a deployed AI system. The framework undergoes engineering testing for component functionality, integration testing for multi-agent scenarios, and conformance testing across .NET and Python implementations. However, AI performance metrics such as accuracy, helpfulness, and safety are dependent on the underlying LLM providers and specific application implementations. Developers using the framework should conduct application-specific evaluation including performance, safety, and accuracy testing appropriate to their chosen LLM providers, deployment contexts, and use cases.
**What are the limitations of Microsoft Agent Framework? How can users minimize the impact of Microsoft Agent Framework's limitations when using the system?**
Microsoft Agent Framework relies on existing LLMs. Using the framework retains common limitations of large language models, including:
**LLM-Inherited Limitations**:
- **Data Biases**: Large language models, trained on extensive data, can inadvertently carry biases present in the source data. Consequently, the models may generate outputs that could be potentially biased or unfair.
- **Lack of Contextual Understanding**: Despite their impressive capabilities in language understanding and generation, these models exhibit limited real-world understanding, resulting in potential inaccuracies or nonsensical responses.
- **Lack of Transparency**: Due to the complexity and size, large language models can act as 'black boxes,' making it difficult to comprehend the rationale behind specific outputs or decisions.
- **Content Harms**: There are various types of content harms that large language models can cause. It is important to be aware of them when using these models, and to take actions to prevent them. It is recommended to leverage various content moderation services provided by different companies and institutions.
- **Inaccurate or ungrounded content**: It is important to be aware and cautious not to entirely rely on a given language model for critical decisions or information that might have deep impact as it is not obvious how to prevent these models to fabricate content without high authority input sources.
- **Potential for Misuse**: Without suitable safeguards, there is a risk that these models could be maliciously used for generating disinformation or harmful content.
- **API Dependencies**: Requires proper configuration of LLM provider keys and endpoints
- **Orchestration Features**: Advanced orchestration patterns like GroupChat, Sequential, and Concurrent orchestrations are "coming soon" for Python implementation
- **Privacy and Data Protection**: The framework allows for human participation in conversations between agents. It is important to ensure that user data and conversations are protected and that developers use appropriate measures to safeguard privacy.
- **Accountability and Transparency**: The framework involves multiple agents conversing and collaborating, it is important to establish clear accountability and transparency mechanisms. Users should be able to understand and trace the decision-making process of the agents involved in order to ensure accountability and address any potential issues or biases.
- **Security & unintended consequences**: The use of multi-agent conversations and automation in complex tasks may have unintended consequences. Especially, allowing agents to make changes in external environments through tool calls or function execution could pose significant risks. Developers should carefully consider the potential risks and ensure that appropriate safeguards are in place to prevent harm or negative outcomes, including keeping a human in the loop for decision making.
**Mitigation Steps**:
- Follow setup guides for proper API key configuration
- Use provided samples as starting points to avoid configuration issues
- Monitor the GitHub repository for feature releases and updates
- Implement content moderation and safety measures when deploying agents
- Maintain human oversight for critical decisions and actions
- Use appropriate security measures to protect user data and conversations
**What operational factors and settings allow for effective and responsible use of Microsoft Agent Framework?**
**Configuration Requirements**:
- **API Keys**: Proper configuration of your LLM provider credentials and endpoints
- **Model Selection**: Choose appropriate deployment models for specific use cases
- **Tool Integration**: Careful selection and validation of external tools and MCP servers
- **Type Safety**: Strong typing and compatibility validation between agents and threads
**Responsible Development Practices**:
- **Human Oversight**: Microsoft Agent Framework prioritizes human involvement in multi-agent conversations. Users should maintain oversight and can step in to provide feedback to agents and steer them in the correct direction. In critical applications, users should confirm actions before they are executed.
- **Agent Modularity**: Modularity allows agents to have different levels of information access. Additional agents can assume roles that help keep other agents in check. For example, one can easily add a dedicated agent to play the role of safeguard.
- **LLM Selection**: Users can choose the LLM that is optimized for responsible use. We encourage developers to review and follow LLM providers’ policies. Developers should add content moderation and/or use safety metaprompts when using agents, like they would do when using LLMs directly.
- **Security Measures**: Implement appropriate security measures for tool execution and external system integrations. Consider using containerization or sandboxing for code execution scenarios to prevent unintended system changes.
- **Testing and Validation**: Use provided testing frameworks (unit, integration, conformance tests) to validate agent behavior and ensure reliability.
- **Monitoring and Observability**: Implement proper error handling, logging, and use OpenTelemetry for observability to track agent behavior and identify potential issues.
**How do I provide feedback on Microsoft Agent Framework?**
- **Bug Reports**: File issues at https://github.com/microsoft/agent-framework/issues
**What are external services and how does Microsoft Agent Framework use them?**
The framework supports multiple external service types:
- **Native Functions**: Custom Python/C# functions that agents can invoke
- **A2A (Agent2Agent)Integration**: Agent-to-agent communication and coordination
- **Model Context Protocol (MCP)**: External tools and data sources through MCP servers
External service development is open to developers who can create custom functions and integrate external APIs. Users have control over which tools are provided to agents during agent creation.
**What data can Microsoft Agent Framework provide to external services? What permissions do Microsoft Agent Framework external services have?**
Microsoft Agent Framework is an open-source framework that allows integration with various types of external services. The data access and permissions depend on how you configure and implement these integrations:
**Data Access by Service Type**:
- **Native Functions**: Custom functions you develop have access to whatever data you explicitly pass to them as parameters
- **A2A (Agent2Agent)**: External agents can access conversation history, messages, and any data you configure to share through the communication interface
- **Model Context Protocol (MCP) Servers**: External MCP servers can access data according to the specific MCP server implementation and your configuration
- **External Tools**: Third-party tools and APIs have access to data you explicitly send to them through function calls
**Important Security Considerations**:
- **Community and Third-Party Services**: Microsoft Agent Framework is an open-source project. When using community-developed tools or services from third-party providers, it is your responsibility to evaluate and ensure their safety, security, and compliance with your data protection requirements.
- **Data Boundary Considerations**: When connecting Azure-hosted agents to external agents or services, data may leave the Azure boundary and Microsoft's security perimeter. You should verify the data handling practices, security measures, and compliance certifications of external providers before sharing sensitive or regulated data.
- **Provider Due Diligence**: Before integrating any external service, you should review their privacy policies, security practices, data retention policies, and terms of service to ensure they meet your organization's requirements and regulatory obligations.
- **Data Minimization**: Only provide external services with the minimum data necessary for their function. Avoid sharing sensitive, personal, or confidential information unless absolutely required and properly secured.
**Recommendation**: Consult with your organization's security, privacy, and legal teams before integrating external services, especially in production environments handling sensitive data.
**What kinds of issues may arise when using Microsoft Agent Framework enabled with external services?**
**Potential Issues**:
- **API Key Security**: Risk of exposing API keys in configuration or logs
@@ -499,7 +499,7 @@ We need to decide what AIContent types, each agent response type will be mapped
| AWS (Strands) | **Approach 2** Supports a special invocation method called [structured_output](https://strandsagents.com/latest/api-reference/agent/#strands.agent.agent.Agent.structured_output) |
| LangGraph | **Approach 1** Supports [configuring an agent](https://langchain-ai.github.io/langgraph/agents/agents/?h=structured#6-configure-structured-output) at agent construction time, and a [structured response](https://langchain-ai.github.io/langgraph/agents/run_agents/#output-format) can be retrieved as a special property on the agent response |
| Agno | **Approach 1** Supports [configuring an agent](https://docs.agno.com/examples/getting-started/structured-output) at agent construction time |
| A2A | **Informal Approach 2** Doesn't formally support schema negotiation, but [hints can be provided via metadata](https://a2aproject.github.io/A2A/v0.2.5/specification/#97-structured-data-exchange-requesting-and-providing-json) at invocation time |
| A2A | **Informal Approach 2** Doesn't formally support schema negotiation, but [hints can be provided via metadata](https://a2a-protocol.org/latest/specification/#97-structured-data-exchange-requesting-and-providing-json) at invocation time |
| Protocol Activity | Supports returning [Complex types](https://github.com/microsoft/Agents/blob/main/specs/activity/protocol-activity.md#complex-types) but no support for requesting a type |
### Response Reason Support
@@ -511,5 +511,5 @@ We need to decide what AIContent types, each agent response type will be mapped
| AWS (Strands) | Exposes a [stop_reason](https://strandsagents.com/latest/api-reference/types/#strands.types.event_loop.StopReason) property on the [AgentResult](https://strandsagents.com/latest/api-reference/agent/#strands.agent.agent_result.AgentResult) class with options that are tied closely to LLM operations. |
| LangGraph | No equivalent present, output contains only [messages](https://langchain-ai.github.io/langgraph/agents/run_agents/#output-format) |
| A2A | No equivalent present, response only contains a [message](https://a2aproject.github.io/A2A/v0.2.5/specification/#64-message-object) or [task](https://a2aproject.github.io/A2A/v0.2.5/specification/#61-task-object). |
| A2A | No equivalent present, response only contains a [message](https://a2a-protocol.org/latest/specification/#64-message-object) or [task](https://a2a-protocol.org/latest/specification/#61-task-object). |
This implementation follows the exact patterns established by Microsoft.Extensions.AI's OpenTelemetry instrumentation, ensuring consistency across the AI ecosystem and leveraging proven patterns for telemetry integration.
# `Azure.AI.Agents.Persistent` package Extensions Methods for Agent Framework
## Context and Problem Statement
To align the `Azure.AI.Agents.Persistent` package and Agent Framework a set of extensions methods have been created which allow a developer to create or retrieve an `AIAgent` using the `PersistentAgentsClient`.
The purpose of this ADR is to decide where these extension methods should live.
## Decision Drivers
- Provide the optimum experience for developers.
- Avoid adding additional dependencies to the `Azure.AI.Agents.Persistent` package (and not in the future)
## Considered Options
- Add the extension methods to the `Azure.AI.Agents.Persistent` package and change it's dependencies
- Add the extension methods to the `Azure.AI.Agents.Persistent` package without changing it's dependencies
- Add the extension methods to a `Microsoft.Extensions.AI.Azure` package
### Add the extension methods to the `Azure.AI.Agents.Persistent` package and change it's dependencies
-`Azure.AI.Agents.Persistent` would depend on `Microsoft.Extensions.AI` instead of `Microsoft.Extensions.AI.Abstractions`
- Good because, extension methods are in the `Azure.AI.Agents.Persistent` package and can be easily kept up-to-date
- Good because, developers don't need to explicitly depend on a new package to get Agent Framework functionality
- Bad because, it introduces additional dependencies which would possibly grow overtime
### - Add the extension methods to the `Azure.AI.Agents.Persistent` package without changing it's dependencies
-`Azure.AI.Agents.Persistent` would depend on `Microsoft.Extensions.AI.Abstractions` (as it currently does)
-`ChatClientAgent` and `FunctionInvokingChatClient` would move to `Microsoft.Extensions.AI.Abstractions`
- Good because, extension methods are in the `Azure.AI.Agents.Persistent` package and can be easily kept up-to-date
- Good because, developers don't need to explicitly depend on a new package to get Agent Framework functionality
- Good because, it introduces minimal additional dependencies
- Bad because, it adds additional dependencies to `Microsoft.Extensions.AI.Abstractions` and these additional dependencies add up as transitive to `Azure`.AI.Agents.Persistent`
### Add the extension methods to a `Microsoft.Extensions.AI.Azure` package
- Introduce a new package called `Microsoft.Extensions.AI.Azure` where the extension methods would live
-`Azure.AI.Agents.Persistent` does not change
- Good because, it introduces no additional dependencies to `Azure.AI.Agents.Persistent` package
- Bad because, extension methods are not in the `Azure.AI.Agents.Persistent` package and cannot be easily kept up-to-date
- Bad because, developers need to explicitly depend on a new package to get Agent Framework functionality
## Decision Outcome
Chosen option: "Add the extension methods to a `Microsoft.Extensions.AI.Azure` package", because
it introduces no additional dependencies to `Azure.AI.Agents.Persistent` package.
The project has a public .NET surface and a Python surface. During a cross-language alignment effort the community proposed renames to make the Python surface more idiomatic while preserving discoverability and mapping to the .NET names. This ADR captures the final naming decisions (or the proposed ones), the rationale, and the alternatives considered and rejected.
## Decision drivers
- Follow Python naming conventions (PEP 8) where appropriate (snake_case for functions and module-level variables, PascalCase for classes).
- Preserve conceptual parity with .NET names to make it easy for developers reading both surfaces to correlate types and behaviors.
- Avoid ambiguous or overloaded names in Python that could conflict with stdlib, common third-party packages, or existing package/module names.
- Prefer clarity and discoverability in the public API surface over strict symmetry with .NET when Python conventions conflict.
- Minimize churn and migration burden for existing Python users where backwards compatibility is feasible.
## Principles applied
- Map .NET PascalCase class names to PascalCase Python classes when they represent types.
- Map .NET method/field names that are camelCase to snake_case in Python where they will be used as functions or module-level attributes.
- When a .NET name is an acronym or initialism, use Python-friendly casing (e.g., `Http` -> `HTTP` in classes, but acronyms in function names should be lowercased per PEP 8 where sensible).
- Avoid names that shadow common stdlib modules (e.g., `logging`, `asyncio`) or widely used third-party modules.
- When multiple reasonable Python names exist, prefer the one that communicates intent most clearly to Python users, and record rejected alternatives in the table with justification.
## Renaming table
The table below represents the majority of the naming changes discussed in issue #506. Each row has:
- Original and/or .NET name — the canonical name used in dotnet or earlier Python variants.
- New name — the chosen Python name.
- Status — accepted if the new name differs from the original, rejected if unchanged.
- Reasoning — short rationale why the new name was chosen.
- Rejected alternatives — other candidate new names that were considered and rejected; include the rejected 'new name' values and the reason each was rejected.
| Original and/or .NET name | New name (Python) | Status | Reasoning | Rejected alternatives (as "new name" + reason rejected) |
|---|---|---|---|---|
| AIAgent | AgentProtocol | accepted | The AI prefix is meaningless in the context of the Agent Framework, and the `protocol` suffix makes it very clear that this is a protocol, and not a concrete agent implementation. | <ul><li>AgentLike, not seen in many other places, but was a frontrunner.</li><li>Agent, as too generic.</li><li>BaseAgent/AbstractAgent, it is not a base/ABC class and should not be treated as such.</li></ul> |
| ChatClientAgent | ChatAgent | accepted | Type name is shorter, while it is still clear that a ChatClient is used, also by virtue of the first parameter for initialization. | Agent, as too generic. |
| ChatClient/IChatClient (in dotnet) | ChatClientProtocol | accepted | Keeping this protocol in sync with the AgentProtocol naming. | Similar as AgentProtocol. |
| ChatClientBase | BaseChatClient | accepted | Following convention, serves as base class so, should be named accordingly. | None |
| AITool | ToolProtocol | accepted | In line with other protocols. | Tool, too generic. |
| AIToolBase | BaseTool | accepted | More descriptive than just Tool, while still concise. | AbstractTool/BaseTool, it is not an abstract/base class and should not be treated as such. |
| ChatRole | Role | accepted | More concise while still clear in context. | None |
| ChatFinishReason | FinishReason | accepted | More concise while still clear in context. | None |
| AIContent | BaseContent | accepted | More accurate as it serves as the base class for all content types. | Content, too generic. |
| AIContents | Contents | accepted | This is the annotated typing object that is the union of all concrete content types, so plural makes sense and since this is used as a type hint, the generic nature of the name is acceptable. | None |
| AIAnnotations | Annotations | accepted | In sync with contents | None |
| AIAnnotation | BaseAnnotation | accepted | In sync with contents | None |
| *Mcp* & *Http* | *MCP* & *HTTP* | accepted | Acronyms should be uppercased in class names, according to PEP 8. | None |
| `agent.run_streaming` | `agent.run_stream` | accepted | Shorter and more closely aligns with AutoGen and Semantic Kernel names for the same methods. | None |
| `workflow.run_streaming` | `workflow.run_stream` | accepted | In sync with `agent.run_stream` and shorter and more closely aligns with AutoGen and Semantic Kernel names for the same methods. | None |
| AgentRunResponse & AgentRunResponseUpdate | AgentResponse & AgentResponseUpdate | rejected | Rejected, because it is the response to a run invocation and AgentResponse is too generic. | None |
| *Content | * | rejected | Rejected other content type renames (removing `Content` suffix) because it would reduce clarity and discoverability. | Item was also considered, but rejected as it is very similar to Content, but would be inconsistent with dotnet. |
| ChatResponse & ChatResponseUpdate | Response & ResponseUpdate | rejected | Rejected, because Response is too generic. | None |
## Naming guidance
In general Python tends to prefer shorter names, while .NET tends to prefer more descriptive names. The table above captures the specific renames agreed upon, but in general the following guidelines were applied:
- Use [PEP 8](https://peps.python.org/pep-0008/) for generic naming conventions (snake_case for functions and module-level variables, PascalCase for classes).
When mapping .NET names to Python:
- Remove `AI` prefix when appropriate, as it is often redundant in the context of an AI SDK.
- Remove `Chat` prefix when the context is clear (e.g., Role and FinishReason).
- Use `Protocol` suffix for interfaces/protocols to clarify their purpose.
- Use `Base` prefix for base classes that are not abstract but serve as a common ancestor for internal implementations.
- When readability improves while it is still easy to understand what it does and how it maps to the .NET name, prefer the shorter name.
# Agent User Approvals Content Types and FunctionCall approvals Design
## Context and Problem Statement
When agents are operating on behalf of a user, there may be cases where the agent requires user approval to continue an operation.
This is complicated by the fact that an agent may be remote and the user may not immediately be available to provide the approval.
Inference services are also increasingly supporting built-in tools or service side MCP invocation, which may require user approval before the tool can be invoked.
This document aims to provide options and capture the decision on how to model this user approval interaction with the agent caller.
See various features that would need to be supported via this type of mechanism, plus how various other frameworks support this:
- Also see [dotnet issue 6492](https://github.com/dotnet/extensions/issues/6492), which discusses the need for a similar pattern in the context of MCP approvals.
- Also see [the openai human-in-the-loop guide](https://openai.github.io/openai-agents-js/guides/human-in-the-loop/#approval-requests).
- Also see [the openai MCP guide](https://openai.github.io/openai-agents-js/guides/mcp/#optional-approval-flow).
- Also see [MCP Approval Requests from OpenAI](https://platform.openai.com/docs/guides/tools-remote-mcp#approvals).
- Also see [Azure AI Foundry MCP Approvals](https://learn.microsoft.com/en-us/azure/ai-foundry/agents/how-to/tools/model-context-protocol-samples?pivots=rest#submit-your-approval).
- Also see [MCP Elicitation requests](https://modelcontextprotocol.io/specification/draft/client/elicitation)
## Decision Drivers
- Agents should encapsulate their internal logic and not leak it to the caller.
- We need to support approvals for local actions as well as remote actions.
- We need to support approvals for service-side tool use, such as remote MCP tool invocations
- We should consider how other user input requests will be modeled, so that we can have a consistent approach for user input requests and approvals.
## Considered Options
### 1. Return a FunctionCallContent to the agent caller, that it executes
This introduces a manual function calling element to agents, where the caller of the agent is expected to invoke the function if the user approves it.
This approach is problematic for a number of reasons:
- This may not work for remote agents (e.g. via A2A), where the function that the agent wants to call does not reside on the caller's machine.
- The main value prop of an agent is to encapsulate the internal logic of the agent, but this leaks that logic to the caller, requiring the caller to know how to invoke the agent's function calls.
- Inference services are introducing their own approval content types for server side tool or function invocation, and will not be addressed by this approach.
### 2. Introduce an ApprovalCallback in AgentRunOptions and ChatOptions
This approach allows a caller to provide a callback that the agent can invoke when it requires user approval.
This approach is easy to use when the user and agent are in the same application context, such as a desktop application, where the application can show the approval request to the user and get their response from the callback before continuing the agent run.
This approach does not work well for cases where the agent is hosted in a remote service, and where there is no user available to provide the approval in the same application context.
For cases like this, the agent needs to be suspended, and a network response must be sent to the client app. After the user provides their approval, the client app must call the service that hosts the agent again, with the user's decision, and the agent needs to be resumed. However, with a callback, the agent is deep in the call stack and cannot be suspended or resumed like this.
agent.RunAsync("Please book me a flight for Friday to Paris.",thread,newAgentRunOptions
{
ApprovalCallback=async(approvalRequest)=>
{
// Show the approval request to the user in the appropriate format.
// The user can then approve or reject the request.
// The optional FunctionCallContent can be used to show the user what function the agent wants to call with the parameter set:
// approvalRequest.FunctionCall?.Arguments.
// If the user approves:
returntrue;
}
});
```
### 3. Introduce new ApprovalRequestContent and ApprovalResponseContent types
The agent would return an `ApprovalRequestContent` to the caller, which would then be responsible for getting approval from the user in whatever way is appropriate for the application.
The caller would then invoke the agent again with an `ApprovalResponseContent` to the agent containing the user decision.
When an agent returns an `ApprovalRequestContent`, the run is finished for the time being, and to continue, the agent must be invoked again with an `ApprovalResponseContent` on the same thread as the original request. This doesn't of course have to be the exact same thread object, but it should have the equivalent contents as the original thread, since the agent would have stored the `ApprovalRequestContent` in its thread state.
The `ApprovalRequestContent` could contain an optional `FunctionCallContent` if the approval is for a function call, along with any additional information that the agent wants to provide to the user to help them make a decision.
It is up to the agent to decide when and if a user approval is required, and therefore when to return an `ApprovalRequestContent`.
`ApprovalRequestContent` and `ApprovalResponseContent` will not necessarily always map to a supported content type for the underlying service or agent thread storage.
Specifically, when we are deciding in the IChatClient stack to ask for approval from the user, for a function call, this does not mean that the underlying ai service or
service side thread type (where applicable) supports the concept of a function call approval request. While we can store the approval requests and response in local
threads, service managed threads won't necessarily support this. For service managed threads, there will therefore be no long term record of the approval request in the chat history.
We should however log approvals so that there is a trace of this for debugging and auditing purposes.
Suggested Types:
```csharp
classApprovalRequestContent:AIContent
{
// An ID to uniquely identify the approval request/response pair.
publicstringId{get;set;}
// An optional user targeted message to explain what needs to be approved.
publicstring?Text{get;set;}
// Optional: If the approval is for a function call, this will contain the function call content.
publicFunctionCallContent?FunctionCall{get;set;}
publicApprovalResponseContentCreateApproval()
{
returnnewApprovalResponseContent
{
Id=this.Id,
Approved=true,
FunctionCall=this.FunctionCall
};
}
publicApprovalResponseContentCreateRejection()
{
returnnewApprovalResponseContent
{
Id=this.Id,
Approved=false,
FunctionCall=this.FunctionCall
};
}
}
classApprovalResponseContent:AIContent
{
// An ID to uniquely identify the approval request/response pair.
publicstringId{get;set;}
// Indicates whether the user approved the request.
publicboolApproved{get;set;}
// Optional: If the approval is for a function call, this will contain the function call content.
publicFunctionCallContent?FunctionCall{get;set;}
}
varresponse=awaitagent.RunAsync("Please book me a flight for Friday to Paris.",thread);
### 4. Introduce new Container UserInputRequestContent and UserInputResponseContent types
This approach is similar to the `ApprovalRequestContent` and `ApprovalResponseContent` types, but is more generic and can be used for any type of user input request, not just approvals.
There is some ambiguity with this approach. When using an LLM based agent the LLM may return a text response about missing user input.
E.g the LLM may need to invoke a function but the user did not supply all necessary information to fill out all arguments.
Typically an LLM would just respond with a text message asking the user for the missing information.
In this case, the message is not distinguishable from any other result message, and therefore cannot be returned to the caller as a `UserInputRequestContent`, even though it is conceptually a type of unstructured user input request. Ultimately our types are modeled to make it easy for callers to decide on the right way to represent this to users. E.g. is it just a regular message to show to users, or do we need a special UX for it.
Suggested Types:
```csharp
classUserInputRequestContent:AIContent
{
// An ID to uniquely identify the approval request/response pair.
publicstringApprovalId{get;set;}
// DecisionTarget could contain:
// FunctionCallContent: The function call that the agent wants to invoke.
// TextContent: Text that describes the question for that the user should answer.
object?DecisionTarget{get;set;}// Anything else the user may need to make a decision about.
// Possible InputFormat subclasses:
// SchemaInputFormat: Contains a schema for the user input.
// ApprovalInputFormat: Indicates that the user needs to approve something.
// FreeformTextInputFormat: Indicates that the user can provide freeform text input.
// Other formats can be added as needed, e.g. cards when using activity protocol.
publicInputFormatInputFormat{get;set;}// How the user should provide input (e.g., form, options, etc.).
}
classUserInputResponseContent:AIContent
{
// An ID to uniquely identify the approval request/response pair.
publicstringApprovalId{get;set;}
// Possible UserInputResult subclasses:
// SchemaInputResult: Contains the structured data provided by the user.
// ApprovalResult: Contains a bool with approved / rejected.
// FreeformTextResult: Contains the freeform text input provided by the user.
publicUserInputResultResult{get;set;}// The user input.
publicobject?DecisionTarget{get;set;}// A copy of the DecisionTarget from the UserInputRequestContent, if applicable.
}
varresponse=awaitagent.RunAsync("Please book me a flight for Friday to Paris.",thread);
### 5. Introduce new Base UserInputRequestContent and UserInputResponseContent types
This approach is similar to option 4, but the `UserInputRequestContent` and `UserInputResponseContent` types are base classes rather than generic container types.
Suggested Types:
```csharp
classUserInputRequestContent:AIContent
{
// An ID to uniquely identify the approval request/response pair.
publicstringId{get;set;}
}
classUserInputResponseContent:AIContent
{
// An ID to uniquely identify the approval request/response pair.
1. User passes a User message to the agent with a request.
1. Agent calls IChatClient with any functions registered on the agent.
(IChatClient has FunctionInvokingChatClient)
1. Model responds with FunctionCallContent indicating function calls required.
1. FunctionInvokingChatClient decorator identifies any function calls that require user approval and returns an FunctionApprovalRequestContent.
(If there are multiple parallel function calls, all function calls will be returned as FunctionApprovalRequestContent even if only some require approval.)
1. Agent updates the thread with the FunctionApprovalRequestContent (or this may have already been done by a service threaded agent).
1. Agent returns the FunctionApprovalRequestContent to the caller which shows it to the user in the appropriate format.
1. User (via caller) invokes the agent again with FunctionApprovalResponseContent.
1. Agent adds the FunctionApprovalResponseContent to the thread.
1. Agent calls IChatClient with the provided FunctionApprovalResponseContent.
1. Agent invokes IChatClient with FunctionApprovalResponseContent and the FunctionInvokingChatClient decorator identifies the response as an approval for the function call.
Any rejected approvals are converted to FunctionResultContent with a message indicating that the function invocation was denied.
Any approved approvals are executed by the FunctionInvokingChatClient decorator.
1. FunctionInvokingChatClient decorator passes the FunctionCallContent and FunctionResultContent for the approved and rejected function calls to the model.
1. Model responds with the result.
1. FunctionInvokingChatClient returns the FunctionCallContent, FunctionResultContent, and the result message to the agent.
1. Agent responds to caller with the same messages and updates the thread with these as well.
### CustomAgent Approval Process Flow
1. User passes a User message to the agent with a request.
1. Agent adds this message to the thread.
1. Agent executes various steps.
1. Agent encounters a step for which it requires user input to continue.
1. Agent responds with an UserInputRequestContent and also adds it to its thread.
1. User (via caller) invokes the agent again with UserInputResponseContent.
1. Agent adds the UserInputResponseContent to the thread.
1. Agent responds to caller with result message and thread is updated with the result message.
### Sequence Diagram: FunctionInvokingChatClient with built in Approval Generation
This is a ChatClient Approval Stack option has been proven to work via a proof of concept implementation.
```mermaid
---
title: Multiple Functions with partial approval
---
sequenceDiagram
note right of Developer: Developer asks question with two functions.
Developer->>+FunctionInvokingChatClient: What is the special soup today?<br/>[GetMenu, GetSpecials]
FunctionInvokingChatClient->>+ResponseChatClient: What is the special soup today?<br/>[GetMenu, GetSpecials]
note right of FunctionInvokingChatClient:FunctionInvokingChatClient executes the approved<br/>function and generates a failed FunctionResultContent<br/>for the rejected one, before invoking the model again.
FunctionInvokingChatClient->>+ResponseChatClient: What is the special soup today?<br/>[FunctionCallContent(GetMenu)],<br/>[FunctionCallContent(GetSpecials)],<br/>[FunctionResultContent(GetMenu, Function invocation denied")]<br/>[FunctionResultContent(GetSpecials, "Special Soup: Clam Chowder...")]
note right of FunctionInvokingChatClient: ApprovalGeneratingChatClient only returns FunctionCallContent<br/>for approved FunctionApprovalResponseContent.
note right of FunctionInvokingChatClient: FunctionInvokingChatClient has to also include all<br/>FunctionApprovalResponseContent in the new downstream request.
note right of ApprovalGeneratingChatClient: ApprovalGeneratingChatClient now throws away<br/>approvals for executed functions, and creates<br/>failed FunctionResultContent for denied function calls.
### Sequence Diagram: Pre FunctionInvokingChatClient ApprovalGeneratingChatClient - Multiple function calls with partial approval
This is a discarded ChatClient Approval Stack option, but is included here for reference.
It doesn't work for the scenario where we have multiple function calls for the same function in serial with different arguments.
Flow:
- AGCC turns AIFunctions into AIFunctionDefinitions (not invocable) and FICC ignores these.
- We get back a FunctionCall for one of these and it gets approved.
- We invoke the FICC again, this time with an AIFunction.
- We call the service with the FCC and FRC.
- We get back a new Function call for the same function again with different arguments.
- Since we were passed an AIFunction instead of an AIFunctionDefinition, we now incorrectly execute this FC without approval.
```mermaid
---
title: Multiple Functions with partial approval
---
sequenceDiagram
note right of Developer: Developer asks question with two functions.
Developer->>+ApprovalGeneratingChatClient: What is the special soup today? [GetMenu, GetSpecials]
note right of ApprovalGeneratingChatClient: AGCC marks functions as not-invocable
ApprovalGeneratingChatClient->>+FunctionInvokingChatClient: What is the special soup today?<br/>[GetMenu(invocable=false)]<br/>[GetSpecials(invocable=false)]
FunctionInvokingChatClient->>+ResponseChatClient: What is the special soup today?<br/>[GetMenu(invocable=false)]<br/>[GetSpecials(invocable=false)]
The goal is to design a subpackage structure for the Python agent framework that balances ease of use, maintainability, and scalability. How can we organize the codebase to facilitate the development and integration of connectors while minimizing complexity for users?
## Decision Drivers
- Ease of use for developers
- Maintainability of the codebase
- User experience for installing and using the integrations
- Clear lifecycle management for integrations
- Minimize non-GA dependencies in the main package
## Considered Options
1. One subpackage per vendor, so a `google` package that contains all Google related connectors, such as `GoogleChatClient`, `BigQueryCollection`, etc.
* Pros:
- fewer packages to manage, publish and maintain
- easier for users to find and install the right package.
- users that work primarily with one platform have a single package to install.
* Cons:
- larger packages with more dependencies
- larger installation sizes
- more difficult to version, since some parts may be GA, while other are in preview.
2. One subpackage per connector, so a i.e. `google_chat` package, a i.e. `google_bigquery` package, etc.
* Pros:
- smaller packages with fewer dependencies
- smaller installation sizes
- easy to version and do lifecycle management on
* Cons:
- more packages to manage, register, publish and maintain
- more extras, means more difficult for users to find and install the right package.
3. Group connectors by vendor and maturity, so that you can graduate something from the i.e. the `google-preview` package to the `google` package when it becomes GA.
* Pros:
- fewer packages to manage, publish and maintain
- easier for users to find and install the right package.
- users that work primarily with one platform have a single package to install.
- clear what the status is based on extra name
* Cons:
- moving something from one to the other might be a breaking change
- still larger packages with more dependencies
It could be mitigated that the `google-preview` package is still imported from `agent_framework.google`, so that the import path does not change, when something graduates, but it is still a clear choice for users to make. And we could then have three extras on that package, `google`, `google-preview` and `google-all` to make it easy to install the right package or just all.
4. Group connectors by vendor and type, so that you have a `google-chat` package, a `google-data` package, etc.
* Pros:
- smaller packages with fewer dependencies
- smaller installation sizes
* Cons:
- more packages to manage, register, publish and maintain
- more extras, means more difficult for users to find and install the right package.
- still keeps the lifecycle more difficult, since some parts may be GA, while other are in preview.
5. Add `meta`-extras, that combine different subpackages as one extra, so we could have a `google` extra that includes `google-chat`, `google-bigquery`, etc.
* Pros:
- easier for users on a single platform
* Cons:
- more packages to manage, register, publish and maintain
- more extras, means more difficult for users to find and install the right package.
- makes developer package management more complex, because that meta-extra will include both GA and non-GA packages, so during dev they could use that, but then during prod they have to figure out which one they actually need and make a change in their dependencies, leading to mismatches between dev and prod.
6. Make all imports happen from `agent_framework.connectors` (or from two or three groups `agent_framework.chat_clients`, `agent_framework.context_providers`, or something similar) while the underlying code comes from different packages.
* Pros:
- best developer experience, since all imports are from the same place and it is easy to find what you need, and we can raise a meaningfull error with which extra to install.
- easier for users to find and install the right package.
* Cons:
- larger overhead in maintaining the `__init__.py` files that do the lazy loading and error handling.
- larger overhead in package management, since we have to ensure that the main package.
7. Subpackage existence will be based off status of dependencies and/or possibilities of a external support mechanism. What this means is that:
- Integrations that need non-GA dependencies will be subpackages, so that we can avoid having non-GA dependencies in the main package.
- Integrations where the AF-code is still experimental, preview or release candidate will be subpackages, so that we can avoid having non-GA code in the main package and we can version those packages properly.
- Integrations that are outside Microsoft and where we might not always be able to fast-follow breaking changes, will stay as subpackages, to provide some isolation and to be able to version them properly.
- Integrations that are mature and that have released (GA) dependencies and or features on the service side will be moved into the main package, the dependencies of those packages will stay installable under the same `extra` name, so that users do not have to change anything, and we then remove the subpackage itself.
- All subpackage imports in the code should be from a stable place, mostly vendor-based, so that when something moves from a subpackage to the main package, the import path does not change, so `from agent_framework.google import GoogleChatClient` will always work, even if it moves from the `agent-framework-google` package to the main `agent-framework` package.
- The imports in those vendor namespaces (these won't be actual python namespaces, just the folders with a __init__.py file and any code) will do lazy loading and raise a meaningful error if the subpackage or dependencies are not installed, so that users know which extra to install with ease.
- On a case by case basis we can decide to create additional `extras`, that combine multiple subpackages into one extra, so that users that work primarily with one platform can install everything they need with a single extra, for instance you can install with the `agent-framework[azure-purview]` extra that only implement a Azure Purview Middleware, or you can install with the `agent-framework[azure]` extra that includes all Azure related connectors, like `purview`, `content safety` and others (all examples, not actual packages (yet)), regardless of where the code sits, these should always be importable from `agent_framework.azure`.
- Subpackage naming should also follow this, so in principle a package name is `<vendor/folder>-<feature/brand>`, so `google-gemini`, `azure-purview`, `microsoft-copilotstudio`, etc. For smaller vendors, with less likely to have a multitude of connectors, we can skip the feature/brand part, so `mem0`, `redis`, etc.
## Decision Outcome
Option 7: This provides us a good balance between developer experience, user experience, package management and maintenance, while also allowing us to evolve the package structure over time as dependencies and features mature. And it ensures the main package, installed without extras does not include non-GA dependencies or code, extras do not carry that guarantee, for both the code and the dependencies.
# Microsoft vs Azure packages
Another consideration is for Microsoft, since we have a lot of Azure services, but also other Microsoft services, such as Microsoft Copilot Studio, and potentially other services in the future, and maybe Foundry also will be marketed separate from Azure at some point. We could also have both a `microsoft` and an `azure` package, where the `microsoft` package contains all Microsoft services, excluding Azure, while the `azure` package only contains Azure services. Only applicable for the variants where we group by vendor, including with meta packages.
## Decision Outcome
Azure and Microsoft will be the two vendor folders for Microsoft services, so Copilot Studio will be imported from `agent_framework.microsoft`, while Foundry, Azure OpenAI and other Azure services will be imported from `agent_framework.azure`.
The .NET Agent Framework needed a standardized way to enable communication between AI agents and user-facing applications with support for streaming, real-time updates, and bidirectional communication. Without AG-UI protocol support, .NET agents could not interoperate with the growing ecosystem of AG-UI-compatible frontends and agent frameworks (LangGraph, CrewAI, Pydantic AI, etc.), limiting the framework's adoption and utility.
The AG-UI (Agent-User Interaction) protocol is an open, lightweight, event-based protocol that addresses key challenges in agentic applications including streaming support for long-running agents, event-driven architecture for nondeterministic behavior, and protocol interoperability that complements MCP (tool/context) and A2A (agent-to-agent) protocols.
## Decision Drivers
- Need for streaming communication between agents and client applications
- Requirement for protocol interoperability with other AI frameworks
- Support for long-running, multi-turn conversation sessions
- Real-time UI updates for nondeterministic agent behavior
- Standardized approach to agent-to-UI communication
- Framework abstraction to protect consumers from protocol changes
## Considered Options
1. **Implement AG-UI event types as public API surface** - Expose AG-UI event models directly to consumers
2. **Use custom AIContent types for lifecycle events** - Create new content types (RunStartedContent, RunFinishedContent, RunErrorContent)
3. **Current approach** - Internal event types with framework-native abstractions
## Decision Outcome
Chosen option: "Current approach with internal event types and framework-native abstractions", because it:
- Protects consumers from protocol changes by keeping AG-UI events internal
- Maintains framework abstractions through conversion at boundaries
- Uses existing framework types (AgentRunResponseUpdate, ChatMessage) for public API
- Text message events: `TextMessageStart`, `TextMessageContent`, `TextMessageEnd`
- Thread and run ID management via `ConversationId` and `ResponseId`
### Key Design Decisions
1. **Event Models as Internal Types** - AG-UI event types are internal with conversion via extension methods; public API uses the existing types in Microsoft.Extensions.AI as those are the abstractions people are familiar with
2. **No Custom Content Types** - Run lifecycle communicated through existing `ChatResponseUpdate` properties (`ConversationId`, `ResponseId`) and standard `ErrorContent` type
3. **Agent Factory Pattern** - `MapAGUIAgent` uses factory function `(messages) => AIAgent` to allow request-specific agent configuration supporting multi-tenancy
4. **Bidirectional Conversion Architecture** - Symmetric conversion logic in shared namespace compiled into both packages for server (`AgentRunResponseUpdate` → AG-UI events) and client (AG-UI events → `AgentRunResponseUpdate`)
5. **Thread Management** - `AGUIAgentThread` stores only `ThreadId` with thread ID communicated via `ConversationId`; applications manage persistence for parity with other implementations and to be compliant with the protocol. Future extensions will support having the server manage the conversation.
6. **Custom JSON Converter** - Uses custom polymorphic deserialization via `BaseEventJsonConverter` instead of built-in System.Text.Json support to handle AG-UI protocol's flexible discriminator positioning
### Consequences
**Positive:**
- .NET developers can consume AG-UI servers from any framework
- .NET agents accessible from any AG-UI-compatible client
- Standardized streaming communication patterns
- Protected from protocol changes through internal implementation
- Symmetric conversion logic between client and server
* this means developers can use `pip install agent-framework[google]` to get AF with all Google connectors and dependencies, as well as manually installing the subpackage with `pip install agent-framework-google`.
* this means developers can use `pip install agent-framework[google] --pre` to get AF with all Google connectors and dependencies, as well as manually installing the subpackage with `pip install agent-framework-google --pre`.
### Sample getting started code
```python
@@ -53,45 +53,46 @@ Overall the following structure is proposed:
* core components, will be exposed directly from `agent_framework`:
* (single) agents (includes threads)
* tools (includes MCP and OpenAPI)
* models/types (name tbd, will include the equivalent of MEAI for dotnet; content types and client abstractions)
* types
* context_providers
* logging
* advanced components, will be exposed from `agent_framework.<component>`:
* context_providers (tbd)
* guardrails / filters
* vector_data (vector stores and other MEVD pieces)
* text_search
* exceptions
* evaluations
* utils (optional)
* telemetry (could also be observability or monitoring)
* workflows (includes multi-agent orchestration)
* connectors; subpackages
* Subpackages are any additional functionality that is useful for a user, to reduce friction they will imported in a similar way as advanced components, however the code for them will be in a separate package, so that they can be installed separately, they must expose all public items, in their main `__init__.py` file, so that they can be imported from the main package without additional import levels.
In the main package a corresponding folder will be created, with a `__init__.py` file that lazy imports the public items from the subpackage, so that they can be exposed from the main package.
* Some examples are:
* azure (non LLM integrations)
* will be exposed through i.e. `agent_framework.azure`
* anything other then a connector that we want to expose as a separate package, for instance:
* mem0 (memory management)
* would be exposed through i.e. `agent_framework.mem0`
* A package name cannot overlap with each other or with components in the main package, so `guardrails` cannot be used as a package name, since it is already used in the main package.
* A package can implement additional guardrails functionality, but that would become something like `from agent_framework.azure import ContentSafetyGuardrail`, which would contain a guardrail implementation using Azure Content Safety, but it is not the same as the `agent_framework.guardrails` component.
* middleware
* telemetry (user_agent)
* advanced components, will be exposed from `agent_framework.<component>`:
* vector_data (tbd, vector stores and other MEVD-like pieces)
* text_search (tbd)
* exceptions
* evaluations (tbd)
* utils (optional)
* observability
* vendor folders with connectors and integrations, will be exposed from `agent_framework.<vendor>`:
* Code can be both in folder or in subpackage with lazy import.
* See subpackage scope below for more detail
* tests
* samples
* extensions
* azure
* ...
All the init's will use lazy loading so avoid importing the entire package when importing a single component.
All the init's in the subpackages will use lazy loading so avoid importing the entire package when importing a single component.
Internal imports will be done using relative imports, so that the package can be used as a namespace package.
### File structure
The resulting file structure will be as follows:
The resulting file structure will be as follows (not all things currently implemented, just an example):
```plaintext
packages/
main/
agent_framework/
azure/
__init__.py
_chat_client.py
...
microsoft/
__init__.py
_copilot_studio.py
...
openai/
__init__.py
_chat_client.py
@@ -103,17 +104,16 @@ packages/
_tools.py
_models.py
_logging.py
context_providers.py
guardrails.py
_middleware.py
_telemetry.py
observability.py
exceptions.py
evaluations.py
utils.py
telemetry.py
templates.py
text_search.py
vector_data.py
workflows.py
py.typed
_workflow/
__init__.py
_workflow.py
...etc...
tests/
unit/
test_types.py
@@ -122,28 +122,27 @@ packages/
pyproject.toml
README.md
...
mem0/
agent_framework/
mem0/
__init__.py
_mem0.py
...
azure-ai-agents/
agent_framework-azure-ai-agents/
__init__.py
_chat_client.py
...
tests/
test_azure_ai_agents.py
samples/ (optional)
...
pyproject.toml
README.md
...
redis/
...
google/
agent_framework/
google/
__init__.py
_chat.py
_bigquery.py
...
mem0/
agent_framework-mem0/
__init__.py
_provider.py
...
tests/
unit/
test_google_client.py
test_google_tools.py
...
integration/
test_google_integration.py
test_mem0_provider.py
samples/ (optional)
...
pyproject.toml
@@ -163,79 +162,31 @@ We might add a template subpackage as well, to make it easy to setup, this could
In the [`DEV_SETUP.md`](../../python/DEV_SETUP.md) we will add instructions for how to deal with the path depth issues, especially on Windows, where the maximum path length can be a problem.
### Subpackage scope
Sub-packages are comprised of two parts, the code itself and the dependencies, the choice of when to use a subpackage and when to use a extra in the main package is based on the status of dependencies and/or possibilities of a external support mechanism. What this means is that:
- Integrations that need non-GA dependencies will be sub-packages and installed only when using a extra, so that we can avoid having non-GA dependencies in the main package.
- Integrations where the AF-code is still experimental, preview or release candidate will be sub-packages, so that we can avoid having non-GA code in the main package and we can version those packages properly.
- Integrations that are outside Microsoft and where we might not always be able to fast-follow breaking changes, will stay as sub-packages, to provide some isolation and to be able to version them properly.
- Integrations that are mature and that have released (GA) dependencies and features on the service side will be moved into the main package, the dependencies of those packages will stay installable under the same `extra` name, so that users do not have to change anything, and we then remove the subpackage itself.
- All subpackage imports in the code should be from a stable place, mostly vendor-based, so that when something moves from a subpackage to the main package, the import path does not change, so `from agent_framework.microsoft import CopilotAgent` will always work, even if it moves from the `agent-framework-microsoft-copilot` package to the main `agent-framework` package.
- The imports in those vendor namespaces (these won't be actual python namespaces, just the folders with a __init__.py file and any code) will do lazy loading and raise a meaningful error if the subpackage or dependencies are not installed, so that users know which extra to install with ease.
- On a case by case basis we can decide to create additional a `extra`, that combines multiple sub-packages and dependencies into one extra, so that users who work primarily with one platform can install everything they need with a single extra, for example (not implemented) you can install with the `agent-framework[azure-purview]` extra that only implement a `PurviewMiddleware`, or you can install with the `agent-framework[azure]` extra that includes all Azure related connectors, like `purview`, `content-safety` and others (all examples, not actual packages), regardless of where the code sits, these should always be importable from `agent_framework.azure`.
- Subpackage naming should also follow this, so in principle a package name is `<vendor/folder>-<feature/brand>`, so `google-gemini`, `azure-purview`, `microsoft-copilotstudio`, etc. For smaller vendors, where it's less likely to have a multitude of connectors, we can skip the feature/brand part, so `mem0`, `redis`, etc.
- For Microsoft services we will have two vendor folders, `azure` and `microsoft`, where `azure` contains all Azure services, while `microsoft` contains other Microsoft services, such as Copilot Studio Agents.
This setup was discussed at length and the decision is captured in [ADR-0008](../decisions/0008-python-subpackages.md).
#### Evolving the package structure
For each of the advanced components, we have two reason why we may split them into a folder, with an `__init__.py` and optionally a `_files.py`:
1. If the file becomes too large, we can split it into multiple `_files`, while still keeping the public interface in the `__init__.py` file, this is a non-breaking change
2. If we want to partially or fully move that code into a separate package.
In this case we do need to lazy load anything that was moved from the main package to the subpackage, so that existing code still works, and if the subpackage is not installed we can raise a meaningful error.
> **Important**: This setup means that in a users machine, the code from the main package and the code from any installed subpackages will be put in the same folder in their python installation, this means there cannot be name clashes between the contents of a subpackage with each other, or with the main package. So the first level inside of those subpackages should be unique, preferably the same as the subpackage name. A subpackage can contain anything that is useful and related to Agent Framework, in that case for i.e. Azure, that would mean the following structure:
```plaintext
<!-- inside the Azure subpackage: -->
agent_framework/
azure/
__init__.py
_chat.py
_embeddings.py
_context_safety.py
...
```
## Coding standards
Coding standards will be maintained in the [`DEV_SETUP.md`](../../python/DEV_SETUP.md) file.
[tool.ruff.lint]
fixable = ["ALL"]
unfixable = []
select = [
"ASYNC", # async checks
"B", # bugbear checks
"CPY", #copyright
"D", #pydocstyle checks
"E", #error checks
"ERA", #remove connected out code
"F", #pyflakes checks
"FIX", #fixme checks
"I", #isort
"INP", #implicit namespace package
"ISC", #implicit string concat
"Q", # flake8-quotes checks
"RET", #flake8-return check
"RSE", #raise exception parantheses check
"RUF", # RUF specific rules
"SIM", #flake8-simplify check
"T100", # Debugger,
"TD", #todos
"W", # pycodestyle warning checks
]
ignore = [
"D100", #allow missing docstring in public module
"D104", #allow missing docstring in public package
"TD003", #allow missing link to todo issue
"FIX002" #allow todo
]
[tool.ruff.format]
docstring-code-format = true
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.lint.per-file-ignores]
# Ignore all directories named `tests` and `samples`.
"tests/**" = ["D", "INP", "TD", "ERA001", "RUF"]
"samples/**" = ["D", "INP", "ERA001", "RUF"]
# Ignore all files that end in `_test.py`.
"*_test.py" = ["D"]
"*.ipynb" = ["CPY", "E501"]
[tool.ruff.lint.flake8-copyright]
notice-rgx = "^# Copyright \\(c\\) Microsoft\\. All rights reserved\\."
min-file-size = 1
```
### Tooling
uv and ruff are the main tools, for package management and code formatting/linting respectively.
Agent Framework and Foundry SDK have overlapping functionality but serve different audiences & scenarios.
This specification clarifies the positioning of these SDKs to customers, what goes in each and when to use what.
- **Foundry SDK** is a thin-client SDK for accessing everything available in the agent service and is autogenerated from REST APIs in multiple languages
- **Agent Framework SDK** is general-purpose framework for agentic application development, where common agent abstractions enable creating and orchestrating heterogenous agent systems (across local & cloud)
## What is the goal of this feature?
Goals:
- Developers can seamlessly combine Foundry and Agent Framework SDK's and there is no friction when using both SDKs at the same time
- Developers can take advantage of the full capabilities supported by the Foundry SDK
- Developers can create multi-agent orchestrations using Foundry and other agent types
Success Metrics:
- Complexity of basic samples is comparable to other agent frameworks
- Developers can easily discover how to use Foundry Agents in Agent Framework multi-agent orchestrations
## What is the problem being solved?
- In Semantic Kernel the Foundry Agent support isn't integrated into the Foundry SDK so there is a disjointed developer UX
- Customers are confused as to when they should use Foundry SDK versus Semantic Kernel
## API Changes
The proposed solution is to add helper methods which allow developers to either retrieve or create an `AIAgent` using a `PersistentAgentsClient`
- Retrieve an `AIAgent`
```csharp
/// <summary>
/// Retrieves an existing server side agent, wrapped as a <see cref="ChatClientAgent"/> using the provided <see cref="PersistentAgentsClient"/>.
/// </summary>
/// <param name="persistentAgentsClient">The <see cref="PersistentAgentsClient"/> to create the <see cref="ChatClientAgent"/> with.</param>
/// <returns>A <see cref="ChatClientAgent"/> for the persistent agent.</returns>
/// <param name="agentId"> The ID of the server side agent to create a <see cref="ChatClientAgent"/> for.</param>
/// <param name="chatOptions">Options that should apply to all runs of the agent.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the persistent agent.</returns>
public static async Task<ChatClientAgent> GetAIAgentAsync(
this PersistentAgentsClient persistentAgentsClient,
string agentId,
ChatOptions? chatOptions = null,
CancellationToken cancellationToken = default)
```
- Create an `AIAgent`
```csharp
/// <summary>
/// Creates a new server side agent using the provided <see cref="PersistentAgentsClient"/>.
/// </summary>
/// <param name="persistentAgentsClient">The <see cref="PersistentAgentsClient"/> to create the agent with.</param>
/// <param name="model">The model to be used by the agent.</param>
/// <param name="name">The name of the agent.</param>
/// <param name="description">The description of the agent.</param>
/// <param name="instructions">The instructions for the agent.</param>
/// <param name="tools">The tools to be used by the agent.</param>
/// <param name="toolResources">The resources for the tools.</param>
/// <param name="temperature">The temperature setting for the agent.</param>
/// <param name="topP">The top-p setting for the agent.</param>
/// <param name="responseFormat">The response format for the agent.</param>
/// <param name="metadata">The metadata for the agent.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
public static async Task<ChatClientAgent> CreateAIAgentAsync(
this PersistentAgentsClient persistentAgentsClient,
/// Creates a new server side agent using the provided <see cref="PersistentAgentsClient"/>.
/// </summary>
/// <param name="persistentAgentsClient">The <see cref="PersistentAgentsClient"/> to create the agent with.</param>
/// <param name="model">The model to be used by the agent.</param>
/// <param name="name">The name of the agent.</param>
/// <param name="description">The description of the agent.</param>
/// <param name="instructions">The instructions for the agent.</param>
/// <param name="tools">The tools to be used by the agent.</param>
/// <param name="temperature">The temperature setting for the agent.</param>
/// <param name="topP">The top-p setting for the agent.</param>
/// <param name="responseFormat">The response format for the agent.</param>
/// <param name="metadata">The metadata for the agent.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
public static async Task<ChatClientAgent> CreateAIAgentAsync(
this PersistentAgentsClient persistentAgentsClient,
date: {YYYY-MM-DD when the decision was last updated}
deciders: {list everyone involved in the decision}
consulted: {list everyone whose opinions are sought (typically subject-matter experts); and with whom there is a two-way communication}
informed: {list everyone who is kept up-to-date on progress; and with whom there is a one-way communication}
---
# {short title of solved problem and solution}
## What is the goal of this feature?
Make sure to cover:
1. What is the value we are providing to users
1. Include one success metric
1. Implementation free description of outcome
Consult PM on this.
For example:
We want users to be able to refer to external Azure resources easily when consuming them in other features like indexes, agents,
and evaluations. We know we're successful when 40% of project client users are using connections.
## What is the problem being solved?
Make sure to cover:
1. Why is this hard today?
1. Customer pain points?
1. Reducing system complexity (maintenance costs, latency, etc)?
Consult PM on this.
For example:
Today, users have to understand control plane vs data plane endpoints and use multiple packages to stitch their application
code together. This makes using our product confusing and also increases the number of dependencies a customer will have
in their code.
## API Changes
List all new API changes
## E2E Code Samples
Include python or C# examples of how you expect this feature to be used with other things in our system.
For example:
This connection name is unique across the resource. Given a resource name, system should be able to unambiguously resolve a
connection name. A connection name can be used to pass along connection details to individual features. Services will be able to parse this ID and use it to access the underlying resource. The below example shows how a connection can be used to create a dataset.
```python
client.datasets.create_dataset(
name="evaluation_dataset",
file="myblob/product1.pdf",
connection = "my-azure-blob-connection"
)
```
How to use a connection when creating an `AzureAISearchIndex`
```python
from azure.ai.projects.models import AzureAISearchIndex
Microsoft Agent Framework is a comprehensive .NET library for building, orchestrating, and deploying AI agents and multi-agent workflows. The framework provides everything from simple chat agents to complex multi-agent systems with graph-based orchestration capabilities.
## Key Features
- **Multi-Agent Orchestration**: Coordinate multiple agents using sequential, concurrent, group chat, and handoff patterns
- **Graph-based Workflows**: Connect agents and functions with streaming, checkpointing, and human-in-the-loop capabilities, with both imperative or declarative workflow support
- **Multiple Provider Support**: Seamlessly integrate with various LLM providers with more being added continuously
- **Extensible Middleware**: Flexible request/response processing with custom pipelines and exception handling
- **Built-in Observability**: OpenTelemetry integration for distributed tracing, monitoring, and debugging
- **Cross-Platform**: Compatible with .NET 8.0, .NET Standard 2.0, and .NET Framework for broad deployment options
Whether you're building simple AI assistants or complex multi-agent systems, Microsoft Agent Framework provides the tools and abstractions needed to create robust, scalable AI applications in .NET.
# Getting Started ⚡
- Learn more at the [documentation site](https://aka.ms/TBD).
- Join the [Discord community](https://aka.ms/TBD).
- Follow the team on [Semantic Kernel blog](https://aka.ms/TBD).
- Learn more at the [documentation site](https://learn.microsoft.com/agent-framework/overview/agent-framework-overview).
- Join the [Discord community](https://discord.gg/b5zjErwbQM).
- Follow the team on [Semantic Kernel blog](https://devblogs.microsoft.com/semantic-kernel/).
- Check out the [GitHub repository](https://github.com/microsoft/agent-framework) for the latest updates.
<!-- Default description and tags. Packages can override. -->
<Authors>Microsoft</Authors>
<Company>Microsoft</Company>
<Product>Agent Framework</Product>
<Description>Empowers app owners to integrate Agents quickly and easily into their apps.</Description>
<Product>Microsoft Agent Framework</Product>
<Description>Microsoft Agent Framework is a comprehensive .NET library for building, orchestrating, and deploying AI agents and multi-agent workflows. The framework provides everything from simple chat agents to complex multi-agent systems with graph-based orchestration capabilities.</Description>
> The [A2A protocol](https://google.github.io/A2A/) is still under development and changing fast.
> We will try to keep these samples updated as the protocol evolves.
These samples are built with [official A2A C# SDK](https://www.nuget.org/packages/A2A) and demonstrates:
1. Creating an A2A Server which makes an agent available via the A2A protocol.
2. Creating an A2A Client with a command line interface which invokes agents using the A2A protocol.
The demonstration has two components:
1. `A2AServer` - You will run three instances of the server to correspond to three A2A servers each providing a single Agent i.e., the Invoice, Policy and Logistics agents.
2. `A2AClient` - This represents a client application which will connect to the remote A2A servers using the A2A protocol so that it can use those agents when answering questions you will ask.
The samples can be configured to use chat completion agents or Azure AI agents.
### Configuring for use with Chat Completion Agents
Provide your OpenAI API key via an environment variable
```powershell
$env:OPENAI_API_KEY="<Your OpenAI API Key>"
```
Use the following commands to run each A2A server:
Execute the following command to build the sample:
```powershell
cd A2AServer
dotnet build
```
```bash
dotnet run --urls "http://localhost:5000;https://localhost:5010" --agentType "invoice" --no-build
```
```bash
dotnet run --urls "http://localhost:5001;https://localhost:5011" --agentType "policy" --no-build
```
```bash
dotnet run --urls "http://localhost:5002;https://localhost:5012" --agentType "logistics" --no-build
```
### Configuring for use with Azure AI Agents
You must create the agents in an Azure AI Foundry project and then provide the project endpoint and agents ids. The instructions for each agent are as follows:
- Invoice Agent
```
You specialize in handling queries related to invoices.
```
- Policy Agent
```
You specialize in handling queries related to policies and customer communications.
Always reply with exactly this text:
Policy: Short Shipment Dispute Handling Policy V2.1
Summary: "For short shipments reported by customers, first verify internal shipment records
(SAP) and physical logistics scan data (BigQuery). If discrepancy is confirmed and logistics data
shows fewer items packed than invoiced, issue a credit for the missing items. Document the
resolution in SAP CRM and notify the customer via email within 2 business days, referencing the
original invoice and the credit memo number. Use the 'Formal Credit Notification' email
template."
```
- Logistics Agent
```
You specialize in handling queries related to logistics.
Always reply with exactly:
Shipment number: SHPMT-SAP-001
Item: TSHIRT-RED-L
Quantity: 900"
```
```powershell
$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://ai-foundry-your-project.services.ai.azure.com/api/projects/ai-proj-ga-your-project" # Replace with your Foundry Project endpoint
The A2A Inspector is a web-based tool designed to help developers inspect, debug, and validate servers that implement the Google A2A (Agent2Agent) protocol. It provides a user-friendly interface to interact with an A2A agent, view communication, and ensure specification compliance.
For more information go [here](https://github.com/a2aproject/a2a-inspector).
Running the [inspector with Docker](https://github.com/a2aproject/a2a-inspector?tab=readme-ov-file#option-two-run-with-docker) is the easiest way to get started.
1. Navigate to the A2A Inspector in your browser: [http://127.0.0.1:8080/](http://127.0.0.1:8080/)
1. Enter the URL of the Agent you are running e.g., [http://host.docker.internal:5000](http://host.docker.internal:5000)
1. Connect to the agent and the agent card will be displayed and validated.
1. Type a message and send it to the agent using A2A protocol.
1. The response will be validated automatically and then displayed in the UI.
1. You can select the response to view the raw json.
Agent card after connecting to an agent using the A2A protocol:
1. Run the A2A server's using the commands shown earlier
2. Run the A2A client:
```bash
cd A2AClient
dotnet run
```
3. Enter your request e.g. "Customer is disputing transaction TICKET-XYZ987 as they claim the received fewer t-shirts than ordered."
4. The host client agent will call the remote agents, these calls will be displayed as console output. The final answer will use information from the remote agents. The sample below includes all three agents but in your case you may only see the policy and invoice agent.
Sample output from the A2A client:
```
A2AClient> dotnet run
info: HostClientAgent[0]
Initializing Agent Framework agent with model: gpt-4o-mini
User (:q or quit to exit): Customer is disputing transaction TICKET-XYZ987 as they claim the received fewer t-shirts than ordered.
Agent:
Agent:
Agent: The transaction details for **TICKET-XYZ987** are as follows:
- **Invoice ID:** INV789
- **Company Name:** Contoso
- **Invoice Date:** September 4, 2025
- **Products:**
- **T-Shirts:** 150 units at $10.00 each
- **Hats:** 200 units at $15.00 each
- **Glasses:** 300 units at $5.00 each
To proceed with the dispute regarding the quantity of t-shirts delivered, please specify the exact quantity issue � how many t-shirts were actually received compared to the ordered amount.
### Customer Service Policy for Handling Disputes
**Short Shipment Dispute Handling Policy V2.1**
- **Summary:** For short shipments reported by customers, first verify internal shipment records and physical logistics scan data. If a discrepancy is confirmed and the logistics data shows fewer items were packed than invoiced, a credit for the missing items will be issued.
- **Follow-up Actions:** Document the resolution in the SAP CRM and notify the customer via email within 2 business days, referencing the original invoice and the credit memo number, using the 'Formal Credit Notification' email template.
Please provide me with the information regarding the specific quantity issue so I can assist you further.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.