diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 844739c7abaf..f1d4487e92a6 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -5,6 +5,8 @@
true
+
+
@@ -60,6 +62,7 @@
+
diff --git a/dotnet/SK-dotnet.sln b/dotnet/SK-dotnet.sln
index 21f3cbc1da67..34d4ad104c10 100644
--- a/dotnet/SK-dotnet.sln
+++ b/dotnet/SK-dotnet.sln
@@ -445,6 +445,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugins.AI.UnitTests", "src
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Connectors.Postgres.UnitTests", "src\Connectors\Connectors.Postgres.UnitTests\Connectors.Postgres.UnitTests.csproj", "{2A1EC0DA-AD01-4421-AADC-1DFF65C71CCC}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Agents.Bedrock", "src\Agents\Bedrock\Agents.Bedrock.csproj", "{8C658E1E-83C8-4127-B8BF-27A638A45DDD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1196,6 +1198,12 @@ Global
{2A1EC0DA-AD01-4421-AADC-1DFF65C71CCC}.Publish|Any CPU.Build.0 = Debug|Any CPU
{2A1EC0DA-AD01-4421-AADC-1DFF65C71CCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A1EC0DA-AD01-4421-AADC-1DFF65C71CCC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C658E1E-83C8-4127-B8BF-27A638A45DDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C658E1E-83C8-4127-B8BF-27A638A45DDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8C658E1E-83C8-4127-B8BF-27A638A45DDD}.Publish|Any CPU.ActiveCfg = Publish|Any CPU
+ {8C658E1E-83C8-4127-B8BF-27A638A45DDD}.Publish|Any CPU.Build.0 = Publish|Any CPU
+ {8C658E1E-83C8-4127-B8BF-27A638A45DDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8C658E1E-83C8-4127-B8BF-27A638A45DDD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1360,6 +1368,7 @@ Global
{0C64EC81-8116-4388-87AD-BA14D4B59974} = {D6D598DF-C17C-46F4-B2B9-CDE82E2DE132}
{03ACF9DD-00C9-4F2B-80F1-537E2151AF5F} = {D6D598DF-C17C-46F4-B2B9-CDE82E2DE132}
{2A1EC0DA-AD01-4421-AADC-1DFF65C71CCC} = {5A7028A7-4DDF-4E4F-84A9-37CE8F8D7E89}
+ {8C658E1E-83C8-4127-B8BF-27A638A45DDD} = {6823CD5E-2ABE-41EB-B865-F86EC13F0CF9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FBDC56A3-86AD-4323-AA0F-201E59123B83}
diff --git a/dotnet/samples/Concepts/Concepts.csproj b/dotnet/samples/Concepts/Concepts.csproj
index ee798e863b7a..b5cfce829772 100644
--- a/dotnet/samples/Concepts/Concepts.csproj
+++ b/dotnet/samples/Concepts/Concepts.csproj
@@ -58,6 +58,7 @@
+
diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs
index dba8ff1264dd..361025c44832 100644
--- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs
+++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs
@@ -9,7 +9,7 @@
namespace GettingStarted.AzureAgents;
///
-/// Demonstrate using code-interpreter on .
+/// Demonstrate using with file search.
///
public class Step05_AzureAIAgent_FileSearch(ITestOutputHelper output) : BaseAzureAgentTest(output)
{
diff --git a/dotnet/samples/GettingStartedWithAgents/BedrockAgent/README.md b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/README.md
new file mode 100644
index 000000000000..083a1c71a156
--- /dev/null
+++ b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/README.md
@@ -0,0 +1,38 @@
+# Concept samples on how to use AWS Bedrock agents
+
+## Pre-requisites
+
+1. You need to have an AWS account and [access to the foundation models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access-permissions.html)
+2. [AWS CLI installed](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [configured](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration)
+
+## Before running the samples
+
+You need to set up some user secrets to run the samples.
+
+### `BedrockAgent:AgentResourceRoleArn`
+
+On your AWS console, go to the IAM service and go to **Roles**. Find the role you want to use and click on it. You will find the ARN in the summary section.
+
+```
+dotnet user-secrets set "BedrockAgent:AgentResourceRoleArn" "arn:aws:iam::...:role/..."
+```
+
+### `BedrockAgent:FoundationModel`
+
+You need to make sure you have permission to access the foundation model. You can find the model ID in the [AWS documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html). To see the models you have access to, find the policy attached to your role you should see a list of models you have access to under the `Resource` section.
+
+```
+dotnet user-secrets set "BedrockAgent:FoundationModel" "..."
+```
+
+### How to add the `bedrock:InvokeModelWithResponseStream` action to an IAM policy
+
+1. Open the [IAM console](https://console.aws.amazon.com/iam/).
+2. On the left navigation pane, choose `Roles` under `Access management`.
+3. Find the role you want to edit and click on it.
+4. Under the `Permissions policies` tab, click on the policy you want to edit.
+5. Under the `Permissions defined in this policy` section, click on the service. You should see **Bedrock** if you already have access to the Bedrock agent service.
+6. Click on the service, and then click `Edit`.
+7. On the right, you will be able to add an action. Find the service and search for `InvokeModelWithResponseStream`.
+8. Check the box next to the action and then scroll all the way down and click `Next`.
+9. Follow the prompts to save the changes.
diff --git a/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step01_BedrockAgent.cs b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step01_BedrockAgent.cs
new file mode 100644
index 000000000000..2c4aa4355097
--- /dev/null
+++ b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step01_BedrockAgent.cs
@@ -0,0 +1,73 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using Microsoft.SemanticKernel.Agents.Bedrock;
+using Microsoft.SemanticKernel.Agents.Bedrock.Extensions;
+
+namespace GettingStarted.BedrockAgents;
+
+///
+/// This example demonstrates how to interact with a in the most basic way.
+///
+public class Step01_BedrockAgent(ITestOutputHelper output) : BaseBedrockAgentTest(output)
+{
+ private const string UserQuery = "Why is the sky blue in one sentence?";
+
+ ///
+ /// Demonstrates how to create a new and interact with it.
+ /// The agent will respond to the user query.
+ ///
+ [Fact]
+ public async Task UseNewAgentAsync()
+ {
+ // Create the agent
+ var bedrockAgent = await this.CreateAgentAsync("Step01_BedrockAgent");
+
+ // Respond to user input
+ try
+ {
+ var responses = bedrockAgent.InvokeAsync(BedrockAgent.CreateSessionId(), UserQuery, null);
+ await foreach (var response in responses)
+ {
+ this.Output.WriteLine(response.Content);
+ }
+ }
+ finally
+ {
+ await this.Client.DeleteAgentAsync(new() { AgentId = bedrockAgent.Id });
+ }
+ }
+
+ ///
+ /// Demonstrates how to create a new and interact with it using streaming.
+ /// The agent will respond to the user query.
+ ///
+ [Fact]
+ public async Task UseNewAgentStreamingAsync()
+ {
+ // Create the agent
+ var bedrockAgent = await this.CreateAgentAsync("Step01_BedrockAgent_Streaming");
+
+ // Respond to user input
+ try
+ {
+ var streamingResponses = bedrockAgent.InvokeStreamingAsync(BedrockAgent.CreateSessionId(), UserQuery, null);
+ await foreach (var response in streamingResponses)
+ {
+ this.Output.WriteLine(response.Content);
+ }
+ }
+ finally
+ {
+ await this.Client.DeleteAgentAsync(new() { AgentId = bedrockAgent.Id });
+ }
+ }
+
+ protected override async Task CreateAgentAsync(string agentName)
+ {
+ // Create a new agent on the Bedrock Agent service and prepare it for use
+ var agentModel = await this.Client.CreateAndPrepareAgentAsync(this.GetCreateAgentRequest(agentName));
+ // Create a new BedrockAgent instance with the agent model and the client
+ // so that we can interact with the agent using Semantic Kernel contents.
+ return new BedrockAgent(agentModel, this.Client);
+ }
+}
diff --git a/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step02_BedrockAgent_CodeInterpreter.cs b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step02_BedrockAgent_CodeInterpreter.cs
new file mode 100644
index 000000000000..70bde61a9aab
--- /dev/null
+++ b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step02_BedrockAgent_CodeInterpreter.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Reflection;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents.Bedrock;
+using Microsoft.SemanticKernel.Agents.Bedrock.Extensions;
+
+namespace GettingStarted.BedrockAgents;
+
+///
+/// This example demonstrates how to interact with a with code interpreter enabled.
+///
+public class Step02_BedrockAgent_CodeInterpreter(ITestOutputHelper output) : BaseBedrockAgentTest(output)
+{
+ private const string UserQuery = @"Create a bar chart for the following data:
+Panda 5
+Tiger 8
+Lion 3
+Monkey 6
+Dolphin 2";
+
+ ///
+ /// Demonstrates how to create a new with code interpreter enabled and interact with it.
+ /// The agent will respond to the user query by creating a Python code that will be executed by the code interpreter.
+ /// The output of the code interpreter will be a file containing the bar chart, which will be returned to the user.
+ ///
+ [Fact]
+ public async Task UseAgentWithCodeInterpreterAsync()
+ {
+ // Create the agent
+ var bedrockAgent = await this.CreateAgentAsync("Step02_BedrockAgent_CodeInterpreter");
+
+ // Respond to user input
+ try
+ {
+ BinaryContent? binaryContent = null;
+ var responses = bedrockAgent.InvokeAsync(BedrockAgent.CreateSessionId(), UserQuery, null);
+ await foreach (var response in responses)
+ {
+ if (response.Content != null)
+ {
+ this.Output.WriteLine(response.Content);
+ }
+ if (binaryContent == null && response.Items.Count > 0)
+ {
+ binaryContent = response.Items.OfType().FirstOrDefault();
+ }
+ }
+
+ if (binaryContent == null)
+ {
+ throw new InvalidOperationException("No file found in the response.");
+ }
+
+ // Save the file to the same directory as the test assembly
+ var filePath = Path.Combine(
+ Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!,
+ binaryContent.Metadata!["Name"]!.ToString()!);
+ this.Output.WriteLine($"Saving file to {filePath}");
+ binaryContent.WriteToFile(filePath, overwrite: true);
+
+ // Expected output:
+ // Here is the bar chart for the given data:
+ // [A bar chart showing the following data:
+ // Panda 5
+ // Tiger 8
+ // Lion 3
+ // Monkey 6
+ // Dolphin 2]
+ // Saving file to ...
+ }
+ finally
+ {
+ await this.Client.DeleteAgentAsync(new() { AgentId = bedrockAgent.Id });
+ }
+ }
+
+ protected override async Task CreateAgentAsync(string agentName)
+ {
+ // Create a new agent on the Bedrock Agent service and prepare it for use
+ var agentModel = await this.Client.CreateAndPrepareAgentAsync(this.GetCreateAgentRequest(agentName));
+ // Create a new BedrockAgent instance with the agent model and the client
+ // so that we can interact with the agent using Semantic Kernel contents.
+ var bedrockAgent = new BedrockAgent(agentModel, this.Client);
+ // Create the code interpreter action group and prepare the agent for interaction
+ await bedrockAgent.CreateCodeInterpreterActionGroupAsync();
+
+ return bedrockAgent;
+ }
+}
diff --git a/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step03_BedrockAgent_Functions.cs b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step03_BedrockAgent_Functions.cs
new file mode 100644
index 000000000000..ab23b4be0128
--- /dev/null
+++ b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step03_BedrockAgent_Functions.cs
@@ -0,0 +1,141 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.ComponentModel;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents.Bedrock;
+using Microsoft.SemanticKernel.Agents.Bedrock.Extensions;
+
+namespace GettingStarted.BedrockAgents;
+
+///
+/// This example demonstrates how to interact with a with kernel functions.
+///
+public class Step03_BedrockAgent_Functions(ITestOutputHelper output) : BaseBedrockAgentTest(output)
+{
+ ///
+ /// Demonstrates how to create a new with kernel functions enabled and interact with it.
+ /// The agent will respond to the user query by calling kernel functions to provide weather information.
+ ///
+ [Fact]
+ public async Task UseAgentWithFunctionsAsync()
+ {
+ // Create the agent
+ var bedrockAgent = await this.CreateAgentAsync("Step03_BedrockAgent_Functions");
+
+ // Respond to user input
+ try
+ {
+ var responses = bedrockAgent.InvokeAsync(
+ BedrockAgent.CreateSessionId(),
+ "What is the weather in Seattle?",
+ null);
+ await foreach (var response in responses)
+ {
+ if (response.Content != null)
+ {
+ this.Output.WriteLine(response.Content);
+ }
+ }
+ }
+ finally
+ {
+ await this.Client.DeleteAgentAsync(new() { AgentId = bedrockAgent.Id });
+ }
+ }
+
+ ///
+ /// Demonstrates how to create a new with kernel functions enabled and interact with it using streaming.
+ /// The agent will respond to the user query by calling kernel functions to provide weather information.
+ ///
+ [Fact]
+ public async Task UseAgentStreamingWithFunctionsAsync()
+ {
+ // Create the agent
+ var bedrockAgent = await this.CreateAgentAsync("Step03_BedrockAgent_Functions_Streaming");
+
+ // Respond to user input
+ try
+ {
+ var streamingResponses = bedrockAgent.InvokeStreamingAsync(
+ BedrockAgent.CreateSessionId(),
+ "What is the weather forecast in Seattle?",
+ null);
+ await foreach (var response in streamingResponses)
+ {
+ if (response.Content != null)
+ {
+ this.Output.WriteLine(response.Content);
+ }
+ }
+ }
+ finally
+ {
+ await this.Client.DeleteAgentAsync(new() { AgentId = bedrockAgent.Id });
+ }
+ }
+
+ ///
+ /// Demonstrates how to create a new with kernel functions enabled and interact with it.
+ /// The agent will respond to the user query by calling multiple kernel functions in parallel to provide weather information.
+ ///
+ [Fact]
+ public async Task UseAgentWithParallelFunctionsAsync()
+ {
+ // Create the agent
+ var bedrockAgent = await this.CreateAgentAsync("Step03_BedrockAgent_Functions_Parallel");
+
+ // Respond to user input
+ try
+ {
+ var responses = bedrockAgent.InvokeAsync(
+ BedrockAgent.CreateSessionId(),
+ "What is the current weather in Seattle and what is the weather forecast in Seattle?",
+ null);
+ await foreach (var response in responses)
+ {
+ if (response.Content != null)
+ {
+ this.Output.WriteLine(response.Content);
+ }
+ }
+ }
+ finally
+ {
+ await this.Client.DeleteAgentAsync(new() { AgentId = bedrockAgent.Id });
+ }
+ }
+
+ protected override async Task CreateAgentAsync(string agentName)
+ {
+ // Create a new agent on the Bedrock Agent service and prepare it for use
+ var agentModel = await this.Client.CreateAndPrepareAgentAsync(this.GetCreateAgentRequest(agentName));
+ // Create a new kernel with plugins
+ Kernel kernel = new();
+ kernel.Plugins.Add(KernelPluginFactory.CreateFromType());
+ // Create a new BedrockAgent instance with the agent model and the client
+ // so that we can interact with the agent using Semantic Kernel contents.
+ var bedrockAgent = new BedrockAgent(agentModel, this.Client)
+ {
+ Kernel = kernel,
+ };
+ // Create the kernel function action group and prepare the agent for interaction
+ await bedrockAgent.CreateKernelFunctionActionGroupAsync();
+
+ return bedrockAgent;
+ }
+
+ private sealed class WeatherPlugin
+ {
+ [KernelFunction, Description("Provides realtime weather information.")]
+ public string Current([Description("The location to get the weather for.")] string location)
+ {
+ return $"The current weather in {location} is 72 degrees.";
+ }
+
+ [KernelFunction, Description("Forecast weather information.")]
+ public string Forecast([Description("The location to get the weather for.")] string location)
+ {
+ return $"The forecast for {location} is 75 degrees tomorrow.";
+ }
+ }
+}
diff --git a/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step04_BedrockAgent_Trace.cs b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step04_BedrockAgent_Trace.cs
new file mode 100644
index 000000000000..3e1400a5115d
--- /dev/null
+++ b/dotnet/samples/GettingStartedWithAgents/BedrockAgent/Step04_BedrockAgent_Trace.cs
@@ -0,0 +1,176 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.ComponentModel;
+using Amazon.BedrockAgentRuntime.Model;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents.Bedrock;
+using Microsoft.SemanticKernel.Agents.Bedrock.Extensions;
+
+namespace GettingStarted.BedrockAgents;
+
+///
+/// This example demonstrates how to interact with a and inspect the agent's thought process.
+/// To learn more about different traces available, see:
+/// https://docs.aws.amazon.com/bedrock/latest/userguide/trace-events.html
+///
+public class Step04_BedrockAgent_Trace(ITestOutputHelper output) : BaseBedrockAgentTest(output)
+{
+ ///
+ /// Demonstrates how to inspect the thought process of a by enabling trace.
+ ///
+ [Fact]
+ public async Task UseAgentWithTraceAsync()
+ {
+ // Create the agent
+ var bedrockAgent = await this.CreateAgentAsync("Step04_BedrockAgent_Trace");
+
+ // Respond to user input
+ var userQuery = "What is the current weather in Seattle and what is the weather forecast in Seattle?";
+ try
+ {
+ // Customize the request for advanced scenarios
+ InvokeAgentRequest invokeAgentRequest = new()
+ {
+ AgentAliasId = BedrockAgent.WorkingDraftAgentAlias,
+ AgentId = bedrockAgent.Id,
+ SessionId = BedrockAgent.CreateSessionId(),
+ InputText = userQuery,
+ // Enable trace to inspect the agent's thought process
+ EnableTrace = true,
+ };
+
+ var responses = bedrockAgent.InvokeAsync(invokeAgentRequest, null);
+ await foreach (var response in responses)
+ {
+ if (response.Content != null)
+ {
+ this.Output.WriteLine(response.Content);
+ }
+ if (response.InnerContent is List
-
+
\ No newline at end of file
diff --git a/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step05_AssistantTool_FileSearch.cs b/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step05_AssistantTool_FileSearch.cs
index 361c9c0621e9..72248118577b 100644
--- a/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step05_AssistantTool_FileSearch.cs
+++ b/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step05_AssistantTool_FileSearch.cs
@@ -9,7 +9,7 @@
namespace GettingStarted.OpenAIAssistants;
///
-/// Demonstrate using code-interpreter on .
+/// Demonstrate using with file search.
///
public class Step05_AssistantTool_FileSearch(ITestOutputHelper output) : BaseAssistantTest(output)
{
diff --git a/dotnet/samples/GettingStartedWithAgents/README.md b/dotnet/samples/GettingStartedWithAgents/README.md
index 58569a96d90f..6c54a26c0d90 100644
--- a/dotnet/samples/GettingStartedWithAgents/README.md
+++ b/dotnet/samples/GettingStartedWithAgents/README.md
@@ -2,13 +2,14 @@
This project contains a step by step guide to get started with _Semantic Kernel Agents_.
+## NuGet
-#### NuGet:
- [Microsoft.SemanticKernel.Agents.Abstractions](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.Abstractions)
- [Microsoft.SemanticKernel.Agents.Core](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.Core)
- [Microsoft.SemanticKernel.Agents.OpenAI](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.OpenAI)
-#### Source
+## Source
+
- [Semantic Kernel Agent Framework](https://github.com/microsoft/semantic-kernel/tree/main/dotnet/src/Agents)
The examples can be run as integration tests but their code can also be copied to stand-alone programs.
@@ -50,6 +51,17 @@ Example|Description
[Step05_AzureAIAgent_FileSearch](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step04_AzureAIAgent_FileSearch.cs)|How to use the file-search tool for an Azure AI agent.
[Step06_AzureAIAgent_OpenAPI](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_OpenAPI.cs)|How to use the Open API tool for an Azure AI agent.
+### Bedrock Agent
+
+Example|Description
+---|---
+[Step01_BedrockAgent](./BedrockAgent/Step01_BedrockAgent.cs)|How to create a Bedrock agent and interact with it in the most basic way.
+[Step02_BedrockAgent_CodeInterpreter](./BedrockAgent/Step02_BedrockAgent_CodeInterpreter.cs)|How to use the code-interpreter tool with a Bedrock agent.
+[Step03_BedrockAgent_Functions](./BedrockAgent/Step03_BedrockAgent_Functions.cs)|How to use kernel functions with a Bedrock agent.
+[Step04_BedrockAgent_Trace](./BedrockAgent/Step04_BedrockAgent_Trace.cs)|How to enable tracing for a Bedrock agent to inspect the chain of thoughts.
+[Step05_BedrockAgent_FileSearch](./BedrockAgent/Step05_BedrockAgent_FileSearch.cs)|How to use file search with a Bedrock agent (i.e. Bedrock knowledge base).
+[Step06_BedrockAgent_AgentChat](./BedrockAgent/Step06_BedrockAgent_AgentChat.cs)|How to create a conversation between two agents and one of them in a Bedrock agent.
+
## Legacy Agents
Support for the OpenAI Assistant API was originally published in `Microsoft.SemanticKernel.Experimental.Agents` package:
@@ -57,8 +69,8 @@ Support for the OpenAI Assistant API was originally published in `Microsoft.Sema
This package has been superseded by _Semantic Kernel Agents_, which includes support for Open AI Assistant agents.
-
## Running Examples with Filters
+
Examples may be explored and ran within _Visual Studio_ using _Test Explorer_.
You can also run specific examples via the command-line by using test filters (`dotnet test --filter`). Type `dotnet test --help` at the command line for more details.
@@ -110,13 +122,20 @@ To set your secrets with .NET Secret Manager:
dotnet user-secrets set "AzureOpenAI:ApiKey" "..."
```
-5. Or Azure AI:
+6. Or Azure AI:
```
dotnet user-secrets set "AzureAI:ConnectionString" "..."
dotnet user-secrets set "AzureAI:ChatModelId" "gpt-4o"
```
+7. Or Bedrock:
+
+ ```
+ dotnet user-secrets set "BedrockAgent:AgentResourceRoleArn" "arn:aws:iam::...:role/..."
+ dotnet user-secrets set "BedrockAgent:FoundationModel" "..."
+ ```
+
> NOTE: Azure secrets will take precedence, if both Open AI and Azure Open AI secrets are defined, unless `ForceOpenAI` is set:
```
diff --git a/dotnet/src/Agents/Bedrock/Agents.Bedrock.csproj b/dotnet/src/Agents/Bedrock/Agents.Bedrock.csproj
new file mode 100644
index 000000000000..e17d43f63fcc
--- /dev/null
+++ b/dotnet/src/Agents/Bedrock/Agents.Bedrock.csproj
@@ -0,0 +1,50 @@
+
+
+
+
+ Microsoft.SemanticKernel.Agents.Bedrock
+ Microsoft.SemanticKernel.Agents.Bedrock
+ net8.0;netstandard2.0
+ $(NoWarn);SKEXP0110;CA1724
+ false
+ alpha
+
+
+
+
+
+
+ Semantic Kernel Agents - Bedrock
+ Defines a concrete Agent based on the Bedrock Agent Service.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/src/Agents/Bedrock/BedrockAgent.cs b/dotnet/src/Agents/Bedrock/BedrockAgent.cs
new file mode 100644
index 000000000000..31f199541c6a
--- /dev/null
+++ b/dotnet/src/Agents/Bedrock/BedrockAgent.cs
@@ -0,0 +1,263 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Amazon.BedrockAgent;
+using Amazon.BedrockAgentRuntime;
+using Amazon.BedrockAgentRuntime.Model;
+using Microsoft.SemanticKernel.Agents.Bedrock.Extensions;
+using Microsoft.SemanticKernel.Agents.Extensions;
+using Microsoft.SemanticKernel.ChatCompletion;
+using Microsoft.SemanticKernel.Diagnostics;
+
+namespace Microsoft.SemanticKernel.Agents.Bedrock;
+
+///
+/// Provides a specialized for the Bedrock Agent service.
+///
+public class BedrockAgent : KernelAgent
+{
+ internal readonly AmazonBedrockAgentClient Client;
+
+ internal readonly AmazonBedrockAgentRuntimeClient RuntimeClient;
+
+ internal readonly Amazon.BedrockAgent.Model.Agent AgentModel;
+
+ ///
+ /// There is a default alias created by Bedrock for the working draft version of the agent.
+ /// https://docs.aws.amazon.com/bedrock/latest/userguide/agents-deploy.html
+ ///
+ public static readonly string WorkingDraftAgentAlias = "TSTALIASID";
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Unlike other types of agents in Semantic Kernel, prompt templates are not supported for Bedrock agents,
+ /// since Bedrock agents don't support using an alternative instruction in runtime.
+ ///
+ /// The agent model of an agent that exists on the Bedrock Agent service.
+ /// A client used to interact with the Bedrock Agent service.
+ /// A client used to interact with the Bedrock Agent runtime service.
+ public BedrockAgent(
+ Amazon.BedrockAgent.Model.Agent agentModel,
+ AmazonBedrockAgentClient? client = null,
+ AmazonBedrockAgentRuntimeClient? runtimeClient = null)
+ {
+ this.AgentModel = agentModel;
+ this.Client ??= new AmazonBedrockAgentClient();
+ this.RuntimeClient ??= new AmazonBedrockAgentRuntimeClient();
+
+ this.Id = agentModel.AgentId;
+ this.Name = agentModel.AgentName;
+ this.Description = agentModel.Description;
+ this.Instructions = agentModel.Instruction;
+ }
+
+ #region static methods
+
+ ///
+ /// Convenient method to create an unique session id.
+ ///
+ public static string CreateSessionId()
+ {
+ return Guid.NewGuid().ToString();
+ }
+
+ #endregion
+
+ #region public methods
+
+ ///
+ /// Invoke the Bedrock agent with the given message.
+ ///
+ /// The session id.
+ /// The message to send to the agent.
+ /// The arguments to use when invoking the agent.
+ /// The alias id of the agent to use. The default is the working draft alias id.
+ /// The to monitor for cancellation requests. The default is .
+ /// An of .
+ public IAsyncEnumerable InvokeAsync(
+ string sessionId,
+ string message,
+ KernelArguments? arguments,
+ string? agentAliasId = null,
+ CancellationToken cancellationToken = default)
+ {
+ var invokeAgentRequest = new InvokeAgentRequest
+ {
+ AgentAliasId = agentAliasId ?? WorkingDraftAgentAlias,
+ AgentId = this.Id,
+ SessionId = sessionId,
+ InputText = message,
+ };
+
+ return this.InvokeAsync(invokeAgentRequest, arguments, cancellationToken);
+ }
+
+ ///
+ /// Invoke the Bedrock agent with the given request. Use this method when you want to customize the request.
+ ///
+ /// The request to send to the agent.
+ /// The arguments to use when invoking the agent.
+ /// The to monitor for cancellation requests. The default is .
+ public IAsyncEnumerable InvokeAsync(
+ InvokeAgentRequest invokeAgentRequest,
+ KernelArguments? arguments,
+ CancellationToken cancellationToken = default)
+ {
+ return invokeAgentRequest.StreamingConfigurations != null && invokeAgentRequest.StreamingConfigurations.StreamFinalResponse
+ ? throw new ArgumentException("The streaming configuration must be null for non-streaming responses.")
+ : ActivityExtensions.RunWithActivityAsync(
+ () => ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description),
+ InvokeInternal,
+ cancellationToken);
+
+ // Collect all responses from the agent and return them as a single chat message content since this
+ // is a non-streaming API.
+ // The Bedrock Agent API streams beck different types of responses, i.e. text, files, metadata, etc.
+ // The Bedrock Agent API also won't stream back any content when it needs to call a function. It will
+ // only start streaming back content after the function has been called and the response is ready.
+ async IAsyncEnumerable InvokeInternal()
+ {
+ ChatMessageContentItemCollection items = [];
+ string content = "";
+ Dictionary metadata = [];
+ List