Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / paths-filter (push) Waiting to run
dotnet-build-and-test / dotnet-build-and-test (Debug, windows-latest, net9.0) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test (Release, integration, true, ubuntu-latest, net10.0) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test (Release, integration, true, windows-latest, net472) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test (Release, ubuntu-latest, net8.0) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test-check (push) Blocked by required conditions
291 lines
13 KiB
Markdown
291 lines
13 KiB
Markdown
---
|
|
# These are optional elements. Feel free to remove any of them.
|
|
status: accepted
|
|
contact: markwallace
|
|
date: 2025-08-06
|
|
deciders: markwallace-microsoft, westey-m, quibitron
|
|
consulted: shawnhenry, elijahstraight
|
|
informed:
|
|
---
|
|
|
|
# Agent Framework / Foundry SDK Alignment
|
|
|
|
Agent Framework and Foundry SDK have overlapping functionality but serve different audiences & scenarios.
|
|
This specification clarifies the positioning of these SDKs to customers, what goes in each and when to use what.
|
|
|
|
- **Foundry SDK** is a thin-client SDK for accessing everything available in the agent service and is autogenerated from REST APIs in multiple languages
|
|
- **Agent Framework SDK** is general-purpose framework for agentic application development, where common agent abstractions enable creating and orchestrating heterogenous agent systems (across local & cloud)
|
|
|
|
## What is the goal of this feature?
|
|
|
|
Goals:
|
|
- Developers can seamlessly combine Foundry and Agent Framework SDK's and there is no friction when using both SDKs at the same time
|
|
- Developers can take advantage of the full capabilities supported by the Foundry SDK
|
|
- Developers can create multi-agent orchestrations using Foundry and other agent types
|
|
|
|
Success Metrics:
|
|
- Complexity of basic samples is comparable to other agent frameworks
|
|
- Developers can easily discover how to use Foundry Agents in Agent Framework multi-agent orchestrations
|
|
|
|
## What is the problem being solved?
|
|
|
|
- In Semantic Kernel the Foundry Agent support isn't integrated into the Foundry SDK so there is a disjointed developer UX
|
|
- Customers are confused as to when they should use Foundry SDK versus Semantic Kernel
|
|
|
|
|
|
## API Changes
|
|
|
|
The proposed solution is to add helper methods which allow developers to either retrieve or create an `AIAgent` using a `PersistentAgentsClient`
|
|
|
|
- Retrieve an `AIAgent`
|
|
```csharp
|
|
/// <summary>
|
|
/// Retrieves an existing server side agent, wrapped as a <see cref="ChatClientAgent"/> using the provided <see cref="PersistentAgentsClient"/>.
|
|
/// </summary>
|
|
/// <param name="persistentAgentsClient">The <see cref="PersistentAgentsClient"/> to create the <see cref="ChatClientAgent"/> with.</param>
|
|
/// <returns>A <see cref="ChatClientAgent"/> for the persistent agent.</returns>
|
|
/// <param name="agentId"> The ID of the server side agent to create a <see cref="ChatClientAgent"/> for.</param>
|
|
/// <param name="chatOptions">Options that should apply to all runs of the agent.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the persistent agent.</returns>
|
|
public static async Task<ChatClientAgent> GetAIAgentAsync(
|
|
this PersistentAgentsClient persistentAgentsClient,
|
|
string agentId,
|
|
ChatOptions? chatOptions = null,
|
|
CancellationToken cancellationToken = default)
|
|
```
|
|
- Create an `AIAgent`
|
|
```csharp
|
|
/// <summary>
|
|
/// Creates a new server side agent using the provided <see cref="PersistentAgentsClient"/>.
|
|
/// </summary>
|
|
/// <param name="persistentAgentsClient">The <see cref="PersistentAgentsClient"/> to create the agent with.</param>
|
|
/// <param name="model">The model to be used by the agent.</param>
|
|
/// <param name="name">The name of the agent.</param>
|
|
/// <param name="description">The description of the agent.</param>
|
|
/// <param name="instructions">The instructions for the agent.</param>
|
|
/// <param name="tools">The tools to be used by the agent.</param>
|
|
/// <param name="toolResources">The resources for the tools.</param>
|
|
/// <param name="temperature">The temperature setting for the agent.</param>
|
|
/// <param name="topP">The top-p setting for the agent.</param>
|
|
/// <param name="responseFormat">The response format for the agent.</param>
|
|
/// <param name="metadata">The metadata for the agent.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
|
public static async Task<ChatClientAgent> CreateAIAgentAsync(
|
|
this PersistentAgentsClient persistentAgentsClient,
|
|
string model,
|
|
string? name = null,
|
|
string? description = null,
|
|
string? instructions = null,
|
|
IEnumerable<ToolDefinition>? tools = null,
|
|
ToolResources? toolResources = null,
|
|
float? temperature = null,
|
|
float? topP = null,
|
|
BinaryData? responseFormat = null,
|
|
IReadOnlyDictionary<string, string>? metadata = null,
|
|
CancellationToken cancellationToken = default)
|
|
```
|
|
- Additional overload using the M.E.AI types:
|
|
```csharp
|
|
/// <summary>
|
|
/// Creates a new server side agent using the provided <see cref="PersistentAgentsClient"/>.
|
|
/// </summary>
|
|
/// <param name="persistentAgentsClient">The <see cref="PersistentAgentsClient"/> to create the agent with.</param>
|
|
/// <param name="model">The model to be used by the agent.</param>
|
|
/// <param name="name">The name of the agent.</param>
|
|
/// <param name="description">The description of the agent.</param>
|
|
/// <param name="instructions">The instructions for the agent.</param>
|
|
/// <param name="tools">The tools to be used by the agent.</param>
|
|
/// <param name="temperature">The temperature setting for the agent.</param>
|
|
/// <param name="topP">The top-p setting for the agent.</param>
|
|
/// <param name="responseFormat">The response format for the agent.</param>
|
|
/// <param name="metadata">The metadata for the agent.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
|
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
|
public static async Task<ChatClientAgent> CreateAIAgentAsync(
|
|
this PersistentAgentsClient persistentAgentsClient,
|
|
string model,
|
|
string? name = null,
|
|
string? description = null,
|
|
string? instructions = null,
|
|
IEnumerable<AITool>? tools = null,
|
|
float? temperature = null,
|
|
float? topP = null,
|
|
BinaryData? responseFormat = null,
|
|
IReadOnlyDictionary<string, string>? metadata = null,
|
|
CancellationToken cancellationToken = default)
|
|
```
|
|
|
|
|
|
## E2E Code Samples
|
|
|
|
### 1. Create and retrieve with Foundry SDK, run with Agent Framework
|
|
|
|
- [Foundry SDK] Create a `PersistentAgentsClient`
|
|
- [Foundry SDK] Create a `PersistentAgent` using the `PersistentAgentsClient`
|
|
- [Foundry SDK] Retrieve an `AIAgent` using the `PersistentAgentsClient`
|
|
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentResponse`
|
|
- [Foundry SDK] Clean up the agent
|
|
|
|
|
|
```csharp
|
|
// Get a client to create server side agents with.
|
|
var persistentAgentsClient = new PersistentAgentsClient(
|
|
TestConfiguration.AzureAI.Endpoint, new AzureCliCredential());
|
|
|
|
// Create a persistent agent.
|
|
var persistentAgentMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
|
|
model: TestConfiguration.AzureAI.DeploymentName!,
|
|
name: JokerName,
|
|
instructions: JokerInstructions);
|
|
|
|
// Get the persistent agent we created in the previous step and expose it as an Agent Framework agent.
|
|
AIAgent agent = await persistentAgentsClient.GetAIAgentAsync(persistentAgent.Value.Id);
|
|
|
|
// Respond to user input.
|
|
var input = "Tell me a joke about a pirate.";
|
|
Console.WriteLine(input);
|
|
Console.WriteLine(await agent.RunAsync(input));
|
|
|
|
// Delete the persistent agent.
|
|
await persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);
|
|
```
|
|
|
|
### 2. Create directly with Foundry SDK, run with Agent Framework
|
|
|
|
- [Foundry SDK] Create a `PersistentAgentsClient`
|
|
- [Foundry SDK] Create a `AIAgent` using the `PersistentAgentsClient`
|
|
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentResponse`
|
|
- [Foundry SDK] Clean up the agent
|
|
|
|
```csharp
|
|
// Get a client to create server side agents with.
|
|
var persistentAgentsClient = new PersistentAgentsClient(
|
|
TestConfiguration.AzureAI.Endpoint, new AzureCliCredential());
|
|
|
|
// Create a persistent agent and expose it as an Agent Framework agent.
|
|
AIAgent agent = await persistentAgentsClient.CreateAIAgentAsync(
|
|
model: TestConfiguration.AzureAI.DeploymentName!,
|
|
name: JokerName,
|
|
instructions: JokerInstructions);
|
|
|
|
// Respond to user input.
|
|
var input = "Tell me a joke about a pirate.";
|
|
Console.WriteLine(input);
|
|
Console.WriteLine(await agent.RunAsync(input));
|
|
|
|
// Delete the persistent agent.
|
|
await persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);
|
|
```
|
|
|
|
### 3. Create directly with Foundry SDK, run with conversation state using Agent Framework
|
|
|
|
- [Foundry SDK] Create a `PersistentAgentsClient`
|
|
- [Foundry SDK] Create a `AIAgent` using the `PersistentAgentsClient`
|
|
- [Agent Framework SDK] Optionally create an `AgentThread` for the agent run
|
|
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentResponse`
|
|
- [Foundry SDK] Clean up the agent and the agent thread
|
|
|
|
```csharp
|
|
// Get a client to create server side agents with.
|
|
var persistentAgentsClient = new PersistentAgentsClient(
|
|
TestConfiguration.AzureAI.Endpoint, new AzureCliCredential());
|
|
|
|
// Create an Agent Framework agent.
|
|
AIAgent agent = await persistentAgentsClient.CreateAIAgentAsync(
|
|
model: TestConfiguration.AzureAI.DeploymentName!,
|
|
name: JokerName,
|
|
instructions: JokerInstructions);
|
|
|
|
// Start a new thread for the agent conversation.
|
|
AgentThread thread = agent.GetNewThread();
|
|
|
|
// Respond to user input.
|
|
await RunAgentAsync("Tell me a joke about a pirate.");
|
|
await RunAgentAsync("Now add some emojis to the joke.");
|
|
|
|
// Local function to run agent and display the conversation messages for the thread.
|
|
async Task RunAgentAsync(string input)
|
|
{
|
|
Console.WriteLine(
|
|
$"""
|
|
User: {input}
|
|
Assistant:
|
|
{await agent.RunAsync(input, thread)}
|
|
|
|
""");
|
|
}
|
|
|
|
// Cleanup
|
|
await persistentAgentsClient.Threads.DeleteThreadAsync(thread.ConversationId);
|
|
await persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);
|
|
```
|
|
|
|
### 4. Create directly with Foundry SDK, orchestrate with Agent Framework
|
|
|
|
- [Foundry SDK] Create a `PersistentAgentsClient`
|
|
- [Foundry SDK] Create multiple `AIAgent` instances using the `PersistentAgentsClient`
|
|
- [Agent Framework SDK] Create a `SequentialOrchestration` and add all of the agents to it
|
|
- [Agent Framework SDK] Invoke the `SequentialOrchestration` instance and access response from the `AgentResponse`
|
|
- [Foundry SDK] Clean up the agents
|
|
|
|
```csharp
|
|
// Get a client to create server side agents with.
|
|
var persistentAgentsClient = new PersistentAgentsClient(
|
|
TestConfiguration.AzureAI.Endpoint, new AzureCliCredential());
|
|
var model = TestConfiguration.OpenAI.ChatModelId;
|
|
|
|
// Define the agents
|
|
AIAgent analystAgent =
|
|
await persistentAgentsClient.CreateAIAgentAsync(
|
|
model,
|
|
name: "Analyst",
|
|
instructions:
|
|
"""
|
|
You are a marketing analyst. Given a product description, identify:
|
|
- Key features
|
|
- Target audience
|
|
- Unique selling points
|
|
""",
|
|
description: "An agent that extracts key concepts from a product description.");
|
|
AIAgent writerAgent =
|
|
await persistentAgentsClient.CreateAIAgentAsync(
|
|
model,
|
|
name: "copywriter",
|
|
instructions:
|
|
"""
|
|
You are a marketing copywriter. Given a block of text describing features, audience, and USPs,
|
|
compose a compelling marketing copy (like a newsletter section) that highlights these points.
|
|
Output should be short (around 150 words), output just the copy as a single text block.
|
|
""",
|
|
description: "An agent that writes a marketing copy based on the extracted concepts.");
|
|
AIAgent editorAgent =
|
|
await persistentAgentsClient.CreateAIAgentAsync(
|
|
model,
|
|
name: "editor",
|
|
instructions:
|
|
"""
|
|
You are an editor. Given the draft copy, correct grammar, improve clarity, ensure consistent tone,
|
|
give format and make it polished. Output the final improved copy as a single text block.
|
|
""",
|
|
description: "An agent that formats and proofreads the marketing copy.");
|
|
|
|
// Define the orchestration
|
|
SequentialOrchestration orchestration =
|
|
new(analystAgent, writerAgent, editorAgent)
|
|
{
|
|
LoggerFactory = this.LoggerFactory,
|
|
};
|
|
|
|
// Run the orchestration
|
|
string input = "An eco-friendly stainless steel water bottle that keeps drinks cold for 24 hours";
|
|
Console.WriteLine($"\n# INPUT: {input}\n");
|
|
AgentResponse result = await orchestration.RunAsync(input);
|
|
Console.WriteLine($"\n# RESULT: {result}");
|
|
|
|
// Cleanup
|
|
await persistentAgentsClient.Administration.DeleteAgentAsync(analystAgent.Id);
|
|
await persistentAgentsClient.Administration.DeleteAgentAsync(writerAgent.Id);
|
|
await persistentAgentsClient.Administration.DeleteAgentAsync(editorAgent.Id);
|
|
``` |