Compare commits

..
Author SHA1 Message Date
Roger Barreto 8755dc4e1a Merge branch 'feature-foundry-agents' of https://github.com/microsoft/agent-framework into feature-foundry-agents 2025-11-15 01:05:10 +00:00
Roger Barreto 3adf2ee3d5 Package descriptions 2025-11-15 01:05:00 +00:00
Roger BarretoandGitHub 2b8291cefc Merge branch 'main' into feature-foundry-agents 2025-11-15 01:04:31 +00:00
5d913539b5 .NET: Added Computer use tool sample (#2235)
* Initial computer use sample implementation.

* Added background thread to allow polling for long running requests.

* Removed unrequired try-catch block and added missing thread for agent call.

* Removed irrelevant chatOptions and updated code based on feedback.

* Updated image assets and fixed response issue.

* Updated based on PR comments.

* Update to Azure.AI.Project

---------

Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2025-11-14 15:44:00 -08:00
Roger BarretoandGitHub 100a1e753e .NET: Add Conformance Integration Tests for AzureAI Package (#2237)
* Conformance tests added and passing

* Correct namespace

* Update Azure.AI.Project to latest public nuget version
2025-11-14 23:20:47 +00:00
ChrisandGitHub 480b7fb084 Merge branch 'main' into feature-foundry-agents 2025-11-14 13:59:40 -08:00
ChrisandGitHub 6e66e6836b Merge branch 'main' into feature-foundry-agents 2025-11-14 11:39:07 -08:00
ChrisandGitHub 3e84a5c4a6 Allow dotnet-format workflow on feature branches
Revert unintentional edit
2025-11-14 11:38:43 -08:00
Roger BarretoandGitHub d95758be10 Merge branch 'main' into feature-foundry-agents 2025-11-14 18:20:52 +00:00
Roger BarretoandGitHub fb32110ca0 Merge branch 'main' into feature-foundry-agents 2025-11-14 12:21:57 +00:00
Roger BarretoandGitHub 0746d7751a .NET: Feature foundry agent/update breaking v2.0 to v1.2 (#2212)
* Migration WIP Checkpoint 1

* Build + UT + Workflow passing

* Address latest commits after break

* Revert rename in unrelated files

* Address PR comments

* Class renames
2025-11-14 12:20:56 +00:00
ChrisandGitHub 7c90690067 Update version (#2206) 2025-11-13 16:04:45 -08:00
ChrisandGitHub 173a1aeeaf Merge branch 'main' into feature-foundry-agents 2025-11-13 15:20:28 -08:00
ChrisandGitHub 692ad48023 Fixed (#2204) 2025-11-13 15:18:28 -08:00
ChrisandGitHub bc6bbc20d1 .NET Workflows - Add sample for hosted declarative workflow (#2199)
* fwiw

* Less blank lines
2025-11-13 12:52:34 -08:00
ChrisandGitHub 5cced10977 Merge branch 'main' into feature-foundry-agents 2025-11-13 11:38:07 -08:00
ChrisandGitHub 1d6f53b3df .NET Workflows - Add "CustomerSupport" sample (#2102) 2025-11-13 11:27:02 -08:00
ChrisandGitHub 5303c700ef Merge branch 'main' into feature-foundry-agents 2025-11-13 11:07:26 -08:00
ChrisandGitHub 18a33a2608 Merge branch 'main' into feature-foundry-agents 2025-11-13 10:17:02 -08:00
ChrisandGitHub 63352137f3 Fixed (#2190) 2025-11-13 10:16:47 -08:00
ChrisandGitHub b404fdfb70 Merge branch 'main' into feature-foundry-agents 2025-11-13 08:05:17 -08:00
Roger BarretoandGitHub 59d08ad29e .NET: Foundry Agents V2 - Add CodeInterpreter Sample (#2180)
* Adding Code Interpreter sample and AgentName naming validation

* Add agent name check UT

* Improve sample code

* Apply suggestion

* Apply suggestion
2025-11-13 15:23:51 +00:00
eb2d573f03 .NET: Add GettingStarted Samples for Agents V2. (#2159)
* Add gettingstarted samples for Foundry Agents

* Address structured outputs

* Net 10 -> Net 9 Temporary

* Net 10 -> Net 9 Temporary

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Address missing docs + old

* Drop var for samples

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Address copilot feedback

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-13 10:58:35 +00:00
ChrisandGitHub 5246edbcb2 Merge branch 'main' into feature-foundry-agents 2025-11-12 19:14:23 -08:00
ChrisandGitHub 95cc5e51f2 Merge branch 'main' into feature-foundry-agents 2025-11-12 19:08:34 -08:00
ChrisandGitHub 668692c6b2 Merge branch 'main' into feature-foundry-agents 2025-11-12 16:57:50 -08:00
ChrisandGitHub 4adb758593 Merge branch 'main' into feature-foundry-agents 2025-11-12 15:51:42 -08:00
ChrisandGitHub 85550834d4 Merge branch 'main' into feature-foundry-agents 2025-11-12 15:07:18 -08:00
Roger BarretoandGitHub 56ced98b27 .NET: Feature foundry agent/agent reference extension (Python Parity with Name + Version option) (#2147)
* Add agent reference extensions

* Add UT covering AgentReference and ModelId
2025-11-12 21:32:24 +00:00
ChrisandGitHub 0f539d9748 Merge branch 'main' into feature-foundry-agents 2025-11-12 12:44:02 -08:00
ChrisandGitHub 3a89a6d28a Fix declarative workflows integration testcase 2025-11-12 09:20:16 -08:00
ChrisandGitHub 119b7eabd4 Merge branch 'main' into feature-foundry-agents 2025-11-12 08:53:51 -08:00
9687e6e6a5 .NET: Updates to Foundry Agents Package (#2125)
* Remove the conversation creation always

* Update unit tests + address IL + refactor

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Internalize unused methods

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-12 13:32:42 +00:00
Mark WallaceandGitHub ec86cb56b5 Merge branch 'main' into feature-foundry-agents 2025-11-12 12:08:27 +00:00
ChrisandGitHub 2707adade7 Merge branch 'main' into feature-foundry-agents 2025-11-11 16:28:53 -08:00
ChrisandGitHub 78fbf5610f Remove unused using directive in AzureAgentProvider
Removed unused using directive for Extensions.
2025-11-11 15:12:00 -08:00
ChrisandGitHub 56f0ec9fa3 Merge branch 'main' into feature-foundry-agents 2025-11-11 15:03:48 -08:00
ChrisandGitHub 4fb7a427b1 .NET Workflows - Separate Foundry/AzureAI Provider into its own package (#2078) 2025-11-11 13:58:27 -08:00
ChrisandGitHub 832b715657 Merge branch 'main' into feature-foundry-agents 2025-11-11 12:23:56 -08:00
Roger BarretoandGitHub 34e811fd36 Merge branch 'main' into feature-foundry-agents 2025-11-11 19:25:25 +00:00
Roger Barreto d3b5c6b18c Bump version for release 2025-11-11 19:22:25 +00:00
ChrisandGitHub 39598741e4 .NET Workflows - Support "structured inputs" feature for declarative workflows (#2053) 2025-11-11 10:36:18 -08:00
ChrisandGitHub d1009845c9 Merge branch 'main' into feature-foundry-agents 2025-11-11 10:09:59 -08:00
ChrisandGitHub 7eec3f3967 Merge branch 'main' into feature-foundry-agents 2025-11-11 10:03:25 -08:00
a257db3aea .NET: Update Extensions to be less restrictive for GetAIAgents (#2091)
* Update behavior / restrictiveness when retrieving agents

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Address format

* Address copilot feedback

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
2025-11-11 17:52:21 +00:00
ChrisandGitHub a746cedf59 Merge branch 'main' into feature-foundry-agents 2025-11-11 09:13:27 -08:00
ChrisandGitHub a58df61837 Merge branch 'main' into feature-foundry-agents 2025-11-11 08:03:27 -08:00
Mark WallaceandGitHub a93824f5c4 Merge branch 'main' into feature-foundry-agents 2025-11-11 12:01:22 +00:00
ChrisandGitHub 168186a5ed Merge branch 'main' into feature-foundry-agents 2025-11-10 21:29:41 -08:00
ChrisandGitHub fb38ae8553 Merge branch 'main' into feature-foundry-agents 2025-11-10 21:09:06 -08:00
105dc82c39 .NET: Feature foundry agent + user agent (#2058)
* Update unit tests

* Add user-agent protocol calls

* Update unit tests

* Update unit tests with http handler confirmation

* UT fix

* Fix xmldoc

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Address copilot feedback

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-10 18:34:32 +00:00
ChrisandGitHub c07e6afe21 Update AgentsClientExtensionsTests.cs
Fix invalid cast format failure
2025-11-10 08:48:26 -08:00
ChrisandGitHub 4ea6411001 Merge branch 'main' into feature-foundry-agents 2025-11-10 08:42:17 -08:00
Roger BarretoandGitHub 68f79d8bea .NET: Update Foundry Agents to latest 2.0.0 alpha.20251107.3 (#2050)
* Update extensions for new CreateVersionOptions structure

* Update unit tests

* Addresss capitalized
2025-11-10 15:40:37 +00:00
fb1f4e2799 .NET: Latest updates Pre/Post V2 Bugbash Findings (#2040)
* Improve V2 logic before/after bugbash prep

* Apply suggestions from code review

Co-authored-by: Stephen Toub <stoub@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Stephen Toub <stoub@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-10 11:13:42 +00:00
ChrisandGitHub e17b4b6441 Merge branch 'main' into feature-foundry-agents 2025-11-07 11:37:33 -08:00
ChrisGitHubrogerbarretoCopilotcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>CopilotDmytro Struk
2b869c2396 .NET Workflows - WIP Declarative action update (#1761)
* WIP

* Fixed build errors (#1638)

Comment and nullable type alignment

* Sync to SDK update

* Checkpoint

* Checkpoint: Tests passing

* Checkpoint: EndWorkflow

* Add trace

* .NET: Azure.AI.Agents Package Split + Initial Extensions (#1657)

* Move packages

* Update nuget.config

* Address Xmldoc

* Remove format from branches checks

* Address Xmldocs

* Add more details to the implementation

* Moving Agent logic to ChatClient

* Adding Name and Id overrides to AzureAIAgent

* Updating extensions

* Add GetAiAgent extensions

* Adding support for version as name can conflict 409 using the Agents API with same name

* Addressing more updates to the extensions

* More improvements

* Remove debugging code from sample

* Address copilot feedback

* Apply suggestions from co-pilot code review

* Checkpoint

* Update Directory.Packages.props

Fix package version rollback:

Azure.AI.Agents.Persistent (beta-6 => beta-7)

* Add project reference

* .NET: Add comprehensive unit tests for Microsoft.Agents.AI.AzureAIAgents extension methods (#1786)

* Initial plan

* Add comprehensive unit test project for Microsoft.Agents.AI.AzureAIAgents

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Add README documenting test project and package dependency requirements

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Fix documentation URL to use learn.microsoft.com

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Bump back AAAP 1.2.0-beta.7

* Address AI generated UT's

* Remove UT Readme

* Apply suggestions from code review

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: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* .NET: Change model to be required just for prompt agent definition specific extensions (#1812)

* Remove unneeded model from extensions

* Add noop justification

* Update Package Nameing: V1 -> AzureAI.Persistent / V2 -> AzureAI (#1829)

* Checkpoint for merge

* No build errors

* .NET: Update Extensions for Strict Agent Definitions + Improvements (#1892)

* Update Package Nameing: V1 -> AzureAI.Persistent / V2 -> AzureAI

* Update agents and extensions to comply with strict agent definitions

* More static updates

* Address UT, and ResponseTool support

* Improving reusability extensions

* Addressing ResponseTools Unit Tests and extension setup

* Adapted workaround on breaking AAA with OpenAI 2.6.0

* Small updates

* Remove strictness when retrieving agents, improved XmlDocs

* Improve sample comments

* Update dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/AgentsClientExtensionsTests.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Address PR comments

* Address UT failing

* Address Copilot feedback

* Address Copilot feedback

* Address comment typo

* Address PR feedback

* Address typo

* Add missing Extensions with ChatClientAgentOptions

* Address comments

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Updated package version (#1897)

* Version update (#1901)

* Checkpoint

* Updated package version (#1906)

* Checkpoint

* Checkpoint

* Checkpoint

* Align with azure ai agent

* Update dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Workflows/Declarative/MCPToolApproval/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactored external input

* Update dotnet/samples/GettingStarted/Workflows/Declarative/MCPToolApproval/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Agent tools patch

* Demos validated

* Checkpoint

* Hygiene

* Checkpoint - Samples

* Update dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Checkpoint

* Checkpoint - Deep Research

* Update baseline

* Update

* Typo

* Checkpoint

* Typos

* Sample cleanup

* Update dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/AzureAgentProvider.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/src/Microsoft.Agents.AI.AzureAI/AgentsClientExtensions.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Workflows/Declarative/ToolApproval/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Typo

* Typo

* Fix input loop

* Sample - Function Calling / External Input

* Typo

* Finessed

* Checkpoint

* Fix feed

* Checkpoint - so close

* Ding dong!

* "there" ***

* Fixup comments

* Fix sample

* Code analysis

* Header

* Typo (variableName)

* Remove dead code

* Skip test (agent api ratchet)

* Comment

* Update dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Typo

---------

Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
2025-11-07 11:37:21 -08:00
ChrisandGitHub 7c3d4fcf30 Merge branch 'main' into feature-foundry-agents 2025-11-07 10:20:58 -08:00
ChrisandGitHub 3d40f309ed Merge branch 'main' into feature-foundry-agents 2025-11-07 09:43:17 -08:00
ChrisandGitHub 73547ce28c Merge branch 'main' into feature-foundry-agents 2025-11-07 09:38:09 -08:00
ChrisandGitHub 91e63df616 Merge branch 'main' into feature-foundry-agents 2025-11-07 09:14:33 -08:00
ChrisandGitHub 4cbde55243 Merge branch 'main' into feature-foundry-agents 2025-11-06 18:48:17 -08:00
Chris Rickman 864b1f7a91 Fix bad merge 2025-11-06 18:40:34 -08:00
ChrisandGitHub 5131f3a129 Merge branch 'main' into feature-foundry-agents 2025-11-06 14:31:48 -08:00
ChrisandGitHub 2ee34beed5 Merge branch 'main' into feature-foundry-agents 2025-11-06 08:32:05 -08:00
Roger BarretoandGitHub d55b15903d .NET: AgentDefinition extensions method simplification (#1967)
* Update extensions methods that accepts AgentDefinition type to not be restrictive

* Update Unit Tests

* Revert yarn/package-lock

* Revert yarn/package-lock

* Address copilot feedback
2025-11-06 16:04:31 +00:00
ChrisandGitHub 5a8c8fe634 Merge branch 'main' into feature-foundry-agents 2025-11-05 19:55:57 -08:00
ChrisandGitHub b2c38ac98c Merge branch 'main' into feature-foundry-agents 2025-11-05 19:14:20 -08:00
ChrisandGitHub 1aa00e6428 Merge branch 'main' into feature-foundry-agents 2025-11-05 16:57:09 -08:00
ChrisandGitHub f0d2dd6774 Merge branch 'main' into feature-foundry-agents 2025-11-05 15:49:58 -08:00
ChrisandGitHub bf007f854c Updated (#1948) 2025-11-05 15:47:50 -08:00
ChrisandGitHub 55a4aa2b53 Merge branch 'main' into feature-foundry-agents 2025-11-05 12:26:13 -08:00
Roger Barreto 95fe891369 Normalize changes 2025-11-05 20:20:48 +00:00
Roger Barreto 4d1a132737 .NET: Allow Declarative AIAgents Extensions (#1931)
* Improve reusability of extension code and additional option to losen the strictiness of in-proc tools

* Add missing UT scenarios

* Add missing UT test scenarios
2025-11-05 20:14:23 +00:00
Dmytro StrukandRoger Barreto 943e37836f Updated package version (#1906) 2025-11-05 20:14:22 +00:00
Roger Barreto 65e1c12dfa Version update (#1901) 2025-11-05 20:14:21 +00:00
Roger BarretoandCopilot 279d91f58e .NET: Update Extensions for Strict Agent Definitions + Improvements (#1892)
* Update Package Nameing: V1 -> AzureAI.Persistent / V2 -> AzureAI

* Update agents and extensions to comply with strict agent definitions

* More static updates

* Address UT, and ResponseTool support

* Improving reusability extensions

* Addressing ResponseTools Unit Tests and extension setup

* Adapted workaround on breaking AAA with OpenAI 2.6.0

* Small updates

* Remove strictness when retrieving agents, improved XmlDocs

* Improve sample comments

* Update dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/AgentsClientExtensionsTests.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Address PR comments

* Address UT failing

* Address Copilot feedback

* Address Copilot feedback

* Address comment typo

* Address PR feedback

* Address typo

* Add missing Extensions with ChatClientAgentOptions

* Address comments

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-05 20:14:12 +00:00
Roger Barreto 51e7a2134a Update Package Nameing: V1 -> AzureAI.Persistent / V2 -> AzureAI (#1829) 2025-11-05 20:13:36 +00:00
Roger Barreto 90226526fa .NET: Change model to be required just for prompt agent definition specific extensions (#1812)
* Remove unneeded model from extensions

* Add noop justification
2025-11-05 20:11:43 +00:00
CopilotRoger BarretoCopilotcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
7405759593 .NET: Add comprehensive unit tests for Microsoft.Agents.AI.AzureAIAgents extension methods (#1786)
* Initial plan

* Add comprehensive unit test project for Microsoft.Agents.AI.AzureAIAgents

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Add README documenting test project and package dependency requirements

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Fix documentation URL to use learn.microsoft.com

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Bump back AAAP 1.2.0-beta.7

* Address AI generated UT's

* Remove UT Readme

* Apply suggestions from code review

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: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-05 20:11:32 +00:00
ChrisandRoger Barreto 698aba5f97 Update Directory.Packages.props
Fix package version rollback:

Azure.AI.Agents.Persistent (beta-6 => beta-7)
2025-11-05 20:10:31 +00:00
Roger Barreto 7e23140ca9 .NET: Azure.AI.Agents Package Split + Initial Extensions (#1657)
* Move packages

* Update nuget.config

* Address Xmldoc

* Remove format from branches checks

* Address Xmldocs

* Add more details to the implementation

* Moving Agent logic to ChatClient

* Adding Name and Id overrides to AzureAIAgent

* Updating extensions

* Add GetAiAgent extensions

* Adding support for version as name can conflict 409 using the Agents API with same name

* Addressing more updates to the extensions

* More improvements

* Remove debugging code from sample

* Address copilot feedback

* Apply suggestions from co-pilot code review
2025-11-05 20:10:24 +00:00
ChrisandRoger Barreto 904e17473f Fixed build errors (#1638)
Comment and nullable type alignment
2025-11-05 20:09:02 +00:00
Roger Barreto 2c5cf6c67b WIP 2025-11-05 20:08:55 +00:00
835 changed files with 8333 additions and 38195 deletions
+2 -3
View File
@@ -1,11 +1,10 @@
{
"name": "C# (.NET)",
"image": "mcr.microsoft.com/devcontainers/dotnet:10.0",
"image": "mcr.microsoft.com/devcontainers/dotnet:9.0",
"features": {
"ghcr.io/devcontainers/features/dotnet:2.4.0": {},
"ghcr.io/devcontainers/features/powershell:1.5.1": {},
"ghcr.io/devcontainers/features/azure-cli:1.2.8": {},
"ghcr.io/devcontainers/features/docker-in-docker:2.12.4": {}
"ghcr.io/devcontainers/features/azure-cli:1.2.8": {}
},
"workspaceFolder": "/workspaces/agent-framework/dotnet/",
"customizations": {
+3 -8
View File
@@ -11,6 +11,9 @@ updates:
schedule:
interval: "cron"
cronjob: "0 8 * * 4,0" # Every Thursday(4) and Sunday(0) at 8:00 UTC
experimental:
nuget-native-updater: false
enable-cooldown-metrics-collection: false
ignore:
# For all System.* and Microsoft.Extensions/Bcl.* packages, ignore all major version updates
- dependency-name: "System.*"
@@ -25,14 +28,6 @@ updates:
- "dependencies"
# Maintain dependencies for python
- package-ecosystem: "pip"
directory: "python/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "python"
- "dependencies"
- package-ecosystem: "uv"
directory: "python/"
schedule:
+15 -40
View File
@@ -18,7 +18,6 @@ on:
env:
COVERAGE_THRESHOLD: 80
COVERAGE_FRAMEWORK: net10.0 # framework target for which we run/report code coverage
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -60,9 +59,9 @@ jobs:
fail-fast: false
matrix:
include:
- { targetFramework: "net10.0", os: "ubuntu-latest", configuration: Release, integration-tests: true, environment: "integration" }
- { targetFramework: "net9.0", os: "windows-latest", configuration: Debug }
- { targetFramework: "net8.0", os: "ubuntu-latest", configuration: Release }
- { targetFramework: "net9.0", os: "ubuntu-latest", configuration: Release, integration-tests: true, environment: "integration" }
- { targetFramework: "net9.0", os: "ubuntu-latest", configuration: Debug }
- { targetFramework: "net9.0", os: "windows-latest", configuration: Release }
- { targetFramework: "net472", os: "windows-latest", configuration: Release, integration-tests: true, environment: "integration" }
runs-on: ${{ matrix.os }}
@@ -70,16 +69,16 @@ jobs:
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
sparse-checkout: |
.
.github
dotnet
python
workflow-samples
persist-credentials: false
sparse-checkout: |
.
.github
dotnet
python
workflow-samples
- name: Setup dotnet
uses: actions/setup-dotnet@v5.0.1
uses: actions/setup-dotnet@v5.0.0
with:
global-json-file: ${{ github.workspace }}/dotnet/global.json
- name: Build dotnet solutions
@@ -124,17 +123,7 @@ jobs:
popd
rm -rf "$TEMP_DIR"
# Start Cosmos DB Emulator for Cosmos-based unit tests (only on Windows)
- name: Start Azure Cosmos DB Emulator
if: runner.os == 'Windows'
shell: pwsh
run: |
Write-Host "Launching Azure Cosmos DB Emulator"
Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator"
Start-CosmosDbEmulator -NoUI -Key "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
echo "COSMOS_EMULATOR_AVAILABLE=true" >> $env:GITHUB_ENV
- name: Run Unit Tests
- name: Run Unit Tests Windows
shell: bash
run: |
export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | tr '\n' ' ')
@@ -144,20 +133,12 @@ jobs:
# Check if the project supports the target framework
if [[ "$target_frameworks" == *"${{ matrix.targetFramework }}"* ]]; then
if [[ "${{ matrix.targetFramework }}" == "${{ env.COVERAGE_FRAMEWORK }}" ]]; then
dotnet test -f ${{ matrix.targetFramework }} -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx --collect:"XPlat Code Coverage" --results-directory:"TestResults/Coverage/" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute
else
dotnet test -f ${{ matrix.targetFramework }} -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx
fi
dotnet test -f ${{ matrix.targetFramework }} -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx --collect:"XPlat Code Coverage" --results-directory:"TestResults/Coverage/" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute
else
echo "Skipping $project - does not support target framework ${{ matrix.targetFramework }} (supports: $target_frameworks)"
fi
done
env:
# Cosmos DB Emulator connection settings
COSMOSDB_ENDPOINT: https://localhost:8081
COSMOSDB_KEY: C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
- name: Log event name and matrix integration-tests
shell: bash
run: echo "github.event_name:${{ github.event_name }} matrix.integration-tests:${{ matrix.integration-tests }} github.event.action:${{ github.event.action }} github.event.pull_request.merged:${{ github.event.pull_request.merged }}"
@@ -195,9 +176,6 @@ jobs:
fi
done
env:
# Cosmos DB Emulator connection settings
COSMOSDB_ENDPOINT: https://localhost:8081
COSMOSDB_KEY: C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
# OpenAI Models
OpenAI__ApiKey: ${{ secrets.OPENAI__APIKEY }}
OpenAI__ChatModelId: ${{ vars.OPENAI__CHATMODELID }}
@@ -216,22 +194,19 @@ jobs:
# Generate test reports and check coverage
- name: Generate test reports
if: matrix.targetFramework == env.COVERAGE_FRAMEWORK
uses: danielpalme/ReportGenerator-GitHub-Action@5.5.0
uses: danielpalme/ReportGenerator-GitHub-Action@5.4.18
with:
reports: "./TestResults/Coverage/**/coverage.cobertura.xml"
targetdir: "./TestResults/Reports"
reporttypes: "HtmlInline;JsonSummary"
- name: Upload coverage report artifact
if: matrix.targetFramework == env.COVERAGE_FRAMEWORK
uses: actions/upload-artifact@v5
with:
name: CoverageReport-${{ matrix.os }}-${{ matrix.targetFramework }}-${{ matrix.configuration }} # Artifact name
path: ./TestResults/Reports # Directory containing files to upload
- name: Check coverage
if: matrix.targetFramework == env.COVERAGE_FRAMEWORK
shell: pwsh
run: .github/workflows/dotnet-check-coverage.ps1 -JsonReportPath "TestResults/Reports/Summary.json" -CoverageThreshold $env:COVERAGE_THRESHOLD
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
fail-fast: false
matrix:
include:
- { dotnet: "10.0", configuration: Release, os: ubuntu-latest }
- { dotnet: "9.0", configuration: Release, os: ubuntu-latest }
runs-on: ${{ matrix.os }}
env:
-2
View File
@@ -204,8 +204,6 @@ agents.md
# AI
.claude/
WARP.md
**/memory-bank/
**/projectBrief.md
# Azurite storage emulator files
*/__azurite_db_blob__.json
-2
View File
@@ -48,8 +48,6 @@ dotnet add package Microsoft.Agents.AI
- **[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
Still have questions? Join our [weekly office hours](./COMMUNITY.md#public-community-office-hours) or ask questions in our [Discord channel](https://discord.gg/b5zjErwbQM) to get help from the team and other users.
### ✨ **Highlights**
- **Graph-based Workflows**: Connect agents and deterministic functions using data flows with streaming, checkpointing, human-in-the-loop, and time-travel capabilities
+2 -2
View File
@@ -42,9 +42,9 @@ Microsoft Agent Framework relies on existing LLMs. Using the framework retains c
**Framework-Specific Limitations**:
- **Platform Requirements**: Python 3.10+ required, specific .NET versions (.NET 8.0, 9.0, 10.0, netstandard2.0, net472)
- **Platform Requirements**: Python 3.10+ required, specific .NET versions (.NET 8.0, 9.0, netstandard2.0, net472)
- **API Dependencies**: Requires proper configuration of LLM provider keys and endpoints
- **Orchestration Features**: Advanced orchestration patterns including GroupChat, Sequential, and Concurrent workflows are now available in both Python and .NET implementations. See the respective language documentation for examples.
- **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.
-3
View File
@@ -1,3 +0,0 @@
# Declarative Agents
This folder contains sample agent definitions than be ran using the declarative agent support, for python see the [declarative agent python sample folder](../python/samples/getting_started/declarative/).
-25
View File
@@ -1,25 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions is the language specified by the user. You return your answers in a JSON format. You must include Chat as the type in your response.
model:
id: =Env.AZURE_OPENAI_DEPLOYMENT_NAME
provider: AzureOpenAI
apiType: Chat
options:
temperature: 0.9
topP: 0.95
outputSchema:
properties:
language:
kind: string
required: true
description: The language of the answer.
answer:
kind: string
required: true
description: The answer text.
type:
kind: string
required: true
description: The type of the response.
@@ -1,25 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format. You must include Assistants as the type in your response.
model:
id: gpt-4o-mini
provider: AzureOpenAI
apiType: Assistants
options:
temperature: 0.9
topP: 0.95
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
type:
type: string
required: true
description: The type of the response.
-25
View File
@@ -1,25 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format. You must include Chat as the type in your response.
model:
id: gpt-4o-mini
provider: AzureOpenAI
apiType: Chat
options:
temperature: 0.9
topP: 0.95
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
type:
type: string
required: true
description: The type of the response.
@@ -1,25 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format. You must include Responses as the type in your response.
model:
id: gpt-4o-mini
provider: AzureOpenAI
apiType: Responses
options:
temperature: 0.9
topP: 0.95
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
type:
type: string
required: true
description: The type of the response.
-18
View File
@@ -1,18 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format.
model:
options:
temperature: 0.9
topP: 0.95
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
-29
View File
@@ -1,29 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions using the tools provided.
model:
options:
temperature: 0.9
topP: 0.95
allowMultipleToolCalls: true
chatToolMode: auto
tools:
- kind: function
name: GetWeather
description: Get the weather for a given location.
bindings:
get_weather: get_weather
parameters:
properties:
location:
kind: string
description: The city and state, e.g. San Francisco, CA
required: true
unit:
kind: string
description: The unit of temperature. Possible values are 'celsius' and 'fahrenheit'.
required: false
enum:
- celsius
- fahrenheit
-22
View File
@@ -1,22 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format.
model:
id: gpt-4.1-mini
options:
temperature: 0.9
topP: 0.95
connection:
kind: Remote
endpoint: =Env.AZURE_FOUNDRY_PROJECT_ENDPOINT
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
@@ -1,21 +0,0 @@
kind: Prompt
name: MicrosoftLearnAgent
description: Microsoft Learn Agent
instructions: You answer questions by searching the Microsoft Learn content only.
model:
id: =Env.AZURE_FOUNDRY_PROJECT_MODEL_ID
options:
temperature: 0.9
topP: 0.95
connection:
kind: remote
endpoint: =Env.AZURE_FOUNDRY_PROJECT_ENDPOINT
tools:
- kind: mcp
name: microsoft_learn
description: Get information from Microsoft Learn.
url: https://learn.microsoft.com/api/mcp
approvalMode:
kind: never
allowedTools:
- microsoft_docs_search
@@ -1,22 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions is the language specified by the user. You return your answers in a JSON format.
model:
id: =Env.AZURE_FOUNDRY_PROJECT_MODEL_ID
options:
temperature: 0.9
topP: 0.95
connection:
kind: remote
endpoint: =Env.AZURE_FOUNDRY_PROJECT_ENDPOINT
outputSchema:
properties:
language:
kind: string
required: true
description: The language of the answer.
answer:
kind: string
required: true
description: The answer text.
-28
View File
@@ -1,28 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions is the language specified by the user. You return your answers in a JSON format. You must include Chat as the type in your response.
model:
id: =Env.OPENAI_MODEL
provider: OpenAI
apiType: Chat
options:
temperature: 0.9
topP: 0.95
connection:
kind: key
key: =Env.OPENAI_API_KEY
outputSchema:
properties:
language:
kind: string
required: true
description: The language of the answer.
answer:
kind: string
required: true
description: The answer text.
type:
kind: string
required: true
description: The type of the response.
@@ -1,28 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format. You must include Assistants as the type in your response.
model:
id: gpt-4.1-mini
provider: OpenAI
apiType: Assistants
options:
temperature: 0.9
topP: 0.95
connection:
kind: ApiKey
key: =Env.OPENAI_APIKEY
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
type:
type: string
required: true
description: The type of the response.
-28
View File
@@ -1,28 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format. You must include Chat as the type in your response.
model:
id: gpt-4.1-mini
provider: OpenAI
apiType: Chat
options:
temperature: 0.9
topP: 0.95
connection:
kind: ApiKey
key: =Env.OPENAI_APIKEY
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
type:
type: string
required: true
description: The type of the response.
-28
View File
@@ -1,28 +0,0 @@
kind: Prompt
name: Assistant
description: Helpful assistant
instructions: You are a helpful assistant. You answer questions in the language specified by the user. You return your answers in a JSON format. You must include Responses as the type in your response.
model:
id: gpt-4.1-mini
provider: OpenAI
apiType: Responses
options:
temperature: 0.9
topP: 0.95
connection:
kind: ApiKey
key: =Env.OPENAI_APIKEY
outputSchema:
properties:
language:
type: string
required: true
description: The language of the answer.
answer:
type: string
required: true
description: The answer text.
type:
type: string
required: true
description: The type of the response.
+6 -4
View File
@@ -6,12 +6,14 @@
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<LangVersion>13</LangVersion>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);NU5128;CS8002</NoWarn>
<NoWarn>$(NoWarn);NU5128</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<TargetFrameworksCore>net10.0;net9.0;net8.0</TargetFrameworksCore>
<TargetFrameworks>$(TargetFrameworksCore);netstandard2.0;net472</TargetFrameworks>
<ProjectsCoreTargetFrameworks>net9.0;net8.0</ProjectsCoreTargetFrameworks>
<ProjectsDebugCoreTargetFrameworks>net9.0</ProjectsDebugCoreTargetFrameworks>
<ProjectsTargetFrameworks>net9.0;net8.0;netstandard2.0;net472</ProjectsTargetFrameworks>
<ProjectsDebugTargetFrameworks>net9.0;net472</ProjectsDebugTargetFrameworks>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">true</IsAotCompatible>
<Configurations>Debug;Release;Publish</Configurations>
</PropertyGroup>
+1 -1
View File
@@ -5,7 +5,7 @@
<Sdk Name="Microsoft.Build.CentralPackageVersions" Version="2.1.3" />
<!-- Only run 'dotnet format' on dev machines, Release builds. Skip on GitHub Actions -->
<!-- as this runs in its own Actions job. -->
<Target Name="DotnetFormatOnBuild" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Release' AND '$(GITHUB_ACTIONS)' == '' ">
<Target Name="DotnetFormatOnBuild" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Release' AND '$(GITHUB_ACTIONS)' == '' AND '$(TargetFramework)' == '$(ProjectsDebugTargetFrameworks)'">
<Message Text="Running dotnet format" Importance="high" />
<Exec Command="dotnet format --no-restore -v diag $(ProjectFileName)" />
</Target>
+20 -33
View File
@@ -7,35 +7,26 @@
</PropertyGroup>
<PropertyGroup>
<!-- Aspire -->
<AspireAppHostSdkVersion>13.0.1</AspireAppHostSdkVersion>
<AspireAppHostSdkVersion>13.0.0</AspireAppHostSdkVersion>
</PropertyGroup>
<ItemGroup>
<!-- Aspire.* -->
<PackageVersion Include="Anthropic" Version="11.0.0" />
<PackageVersion Include="Anthropic.Foundry" Version="0.1.0" />
<PackageVersion Include="Aspire.Azure.AI.OpenAI" Version="13.0.0-preview.1.25560.3" />
<PackageVersion Include="Aspire.Hosting.AppHost" Version="$(AspireAppHostSdkVersion)" />
<PackageVersion Include="Aspire.Hosting.Azure.CognitiveServices" Version="$(AspireAppHostSdkVersion)" />
<PackageVersion Include="Aspire.Microsoft.Azure.Cosmos" Version="$(AspireAppHostSdkVersion)" />
<PackageVersion Include="CommunityToolkit.Aspire.OllamaSharp" Version="13.0.0-beta.440" />
<PackageVersion Include="CommunityToolkit.Aspire.OllamaSharp" Version="13.0.0-beta.435" />
<!-- Azure.* -->
<PackageVersion Include="Azure.AI.Projects" Version="1.2.0-beta.3" />
<PackageVersion Include="Azure.AI.Projects.OpenAI" Version="1.0.0-beta.4" />
<PackageVersion Include="Azure.AI.Projects" Version="1.2.0-beta.1" />
<PackageVersion Include="Azure.AI.Projects.OpenAI" Version="1.0.0-beta.1" />
<PackageVersion Include="Azure.AI.Agents.Persistent" Version="1.2.0-beta.7" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.7.0-beta.1" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
<PackageVersion Include="Azure.Identity" Version="1.17.0" />
<PackageVersion Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.4.0" />
<!-- Google Gemini -->
<PackageVersion Include="Google.GenAI" Version="0.6.0" />
<PackageVersion Include="Mscc.GenerativeAI.Microsoft" Version="2.9.3" />
<!-- Microsoft.Azure.* -->
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.54.0" />
<!-- Newtonsoft.Json -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<!-- System.* -->
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.0" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
<PackageVersion Include="System.ClientModel" Version="1.8.1" />
<PackageVersion Include="System.ClientModel" Version="1.8.0" />
<PackageVersion Include="System.CodeDom" Version="10.0.0" />
<PackageVersion Include="System.Collections.Immutable" Version="10.0.0" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-rc.2.25502.107" />
@@ -57,13 +48,13 @@
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.13.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.13.0" />
<!-- Microsoft.AspNetCore.* -->
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="9.0.11" />
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.0.0" />
<!-- Microsoft.Extensions.* -->
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.AI.AzureAIInference" Version="10.0.0-preview.1.25559.3" />
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.0.1-preview.1.25571.5" />
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.0.0-preview.1.25559.3" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.0" />
@@ -89,21 +80,18 @@
<PackageVersion Include="Microsoft.SemanticKernel.Agents.AzureAI" Version="1.67.0-preview" />
<PackageVersion Include="Microsoft.SemanticKernel.Plugins.OpenApi" Version="1.67.0" />
<!-- Agent SDKs -->
<PackageVersion Include="Microsoft.Agents.CopilotStudio.Client" Version="1.3.171-beta" />
<!-- M365 Agents SDK -->
<PackageVersion Include="AdaptiveCards" Version="3.1.0" />
<PackageVersion Include="Microsoft.Agents.Authentication.Msal" Version="1.3.171-beta" />
<PackageVersion Include="Microsoft.Agents.Hosting.AspNetCore" Version="1.3.171-beta" />
<PackageVersion Include="Microsoft.Agents.CopilotStudio.Client" Version="1.2.41" />
<!-- A2A -->
<PackageVersion Include="A2A" Version="0.3.3-preview" />
<PackageVersion Include="A2A.AspNetCore" Version="0.3.3-preview" />
<!-- MCP -->
<PackageVersion Include="ModelContextProtocol" Version="0.4.0-preview.3" />
<!-- Inference SDKs -->
<PackageVersion Include="Anthropic.SDK" Version="5.8.0" />
<PackageVersion Include="AWSSDK.Extensions.Bedrock.MEAI" Version="4.0.4.6" />
<PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI" Version="0.10.0" />
<PackageVersion Include="OllamaSharp" Version="5.4.8" />
<PackageVersion Include="OpenAI" Version="2.7.0" />
<PackageVersion Include="OpenAI" Version="2.6.0" />
<!-- Identity -->
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.78.0" />
<!-- Workflows -->
@@ -125,17 +113,16 @@
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Mcp" Version="1.0.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7" />
<!-- Community -->
<PackageVersion Include="System.Linq.Async" Version="6.0.3" />
<!-- Test -->
<PackageVersion Include="FluentAssertions" Version="8.8.0" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Condition="'$(TargetFramework)' == 'net8.0'" Version="8.0.22" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Condition="'$(TargetFramework)' == 'net9.0'" Version="9.0.11" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Condition="'$(TargetFramework)' == 'net10.0'" Version="10.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.11" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageVersion Include="Moq" Version="[4.18.4]" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.abstractions" Version="2.0.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.3" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" />
<PackageVersion Include="xretry" Version="1.9.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<!-- Symbols -->
@@ -162,20 +149,20 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageVersion Include="Roslynator.Analyzers" Version="4.14.1" />
<PackageVersion Include="Roslynator.Analyzers" Version="[4.14.1]" />
<PackageReference Include="Roslynator.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageVersion Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" />
<PackageVersion Include="Roslynator.CodeAnalysis.Analyzers" Version="[4.14.0]" />
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="4.14.1" />
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="[4.14.0]" />
<PackageReference Include="Roslynator.Formatting.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
</Project>
+4 -30
View File
@@ -40,19 +40,16 @@
<Folder Name="/Samples/GettingStarted/A2A/">
<File Path="samples/GettingStarted/A2A/README.md" />
<Project Path="samples/GettingStarted/A2A/A2AAgent_AsFunctionTools/A2AAgent_AsFunctionTools.csproj" />
<Project Path="samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/AgentProviders/">
<File Path="samples/GettingStarted/AgentProviders/README.md" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_A2A/Agent_With_A2A.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_Anthropic/Agent_With_Anthropic.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Agent_With_AzureAIAgentsPersistent.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Agent_With_AzureAIProject.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Agent_With_AzureFoundryModel.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Agent_With_AzureOpenAIResponses.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Agent_With_GoogleGemini.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_ONNX/Agent_With_ONNX.csproj" />
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Agent_With_OpenAIAssistants.csproj" />
@@ -79,21 +76,11 @@
<Project Path="samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj" />
<Project Path="samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj" />
<Project Path="samples/GettingStarted/Agents/Agent_Step18_DeepResearch/Agent_Step18_DeepResearch.csproj" />
<Project Path="samples/GettingStarted/Agents/Agent_Step19_Declarative/Agent_Step19_Declarative.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/DeclarativeAgents/">
<Project Path="samples/GettingStarted/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/DevUI/">
<File Path="samples/GettingStarted/DevUI/README.md" />
<Project Path="samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/DevUI_Step01_BasicUsage.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/AgentWithAnthropic/">
<File Path="samples/GettingStarted/AgentWithAnthropic/README.md" />
<Project Path="samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Agent_Anthropic_Step01_Running.csproj" />
<Project Path="samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Agent_Anthropic_Step02_Reasoning.csproj" />
<Project Path="samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Agent_Anthropic_Step03_UsingFunctionTools.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/AgentWithMemory/">
<File Path="samples/GettingStarted/AgentWithMemory/README.md" />
<Project Path="samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/AgentWithMemory_Step01_ChatHistoryMemory.csproj" />
@@ -114,14 +101,13 @@
<Project Path="samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/AgentWithRAG_Step01_BasicTextRAG.csproj" />
<Project Path="samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/AgentWithRAG_Step02_CustomVectorStoreRAG.csproj" />
<Project Path="samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/AgentWithRAG_Step03_CustomRAGDataSource.csproj" />
<Project Path="samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/AgentWithRAG_Step04_FoundryServiceRAG.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/FoundryAgents/">
<File Path="samples/GettingStarted/FoundryAgents/README.md" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step03.1_UsingFunctionTools/FoundryAgents_Step03.1_UsingFunctionTools.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step03.2_UsingFunctionTools_FromOpenAPI/FoundryAgents_Step03.2_UsingFunctionTools_FromOpenAPI.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj" />
<Project Path="samples/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj" />
@@ -205,7 +191,7 @@
<Project Path="samples/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowAsAnAgentObservability.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/Workflows/Visualization/">
<Project Path="samples/GettingStarted/Workflows/Visualization/Visualization.csproj" />
<Project Path="samples/GettingStarted/Workflows/Visualization/Visualization.csproj" Id="99bf0bc6-2440-428e-b3e7-d880e4b7a5fd" />
</Folder>
<Folder Name="/Samples/GettingStarted/Workflows/_Foundational/">
<Project Path="samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/01_ExecutorsAndEdges.csproj" />
@@ -222,9 +208,6 @@
<Project Path="samples/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj" />
<Project Path="samples/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj" />
</Folder>
<Folder Name="/Samples/M365Agent/">
<Project Path="samples/M365Agent/M365Agent.csproj" />
</Folder>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
<File Path=".gitignore" />
@@ -324,7 +307,6 @@
<File Path="src/Shared/Demos/SampleEnvironment.cs" />
</Folder>
<Folder Name="/Solution Items/src/Shared/IntegrationTests/">
<File Path="src/Shared/IntegrationTests/AnthropicConfiguration.cs" />
<File Path="src/Shared/IntegrationTests/AzureAIConfiguration.cs" />
<File Path="src/Shared/IntegrationTests/Mem0Configuration.cs" />
<File Path="src/Shared/IntegrationTests/OpenAIConfiguration.cs" />
@@ -349,12 +331,9 @@
<Project Path="src/Microsoft.Agents.AI.A2A/Microsoft.Agents.AI.A2A.csproj" />
<Project Path="src/Microsoft.Agents.AI.Abstractions/Microsoft.Agents.AI.Abstractions.csproj" />
<Project Path="src/Microsoft.Agents.AI.AGUI/Microsoft.Agents.AI.AGUI.csproj" />
<Project Path="src/Microsoft.Agents.AI.Anthropic/Microsoft.Agents.AI.Anthropic.csproj" />
<Project Path="src/Microsoft.Agents.AI.AzureAI.Persistent/Microsoft.Agents.AI.AzureAI.Persistent.csproj" />
<Project Path="src/Microsoft.Agents.AI.AzureAI/Microsoft.Agents.AI.AzureAI.csproj" />
<Project Path="src/Microsoft.Agents.AI.CopilotStudio/Microsoft.Agents.AI.CopilotStudio.csproj" />
<Project Path="src/Microsoft.Agents.AI.CosmosNoSql/Microsoft.Agents.AI.CosmosNoSql.csproj" />
<Project Path="src/Microsoft.Agents.AI.Declarative/Microsoft.Agents.AI.Declarative.csproj" />
<Project Path="src/Microsoft.Agents.AI.DevUI/Microsoft.Agents.AI.DevUI.csproj" />
<Project Path="src/Microsoft.Agents.AI.DurableTask/Microsoft.Agents.AI.DurableTask.csproj" />
<Project Path="src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/Microsoft.Agents.AI.Hosting.A2A.AspNetCore.csproj" />
@@ -374,7 +353,6 @@
<Folder Name="/Tests/" />
<Folder Name="/Tests/IntegrationTests/">
<Project Path="tests/AgentConformance.IntegrationTests/AgentConformance.IntegrationTests.csproj" />
<Project Path="tests/AnthropicChatCompletion.IntegrationTests/AnthropicChatCompletion.IntegrationTests.csproj" />
<Project Path="tests/AzureAI.IntegrationTests/AzureAI.IntegrationTests.csproj" />
<Project Path="tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistent.IntegrationTests.csproj" />
<Project Path="tests/CopilotStudio.IntegrationTests/CopilotStudio.IntegrationTests.csproj" />
@@ -391,12 +369,8 @@
<Project Path="tests/Microsoft.Agents.AI.A2A.UnitTests/Microsoft.Agents.AI.A2A.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.Abstractions.UnitTests/Microsoft.Agents.AI.Abstractions.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.AGUI.UnitTests/Microsoft.Agents.AI.AGUI.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.Anthropic.UnitTests/Microsoft.Agents.AI.Anthropic.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.AzureAI.Persistent.UnitTests/Microsoft.Agents.AI.AzureAI.Persistent.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.AzureAI.UnitTests/Microsoft.Agents.AI.AzureAI.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.CosmosNoSql.UnitTests/Microsoft.Agents.AI.CosmosNoSql.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.Declarative.UnitTests/Microsoft.Agents.AI.Declarative.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.DevUI.UnitTests/Microsoft.Agents.AI.DevUI.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.DurableTask.UnitTests/Microsoft.Agents.AI.DurableTask.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/Microsoft.Agents.AI.Hosting.A2A.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj" />
@@ -410,4 +384,4 @@
<Project Path="tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests.csproj" />
<Project Path="tests/Microsoft.Agents.AI.Workflows.UnitTests/Microsoft.Agents.AI.Workflows.UnitTests.csproj" />
</Folder>
</Solution>
</Solution>
+2 -2
View File
@@ -1,7 +1,7 @@
{
"sdk": {
"version": "10.0.100",
"rollForward": "minor",
"version": "9.0.300",
"rollForward": "latestMajor",
"allowPrerelease": false
}
}
+3 -3
View File
@@ -2,9 +2,9 @@
<PropertyGroup>
<!-- Central version prefix - applies to all nuget packages. -->
<VersionPrefix>1.0.0</VersionPrefix>
<PackageVersion Condition="'$(VersionSuffix)' != ''">$(VersionPrefix)-$(VersionSuffix).251125.1</PackageVersion>
<PackageVersion Condition="'$(VersionSuffix)' == ''">$(VersionPrefix)-preview.251125.1</PackageVersion>
<GitTag>1.0.0-preview.251125.1</GitTag>
<PackageVersion Condition="'$(VersionSuffix)' != ''">$(VersionPrefix)-$(VersionSuffix).251113.1</PackageVersion>
<PackageVersion Condition="'$(VersionSuffix)' == ''">$(VersionPrefix)-preview.251113.1</PackageVersion>
<GitTag>1.0.0-preview.251113.1</GitTag>
<Configurations>Debug;Release;Publish</Configurations>
<IsPackable>true</IsPackable>
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
@@ -12,11 +12,8 @@
<PackageReference Include="A2A" />
<PackageReference Include="System.CommandLine" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net10.0'))">
<PackageReference Include="System.Net.ServerSentEvents" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup>
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
@@ -11,11 +11,8 @@
<ItemGroup>
<PackageReference Include="Azure.AI.Agents.Persistent" />
<PackageReference Include="Azure.Identity" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net10.0'))">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="System.Linq.AsyncEnumerable" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup>
+1 -1
View File
@@ -103,7 +103,7 @@ dotnet run --urls "http://localhost:5002;https://localhost:5012" --agentId "<Log
### Testing the Agents using the Rest Client
This sample contains a [.http file](https://learn.microsoft.com/aspnet/core/test/http-files?view=aspnetcore-10.0) which can be used to test the agent.
This sample contains a [.http file](https://learn.microsoft.com/aspnet/core/test/http-files?view=aspnetcore-9.0) which can be used to test the agent.
1. In Visual Studio open [./A2AServer/A2AServer.http](./A2AServer/A2AServer.http)
1. There are two sent requests for each agent, e.g., for the invoice agent:
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>a8b2e9f0-1ea3-4f18-9d41-42d1a6f8fe10</UserSecretsId>
@@ -11,6 +11,8 @@
<ItemGroup>
<PackageReference Include="System.CommandLine" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup>
@@ -201,12 +201,12 @@ public static class Program
{
return "";
}
var builder = new StringBuilder().AppendLine();
var builder = new StringBuilder();
builder.AppendLine();
foreach (var kvp in arguments)
{
builder
.AppendLine($" Name: {kvp.Key}")
.AppendLine($" Value: {kvp.Value}");
builder.AppendLine($" Name: {kvp.Key}");
builder.AppendLine($" Value: {kvp.Value}");
}
return builder.ToString();
}
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>b9c3f1e1-2fb4-5g29-0e52-53e2b7g9gf21</UserSecretsId>
@@ -11,6 +11,8 @@
<ItemGroup>
<PackageReference Include="Azure.AI.OpenAI" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup>
@@ -42,4 +42,4 @@ app.MapAGUI("/shared_state", ChatClientAgentFactory.CreateSharedState(jsonOption
await app.RunAsync();
public partial class Program;
public partial class Program { }
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>a8b2e9f0-1ea3-4f18-9d41-42d1a6f8fe10</UserSecretsId>
@@ -11,6 +11,8 @@
<ItemGroup>
<PackageReference Include="Azure.AI.OpenAI" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup>
@@ -2,7 +2,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting;
namespace AgentWebChat.AgentHost;
@@ -10,24 +10,24 @@ internal static class ActorFrameworkWebApplicationExtensions
{
public static void MapAgentDiscovery(this IEndpointRouteBuilder endpoints, [StringSyntax("Route")] string path)
{
var registeredAIAgents = endpoints.ServiceProvider.GetKeyedServices<AIAgent>(KeyedService.AnyKey);
var routeGroup = endpoints.MapGroup(path);
routeGroup.MapGet("/", async (CancellationToken cancellationToken) =>
{
var results = new List<AgentDiscoveryCard>();
foreach (var result in registeredAIAgents)
routeGroup.MapGet("/", async (
AgentCatalog agentCatalog,
CancellationToken cancellationToken) =>
{
results.Add(new AgentDiscoveryCard
var results = new List<AgentDiscoveryCard>();
await foreach (var result in agentCatalog.GetAgentsAsync(cancellationToken).ConfigureAwait(false))
{
Name = result.Name!,
Description = result.Description,
});
}
results.Add(new AgentDiscoveryCard
{
Name = result.Name!,
Description = result.Description,
});
}
return Results.Ok(results);
})
.WithName("GetAgents");
return Results.Ok(results);
})
.WithName("GetAgents");
}
internal sealed class AgentDiscoveryCard
@@ -1,14 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.DevUI\Microsoft.Agents.AI.DevUI.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.Abstractions\Microsoft.Agents.AI.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.Hosting\Microsoft.Agents.AI.Hosting.csproj" />
@@ -31,4 +30,11 @@
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" />
</ItemGroup>
<!-- A2A dependency -->
<ItemGroup>
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<!-- A2A dependency -->
</Project>
@@ -4,7 +4,9 @@ using Microsoft.Extensions.AI;
namespace AgentWebChat.AgentHost.Custom;
public class CustomAITool : AITool;
public class CustomAITool : AITool
{
}
public class CustomFunctionTool : AIFunction
{
@@ -5,7 +5,6 @@ using AgentWebChat.AgentHost;
using AgentWebChat.AgentHost.Custom;
using AgentWebChat.AgentHost.Utilities;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.DevUI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
@@ -22,13 +21,6 @@ builder.Services.AddProblemDetails();
// Configure the chat model and our agent.
builder.AddKeyedChatClient("chat-model");
// Add DevUI services
builder.AddDevUI();
// Add OpenAI services
builder.AddOpenAIChatCompletions();
builder.AddOpenAIResponses();
var pirateAgentBuilder = builder.AddAIAgent(
"pirate",
instructions: "You are a pirate. Speak like a pirate",
@@ -103,48 +95,8 @@ var scienceConcurrentWorkflow = builder.AddWorkflow("science-concurrent-workflow
return AgentWorkflowBuilder.BuildConcurrent(workflowName: key, agents: agents);
}).AddAsAIAgent();
builder.AddWorkflow("nonAgentWorkflow", (sp, key) =>
{
List<IHostedAgentBuilder> usedAgents = [pirateAgentBuilder, chemistryAgent];
var agents = usedAgents.Select(ab => sp.GetRequiredKeyedService<AIAgent>(ab.Name));
return AgentWorkflowBuilder.BuildSequential(workflowName: key, agents: agents);
});
builder.Services.AddKeyedSingleton("NonAgentAndNonmatchingDINameWorkflow", (sp, key) =>
{
List<IHostedAgentBuilder> usedAgents = [pirateAgentBuilder, chemistryAgent];
var agents = usedAgents.Select(ab => sp.GetRequiredKeyedService<AIAgent>(ab.Name));
return AgentWorkflowBuilder.BuildSequential(workflowName: "random-name", agents: agents);
});
builder.Services.AddSingleton<AIAgent>(sp =>
{
var chatClient = sp.GetRequiredKeyedService<IChatClient>("chat-model");
return new ChatClientAgent(chatClient, name: "default-agent", instructions: "you are a default agent.");
});
builder.Services.AddKeyedSingleton<AIAgent>("my-di-nonmatching-agent", (sp, name) =>
{
var chatClient = sp.GetRequiredKeyedService<IChatClient>("chat-model");
return new ChatClientAgent(
chatClient,
name: "some-random-name", // demonstrating registration can be different for DI and actual agent
instructions: "you are a dependency inject agent. Tell me all about dependency injection.");
});
builder.Services.AddKeyedSingleton<AIAgent>("my-di-matchingname-agent", (sp, name) =>
{
if (name is not string nameStr)
{
throw new NotSupportedException("Name should be passed as a key");
}
var chatClient = sp.GetRequiredKeyedService<IChatClient>("chat-model");
return new ChatClientAgent(
chatClient,
name: nameStr, // demonstrating registration with the same name
instructions: "you are a dependency inject agent. Tell me all about dependency injection.");
});
builder.AddOpenAIChatCompletions();
builder.AddOpenAIResponses();
var app = builder.Build();
@@ -166,10 +118,7 @@ app.MapA2A(knightsKnavesAgentBuilder, path: "/a2a/knights-and-knaves", agentCard
// Url = "http://localhost:5390/a2a/knights-and-knaves"
});
app.MapDevUI();
app.MapOpenAIResponses();
app.MapOpenAIConversations();
app.MapOpenAIChatCompletions(pirateAgentBuilder);
app.MapOpenAIChatCompletions(knightsKnavesAgentBuilder);
@@ -4,7 +4,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
@@ -9,9 +9,7 @@ var azOpenAiResourceGroup = builder.AddParameterFromConfiguration("AzureOpenAIRe
var chatModel = builder.AddAIModel("chat-model").AsAzureOpenAI("gpt-4o", o => o.AsExisting(azOpenAiResource, azOpenAiResourceGroup));
var agentHost = builder.AddProject<Projects.AgentWebChat_AgentHost>("agenthost")
.WithHttpEndpoint(name: "devui")
.WithUrlForEndpoint("devui", (url) => new() { Url = "/devui", DisplayText = "Dev UI" })
.WithReference(chatModel);
.WithReference(chatModel);
builder.AddProject<Projects.AgentWebChat_Web>("webfrontend")
.WithExternalHttpEndpoints()
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireSharedProject>true</IsAspireSharedProject>
@@ -25,7 +25,7 @@ internal sealed class A2AAgentClient : AgentClientBase
this._uri = baseUri;
}
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public async override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
@@ -122,7 +122,7 @@ internal sealed class A2AAgentClient : AgentClientBase
}
}
public override async Task<AgentCard?> GetAgentCardAsync(string agentName, CancellationToken cancellationToken = default)
public async override Task<AgentCard?> GetAgentCardAsync(string agentName, CancellationToken cancellationToken = default)
{
this._logger.LogInformation("Retrieving agent card for {Agent}", agentName);
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);CA1812</NoWarn>
@@ -15,4 +15,11 @@
<ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.Abstractions\Microsoft.Agents.AI.Abstractions.csproj" />
</ItemGroup>
<!-- A2A dependency -->
<ItemGroup>
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<!-- A2A dependency -->
</Project>
@@ -16,7 +16,7 @@ namespace AgentWebChat.Web;
/// </summary>
internal sealed class OpenAIChatCompletionsAgentClient(HttpClient httpClient) : AgentClientBase
{
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public async override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
@@ -15,7 +15,7 @@ namespace AgentWebChat.Web;
/// </summary>
internal sealed class OpenAIResponsesAgentClient(HttpClient httpClient) : AgentClientBase
{
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public async override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -47,7 +47,7 @@ curl -X POST http://localhost:7071/api/agents/Joker/run \
To continue a conversation, include the `thread_id` in the query string or JSON body:
```bash
curl -X POST "http://localhost:7071/api/agents/Joker/run?thread_id=your-thread-id" \
curl -X POST "http://localhost:7071/api/agents/Joker/run?thread_id=@dafx-joker@your-thread-id" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"message": "Tell me another one."}'
@@ -64,7 +64,7 @@ The expected `application/json` output will look something like:
```json
{
"status": 200,
"thread_id": "ee6e47a0-f24b-40b1-ade8-16fcebb9eb40",
"thread_id": "@dafx-joker@your-thread-id",
"response": {
"Messages": [
{
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -36,9 +36,8 @@ using IHost app = FunctionsApplication
.ConfigureFunctionsWebApplication()
.ConfigureDurableAgents(options =>
{
options
.AddAIAgent(physicistAgent)
.AddAIAgent(chemistAgent);
options.AddAIAgent(physicistAgent);
options.AddAIAgent(chemistAgent);
})
.Build();
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -39,9 +39,8 @@ using IHost app = FunctionsApplication
.ConfigureFunctionsWebApplication()
.ConfigureDurableAgents(options =>
{
options
.AddAIAgent(spamDetectionAgent)
.AddAIAgent(emailAssistantAgent);
options.AddAIAgent(spamDetectionAgent);
options.AddAIAgent(emailAssistantAgent);
})
.Build();
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -52,7 +52,7 @@ The response will be a text string that looks something like the following, indi
```http
HTTP/1.1 200 OK
Content-Type: text/plain
x-ms-thread-id: 351ec855-7f4d-4527-a60d-498301ced36d
x-ms-thread-id: @publisher@351ec855-7f4d-4527-a60d-498301ced36d
The content generation workflow for the topic "The Future of Artificial Intelligence" has been successfully started, and the instance ID is **6a04276e8d824d8d941e1dc4142cc254**. If you need any further assistance or updates on the workflow, feel free to ask!
```
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
+1 -1
View File
@@ -18,7 +18,7 @@ These samples are designed to be run locally in a cloned repository.
The following prerequisites are required to run the samples:
- [.NET 10.0 SDK or later](https://dotnet.microsoft.com/download/dotnet)
- [.NET 9.0 SDK or later](https://dotnet.microsoft.com/download/dotnet)
- [Azure Functions Core Tools](https://learn.microsoft.com/azure/azure-functions/functions-run-local) (version 4.x or later)
- [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed and authenticated (`az login`) or an API key for the Azure OpenAI service
- [Azure OpenAI Service](https://learn.microsoft.com/azure/ai-services/openai/how-to/create-resource) with a deployed model (gpt-4o-mini or better is recommended)
+1 -1
View File
@@ -5,7 +5,7 @@
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsAotCompatible>false</IsAotCompatible>
<TargetFrameworks>net10.0;net472</TargetFrameworks>
<ProjectsTargetFrameworks>net472;net9.0</ProjectsTargetFrameworks>
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
</PropertyGroup>
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -13,11 +13,8 @@
<PackageReference Include="Azure.AI.OpenAI" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net10.0'))">
<PackageReference Include="System.Net.ServerSentEvents" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup>
@@ -7,7 +7,7 @@ and register these function tools with another AI agent so it can leverage the A
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Access to the A2A agent host service
**Note**: These samples need to be run against a valid A2A server. If no A2A server is available, they can be run against the echo-agent that can be
@@ -1,25 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="A2A" />
<PackageReference Include="Azure.AI.OpenAI" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="System.Net.ServerSentEvents" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.A2A\Microsoft.Agents.AI.A2A.csproj" />
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" />
</ItemGroup>
</Project>
@@ -1,35 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
// This sample demonstrates how to poll for long-running task completion using continuation tokens with an A2A AI agent.
using A2A;
using Microsoft.Agents.AI;
var a2aAgentHost = Environment.GetEnvironmentVariable("A2A_AGENT_HOST") ?? throw new InvalidOperationException("A2A_AGENT_HOST is not set.");
// Initialize an A2ACardResolver to get an A2A agent card.
A2ACardResolver agentCardResolver = new(new Uri(a2aAgentHost));
// Get the agent card
AgentCard agentCard = await agentCardResolver.GetAgentCardAsync();
// Create an instance of the AIAgent for an existing A2A agent specified by the agent card.
AIAgent agent = agentCard.GetAIAgent();
AgentThread thread = agent.GetNewThread();
// Start the initial run with a long-running task.
AgentRunResponse response = await agent.RunAsync("Conduct a comprehensive analysis of quantum computing applications in cryptography, including recent breakthroughs, implementation challenges, and future roadmap. Please include diagrams and visual representations to illustrate complex concepts.", thread);
// Poll until the response is complete.
while (response.ContinuationToken is { } token)
{
// Wait before polling again.
await Task.Delay(TimeSpan.FromSeconds(2));
// Continue with the token.
response = await agent.RunAsync(thread, options: new AgentRunOptions { ContinuationToken = token });
}
// Display the result
Console.WriteLine(response);
@@ -1,25 +0,0 @@
# Polling for A2A Agent Task Completion
This sample demonstrates how to poll for long-running task completion using continuation tokens with an A2A AI agent, following the background responses pattern.
The sample:
- Connects to an A2A agent server specified in the `A2A_AGENT_HOST` environment variable
- Sends a request to the agent that may take time to complete
- Polls the agent at regular intervals using continuation tokens until a final response is received
- Displays the final result
This pattern is useful when an AI model cannot complete a complex task in a single response and needs multiple rounds of processing.
# Prerequisites
Before you begin, ensure you have the following prerequisites:
- .NET 10.0 SDK or later
- An A2A agent server running and accessible via HTTP
Set the following environment variable:
```powershell
$env:A2A_AGENT_HOST="http://localhost:5000" # Replace with your A2A agent server host
```
@@ -14,7 +14,6 @@ See the README.md for each sample for the prerequisites for that sample.
|Sample|Description|
|---|---|
|[A2A Agent As Function Tools](./A2AAgent_AsFunctionTools/)|This sample demonstrates how to represent an A2A agent as a set of function tools, where each function tool corresponds to a skill of the A2A agent, and register these function tools with another AI agent so it can leverage the A2A agent's skills.|
|[A2A Agent Polling For Task Completion](./A2AAgent_PollingForTaskCompletion/)|This sample demonstrates how to poll for long-running task completion using continuation tokens with an A2A agent.|
## Running the samples from the console
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -22,6 +22,7 @@
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" />
</ItemGroup>
<ItemGroup>
@@ -22,7 +22,7 @@ graph TD
## Prerequisites
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Azure OpenAI service endpoint and deployment configured
- Azure CLI installed and authenticated (for Azure credential authentication)
- Docker installed (for running Aspire Dashboard)
@@ -71,7 +71,7 @@ If you prefer to run the components manually:
#### Step 1: Start the Aspire Dashboard via Docker
```powershell
docker run -d --name aspire-dashboard -p 4318:18888 -p 4317:18889 -e DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true mcr.microsoft.com/dotnet/aspire-dashboard:latest
docker run -d --name aspire-dashboard -p 4318:18888 -p 4317:18889 -e DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true mcr.microsoft.com/dotnet/aspire-dashboard:9.0
```
#### Step 2: Access the Dashboard
@@ -207,7 +207,7 @@ If you encounter port binding errors, try:
- Ensure the Azure OpenAI deployment name matches your actual deployment
### Build Issues
- Ensure you're using .NET 10.0 SDK
- Ensure you're using .NET 9.0 SDK
- Run `dotnet restore` if you encounter package restore issues
- Check that all project references are correctly resolved
@@ -65,7 +65,7 @@ $dockerResult = docker run -d `
-p 4317:18889 `
-e DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true `
--restart unless-stopped `
mcr.microsoft.com/dotnet/aspire-dashboard:latest
mcr.microsoft.com/dotnet/aspire-dashboard:9.0
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to start Aspire Dashboard container" -ForegroundColor Red
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -10,6 +10,8 @@
<ItemGroup>
<PackageReference Include="A2A" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>
<ItemGroup>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Access to the A2A agent host service
**Note**: These samples need to be run against a valid A2A server. If no A2A server is available, they can be run against the echo-agent that can be spun up locally by following the guidelines at: https://github.com/a2aproject/a2a-dotnet/blob/main/samples/AgentServer/README.md
@@ -1,21 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>$(NoWarn);IDE0059</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Anthropic.Foundry" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Anthropic\Microsoft.Agents.AI.Anthropic.csproj" />
</ItemGroup>
</Project>
@@ -1,74 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
// This sample shows how to create and use an AI agent with Anthropic as the backend.
using System.Net.Http.Headers;
using Anthropic;
using Anthropic.Foundry;
using Azure.Core;
using Azure.Identity;
using Microsoft.Agents.AI;
using Sample;
var deploymentName = Environment.GetEnvironmentVariable("ANTHROPIC_DEPLOYMENT_NAME") ?? "claude-haiku-4-5";
// The resource is the subdomain name / first name coming before '.services.ai.azure.com' in the endpoint Uri
// ie: https://(resource name).services.ai.azure.com/anthropic/v1/chat/completions
string? resource = Environment.GetEnvironmentVariable("ANTHROPIC_RESOURCE");
string? apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY");
const string JokerInstructions = "You are good at telling jokes.";
const string JokerName = "JokerAgent";
AnthropicClient? client = (resource is null)
? new AnthropicClient() { APIKey = apiKey ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is required when no ANTHROPIC_RESOURCE is provided") } // If no resource is provided, use Anthropic public API
: (apiKey is not null)
? new AnthropicFoundryClient(new AnthropicFoundryApiKeyCredentials(apiKey, resource)) // If an apiKey is provided, use Foundry with ApiKey authentication
: new AnthropicFoundryClient(new AnthropicAzureTokenCredential(new AzureCliCredential(), resource)); // Otherwise, use Foundry with Azure Client authentication
AIAgent agent = client.CreateAIAgent(model: deploymentName, instructions: JokerInstructions, name: JokerName);
// Invoke the agent and output the text result.
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
namespace Sample
{
/// <summary>
/// Provides methods for invoking the Azure hosted Anthropic models using <see cref="TokenCredential"/> types.
/// </summary>
public sealed class AnthropicAzureTokenCredential : IAnthropicFoundryCredentials
{
private readonly TokenCredential _tokenCredential;
private readonly Lock _lock = new();
private AccessToken? _cachedAccessToken;
/// <inheritdoc/>
public string ResourceName { get; }
/// <summary>
/// Creates a new instance of the <see cref="AnthropicAzureTokenCredential"/>.
/// </summary>
/// <param name="tokenCredential">The credential provider. Use any specialization of <see cref="TokenCredential"/> to get your access token in supported environments.</param>
/// <param name="resourceName">The service resource subdomain name to use in the anthropic azure endpoint</param>
internal AnthropicAzureTokenCredential(TokenCredential tokenCredential, string resourceName)
{
this.ResourceName = resourceName ?? throw new ArgumentNullException(nameof(resourceName));
this._tokenCredential = tokenCredential ?? throw new ArgumentNullException(nameof(tokenCredential));
}
/// <inheritdoc/>
public void Apply(HttpRequestMessage requestMessage)
{
lock (this._lock)
{
// Add a 5-minute buffer to avoid using tokens that are about to expire
if (this._cachedAccessToken is null || this._cachedAccessToken.Value.ExpiresOn <= DateTimeOffset.Now.AddMinutes(5))
{
this._cachedAccessToken = this._tokenCredential.GetToken(new TokenRequestContext(scopes: ["https://ai.azure.com/.default"]), CancellationToken.None);
}
}
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", this._cachedAccessToken.Value.Token);
}
}
}
@@ -1,53 +0,0 @@
# Creating an AIAgent with Anthropic
This sample demonstrates how to create an AIAgent using Anthropic Claude models as the underlying inference service.
The sample supports three deployment scenarios:
1. **Anthropic Public API** - Direct connection to Anthropic's public API
2. **Azure Foundry with API Key** - Anthropic models deployed through Azure Foundry using API key authentication
3. **Azure Foundry with Azure CLI** - Anthropic models deployed through Azure Foundry using Azure CLI credentials
## Prerequisites
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
### For Anthropic Public API
- Anthropic API key
Set the following environment variables:
```powershell
$env:ANTHROPIC_API_KEY="your-anthropic-api-key" # Replace with your Anthropic API key
$env:ANTHROPIC_DEPLOYMENT_NAME="claude-haiku-4-5" # Optional, defaults to claude-haiku-4-5
```
### For Azure Foundry with API Key
- Azure Foundry service endpoint and deployment configured
- Anthropic API key
Set the following environment variables:
```powershell
$env:ANTHROPIC_RESOURCE="your-foundry-resource-name" # Replace with your Azure Foundry resource name (subdomain before .services.ai.azure.com)
$env:ANTHROPIC_API_KEY="your-anthropic-api-key" # Replace with your Anthropic API key
$env:ANTHROPIC_DEPLOYMENT_NAME="claude-haiku-4-5" # Optional, defaults to claude-haiku-4-5
```
### For Azure Foundry with Azure CLI
- Azure Foundry service endpoint and deployment configured
- Azure CLI installed and authenticated (for Azure credential authentication)
Set the following environment variables:
```powershell
$env:ANTHROPIC_RESOURCE="your-foundry-resource-name" # Replace with your Azure Foundry resource name (subdomain before .services.ai.azure.com)
$env:ANTHROPIC_DEPLOYMENT_NAME="claude-haiku-4-5" # Optional, defaults to claude-haiku-4-5
```
**Note**: When using Azure Foundry with Azure CLI, make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,18 +1,8 @@
# Classic Foundry Agents
This sample demonstrates how to create an agent using the classic Foundry Agents experience.
# Classic vs New Foundry Agents
Below is a comparison between the classic and new Foundry Agents approaches:
[Migration Guide](https://learn.microsoft.com/en-us/azure/ai-foundry/agents/how-to/migrate?view=foundry)
# Prerequisites
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Azure Foundry service endpoint and deployment configured
- Azure CLI installed and authenticated (for Azure credential authentication)
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -10,34 +10,35 @@ using Microsoft.Agents.AI;
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
const string JokerInstructions = "You are good at telling jokes.";
const string JokerName = "JokerAgent";
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
var aiProjectClient = new AIProjectClient(new Uri(endpoint), new AzureCliCredential());
// Define the agent you want to create. (Prompt Agent in this case)
var agentVersionCreationOptions = new AgentVersionCreationOptions(new PromptAgentDefinition(model: deploymentName) { Instructions = "You are good at telling jokes." });
var agentVersionCreationOptions = new AgentVersionCreationOptions(new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions });
// Azure.AI.Agents SDK creates and manages agent by name and versions.
// You can create a server side agent version with the Azure.AI.Agents SDK client below.
var createdAgentVersion = aiProjectClient.Agents.CreateAgentVersion(agentName: JokerName, options: agentVersionCreationOptions);
var agentVersion = aiProjectClient.Agents.CreateAgentVersion(agentName: JokerName, options: agentVersionCreationOptions);
// Note:
// agentVersion.Id = "<agentName>:<versionNumber>",
// agentVersion.Version = <versionNumber>,
// agentVersion.Name = <agentName>
// You can retrieve an AIAgent for an already created server side agent version.
AIAgent existingJokerAgent = aiProjectClient.GetAIAgent(createdAgentVersion);
// You can retrieve an AIAgent for a already created server side agent version.
AIAgent jokerAgentV1 = aiProjectClient.GetAIAgent(agentVersion);
// You can also create another AIAgent version by providing the same name with a different definition.
AIAgent newJokerAgent = aiProjectClient.CreateAIAgent(name: JokerName, model: deploymentName, instructions: "You are extremely hilarious at telling jokes.");
// You can also create another AIAgent version (V2) by providing the same name with a different definition.
AIAgent jokerAgentV2 = aiProjectClient.CreateAIAgent(name: JokerName, model: deploymentName, instructions: JokerInstructions + "V2");
// You can also get the AIAgent latest version just providing its name.
AIAgent jokerAgentLatest = aiProjectClient.GetAIAgent(name: JokerName);
var latestAgentVersion = jokerAgentLatest.GetService<AgentVersion>()!;
var latestVersion = jokerAgentLatest.GetService<AgentVersion>()!;
// The AIAgent version can be accessed via the GetService method.
Console.WriteLine($"Latest agent version id: {latestAgentVersion.Id}");
Console.WriteLine($"Latest agent version id: {latestVersion.Id}");
// Once you have the AIAgent, you can invoke it like any other AIAgent.
AgentThread thread = jokerAgentLatest.GetNewThread();
@@ -46,5 +47,5 @@ Console.WriteLine(await jokerAgentLatest.RunAsync("Tell me a joke about a pirate
// This will use the same thread to continue the conversation.
Console.WriteLine(await jokerAgentLatest.RunAsync("Now tell me a joke about a cat and a dog using last joke as the anchor.", thread));
// Cleanup by agent name removes both agent versions created.
aiProjectClient.Agents.DeleteAgent(existingJokerAgent.Name);
// Cleanup by agent name removes both agent versions created (jokerAgentV1 + jokerAgentV2).
aiProjectClient.Agents.DeleteAgent(jokerAgentV1.Name);
@@ -1,18 +1,8 @@
# New Foundry Agents
This sample demonstrates how to create an agent using the new Foundry Agents experience.
# Classic vs New Foundry Agents
Below is a comparison between the classic and new Foundry Agents approaches:
[Migration Guide](https://learn.microsoft.com/en-us/azure/ai-foundry/agents/how-to/migrate?view=foundry)
# Prerequisites
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Azure Foundry service endpoint and deployment configured
- Azure CLI installed and authenticated (for Azure credential authentication)
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -10,7 +10,7 @@ You could use models from Microsoft, OpenAI, DeepSeek, Hugging Face, Meta, xAI o
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Azure AI Foundry resource
- A model deployment in your Azure AI Foundry resource. This example defaults to using the `Phi-4-mini-instruct` model,
so if you want to use a different model, ensure that you set your `AZURE_FOUNDRY_MODEL_DEPLOYMENT` environment
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Azure OpenAI service endpoint and deployment configured
- Azure CLI installed and authenticated (for Azure credential authentication)
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Azure OpenAI service endpoint and deployment configured
- Azure CLI installed and authenticated (for Azure credential authentication)
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -39,16 +39,11 @@ namespace SampleApp
// Create a thread if the user didn't supply one.
thread ??= this.GetNewThread();
if (thread is not CustomAgentThread typedThread)
{
throw new ArgumentException($"The provided thread is not of type {nameof(CustomAgentThread)}.", nameof(thread));
}
// Clone the input messages and turn them into response messages with upper case text.
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
// Notify the thread of the input and output messages.
await typedThread.MessageStore.AddMessagesAsync(messages.Concat(responseMessages), cancellationToken);
await NotifyThreadOfNewMessagesAsync(thread, messages.Concat(responseMessages), cancellationToken);
return new AgentRunResponse
{
@@ -63,16 +58,11 @@ namespace SampleApp
// Create a thread if the user didn't supply one.
thread ??= this.GetNewThread();
if (thread is not CustomAgentThread typedThread)
{
throw new ArgumentException($"The provided thread is not of type {nameof(CustomAgentThread)}.", nameof(thread));
}
// Clone the input messages and turn them into response messages with upper case text.
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
// Notify the thread of the input and output messages.
await typedThread.MessageStore.AddMessagesAsync(messages.Concat(responseMessages), cancellationToken);
await NotifyThreadOfNewMessagesAsync(thread, messages.Concat(responseMessages), cancellationToken);
foreach (var message in responseMessages)
{
@@ -1,21 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>$(NoWarn);IDE0059</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.GenAI" />
<PackageReference Include="Mscc.GenerativeAI.Microsoft" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
</ItemGroup>
</Project>
@@ -1,558 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Runtime.CompilerServices;
using Google.Apis.Util;
using Google.GenAI;
using Google.GenAI.Types;
namespace Microsoft.Extensions.AI;
/// <summary>Provides an <see cref="IChatClient"/> implementation based on <see cref="Client"/>.</summary>
internal sealed class GoogleGenAIChatClient : IChatClient
{
/// <summary>The wrapped <see cref="Client"/> instance (optional).</summary>
private readonly Client? _client;
/// <summary>The wrapped <see cref="Models"/> instance.</summary>
private readonly Models _models;
/// <summary>The default model that should be used when no override is specified.</summary>
private readonly string? _defaultModelId;
/// <summary>Lazily-initialized metadata describing the implementation.</summary>
private ChatClientMetadata? _metadata;
/// <summary>Initializes a new <see cref="GoogleGenAIChatClient"/> instance.</summary>
public GoogleGenAIChatClient(Client client, string? defaultModelId)
{
this._client = client;
this._models = client.Models;
this._defaultModelId = defaultModelId;
}
/// <summary>Initializes a new <see cref="GoogleGenAIChatClient"/> instance.</summary>
public GoogleGenAIChatClient(Models client, string? defaultModelId)
{
this._models = client;
this._defaultModelId = defaultModelId;
}
/// <inheritdoc />
public async Task<ChatResponse> GetResponseAsync(IEnumerable<ChatMessage> messages, ChatOptions? options = null, CancellationToken cancellationToken = default)
{
Utilities.ThrowIfNull(messages, nameof(messages));
// Create the request.
(string? modelId, List<Content> contents, GenerateContentConfig config) = this.CreateRequest(messages, options);
// Send it.
GenerateContentResponse generateResult = await this._models.GenerateContentAsync(modelId!, contents, config).ConfigureAwait(false);
// Create the response.
ChatResponse chatResponse = new(new ChatMessage(ChatRole.Assistant, new List<AIContent>()))
{
CreatedAt = generateResult.CreateTime is { } dt ? new DateTimeOffset(dt) : null,
ModelId = !string.IsNullOrWhiteSpace(generateResult.ModelVersion) ? generateResult.ModelVersion : modelId,
RawRepresentation = generateResult,
ResponseId = generateResult.ResponseId,
};
// Populate the response messages.
chatResponse.FinishReason = PopulateResponseContents(generateResult, chatResponse.Messages[0].Contents);
// Populate usage information if there is any.
if (generateResult.UsageMetadata is { } usageMetadata)
{
chatResponse.Usage = ExtractUsageDetails(usageMetadata);
}
// Return the response.
return chatResponse;
}
/// <inheritdoc />
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(IEnumerable<ChatMessage> messages, ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
Utilities.ThrowIfNull(messages, nameof(messages));
// Create the request.
(string? modelId, List<Content> contents, GenerateContentConfig config) = this.CreateRequest(messages, options);
// Send it, and process the results.
await foreach (GenerateContentResponse generateResult in this._models.GenerateContentStreamAsync(modelId!, contents, config).WithCancellation(cancellationToken).ConfigureAwait(false))
{
// Create a response update for each result in the stream.
ChatResponseUpdate responseUpdate = new(ChatRole.Assistant, new List<AIContent>())
{
CreatedAt = generateResult.CreateTime is { } dt ? new DateTimeOffset(dt) : null,
ModelId = !string.IsNullOrWhiteSpace(generateResult.ModelVersion) ? generateResult.ModelVersion : modelId,
RawRepresentation = generateResult,
ResponseId = generateResult.ResponseId,
};
// Populate the response update contents.
responseUpdate.FinishReason = PopulateResponseContents(generateResult, responseUpdate.Contents);
// Populate usage information if there is any.
if (generateResult.UsageMetadata is { } usageMetadata)
{
responseUpdate.Contents.Add(new UsageContent(ExtractUsageDetails(usageMetadata)));
}
// Yield the update.
yield return responseUpdate;
}
}
/// <inheritdoc />
public object? GetService(System.Type serviceType, object? serviceKey = null)
{
Utilities.ThrowIfNull(serviceType, nameof(serviceType));
if (serviceKey is null)
{
// If there's a request for metadata, lazily-initialize it and return it. We don't need to worry about race conditions,
// as there's no requirement that the same instance be returned each time, and creation is idempotent.
if (serviceType == typeof(ChatClientMetadata))
{
return this._metadata ??= new("gcp.gen_ai", new("https://generativelanguage.googleapis.com/"), defaultModelId: this._defaultModelId);
}
// Allow a consumer to "break glass" and access the underlying client if they need it.
if (serviceType.IsInstanceOfType(this._models))
{
return this._models;
}
if (this._client is not null && serviceType.IsInstanceOfType(this._client))
{
return this._client;
}
if (serviceType.IsInstanceOfType(this))
{
return this;
}
}
return null;
}
/// <inheritdoc />
void IDisposable.Dispose() { /* nop */ }
/// <summary>Creates the message parameters for <see cref="Models.GenerateContentAsync(string, List{Content}, GenerateContentConfig?)"/> from <paramref name="messages"/> and <paramref name="options"/>.</summary>
private (string? ModelId, List<Content> Contents, GenerateContentConfig Config) CreateRequest(IEnumerable<ChatMessage> messages, ChatOptions? options)
{
// Create the GenerateContentConfig object. If the options contains a RawRepresentationFactory, try to use it to
// create the request instance, allowing the caller to populate it with GenAI-specific options. Otherwise, create
// a new instance directly.
string? model = this._defaultModelId;
List<Content> contents = new();
GenerateContentConfig config = options?.RawRepresentationFactory?.Invoke(this) as GenerateContentConfig ?? new();
if (options is not null)
{
if (options.FrequencyPenalty is { } frequencyPenalty)
{
config.FrequencyPenalty ??= frequencyPenalty;
}
if (options.Instructions is { } instructions)
{
((config.SystemInstruction ??= new()).Parts ??= new()).Add(new() { Text = instructions });
}
if (options.MaxOutputTokens is { } maxOutputTokens)
{
config.MaxOutputTokens ??= maxOutputTokens;
}
if (!string.IsNullOrWhiteSpace(options.ModelId))
{
model = options.ModelId;
}
if (options.PresencePenalty is { } presencePenalty)
{
config.PresencePenalty ??= presencePenalty;
}
if (options.Seed is { } seed)
{
config.Seed ??= (int)seed;
}
if (options.StopSequences is { } stopSequences)
{
(config.StopSequences ??= new()).AddRange(stopSequences);
}
if (options.Temperature is { } temperature)
{
config.Temperature ??= temperature;
}
if (options.TopP is { } topP)
{
config.TopP ??= topP;
}
if (options.TopK is { } topK)
{
config.TopK ??= topK;
}
// Populate tools. Each kind of tool is added on its own, except for function declarations,
// which are grouped into a single FunctionDeclaration.
List<FunctionDeclaration>? functionDeclarations = null;
if (options.Tools is { } tools)
{
foreach (var tool in tools)
{
switch (tool)
{
case AIFunctionDeclaration af:
functionDeclarations ??= new();
functionDeclarations.Add(new()
{
Name = af.Name,
Description = af.Description ?? "",
ParametersJsonSchema = af.JsonSchema,
});
break;
case HostedCodeInterpreterTool:
(config.Tools ??= new()).Add(new() { CodeExecution = new() });
break;
case HostedFileSearchTool:
(config.Tools ??= new()).Add(new() { Retrieval = new() });
break;
case HostedWebSearchTool:
(config.Tools ??= new()).Add(new() { GoogleSearch = new() });
break;
}
}
}
if (functionDeclarations is { Count: > 0 })
{
Tool functionTools = new();
(functionTools.FunctionDeclarations ??= new()).AddRange(functionDeclarations);
(config.Tools ??= new()).Add(functionTools);
}
// Transfer over the tool mode if there are any tools.
if (options.ToolMode is { } toolMode && config.Tools?.Count > 0)
{
switch (toolMode)
{
case NoneChatToolMode:
config.ToolConfig = new() { FunctionCallingConfig = new() { Mode = FunctionCallingConfigMode.NONE } };
break;
case AutoChatToolMode:
config.ToolConfig = new() { FunctionCallingConfig = new() { Mode = FunctionCallingConfigMode.AUTO } };
break;
case RequiredChatToolMode required:
config.ToolConfig = new() { FunctionCallingConfig = new() { Mode = FunctionCallingConfigMode.ANY } };
if (required.RequiredFunctionName is not null)
{
((config.ToolConfig.FunctionCallingConfig ??= new()).AllowedFunctionNames ??= new()).Add(required.RequiredFunctionName);
}
break;
}
}
// Set the response format if specified.
if (options.ResponseFormat is ChatResponseFormatJson responseFormat)
{
config.ResponseMimeType = "application/json";
if (responseFormat.Schema is { } schema)
{
config.ResponseJsonSchema = schema;
}
}
}
// Transfer messages to request, handling system messages specially
Dictionary<string, string>? callIdToFunctionNames = null;
foreach (var message in messages)
{
if (message.Role == ChatRole.System)
{
string instruction = message.Text;
if (!string.IsNullOrWhiteSpace(instruction))
{
((config.SystemInstruction ??= new()).Parts ??= new()).Add(new() { Text = instruction });
}
continue;
}
Content content = new() { Role = message.Role == ChatRole.Assistant ? "model" : "user" };
content.Parts ??= new();
AddPartsForAIContents(ref callIdToFunctionNames, message.Contents, content.Parts);
contents.Add(content);
}
// Make sure the request contains at least one content part (the request would always fail if empty).
if (!contents.SelectMany(c => c.Parts ?? Enumerable.Empty<Part>()).Any())
{
contents.Add(new() { Role = "user", Parts = new() { { new() { Text = "" } } } });
}
return (model, contents, config);
}
/// <summary>Creates <see cref="Part"/>s for <paramref name="contents"/> and adds them to <paramref name="parts"/>.</summary>
private static void AddPartsForAIContents(ref Dictionary<string, string>? callIdToFunctionNames, IList<AIContent> contents, List<Part> parts)
{
for (int i = 0; i < contents.Count; i++)
{
var content = contents[i];
byte[]? thoughtSignature = null;
if (content is not TextReasoningContent { ProtectedData: not null } &&
i + 1 < contents.Count &&
contents[i + 1] is TextReasoningContent nextReasoning &&
string.IsNullOrWhiteSpace(nextReasoning.Text) &&
nextReasoning.ProtectedData is { } protectedData)
{
i++;
thoughtSignature = Convert.FromBase64String(protectedData);
}
Part? part = null;
switch (content)
{
case TextContent textContent:
part = new() { Text = textContent.Text };
break;
case TextReasoningContent reasoningContent:
part = new()
{
Thought = true,
Text = !string.IsNullOrWhiteSpace(reasoningContent.Text) ? reasoningContent.Text : null,
ThoughtSignature = reasoningContent.ProtectedData is not null ? Convert.FromBase64String(reasoningContent.ProtectedData) : null,
};
break;
case DataContent dataContent:
part = new()
{
InlineData = new()
{
MimeType = dataContent.MediaType,
Data = dataContent.Data.ToArray(),
DisplayName = dataContent.Name,
}
};
break;
case UriContent uriContent:
part = new()
{
FileData = new()
{
FileUri = uriContent.Uri.AbsoluteUri,
MimeType = uriContent.MediaType,
}
};
break;
case FunctionCallContent functionCallContent:
(callIdToFunctionNames ??= new())[functionCallContent.CallId] = functionCallContent.Name;
callIdToFunctionNames[""] = functionCallContent.Name; // track last function name in case calls don't have IDs
part = new()
{
FunctionCall = new()
{
Id = functionCallContent.CallId,
Name = functionCallContent.Name,
Args = functionCallContent.Arguments is null ? null : functionCallContent.Arguments as Dictionary<string, object> ?? new(functionCallContent.Arguments!),
}
};
break;
case FunctionResultContent functionResultContent:
part = new()
{
FunctionResponse = new()
{
Id = functionResultContent.CallId,
Name = callIdToFunctionNames?.TryGetValue(functionResultContent.CallId, out string? functionName) is true || callIdToFunctionNames?.TryGetValue("", out functionName) is true ?
functionName :
null,
Response = functionResultContent.Result is null ? null : new() { ["result"] = functionResultContent.Result },
}
};
break;
}
if (part is not null)
{
part.ThoughtSignature ??= thoughtSignature;
parts.Add(part);
}
}
}
/// <summary>Creates <see cref="AIContent"/>s for <paramref name="parts"/> and adds them to <paramref name="contents"/>.</summary>
private static void AddAIContentsForParts(List<Part> parts, IList<AIContent> contents)
{
foreach (var part in parts)
{
AIContent? content = null;
if (!string.IsNullOrEmpty(part.Text))
{
content = part.Thought is true ?
new TextReasoningContent(part.Text) :
new TextContent(part.Text);
}
else if (part.InlineData is { } inlineData)
{
content = new DataContent(inlineData.Data, inlineData.MimeType ?? "application/octet-stream")
{
Name = inlineData.DisplayName,
};
}
else if (part.FileData is { FileUri: not null } fileData)
{
content = new UriContent(new Uri(fileData.FileUri), fileData.MimeType ?? "application/octet-stream");
}
else if (part.FunctionCall is { Name: not null } functionCall)
{
content = new FunctionCallContent(functionCall.Id ?? "", functionCall.Name, functionCall.Args!);
}
else if (part.FunctionResponse is { } functionResponse)
{
content = new FunctionResultContent(
functionResponse.Id ?? "",
functionResponse.Response?.TryGetValue("output", out var output) is true ? output :
functionResponse.Response?.TryGetValue("error", out var error) is true ? error :
null);
}
if (content is not null)
{
content.RawRepresentation = part;
contents.Add(content);
if (part.ThoughtSignature is { } thoughtSignature)
{
contents.Add(new TextReasoningContent(null)
{
ProtectedData = Convert.ToBase64String(thoughtSignature),
});
}
}
}
}
private static ChatFinishReason? PopulateResponseContents(GenerateContentResponse generateResult, IList<AIContent> responseContents)
{
ChatFinishReason? finishReason = null;
// Populate the response messages. There should only be at most one candidate, but if there are more, ignore all but the first.
if (generateResult.Candidates is { Count: > 0 } &&
generateResult.Candidates[0] is { Content: { } candidateContent } candidate)
{
// Grab the finish reason if one exists.
finishReason = ConvertFinishReason(candidate.FinishReason);
// Add all of the response content parts as AIContents.
if (candidateContent.Parts is { } parts)
{
AddAIContentsForParts(parts, responseContents);
}
// Add any citation metadata.
if (candidate.CitationMetadata is { Citations: { Count: > 0 } citations } &&
responseContents.OfType<TextContent>().FirstOrDefault() is TextContent textContent)
{
foreach (var citation in citations)
{
textContent.Annotations = new List<AIAnnotation>()
{
new CitationAnnotation()
{
Title = citation.Title,
Url = Uri.TryCreate(citation.Uri, UriKind.Absolute, out Uri? uri) ? uri : null,
AnnotatedRegions = new List<AnnotatedRegion>()
{
new TextSpanAnnotatedRegion()
{
StartIndex = citation.StartIndex,
EndIndex = citation.EndIndex,
}
},
}
};
}
}
}
// Populate error information if there is any.
if (generateResult.PromptFeedback is { } promptFeedback)
{
responseContents.Add(new ErrorContent(promptFeedback.BlockReasonMessage));
}
return finishReason;
}
/// <summary>Creates an M.E.AI <see cref="ChatFinishReason"/> from a Google <see cref="FinishReason"/>.</summary>
private static ChatFinishReason? ConvertFinishReason(FinishReason? finishReason)
{
return finishReason switch
{
null => null,
FinishReason.MAX_TOKENS =>
ChatFinishReason.Length,
FinishReason.MALFORMED_FUNCTION_CALL or
FinishReason.UNEXPECTED_TOOL_CALL =>
ChatFinishReason.ToolCalls,
FinishReason.FINISH_REASON_UNSPECIFIED or
FinishReason.STOP =>
ChatFinishReason.Stop,
_ => ChatFinishReason.ContentFilter,
};
}
/// <summary>Creates a <see cref="UsageDetails"/> populated from the supplied <paramref name="usageMetadata"/>.</summary>
private static UsageDetails ExtractUsageDetails(GenerateContentResponseUsageMetadata usageMetadata)
{
UsageDetails details = new()
{
InputTokenCount = usageMetadata.PromptTokenCount,
OutputTokenCount = usageMetadata.CandidatesTokenCount,
TotalTokenCount = usageMetadata.TotalTokenCount,
};
AddIfPresent(nameof(usageMetadata.CachedContentTokenCount), usageMetadata.CachedContentTokenCount);
AddIfPresent(nameof(usageMetadata.ThoughtsTokenCount), usageMetadata.ThoughtsTokenCount);
AddIfPresent(nameof(usageMetadata.ToolUsePromptTokenCount), usageMetadata.ToolUsePromptTokenCount);
return details;
void AddIfPresent(string key, int? value)
{
if (value is int i)
{
(details.AdditionalCounts ??= new())[key] = i;
}
}
}
}
@@ -1,36 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
using Google.Apis.Util;
using Google.GenAI;
namespace Microsoft.Extensions.AI;
/// <summary>Provides implementations of Microsoft.Extensions.AI abstractions based on <see cref="Client"/>.</summary>
public static class GoogleGenAIExtensions
{
/// <summary>
/// Creates an <see cref="IChatClient"/> wrapper around the specified <see cref="Client"/>.
/// </summary>
/// <param name="client">The <see cref="Client"/> to wrap.</param>
/// <param name="defaultModelId">The default model ID to use for chat requests if not specified in <see cref="ChatOptions.ModelId"/>.</param>
/// <returns>An <see cref="IChatClient"/> that wraps the specified client.</returns>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
public static IChatClient AsIChatClient(this Client client, string? defaultModelId = null)
{
Utilities.ThrowIfNull(client, nameof(client));
return new GoogleGenAIChatClient(client, defaultModelId);
}
/// <summary>
/// Creates an <see cref="IChatClient"/> wrapper around the specified <see cref="Models"/>.
/// </summary>
/// <param name="models">The <see cref="Models"/> client to wrap.</param>
/// <param name="defaultModelId">The default model ID to use for chat requests if not specified in <see cref="ChatOptions.ModelId"/>.</param>
/// <returns>An <see cref="IChatClient"/> that wraps the specified <see cref="Models"/> client.</returns>
/// <exception cref="ArgumentNullException"><paramref name="models"/> is <see langword="null"/>.</exception>
public static IChatClient AsIChatClient(this Models models, string? defaultModelId = null)
{
Utilities.ThrowIfNull(models, nameof(models));
return new GoogleGenAIChatClient(models, defaultModelId);
}
}
@@ -1,36 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
// This sample shows how to create and use an AI agent with Google Gemini
using Google.GenAI;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Mscc.GenerativeAI.Microsoft;
const string JokerInstructions = "You are good at telling jokes.";
const string JokerName = "JokerAgent";
string apiKey = Environment.GetEnvironmentVariable("GOOGLE_GENAI_API_KEY") ?? throw new InvalidOperationException("Please set the GOOGLE_GENAI_API_KEY environment variable.");
string model = Environment.GetEnvironmentVariable("GOOGLE_GENAI_MODEL") ?? "gemini-2.5-fast";
// Using a Google GenAI IChatClient implementation
// Until the PR https://github.com/googleapis/dotnet-genai/pull/81 is not merged this option
// requires usage of also both GeminiChatClient.cs and GoogleGenAIExtensions.cs polyfills to work.
ChatClientAgent agentGenAI = new(
new Client(vertexAI: false, apiKey: apiKey).AsIChatClient(model),
name: JokerName,
instructions: JokerInstructions);
AgentRunResponse response = await agentGenAI.RunAsync("Tell me a joke about a pirate.");
Console.WriteLine($"Google GenAI client based agent response:\n{response}");
// Using a community driven Mscc.GenerativeAI.Microsoft package
ChatClientAgent agentCommunity = new(
new GeminiChatClient(apiKey, model),
name: JokerName,
instructions: JokerInstructions);
response = await agentCommunity.RunAsync("Tell me a joke about a pirate.");
Console.WriteLine($"Community client based agent response:\n{response}");
@@ -1,37 +0,0 @@
# Creating an AIAgent with Google Gemini
This sample demonstrates how to create an AIAgent using Google Gemini models as the underlying inference service.
The sample showcases two different `IChatClient` implementations:
1. **Google GenAI** - Using the official [Google.GenAI](https://www.nuget.org/packages/Google.GenAI) package
2. **Mscc.GenerativeAI.Microsoft** - Using the community-driven [Mscc.GenerativeAI.Microsoft](https://www.nuget.org/packages/Mscc.GenerativeAI.Microsoft) package
## Prerequisites
Before you begin, ensure you have the following prerequisites:
- .NET 10.0 SDK or later
- Google AI Studio API key (get one at [Google AI Studio](https://aistudio.google.com/apikey))
Set the following environment variables:
```powershell
$env:GOOGLE_GENAI_API_KEY="your-google-api-key" # Replace with your Google AI Studio API key
$env:GOOGLE_GENAI_MODEL="gemini-2.5-fast" # Optional, defaults to gemini-2.5-fast
```
## Package Options
### Google GenAI (Official)
The official Google GenAI package provides direct access to Google's Generative AI models. This sample uses an extension method to convert the Google client to an `IChatClient`.
> [!NOTE]
> Until PR [googleapis/dotnet-genai#81](https://github.com/googleapis/dotnet-genai/pull/81) is merged, this option requires the additional `GeminiChatClient.cs` and `GoogleGenAIExtensions.cs` files included in this sample.
>
> We appreciate any community push by liking and commenting in the above PR to get it merged and release as part of official Google GenAI package.
### Mscc.GenerativeAI.Microsoft (Community)
The community-driven Mscc.GenerativeAI.Microsoft package provides a ready-to-use `IChatClient` implementation for Google Gemini models through the `GeminiChatClient` class.
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -4,7 +4,7 @@ WARNING: ONNX doesn't support function calling, so any function tools passed to
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- An ONNX model downloaded to your machine
You can download an ONNX model from hugging face, using git clone:
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- Docker installed and running on your machine
- An Ollama model downloaded into Ollama
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -5,7 +5,7 @@ For more information see the OpenAI documentation: https://platform.openai.com/d
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- OpenAI API key
Set the following environment variables:
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -3,7 +3,6 @@
// This sample shows how to create and use a simple AI agent with OpenAI Chat Completion as the backend.
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_APIKEY") ?? throw new InvalidOperationException("OPENAI_APIKEY is not set.");
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 10 SDK or later
- .NET 8.0 SDK or later
- OpenAI api key
Set the following environment variables:

Some files were not shown because too many files have changed in this diff Show More