Compare commits

..
Author SHA1 Message Date
Dmytro StrukandGitHub f5786b2c5b Updated package versions (#2643) 2025-12-04 22:08:47 +00:00
Tao ChenandGitHub d858c23bab Fix observability module mypy error (#2641) 2025-12-04 19:11:05 +00:00
Giles OdigweandGitHub 365e438981 Python: AzureAI Local MCP Sample (#2616)
* added azure ai local mcp sample

* small fix

* handling for local mcp

* remove redundant local mcp handling
2025-12-04 19:10:00 +00:00
01a04a3114 seal options and context classes (#2633)
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2025-12-04 13:16:14 +00:00
Roger BarretoandGitHub ee340bef1d Address vulnerability (#2631) 2025-12-04 11:42:35 +00:00
Evan MattsonandGitHub 19ac6e57c0 Python [BREAKING]: support magentic agent tool call approvals and plan stalling HITL behavior (#2569)
* Provide way for HITL with magentic

* support tool call approvals and hitl stall replan

* human plan intervention sample

* Clean up

* Improve loging

* updates
2025-12-04 05:13:27 +00:00
CopilotGitHubmoonbox3copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Evan Mattson
292a2078fa Python: Fix: AgentRunResponse.created_at returns local datetime labeled as UTC (#2590)
* Initial plan

* Fix created_at to use UTC datetime and add unit tests

Co-authored-by: moonbox3 <35585003+moonbox3@users.noreply.github.com>

* Address code review feedback: move datetime imports to top of test files

Co-authored-by: moonbox3 <35585003+moonbox3@users.noreply.github.com>

* Add UTC timestamp test for OpenAIResponsesClient._create_response_content

Co-authored-by: moonbox3 <35585003+moonbox3@users.noreply.github.com>

* Fix lint issue

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: moonbox3 <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
2025-12-04 05:09:52 +00:00
CopilotGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>eavanvalkenburgEvan Mattson
ae06c9e4bb Add support for Pydantic BaseModel as function call result (#2606)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2025-12-04 01:41:47 +00:00
Evan MattsonandGitHub f7a9005235 Python: Add executor I/O data to ExecutorInvokedEvent and ExecutorCompletedEvent (#2591)
* Add executor I/O data to ExecutorInvokedEvent and ExecutorCompletedEvent

* Sample cleanup
2025-12-04 01:41:40 +00:00
b86c130411 Python: Fixed empty text content pydantic validation failure (#2539)
* Fixed empty text content pydantic validation failure

* simplify syntax. renamed test

---------

Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2025-12-04 01:41:27 +00:00
d774b64df0 Python: added inline yaml sample (#2582)
* added inline yaml sample

* fixed some typos and added intro comment

* added description params and pass through to client

* add azure assistants

* fix tests

* observabiltiy mypy fix

* for some reason mypy doesn't accept a subclass

---------

Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2025-12-04 01:30:56 +00:00
Victor DibiaandGitHub 42ffe59592 Python: Document ChatKit frontend requirements and air-gapped limitations (#2587)
- Add "Requirements and Limitations" section to chatkit package README
- Add "Network Requirements" and "Limitations" sections to chatkit-integration sample README
- Add explanatory comments in frontend code for CDN dependency and domain key configuration

Fixes #2347
2025-12-04 01:19:14 +00:00
Evan MattsonandGitHub a683c0e865 Python: Use executor_id and edge_group_id as span names for meaningful observability traces (#2538)
* Use executor_id and edge_group_id as span names for meaningful observability traces

* Update tests

* Adjust naming
2025-12-04 01:03:12 +00:00
Evan MattsonandGitHub a597a925cb Python: Add type annotations for AgentRunEvent and AgentRunUpdateEvent data attributes (#2589)
* Add type annotations for AgentRunEvent and AgentRunUpdateEvent data attributes

* Fix unnecessary cast after typing improvement

* Mcp pkg update introduced type change. Fix it.

* update opentelemetry deps to 1.39.0 and use LogRecordExporter for type compatibility
2025-12-04 00:40:49 +00:00
9c2e800189 Remove unnecessary PackageReferences after .NET 10 update (#2394)
Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
2025-12-04 00:09:51 +00:00
Peter IbekweandGitHub a26e9d6274 .NET: Add Unit test for declarative object model AddConversationMessageExecutor (#2613)
* Added unit test for RetrieveConversationMessagesExecutor

* Unit test for declarative object model AddConversationMessageExecutor

* Remove unnecessary test.

* Fix test.
2025-12-03 23:25:27 +00:00
Victor DibiaandGitHub 411ee7a60f Python: DevUI fixes : Add multimodal input support for workflows and refactor chat input (#2593)
* show app version in devui .NET: Python: Improved Versioning for DevUI
Fixes #2059

* feat: Add multimodal input support for workflows and refactor chat input

This PR adds support for multimodal content (images, files) in workflow
inputs and refactors the chat input into a reusable component.

## Multimodal Workflow Support
- Add `isChatMessageSchema()` to detect ChatMessage input schemas
- Update `RunWorkflowButton` to use `ChatMessageInput` for ChatMessage workflows
- Wrap multimodal content in OpenAI message format for backend processing
- Add `_is_openai_multimodal_format()` to detect OpenAI ResponseInputParam
- Update `_parse_workflow_input()` to route multimodal input through
  existing `_convert_input_to_chat_message()` converter

## Reusable ChatMessageInput Component
- Extract chat input logic from agent-view into `ChatMessageInput` component
- Support file upload, drag & drop, paste handling, and attachments
- Add `useDragDrop` hook for parent-level drag handling with full-area
  drop zones
- Refactor agent-view to use the new shared component

## Other Improvements
- Add `isStreaming` prop to executor nodes for animation control
- Clean up unused imports and state variables in agent-view
- Add tests for multimodal workflow input handling

Fixes workflow input not receiving images when using AgentExecutor nodes.

* add self loop edge, fix #2470

* fix test
2025-12-03 20:15:51 +00:00
CopilotGitHubrogerbarretocopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
6835161f2d .NET: Fix flaky vector store integration tests - race condition on indexing (#2586)
* Initial plan

* Add vector store indexing wait helpers to fix flaky tests

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

* Use proper VectorStoreStatus struct comparison in Azure tests

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

* Remove unused System.ClientModel import

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

* Remove excessive comments and unnecessary status variable per code review

Co-authored-by: rogerbarreto <19890735+rogerbarreto@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>
2025-12-03 20:06:21 +00:00
3cfd34836f Python: Update _provider.py (#2548)
* Update _provider.py

* Update test_mem0_context_provider.py

* Update test_mem0_context_provider.py

Ruff linting fixes

* Update test_mem0_context_provider.py

---------

Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
2025-12-03 19:54:05 +00:00
Eduard van ValkenburgandGitHub a81279d960 Python: Pin meta core (#2597)
* pin core dependency in the meta package

* fix for mcp latest

* fix mypy

* test fix

* test fix

* fix tests for content parsing
2025-12-03 18:19:17 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Chris
931197ba95 Bump Aspire.Hosting.AppHost from 13.0.0 to 13.0.1 (#2493)
---
updated-dependencies:
- dependency-name: Aspire.Hosting.AppHost
  dependency-version: 13.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
2025-12-03 16:55:04 +00:00
Roger BarretoandGitHub d57303cf53 Bump Persistent V1 package with bugfixes (#2602) 2025-12-03 16:01:37 +00:00
b5595f6f70 Python: Enable Agentic Mode to Use Existing Knowledge Bases Without index_name (#2464)
* refactor KB for index creation logic

* add user agent header for tracking

* fix mypy issues

---------

Co-authored-by: farzad528 <farzad528@users.noreply.github.com>
2025-12-03 16:00:59 +00:00
6232dd8305 .NET [Breaking] Simplify and Refactor ChatclientAgentOptions Ctor + Instructions (#1517)
* Point AgentOptions.Instructions to ChatOptions

* Update tests and checks

* Update xml docs

* Removal of agentOptions.Instructions in favor of chatOptions.Instructions

* Instructions and tool check consistency

* Instructions and tool check consistency

* Address comment

* Update .github/upgrades/prompts/SemanticKernelToAgentFramework.md

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>

* Address PR Comment

* Update latest changes to comply with the PR proposal

* Address feedback

* Update dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentTests.cs

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>

* Address instructions

* Update declarative to use promptAgent.Instrucitons with chatOptions.Instructions

---------

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
2025-12-03 13:39:47 +00:00
David WuandGitHub e9ab514696 Python: Replace Eval SDK with AI Projects SDK in evaluation sample (#2540)
* Replace Eval SDK with AI Projects SDK

* Update per PR review suggestions
2025-12-02 20:28:52 +00:00
Javier Calvarro NelsonandGitHub b69f994840 .NET: Fix AG-UI forwardedProps JSON property name (#2543)
* Fix AG-UI forwardedProps JSON property name

The RunAgentInput.ForwardedProperties property was using the wrong JSON property
name 'forwardedProperties' instead of 'forwardedProps' per the AG-UI protocol
specification.

This fix:
- Changes JsonPropertyName from 'forwardedProperties' to 'forwardedProps'
- Adds comprehensive integration tests for forwarded properties

Fixes #2468

* Fix formatting
2025-12-02 17:00:40 +00:00
ceaea46765 .NET: Change Anthropic Azure sample to use Athropic.Foundry package + cachi… (#2578)
* Change Anthropic Azure sample to use Athropic.Foundry package + caching token

* Fix apikey null

* Update dotnet/samples/GettingStarted/AgentProviders/Agent_With_Anthropic/Program.cs

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

* Address copilot feedback

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-02 16:50:14 +00:00
1edd28b264 feat: pass agent run kwargs through to context providers (#1681)
`_prepare_thread_and_messages` and `_notify_thread_of_new_messages` now are passing through the agent's `run` kwargs, sothat they can provide the context_provider with said kwargs

#1679

Co-authored-by: David Jadczyk <david.jadczyk@lht.dlh.de>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
2025-12-02 14:35:32 +00:00
SergeyMenshykhandGitHub 5c70e143a0 .NET: Fix samples for hosted agents (#2550)
* update .net sdk and runtime images and update nuget packages to the latests versions

* align version of roslyn analyzers

* unlock roslyn analyzer packages
2025-12-02 11:12:46 +00:00
Evan MattsonandGitHub c2d285e614 Fix MangenticAgentExecutor producing repr str for tool call content (#2566) 2025-12-02 08:40:11 +00:00
CopilotGitHublarohracopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Laveesh Rohra
cb343dd707 Python: Add orchestration ID to durable agent entity state and code refactor (#2484)
* Initial plan

* Add orchestration ID to durable agent entity state for Python

Co-authored-by: larohra <41490930+larohra@users.noreply.github.com>

* Fix type safety checks

* Fix tests

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: larohra <41490930+larohra@users.noreply.github.com>
Co-authored-by: Laveesh Rohra <larohra@microsoft.com>
2025-12-02 01:34:18 +00:00
Evan MattsonandGitHub 0d5d10d24a Python: Emit ExecutorFailedEvent before WorkflowFailedEvent when executor throws exception (#2537)
* Emit ExecutorFailedEvent before WorkflowFailedEvent when executor throws exception

* Cleanup
2025-12-02 01:21:28 +00:00
Evan MattsonandGitHub e3b700ad9f Python: Add sample to show handoff as agent with HITL (#2534)
* Add sample to show handoff as agent with HITL

* Update uv.lock with latest pkg versions. Fix lint error.

* Upgrade grpcio to 1.76.0

* Handle grpcio versions

* Case insensitive compare for declarative
2025-12-02 00:50:13 +00:00
Roger BarretoandGitHub 8ae33d3c2b Address gap IServiceProvider options (#2551) 2025-12-01 20:01:13 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
bf326e7f78 Bump actions/setup-dotnet from 5.0.0 to 5.0.1 (#2530)
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v5.0.0...v5.0.1)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 19:12:06 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b457d3cdbe Bump Aspire.Hosting.Azure.CognitiveServices from 13.0.0 to 13.0.1 (#2528)
---
updated-dependencies:
- dependency-name: Aspire.Hosting.Azure.CognitiveServices
  dependency-version: 13.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 19:12:02 +00:00
Roger BarretoandGitHub 139c292807 .NET: Add Google ChatClientAgent provider sample using with Gemini model (#2554)
* Add Gemini model sample

* Update Readme

* Address Comments

* Address format
2025-12-01 18:51:15 +00:00
Mark WallaceandGitHub b26108975d .NET: Declarative Agents (#2476)
* Update the declarative agent samples

* Add the Microsoft.Agents.AI.Declarative project

* Make the package non packable

* Use the RecalcEngine when creating the ChatOptions

* Ignore VSTHRD200

* Add geting started samples

* Address code review feedback
2025-12-01 15:15:18 +00:00
a3909b8b5b Change sample to use official Anthropic C# package (#2471)
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2025-11-28 19:10:54 +00:00
67de7bcd93 .NET: Prevent streamed updates loss when resuming streaming (#2516)
* prevent stremed updates loss when resuming streaming with non-agent managed store or/and context provider

* Update dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgent.cs

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

* throw not supported exception instead invalid operation

* Update dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgent.cs

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>

* Update dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgent.cs

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>

* use conversation id to check if chat history is managed by agent service or not

* extract background responses tests into a separate file

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
2025-11-28 16:11:30 +00:00
SergeyMenshykhandGitHub e769256976 .NET: Require thread for background responses (#2498)
* require thread for backgraund responses

* address pr review feedback
2025-11-27 16:26:52 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
257e717608 Bump Anthropic from 10.2.1 to 10.4.0 (#2492)
---
updated-dependencies:
- dependency-name: Anthropic
  dependency-version: 10.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-27 16:00:25 +00:00
Stephen ToubandGitHub 66a399ee2d Update Azure.AI.OpenAI to latest release (#2501) 2025-11-27 15:28:43 +00:00
Evan MattsonandGitHub 8cf8b0f995 Python: Refactor ag-ui to clean up some patterns (#2363)
* Refactor ag-ui to clean up some patterns

* Mypy fixes

* Fix imports, typing, tests, logging.

* Fix test import error

* Fix imports again

* Fix thread handling
2025-11-27 02:13:03 +00:00
6c624319db Python: docs: Update Python orchestration documentation (#2087)
* docs: Update Python orchestration documentation

Remove outdated 'coming soon' statements for GroupChat, Sequential,
and Concurrent orchestrations in core package README and transparency FAQ.

Add links to existing samples in python/samples/getting_started/workflows/orchestration/.

Note: python/README.md was already updated in PR #1914 (2499262f).

Fixes documentation inconsistency found in Issue #1899.

* Address review feedback: make TRANSPARENCY_FAQ language-neutral

Remove Python-specific sample links from TRANSPARENCY_FAQ.md as it should
pertain to all MAF languages (Python and .NET), not strictly Python.

The python/packages/core/README.md retains the specific sample links as
that is Python-specific documentation.

* Update Learn documentation link in README

---------

Co-authored-by: kishikawa-hayato <84244732+HerBest-max@users.noreply.github.com>
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
2025-11-27 00:13:15 +00:00
Laveesh RohraandGitHub 306c81aef8 Python: [Breaking] Python: Respond with AgentRunResponse with serialized structured output (#2285)
* Respond with AgentRunResponse

* Fix response_Format type

* Address comments

* Fix tests

* Fix log

* Addressed comments

* Code cleanup

* Use AgentTask vs Generator

* Address comments

* use lazy logging

* fix mypy errors
2025-11-26 18:44:28 +00:00
westeyandGitHub 0f2c5e6cb8 Add office hours call to action to readme.me (#2480) 2025-11-26 18:21:02 +00:00
Phillip HoffandGitHub 17b4dfab14 .NET: Add orchestration ID to durable agent entity state (#2137)
* Propagate orchestration ID (if any).

* Add integration test for orchestration ID in entity state.

* Update schema.

* Fixup formatting issues.

* Fix more formatting issues.
2025-11-26 16:32:32 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Chris
486b78126d Bump danielpalme/ReportGenerator-GitHub-Action from 5.4.18 to 5.5.0 (#2256)
Bumps [danielpalme/ReportGenerator-GitHub-Action](https://github.com/danielpalme/reportgenerator-github-action) from 5.4.18 to 5.5.0.
- [Release notes](https://github.com/danielpalme/reportgenerator-github-action/releases)
- [Commits](https://github.com/danielpalme/reportgenerator-github-action/compare/5.4.18...5.5.0)

---
updated-dependencies:
- dependency-name: danielpalme/ReportGenerator-GitHub-Action
  dependency-version: 5.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
2025-11-26 14:41:49 +00:00
0723f1d183 .NET: Foundry V2 - Update Sample and Docs for clear distinction between Classic/New Foundry Agents. (#2459)
* Address potential confusion around agent version vs API version

* Address potential confusion around agent version vs API version

* Add extra documentation for clarity

* Remove V2 remainers

* Apply suggestions from code review

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

* Apply suggestions from code review

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
2025-11-26 14:37:03 +00:00
Theo van KraayandGitHub a57b37d5fa .NET: Add Cosmos DB implementations for ChatMessageStore and CheckpointStore. (#1838)
* draft commit

* Added Cosmos agent thread and tests

* revert unnecessary changes and fix tests

* add multi-tenant support with hierarchical partition keys (and tests).

* enhance transactional batch

* address review comments

* Address PR review comments from @westey-m

* Merge upstream/main - resolve slnx conflicts

* use param validation helpers

* Replace useManagedIdentity boolean with TokenCredential parameter

* Remove redundant suppressions and fix tests

* Rename project from Microsoft.Agents.AI.Abstractions.CosmosNoSql to Microsoft.Agents.AI.CosmosNoSql

* Refactor constructors to use chaining pattern

* Reorder deserialization constructor parameters for consistency

* Remove database/container IDs from serialized state

* Remove auto-generation of MessageId

* Optimize AddMessagesAsync to avoid enumeration when possible

* Add MaxMessagesToRetrieve to limit context window

* Make Role nullable instead of defaulting

* Fix net472 build without rebasing 19 commits

* Add Cosmos DB emulator to CI workflow

* Fix Cosmos DB emulator tests: use Skip.If instead of Assert.Fail and start emulator before unit tests

* Replace Skip.If() with conditional return to fix compilation

* Use env var to skip Cosmos tests on non-Windows CI

* Add Xunit.SkippableFact package to properly skip Cosmos tests on Linux

* Change [Fact] to [SkippableFact] for proper test skipping behavior

* Remove stale Microsoft.Agents.AI.Abstractions.CosmosNoSql directory

* Fix code formatting: add braces, this. qualifications, and final newlines

* Fix file encoding to UTF-8 with BOM, fix import ordering, and remove unnecessary using directives

* Convert backing fields to auto-properties and remove Azure.Identity using directive

* Fix CosmosChatMessageStore.cs encoding back to UTF-8 with BOM

* Fix test file formatting: indentation, encoding, imports, this. qualifications, naming conventions, and simplify new expressions

* Fix const field naming violations: Remove s_ prefix from const fields and add this. qualification to Dispose call

* Add local .editorconfig for Cosmos DB tests to suppress IDE0005 false positives from multi-targeting

* Fix IDE1006 naming violations: Rename TestDatabaseId to s_testDatabaseId and add final newlines

* Address PR review comments

Address Wesley's review comments:

- Remove Cosmos DB package references from core projects

- Delete duplicate test files from old package structure

- Remove redundant parameter validation from extension methods

Address Kiran's review comments:

- Remove redundant 429 retry logic (SDK handles automatically)

- Add explicit RequestEntityTooLarge error handling

- Remove dead code in GetMessageCountAsync

- Add defensive partition key validation comments

* Fix IDE0001 formatting error in AgentProviderExtensions.cs. Use type alias to resolve namespace conflict between Azure.AI.Agents.Persistent.RunStatus and Microsoft.Agents.AI.Workflows.RunStatus. This eliminates the need for global:: qualifier which triggered the formatter warning.

* Update package versions for Aspire 13.0.0 compatibility

* Fix TargetFrameworks in Cosmos DB projects

- Replace  with  which is defined in Directory.Build.props
- Fix package reference from System.Linq.Async to System.Linq.AsyncEnumerable to match Directory.Packages.props

* Remove redundant counter, add partition key validation, use factory pattern for deserialization
2025-11-26 12:36:27 +00:00
Evan MattsonandGitHub 907d79ab3c [BREAKING] Python: Standardize orchestration outputs as list of ChatMessage. Allow agent as group chat manager. (#2291)
* Standardize orchestration outputs as list of chatmessage. Add chat options to group chat prompt manager

* refactor group chat

* Improve group chat manager

* README Update

* Cleanup

* Add comment

* More cleanup

* Standardize termination condition for group chat

* Improvements on termination logic

* Fix tests

* Fix new line

* PR feedback

* Update ChatKit based on OpenAI type change

* Raise error if response format is not expected type

* Only one starting executor required. Add tests.

* Add magentic start executor test
2025-11-26 07:51:04 +00:00
Dmytro StrukandGitHub ed53ba158b Temporarily suppress CS8002 error (#2462) 2025-11-25 17:24:46 -08:00
5d8be5836c Python: Added support for application endpoints in Azure AI client (#2460)
* Added support for application endpoints in Azure AI client

* Fixed tests

* Update python/samples/getting_started/agents/azure_ai/azure_ai_with_application_endpoint.py

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

* Addressed comments

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-25 19:32:55 +00:00
Dmytro StrukandGitHub 0c1d12feca Suppressed CS8002 for Anthropic package (#2461) 2025-11-25 19:11:49 +00:00
b1c210c9d8 Python: Added MCP tool support for azure functions package. (#2385)
* Python: Add Scaffolding for Durable AzureFunctions package to Agent Framework (#1823)

* Add scafolding

* update readme

* add code owners and label

* update owners

* .NET: Durable extension: initial src and unit tests (#1900)

* Python: Add Durable Agent Wrapper code (#1913)

* add initial changes

* Move code and add single sample

* Update logger

* Remove unused code

* address PR comments

* cleanup code and address comments

---------

Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>

* Azure Functions .NET samples (#1939)

* Python: Add Unit tests for Azurefunctions package (#1976)

* Add Unit tests for Azurefunctions

* remove duplicate import

* .NET: [Feature Branch] Migrate state schema updates and support for agents as MCP tools (#1979)

* Python: Add more samples for Azure Functions (#1980)

* Move all samples

* fix comments

* remove dead lines

* Make samples simpler

* Agents as MCP tools

* Removed unused files and updated sample

* .NET: [Feature Branch] Durable Task extension integration tests (#2017)

* .NET: [Feature Branch] Update OpenAI config for integration tests (#2063)

* Python: Add Integration tests for AzureFunctions  (#2020)

* Add Integration tests

* Remove DTS extension

* 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>

* Add pyi file for type safety

* Add samples in readme

* Updated all readme instructions

* Address comments

* Update readmes

* Fix requirements

* Address comments

---------

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

* Addressed copilot feedback

* Minor refactoring and added tests

* Updated mcp sample

* Fixed broken link in readme

* Addressed copilot comments

* Addressed feedback

* Updated property to enable_mcp_tool_trigger

---------

Co-authored-by: Laveesh Rohra <larohra@microsoft.com>
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
Co-authored-by: Chris Gillum <cgillum@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-25 18:50:02 +00:00
Dmytro StrukandGitHub b8260ae24c Python: [BREAKING] Removed default "store" value (#2443)
* Removed default store value

* Small fix
2025-11-25 17:53:08 +00:00
Dmytro StrukandGitHub d302bffc63 Updated package versions (#2455) 2025-11-25 17:16:00 +00:00
Stephen ToubandGitHub 7a4f6877c3 Use Random.GetString in hosting IdGenerator (#2427) 2025-11-25 12:01:28 +00:00
westeyandGitHub b6c3b8d3f2 [BREAKING] Remove NotifyThreadOfNewMessagesAsync AIAgent helper (#2450)
* Remove NotifyThreadOfNewMessagesAsync helper from AIAgent

* Fix bug

* Update comment
2025-11-25 11:59:26 +00:00
1dde57981e .NET: Add Anthropic Agent Package (#2359)
* WIP

* WIP

* Simple call working

* Update Thinking sample

* Non-Streaming Function calling working

* Update Anthropic Impl

* Public Preps

* UT + IT working

* Update documentation + samples

* Update variable

* Revert nuget.config

* Add IT for BetaService implementation

* Remove polyfill + enable IT to run for netstandard 2.0

* Skipping Anthropic IT's for manual execution and avoid pipeline execution

* Fix compilation error

* Address error in UT

* Apply suggestions from code review

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

* Fix warning

* Net 10 update

* Update for NET 10, remove Anthropic.Foundry due to vulnerability

* Final missing adjustments for NET 10

* Address PR comments

* Remove unused code

* Address feedback

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-25 11:53:18 +00:00
112410ecd6 .NET: [BREAKING] Add GetNewThread overload for taking a ChatMessageStore at thread creation time (#2429)
* Add GetNewThread overload for taking a ChatMessageStore at thread creation time and move message store creation to thread creation time.

* Fix formatting.

* Apply suggestions from code review

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

* Apply suggestion from @rogerbarreto

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2025-11-25 10:49:01 +00:00
SergeyMenshykhandGitHub a89c15d6e6 .NET: Change type of props representing continuation token (#2430)
* change type of props representing continuation token

* use explict cast instead of the as operator
2025-11-25 09:59:43 +00:00
27b3a517eb [BREAKING] Python: Adjust magentic event types raised. No need for custom events. (#2215)
* Adjust magentic event types raised. No need for custom events.

* Cleanup

* Fix test

* Update python/packages/core/agent_framework/_workflows/_magentic.py

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-25 08:24:08 +00:00
Eduard van ValkenburgandGitHub 1b4103dce3 Python: fix for logging setup (#2371)
* fix for logging setup

* typo fixes

* fix text
2025-11-25 08:19:34 +00:00
Evan MattsonandGitHub 2a4802eac3 Python: Fix runtime response format for responses client (#2440)
* Fix runtime response format for responses client

* Handle run time schema for Azure AI Client.
2025-11-25 07:50:20 +00:00
Giles OdigweandGitHub e303cc963d Python: AzureAI OpenAPI + Memory Search Samples (#2390)
* openapi + memory search samples

* readme update

* memory store name fix
2025-11-25 01:17:14 +00:00
Tomek SłomaandGitHub c78edda64f fix: always include output in function call result message (#2414)
This follows the official OpenAI API schema
2025-11-25 00:44:43 +00:00
a610a4769c .NET: Add support for background responses to A2A agent (#2381)
* add support for baackground responses to a2a agent

* fix line endings

* address pr review comments

* address pr review comments

* update sample to net10.0

* Update dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/README.md

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

* Update dotnet/src/Microsoft.Agents.AI.A2A/Extensions/A2AAgentTaskExtensions.cs

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

* Update dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/Program.cs

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

* address pr review feedback

* add clarification regarding background responses

---------

Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
2025-11-24 19:41:06 +00:00
Giles OdigweandGitHub bcbf1b33e8 Python: Preserve MCP array items schema in Pydantic field generation (#2382)
* mcp tool parameter fix

* small fixes
2025-11-24 17:16:30 +00:00
Eduard van ValkenburgandGitHub 9f43108ef1 Python: renamed ai search and cleanup of samples and unified import logic (#2369)
* renamed ai search and cleanup of samples and unified import logic

* fixed error messages

* fixed folder name

* remove old samples from readme
2025-11-24 17:06:22 +00:00
westeyandGitHub db424d56f3 Update to latest dotnet devcontainer and add docker in docker. (#2426) 2025-11-24 15:42:53 +00:00
Roger BarretoandGitHub c692821869 Address IT failure for V2 (#2421) 2025-11-24 14:02:32 +00:00
Stephen ToubandGitHub a116edaf5a Update to latest MEAI 10.0.1 and OpenAI 2.7.0 (#2392) 2025-11-24 13:51:27 +00:00
b66efcc09d remove version override for v10 packages (#2393)
Co-authored-by: SergeyMenshykh <sergemenshikh@gmail.com>
2025-11-24 13:01:07 +00:00
Giles OdigweandGitHub ec08ee541d a2a sample update (#2391) 2025-11-24 10:57:00 +00:00
Evan MattsonandGitHub f9a94ce7b5 Bug fix for Redis TypeError (#2411) 2025-11-24 10:48:33 +00:00
Victor DibiaandGitHub f0f1051c7d Python: make tool call view optional in DevUI + other link fixes (#2243)
* make tool call view optional in devui + other link fixes

* fix #2310, ensure correct port is shown in command

* fix dialog bug

* ensure executor ids are tracked per items, fix bug where data from concurrent executors where not seperated properly fix #2351

* fix: Enable multi-round human-in-the-loop (HIL) in DevUI workflows

- Backend: Enrich RequestInfoEvents with response schemas in send_responses_streaming path
- Frontend: Replace old HIL requests with new ones instead of accumulating them
- Frontend: Fix HIL response state management to prevent sending stale request responses

This allows workflows to properly handle sequential HIL requests, showing only the
current request to users and progressing through multiple input rounds correctly.

fixes #2334

* fix bug to ensure in memory entities cannot be reloaded in ui
2025-11-24 07:22:53 +00:00
Stephen ToubandGitHub dc2b109b50 .NET: Upgrade to .NET 10 (#2128)
* Upgrade to .NET 10

- Require .NET 10 SDK
- Include net10.0 assets in all assemblies
- Move net9.0-only targets to net10.0
- Update LangVersion to latest
- Remove complicated distinctions between debug target TFMs and release target TFMs
- Remove unnecessary package dependencies when built into netcoreapp
- Clean up some ifdefs
- Clean up some analyzer warnings

* Fix CI
2025-11-22 04:14:15 +00:00
ee8936d514 Python: Integration tests for Azure AI client and fixes in samples (#2387)
* Added integration tests

* Update python/packages/azure-ai/tests/test_azure_ai_client.py

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

* Small fixes in samples

* Small fix

* Small fix

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-22 00:31:57 +00:00
Peter IbekweandGitHub b7a19b0fa2 Added unit test for RetrieveConversationMessagesExecutor (#2388) 2025-11-21 21:03:21 +00:00
Korolev DmitryandGitHub 02b8ac277e .NET: sanitize redirectUrl for logs (#2356)
* sanitize redirectUrl for logs

* use basepath

* sanitize both path and reddirect url
2025-11-21 12:25:53 +00:00
westeyandGitHub 7148718804 Redacting log data unless opting out. (#2372) 2025-11-21 11:09:17 +00:00
4c529037b8 Python: Use Foundry evaluators to evaluate agent workflows (#2322)
* Create workflow evaluation with Foundry demo

* Upgrade syntax

* Add copyright line

* import fix

* import fix

* address pr comments

* Python: Workflow eval sample - print evaluator names

* Python: Workflow eval - address PR comments

* Update samples readme

---------

Co-authored-by: Salma Elshafey <selshafey@microsoft.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
2025-11-21 09:51:44 +00:00
1bf926bfc9 Python: Fix the example of multi-tier handoff workflow with specialist-to-specialist routing (#2332)
* Fix the example (1) to send only one initial message (2) to end conversation after trigger the last response as the comment describes

* Apply suggestions from code review

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

* changed the hard-coded user query

---------

Co-authored-by: tsuting.kao <tsu.kao@microsoft.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-21 09:36:35 +00:00
d18ce24bf8 Python: feat(mcp): add full _meta field support for CallToolResult objects (#2286)
* feat(mcp): add full _meta field support for CallToolResult objects

- Extract and preserve complete _meta field from MCP CallToolResult responses
- Merge metadata into additional_properties of converted content items
- Handle isError field for proper error state integration
- Support arbitrary metadata like token usage, costs, and performance metrics
- Maintain backward compatibility with existing tool execution workflows
- Add comprehensive test coverage for all metadata scenarios including edge cases
- Update documentation with metadata handling examples and patterns

Fixes protocol compliance violation where _meta fields were being dropped,
enables proper monitoring and cost tracking of MCP tool usage.

* Update python/packages/core/agent_framework/_mcp.py

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

* Clarify MCP _meta field test to use generic example metadata

- Updated test_mcp_call_tool_result_with_meta_arbitrary_data to use arbitrary metadata fields
- Added comments to emphasize that _meta structure is server-specific and not standardized

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-21 08:43:24 +00:00
Eduard van ValkenburgandGitHub a7a0660cac removed additional properties from messages sent to OAI responses and chat (#2344) 2025-11-21 08:41:38 +00:00
0781d4b459 Python: Add Handoff + tool approval + checkpointing sample (#2346)
* Handoff sample

* handoff with tool approval

* add Hanoff sample with tool approval and checkpointing

* Add to README

* Remove unnecessary files

* Update python/samples/getting_started/workflows/checkpoint/handoff_with_tool_approval_checkpoint_resume.py

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

* Fix comment

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-21 13:13:27 +09:00
Evan MattsonandGitHub 5bdf8a774a Sample to show passing in JSON schema for structured outputs (#2362) 2025-11-21 01:42:46 +00:00
741 changed files with 29053 additions and 8074 deletions
+3 -2
View File
@@ -1,10 +1,11 @@
{
"name": "C# (.NET)",
"image": "mcr.microsoft.com/devcontainers/dotnet:9.0",
"image": "mcr.microsoft.com/devcontainers/dotnet:10.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/azure-cli:1.2.8": {},
"ghcr.io/devcontainers/features/docker-in-docker:2.12.4": {}
},
"workspaceFolder": "/workspaces/agent-framework/dotnet/",
"customizations": {
@@ -1636,4 +1636,4 @@ The property mapping guide from a `AutoFunctionInvocationContext` to a `Function
| Result | Use `return` from the delegate |
| Terminate | Terminate |
| CancellationToken | provided via argument to middleware delegate |
| Arguments | Arguments |
| Arguments | Arguments |
+40 -15
View File
@@ -18,6 +18,7 @@ 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 }}
@@ -59,9 +60,9 @@ jobs:
fail-fast: false
matrix:
include:
- { 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: "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: "net472", os: "windows-latest", configuration: Release, integration-tests: true, environment: "integration" }
runs-on: ${{ matrix.os }}
@@ -69,16 +70,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.0
uses: actions/setup-dotnet@v5.0.1
with:
global-json-file: ${{ github.workspace }}/dotnet/global.json
- name: Build dotnet solutions
@@ -123,7 +124,17 @@ jobs:
popd
rm -rf "$TEMP_DIR"
- name: Run Unit Tests Windows
# 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
shell: bash
run: |
export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | tr '\n' ' ')
@@ -133,12 +144,20 @@ jobs:
# Check if the project supports the target framework
if [[ "$target_frameworks" == *"${{ matrix.targetFramework }}"* ]]; 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
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
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 }}"
@@ -176,6 +195,9 @@ 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 }}
@@ -194,19 +216,22 @@ jobs:
# Generate test reports and check coverage
- name: Generate test reports
uses: danielpalme/ReportGenerator-GitHub-Action@5.4.18
if: matrix.targetFramework == env.COVERAGE_FRAMEWORK
uses: danielpalme/ReportGenerator-GitHub-Action@5.5.0
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: "9.0", configuration: Release, os: ubuntu-latest }
- { dotnet: "10.0", configuration: Release, os: ubuntu-latest }
runs-on: ${{ matrix.os }}
env:
+2
View File
@@ -48,6 +48,8 @@ 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, netstandard2.0, net472)
- **Platform Requirements**: Python 3.10+ required, specific .NET versions (.NET 8.0, 9.0, 10.0, netstandard2.0, net472)
- **API Dependencies**: Requires proper configuration of LLM provider keys and endpoints
- **Orchestration Features**: Advanced orchestration patterns like GroupChat, Sequential, and Concurrent orchestrations are "coming soon" for Python implementation
- **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.
- **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.
@@ -1,9 +1,9 @@
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 Assistants as the type in your response.
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: =Env.AZURE_OPENAI_DEPLOYMENT_NAME
id: gpt-4o-mini
provider: AzureOpenAI
apiType: Assistants
options:
@@ -12,14 +12,14 @@ model:
outputSchema:
properties:
language:
kind: string
type: string
required: true
description: The language of the answer.
answer:
kind: string
type: string
required: true
description: The answer text.
type:
kind: string
type: string
required: true
description: The type of the response.
+25
View File
@@ -0,0 +1,25 @@
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.
+7 -10
View File
@@ -1,28 +1,25 @@
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 Responses as the type in your response.
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: =Env.AZURE_OPENAI_DEPLOYMENT_NAME
id: gpt-4o-mini
provider: AzureOpenAI
apiType: Responses
options:
text:
verbosity: medium
connection:
kind: remote
endpoint: =Env.AZURE_OPENAI_ENDPOINT
temperature: 0.9
topP: 0.95
outputSchema:
properties:
language:
kind: string
type: string
required: true
description: The language of the answer.
answer:
kind: string
type: string
required: true
description: The answer text.
type:
kind: string
type: string
required: true
description: The type of the response.
+3 -3
View File
@@ -1,7 +1,7 @@
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.
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
@@ -9,10 +9,10 @@ model:
outputSchema:
properties:
language:
kind: string
type: string
required: true
description: The language of the answer.
answer:
kind: string
type: string
required: true
description: The answer text.
+2
View File
@@ -4,6 +4,8 @@ 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:
+22
View File
@@ -0,0 +1,22 @@
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.
+6 -8
View File
@@ -1,30 +1,28 @@
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 Assistants as the type in your response.
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: =Env.OPENAI_MODEL
id: gpt-4.1-mini
provider: OpenAI
apiType: Assistants
options:
temperature: 0.9
topP: 0.95
connection:
kind: key
kind: ApiKey
key: =Env.OPENAI_APIKEY
outputSchema:
name: AssistantResponse
description: The response from the assistant.
properties:
language:
kind: string
type: string
required: true
description: The language of the answer.
answer:
kind: string
type: string
required: true
description: The answer text.
type:
kind: string
type: string
required: true
description: The type of the response.
+28
View File
@@ -0,0 +1,28 @@
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.
+8 -8
View File
@@ -1,28 +1,28 @@
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 Responses as the type in your response.
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: =Env.OPENAI_MODEL
id: gpt-4.1-mini
provider: OpenAI
apiType: Responses
options:
text:
verbosity: medium
temperature: 0.9
topP: 0.95
connection:
kind: key
kind: ApiKey
key: =Env.OPENAI_APIKEY
outputSchema:
properties:
language:
kind: string
type: string
required: true
description: The language of the answer.
answer:
kind: string
type: string
required: true
description: The answer text.
type:
kind: string
type: string
required: true
description: The type of the response.
+4 -6
View File
@@ -6,14 +6,12 @@
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>13</LangVersion>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);NU5128</NoWarn>
<NoWarn>$(NoWarn);NU5128;CS8002</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<ProjectsCoreTargetFrameworks>net9.0;net8.0</ProjectsCoreTargetFrameworks>
<ProjectsDebugCoreTargetFrameworks>net9.0</ProjectsDebugCoreTargetFrameworks>
<ProjectsTargetFrameworks>net9.0;net8.0;netstandard2.0;net472</ProjectsTargetFrameworks>
<ProjectsDebugTargetFrameworks>net9.0;net472</ProjectsDebugTargetFrameworks>
<TargetFrameworksCore>net10.0;net9.0;net8.0</TargetFrameworksCore>
<TargetFrameworks>$(TargetFrameworksCore);netstandard2.0;net472</TargetFrameworks>
<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)' == '' AND '$(TargetFramework)' == '$(ProjectsDebugTargetFrameworks)'">
<Target Name="DotnetFormatOnBuild" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Release' AND '$(GITHUB_ACTIONS)' == '' ">
<Message Text="Running dotnet format" Importance="high" />
<Exec Command="dotnet format --no-restore -v diag $(ProjectFileName)" />
</Target>
+31 -21
View File
@@ -7,10 +7,12 @@
</PropertyGroup>
<PropertyGroup>
<!-- Aspire -->
<AspireAppHostSdkVersion>13.0.0</AspireAppHostSdkVersion>
<AspireAppHostSdkVersion>13.0.1</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)" />
@@ -18,15 +20,22 @@
<PackageVersion Include="CommunityToolkit.Aspire.OllamaSharp" Version="13.0.0-beta.440" />
<!-- Azure.* -->
<PackageVersion Include="Azure.AI.Projects" Version="1.2.0-beta.3" />
<PackageVersion Include="Azure.AI.Projects.OpenAI" Version="1.0.0-beta.3" />
<PackageVersion Include="Azure.AI.Agents.Persistent" Version="1.2.0-beta.7" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
<PackageVersion Include="Azure.AI.Projects.OpenAI" Version="1.0.0-beta.4" />
<PackageVersion Include="Azure.AI.Agents.Persistent" Version="1.2.0-beta.8" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.7.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.0" />
<PackageVersion Include="System.ClientModel" Version="1.8.1" />
<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" />
@@ -37,6 +46,7 @@
<PackageVersion Include="System.Text.Json" Version="10.0.0" />
<PackageVersion Include="System.Threading.Channels" Version="10.0.0" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
<PackageVersion Include="System.Net.Security" Version="4.3.2" />
<!-- OpenTelemetry -->
<PackageVersion Include="OpenTelemetry" Version="1.13.1" />
<PackageVersion Include="OpenTelemetry.Api" Version="1.13.1" />
@@ -48,13 +58,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="9.0.11" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.0.0" />
<!-- Microsoft.Extensions.* -->
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.AI.AzureAIInference" Version="10.0.0-preview.1.25559.3" />
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" 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.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" />
@@ -80,22 +90,21 @@
<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.2.41" />
<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.2.41" />
<PackageVersion Include="Microsoft.Agents.Hosting.AspNetCore" Version="1.2.41" />
<PackageVersion Include="Microsoft.Agents.Authentication.Msal" Version="1.3.171-beta" />
<PackageVersion Include="Microsoft.Agents.Hosting.AspNetCore" Version="1.3.171-beta" />
<!-- 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.6.0" />
<PackageVersion Include="OpenAI" Version="2.7.0" />
<!-- Identity -->
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.78.0" />
<!-- Workflows -->
@@ -117,16 +126,17 @@
<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" Version="9.0.11" />
<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.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 -->
@@ -153,20 +163,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.0]" />
<PackageVersion Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" />
<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.0]" />
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="4.14.1" />
<PackageReference Include="Roslynator.Formatting.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
</Project>
+22 -1
View File
@@ -40,16 +40,19 @@
<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" />
@@ -76,11 +79,21 @@
<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" />
@@ -311,6 +324,7 @@
<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" />
@@ -335,9 +349,12 @@
<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" />
@@ -357,6 +374,7 @@
<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" />
@@ -373,8 +391,11 @@
<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" />
@@ -389,4 +410,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": "9.0.300",
"rollForward": "latestMajor",
"version": "10.0.100",
"rollForward": "minor",
"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).251114.1</PackageVersion>
<PackageVersion Condition="'$(VersionSuffix)' == ''">$(VersionPrefix)-preview.251114.1</PackageVersion>
<GitTag>1.0.0-preview.251114.1</GitTag>
<PackageVersion Condition="'$(VersionSuffix)' != ''">$(VersionPrefix)-$(VersionSuffix).251125.1</PackageVersion>
<PackageVersion Condition="'$(VersionSuffix)' == ''">$(VersionPrefix)-preview.251125.1</PackageVersion>
<GitTag>1.0.0-preview.251125.1</GitTag>
<Configurations>Debug;Release;Publish</Configurations>
<IsPackable>true</IsPackable>
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
@@ -12,8 +12,6 @@
<PackageReference Include="A2A" />
<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>
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
@@ -11,8 +11,11 @@
<ItemGroup>
<PackageReference Include="Azure.AI.Agents.Persistent" />
<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 Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net10.0'))">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="System.Linq.AsyncEnumerable" />
</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-9.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-10.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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>a8b2e9f0-1ea3-4f18-9d41-42d1a6f8fe10</UserSecretsId>
@@ -11,8 +11,6 @@
<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();
builder.AppendLine();
var builder = new StringBuilder().AppendLine();
foreach (var kvp in arguments)
{
builder.AppendLine($" Name: {kvp.Key}");
builder.AppendLine($" Value: {kvp.Value}");
builder
.AppendLine($" Name: {kvp.Key}")
.AppendLine($" Value: {kvp.Value}");
}
return builder.ToString();
}
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>b9c3f1e1-2fb4-5g29-0e52-53e2b7g9gf21</UserSecretsId>
@@ -11,8 +11,6 @@
<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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>a8b2e9f0-1ea3-4f18-9d41-42d1a6f8fe10</UserSecretsId>
@@ -11,8 +11,6 @@
<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>
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -31,11 +31,4 @@
<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,9 +4,7 @@ using Microsoft.Extensions.AI;
namespace AgentWebChat.AgentHost.Custom;
public class CustomAITool : AITool
{
}
public class CustomAITool : AITool;
public class CustomFunctionTool : AIFunction
{
@@ -4,7 +4,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireSharedProject>true</IsAspireSharedProject>
@@ -25,7 +25,7 @@ internal sealed class A2AAgentClient : AgentClientBase
this._uri = baseUri;
}
public async override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
@@ -122,7 +122,7 @@ internal sealed class A2AAgentClient : AgentClientBase
}
}
public async override Task<AgentCard?> GetAgentCardAsync(string agentName, CancellationToken cancellationToken = default)
public override async 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);CA1812</NoWarn>
@@ -15,11 +15,4 @@
<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 async override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public override async 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 async override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -36,8 +36,9 @@ using IHost app = FunctionsApplication
.ConfigureFunctionsWebApplication()
.ConfigureDurableAgents(options =>
{
options.AddAIAgent(physicistAgent);
options.AddAIAgent(chemistAgent);
options
.AddAIAgent(physicistAgent)
.AddAIAgent(chemistAgent);
})
.Build();
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -39,8 +39,9 @@ using IHost app = FunctionsApplication
.ConfigureFunctionsWebApplication()
.ConfigureDurableAgents(options =>
{
options.AddAIAgent(spamDetectionAgent);
options.AddAIAgent(emailAssistantAgent);
options
.AddAIAgent(spamDetectionAgent)
.AddAIAgent(emailAssistantAgent);
})
.Build();
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<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 9.0 SDK or later](https://dotnet.microsoft.com/download/dotnet)
- [.NET 10.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>
<ProjectsTargetFrameworks>net472;net9.0</ProjectsTargetFrameworks>
<TargetFrameworks>net10.0;net472</TargetFrameworks>
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
</PropertyGroup>
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -13,8 +13,6 @@
<PackageReference Include="Azure.AI.OpenAI" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<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 8.0 SDK or later
- .NET 10 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
@@ -0,0 +1,25 @@
<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>
@@ -0,0 +1,35 @@
// 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);
@@ -0,0 +1,25 @@
# 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,6 +14,7 @@ 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -22,7 +22,6 @@
<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 8.0 SDK or later
- .NET 10 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:9.0
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
```
#### 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 9.0 SDK
- Ensure you're using .NET 10.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:9.0
mcr.microsoft.com/dotnet/aspire-dashboard:latest
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to start Aspire Dashboard container" -ForegroundColor Red
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -10,8 +10,6 @@
<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 8.0 SDK or later
- .NET 10 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
@@ -0,0 +1,21 @@
<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>
@@ -0,0 +1,74 @@
// 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);
}
}
}
@@ -0,0 +1,53 @@
# 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -1,8 +1,18 @@
# 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 8.0 SDK or later
- .NET 10 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -10,35 +10,34 @@ 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 = JokerInstructions });
var agentVersionCreationOptions = new AgentVersionCreationOptions(new PromptAgentDefinition(model: deploymentName) { Instructions = "You are good at telling jokes." });
// 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 agentVersion = aiProjectClient.Agents.CreateAgentVersion(agentName: JokerName, options: agentVersionCreationOptions);
var createdAgentVersion = aiProjectClient.Agents.CreateAgentVersion(agentName: JokerName, options: agentVersionCreationOptions);
// Note:
// agentVersion.Id = "<agentName>:<versionNumber>",
// agentVersion.Version = <versionNumber>,
// agentVersion.Name = <agentName>
// You can retrieve an AIAgent for a already created server side agent version.
AIAgent jokerAgentV1 = aiProjectClient.GetAIAgent(agentVersion);
// You can retrieve an AIAgent for an already created server side agent version.
AIAgent existingJokerAgent = aiProjectClient.GetAIAgent(createdAgentVersion);
// 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 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 get the AIAgent latest version just providing its name.
AIAgent jokerAgentLatest = aiProjectClient.GetAIAgent(name: JokerName);
var latestVersion = jokerAgentLatest.GetService<AgentVersion>()!;
var latestAgentVersion = jokerAgentLatest.GetService<AgentVersion>()!;
// The AIAgent version can be accessed via the GetService method.
Console.WriteLine($"Latest agent version id: {latestVersion.Id}");
Console.WriteLine($"Latest agent version id: {latestAgentVersion.Id}");
// Once you have the AIAgent, you can invoke it like any other AIAgent.
AgentThread thread = jokerAgentLatest.GetNewThread();
@@ -47,5 +46,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 (jokerAgentV1 + jokerAgentV2).
aiProjectClient.Agents.DeleteAgent(jokerAgentV1.Name);
// Cleanup by agent name removes both agent versions created.
aiProjectClient.Agents.DeleteAgent(existingJokerAgent.Name);
@@ -1,8 +1,18 @@
# 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 8.0 SDK or later
- .NET 10 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<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 8.0 SDK or later
- .NET 10 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
- .NET 10 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
- .NET 10 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -39,11 +39,16 @@ 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 NotifyThreadOfNewMessagesAsync(thread, messages.Concat(responseMessages), cancellationToken);
await typedThread.MessageStore.AddMessagesAsync(messages.Concat(responseMessages), cancellationToken);
return new AgentRunResponse
{
@@ -58,11 +63,16 @@ 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 NotifyThreadOfNewMessagesAsync(thread, messages.Concat(responseMessages), cancellationToken);
await typedThread.MessageStore.AddMessagesAsync(messages.Concat(responseMessages), cancellationToken);
foreach (var message in responseMessages)
{
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>$(NoWarn);IDE0059;NU1510</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.GenAI" />
<PackageReference Include="Mscc.GenerativeAI.Microsoft" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0' or '$(TargetFramework)' == 'net9.0'">
<PackageReference Include="System.Net.Security" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,558 @@
// 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;
}
}
}
}
@@ -0,0 +1,36 @@
// 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);
}
}
@@ -0,0 +1,36 @@
// 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}");
@@ -0,0 +1,37 @@
# 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<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 8.0 SDK or later
- .NET 10 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>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
- .NET 10 SDK or later
- Docker installed and running on your machine
- An Ollama model downloaded into Ollama
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<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 8.0 SDK or later
- .NET 10 SDK or later
- OpenAI API key
Set the following environment variables:
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -3,6 +3,7 @@
// 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 8.0 SDK or later
- .NET 10 SDK or later
- OpenAI api key
Set the following environment variables:
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -2,7 +2,7 @@
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
- .NET 10 SDK or later
- OpenAI api key
Set the following environment variables:
@@ -15,6 +15,7 @@ See the README.md for each sample for the prerequisites for that sample.
|Sample|Description|
|---|---|
|[Creating an AIAgent with A2A](./Agent_With_A2A/)|This sample demonstrates how to create AIAgent for an existing A2A agent.|
|[Creating an AIAgent with Anthropic](./Agent_With_Anthropic/)|This sample demonstrates how to create an AIAgent using Anthropic Claude models as the underlying inference service|
|[Creating an AIAgent with Foundry Agents using Azure.AI.Agents.Persistent](./Agent_With_AzureAIAgentsPersistent/)|This sample demonstrates how to create a Foundry Persistent agent and expose it as an AIAgent using the Azure.AI.Agents.Persistent SDK|
|[Creating an AIAgent with Foundry Agents using Azure.AI.Project](./Agent_With_AzureAIProject/)|This sample demonstrates how to create an Foundry Project agent and expose it as an AIAgent using the Azure.AI.Project SDK|
|[Creating an AIAgent with AzureFoundry Model](./Agent_With_AzureFoundryModel/)|This sample demonstrates how to use any model deployed to Azure Foundry to create an AIAgent|
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Anthropic\Microsoft.Agents.AI.Anthropic.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft. All rights reserved.
// This sample shows how to create and use a simple AI agent with Anthropic as the backend.
using Anthropic;
using Anthropic.Core;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
var apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is not set.");
var model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-haiku-4-5";
AIAgent agent = new AnthropicClient(new ClientOptions { APIKey = apiKey })
.CreateAIAgent(model: model, instructions: "You are good at telling jokes.", name: "Joker");
// Invoke the agent and output the text result.
var response = await agent.RunAsync("Tell me a joke about a pirate.");
Console.WriteLine(response);
// Invoke the agent with streaming support.
await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate."))
{
Console.WriteLine(update);
}
@@ -0,0 +1,43 @@
# Running a simple agent with Anthropic
This sample demonstrates how to create and run a basic agent with Anthropic Claude models.
## What this sample demonstrates
- Creating an AI agent with Anthropic Claude
- Running a simple agent with instructions
- Managing agent lifecycle
## Prerequisites
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
- Anthropic API key configured
**Note**: This sample uses Anthropic Claude models. For more information, see [Anthropic documentation](https://docs.anthropic.com/).
Set the following environment variables:
```powershell
$env:ANTHROPIC_API_KEY="your-anthropic-api-key" # Replace with your Anthropic API key
$env:ANTHROPIC_MODEL="your-anthropic-model" # Replace with your Anthropic model
```
## Run the sample
Navigate to the AgentWithAnthropic sample directory and run:
```powershell
cd dotnet\samples\GettingStarted\AgentWithAnthropic
dotnet run --project .\Agent_Anthropic_Step01_Running
```
## Expected behavior
The sample will:
1. Create an agent with Anthropic Claude
2. Run the agent with a simple prompt
3. Display the agent's response
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Anthropic\Microsoft.Agents.AI.Anthropic.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft. All rights reserved.
// This sample shows how to create and use an AI agent with reasoning capabilities.
using Anthropic;
using Anthropic.Core;
using Anthropic.Models.Messages;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
var apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is not set.");
var model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-haiku-4-5";
var maxTokens = 4096;
var thinkingTokens = 2048;
var agent = new AnthropicClient(new ClientOptions { APIKey = apiKey })
.CreateAIAgent(
model: model,
clientFactory: (chatClient) => chatClient
.AsBuilder()
.ConfigureOptions(
options => options.RawRepresentationFactory = (_) => new MessageCreateParams()
{
Model = options.ModelId ?? model,
MaxTokens = options.MaxOutputTokens ?? maxTokens,
Messages = [],
Thinking = new ThinkingConfigParam(new ThinkingConfigEnabled(budgetTokens: thinkingTokens))
})
.Build());
Console.WriteLine("1. Non-streaming:");
var response = await agent.RunAsync("Solve this problem step by step: If a train travels 60 miles per hour and needs to cover 180 miles, how long will the journey take? Show your reasoning.");
Console.WriteLine("#### Start Thinking ####");
Console.WriteLine($"\e[92m{string.Join("\n", response.Messages.SelectMany(m => m.Contents.OfType<TextReasoningContent>().Select(c => c.Text)))}\e[0m");
Console.WriteLine("#### End Thinking ####");
Console.WriteLine("\n#### Final Answer ####");
Console.WriteLine(response.Text);
Console.WriteLine("Token usage:");
Console.WriteLine($"Input: {response.Usage?.InputTokenCount}, Output: {response.Usage?.OutputTokenCount}, {string.Join(", ", response.Usage?.AdditionalCounts ?? [])}");
Console.WriteLine();
Console.WriteLine("2. Streaming");
await foreach (var update in agent.RunStreamingAsync("Explain the theory of relativity in simple terms."))
{
foreach (var item in update.Contents)
{
if (item is TextReasoningContent reasoningContent)
{
Console.WriteLine($"\e[92m{reasoningContent.Text}\e[0m");
}
else if (item is TextContent textContent)
{
Console.WriteLine(textContent.Text);
}
}
}
@@ -0,0 +1,46 @@
# Using reasoning with Anthropic agents
This sample demonstrates how to use extended thinking/reasoning capabilities with Anthropic Claude agents.
## What this sample demonstrates
- Creating an AI agent with Anthropic Claude extended thinking
- Using reasoning capabilities for complex problem solving
- Extracting thinking and response content from agent output
- Managing agent lifecycle
## Prerequisites
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
- Anthropic API key configured
- Access to Anthropic Claude models with extended thinking support
**Note**: This sample uses Anthropic Claude models with extended thinking. For more information, see [Anthropic documentation](https://docs.anthropic.com/).
Set the following environment variables:
```powershell
$env:ANTHROPIC_API_KEY="your-anthropic-api-key" # Replace with your Anthropic API key
$env:ANTHROPIC_MODEL="your-anthropic-model" # Replace with your Anthropic model
```
## Run the sample
Navigate to the AgentWithAnthropic sample directory and run:
```powershell
cd dotnet\samples\GettingStarted\AgentWithAnthropic
dotnet run --project .\Agent_Anthropic_Step02_Reasoning
```
## Expected behavior
The sample will:
1. Create an agent with Anthropic Claude extended thinking enabled
2. Run the agent with a complex reasoning prompt
3. Display the agent's thinking process
4. Display the agent's final response
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Anthropic\Microsoft.Agents.AI.Anthropic.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft. All rights reserved.
// This sample demonstrates how to use an agent with function tools.
// It shows both non-streaming and streaming agent interactions using weather-related tools.
using System.ComponentModel;
using Anthropic;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
var apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is not set.");
var model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-haiku-4-5";
[Description("Get the weather for a given location.")]
static string GetWeather([Description("The location to get the weather for.")] string location)
=> $"The weather in {location} is cloudy with a high of 15°C.";
const string AssistantInstructions = "You are a helpful assistant that can get weather information.";
const string AssistantName = "WeatherAssistant";
// Define the agent with function tools.
AITool tool = AIFunctionFactory.Create(GetWeather);
// Get anthropic client to create agents.
AIAgent agent = new AnthropicClient { APIKey = apiKey }
.CreateAIAgent(model: model, instructions: AssistantInstructions, name: AssistantName, tools: [tool]);
// Non-streaming agent interaction with function tools.
AgentThread thread = agent.GetNewThread();
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", thread));
// Streaming agent interaction with function tools.
thread = agent.GetNewThread();
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync("What is the weather like in Amsterdam?", thread))
{
Console.WriteLine(update);
}

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