Skip to content

Commit 6370247

Browse files
committed
fix: recommend AIProjectClient instead of PersistentAgentsClient
1 parent 5fe9dae commit 6370247

File tree

3 files changed

+96
-66
lines changed

3 files changed

+96
-66
lines changed

tools/Azure.Mcp.Tools.AzureAIBestPractices/src/Resources/ai-background-knowledge.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ Use this hierarchy to analyze and select AI models
1818
- **Multi-LLM Support**: Works with OpenAI, Azure OpenAI, Azure AI Foundry, and other providers
1919

2020
**Agent Types:**
21-
- **[RECOMMENDED] Azure AI Foundry Agent (`PersistentAgentsClient`)**: Service-managed persistent agents with conversation threads - best for production applications requiring conversation continuity
21+
- **[RECOMMENDED] Azure AI Foundry Agent (`AIProjectClient`)**: Latest unified client for Azure AI Foundry agents with conversation threads - best for production applications requiring conversation continuity and modern agent features
22+
- **[LEGACY] Azure AI Foundry Agent (`PersistentAgentsClient`)**: Older client for service-managed persistent agents - superseded by `AIProjectClient`
2223
- **OpenAI ChatCompletion / Responses / Assistants Agent (`OpenAIClient`)**: Stateless or service-managed agents using OpenAI service
2324
- **Azure AI Foundry Models ChatCompletion / Responses Agent (`OpenAIClient` / `AzureOpenAIClient`)**: For testing Foundry-deployed models (stateless)
2425
- **Azure OpenAI ChatCompletion / Responses (`AzureOpenAIClient`)**: Stateless agents using Azure OpenAI ChatCompletion / Responses service

tools/Azure.Mcp.Tools.AzureAIBestPractices/src/Resources/ai-best-practices-core.txt

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,9 @@ Always search / fetch / query for sufficient knowledge (quickstarts, tutorials,
6565
### 1. Search for Implementation Knowledge
6666
After completing the required model selection process above, gather SDK and implementation information.
6767
#### Step 1: Fetch common quickstart pages
68-
Use the Microsoft Document **fetch** operation to retrieve these pages directly for complete, unabridged content. These are the most commonly needed references and should be fetched for EVERY implementation:
69-
- [Default] Azure AI Foundry Quickstart: `https://learn.microsoft.com/agent-framework/user-guide/agents/agent-types/azure-ai-foundry-agent`
70-
71-
#### Step 2 (Optional): Search for specific agent type documentation
72-
**ONLY if user explicitly requests a NON-Azure AI Foundry service provider:**
73-
- **Default for Azure AI Foundry**: ALWAYS use Azure AI Foundry Agent (`PersistentAgentsClient`) - skip this step
74-
- **DO NOT use this step for demos, prototypes, or "local testing"** - still use `PersistentAgentsClient`
75-
- **ONLY search other agent types if user explicitly says**: "use OpenAI service", "use Azure OpenAI service", etc.
76-
- Example: User says "use OpenAI service" → Search "Agent Framework OpenAI ChatCompletion Agents"
77-
- Example: User says "use Azure OpenAI" → Search "Agent Framework Azure OpenAI ChatCompletion Agents"
78-
79-
#### Step 3: Search for feature guidelines
68+
Use the **fetch** operation to retrieve GitHub pages directly for complete, unabridged content. These are the most commonly needed references and should be fetched for EVERY implementation:
69+
- [Default] Microsoft Agent Framework Quickstart: `https://github.com/microsoft/agent-framework/blob/main/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Program.cs`
70+
#### Step 2: Search for feature guidelines
8071
**Stage 1 - Identify Core Capabilities:**
8172
Break down the user's requirement into individual capabilities
8273
- Example: "Build a weather agent for user to query weather" → ["function calling"]
@@ -142,20 +133,20 @@ User Requirements Analysis:
142133

143134
### 2. Explain SDK selection
144135
**Recommended SDK:** Microsoft Agent Framework
145-
**Recommended Agent Type:** Azure AI Foundry Agents with PersistentAgentsClient
136+
**Recommended Agent Type:** Azure AI Foundry Agents with AIProjectClient
146137
**Default Programming Language:** .NET
147138

148139
** Agent Type Selection Rules **
149-
- **ALWAYS use `PersistentAgentsClient` for Azure AI Foundry**
150-
- **DO NOT use `AzureOpenAIClient`** for Azure AI Foundry models, even for demos, prototypes, or local testing
151-
- `PersistentAgentsClient` provides service-managed persistence, conversation threads, and full agent capabilities
140+
- **ALWAYS use `AIProjectClient` for Azure AI Foundry**
141+
- **DO NOT use `AzureOpenAIClient` or `PersistentAgentsClient`** for Azure AI Foundry models, even for demos, prototypes, or local testing
142+
- `AIProjectClient` provides service-managed persistence, conversation threads, and full agent capabilities
152143
- Only use other agent types (OpenAI ChatCompletion, Azure OpenAI, etc.) if the user **explicitly requests a different service provider**
153144

154145
**Output format:**
155146
```
156147
SDK Selection: Microsoft Agent Framework
157148

158-
Agent Type: Azure AI Foundry Agents (PersistentAgentsClient)
149+
Agent Type: Azure AI Foundry Agents (AIProjectClient)
159150

160151
Programming Language: [.NET (default) OR Python (if user specified)]
161152

@@ -210,6 +201,7 @@ Create a step-by-step plan / todo list covering project initialization, installa
210201
- If build fails: Analyze build errors → Fix code issues → Rebuild
211202
- Repeat fix-rebuild cycle until build succeeds with zero errors
212203

204+
Creating the plan is NOT the end - it's the beginning. Continue to implement the code.
213205

214206
## Code - Implementation Guidelines
215207
**Note**: Continue using Microsoft Document Search throughout implementation for any unknowns.
@@ -233,11 +225,15 @@ DO REMIND USER THE `--pre` OR `--prerelease` FLAG IS REQUIRED IN GENERATED DOC.
233225

234226
#### .NET
235227
Agent type-specific installation packages:
236-
- **Azure AI Foundry Agent (RECOMMENDED)** - `PersistentAgentsClient`:
228+
- **Azure AI Foundry Agent (RECOMMENDED)** - `AIProjectClient`:
237229
```bash
238230
dotnet add package Azure.Identity
239231
dotnet add package Microsoft.Agents.AI.AzureAI --prerelease
240232
```
233+
234+
Do NOT add `Azure.AI.Projects` separately - it's already included in `Microsoft.Agents.AI.AzureAI`.
235+
Adding `Azure.AI.Projects` manually may introduce version mismatches and build errors
236+
241237
- **Workflows and Orchestration** - For multi-agent systems and workflow features, also add:
242238
```bash
243239
dotnet add package Microsoft.Agents.AI.Workflows --prerelease

tools/Azure.Mcp.Tools.AzureAIBestPractices/src/Resources/ai-error-patterns.txt

Lines changed: 80 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -74,79 +74,112 @@ var data = await context.ReadStateAsync<string>(key: stateId, scopeName: "MyScop
7474

7575
### Agent Type
7676
#### Agent Type Selection
77-
**IMPORTANT**: When using Azure AI Foundry, always use `PersistentAgentsClient` to create agents - NOT `AzureOpenAIClient`.
77+
78+
**For .NET:**
79+
**IMPORTANT**: When using Azure AI Foundry, always use `AIProjectClient` to create agents - NOT `AzureOpenAIClient`.
7880
- ❌ Do NOT use `AzureOpenAIClient` for Azure AI Foundry models - that's only for testing and lacks conversation persistence
79-
- ✅ DO use `PersistentAgentsClient` - it provides full agent capabilities with service-managed state
81+
- ✅ DO use `AIProjectClient` - it provides full agent capabilities with service-managed state and is the latest recommended approach
82+
- ⚠️ `PersistentAgentsClient` is legacy - use `AIProjectClient` instead
8083

81-
Code samples may show `AzureOpenAIClient` for simplicity or backward compatibility, but production implementations should use `PersistentAgentsClient` for Azure AI Foundry.
84+
Code samples may show `AzureOpenAIClient` for simplicity or backward compatibility, but production implementations should use `AIProjectClient` for Azure AI Foundry.
8285

83-
#### Key Difference: When to Pass ChatOptions
84-
The main difference between `PersistentAgentsClient` and `AzureOpenAIClient` is **when** you configure ChatOptions (Tools, ResponseFormat, etc. ):
85-
- **PersistentAgentsClient**: Pass ChatOptions when **retrieving** the agent via `GetAIAgentAsync()`
86-
- **AzureOpenAIClient**: Pass options when **creating** the agent via `CreateAIAgent()`
86+
#### Key Differences: AIProjectClient vs AzureOpenAIClient
8787

88-
Note: Only add ChatOptions properties (Tools, ResponseFormat, etc.) when user requirements explicitly need them. Do NOT add them by default.
88+
**1. Creation Pattern:**
89+
- `AIProjectClient` uses `await aiProjectClient.CreateAIAgentAsync(...)` - creates agents on the server
90+
- `AzureOpenAIClient` uses `.GetChatClient(deploymentName).CreateAIAgent(...)` - creates local agents
8991

90-
#### ✅ CORRECT - PersistentAgentsClient Pattern
91-
Pass all ChatOptions properties (tools, ResponseFormat, etc.) to `GetAIAgentAsync()`:
92+
#### ✅ CORRECT - AIProjectClient Pattern (Recommended)
9293

9394
```csharp
94-
using Azure.AI.Agents.Persistent;
95+
using System.ComponentModel;
96+
using System.Text.Json.Serialization;
97+
using Azure.AI.Projects;
9598
using Azure.Identity;
9699
using Microsoft.Agents.AI;
97100
using Microsoft.Extensions.AI;
98-
using System.ComponentModel;
99-
using System.Text.Json.Serialization;
100101

101-
// Define function tool
102-
[Description("Get weather for a location")]
103-
static string GetWeather([Description("Location")] string location)
104-
=> $"Weather in {location}: 25°C, sunny";
102+
string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
103+
string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
104+
105+
[Description("Get the weather for a given location.")]
106+
static string GetWeather([Description("The location to get the weather for.")] string location)
107+
=> $"The weather in {location} is cloudy with a high of 15°C.";
108+
109+
const string AssistantInstructions = "You are a helpful assistant that can get weather information.";
110+
const string AssistantName = "WeatherAssistant";
111+
112+
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
113+
AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
114+
115+
// Define the agent with function tools.
116+
AITool tool = AIFunctionFactory.Create(GetWeather);
117+
118+
// Create AIAgent directly - Simple agent with tools for basic scenarios
119+
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
120+
name: AssistantName,
121+
model: deploymentName,
122+
instructions: AssistantInstructions,
123+
tools: [tool]);
124+
125+
// Create ChatClientAgent - Advanced agent with structured output support via ResponseFormat
126+
// Use this when you need structured JSON responses with schema validation
127+
ChatClientAgent agent1 = await aiProjectClient.CreateAIAgentAsync(
128+
model: deploymentName,
129+
new ChatClientAgentOptions(name: AssistantName, instructions: AssistantInstructions, tools: [tool])
130+
{
131+
ChatOptions = new()
132+
{
133+
ResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat.ForJsonSchema<WeatherResponse>()
134+
}
135+
});
136+
137+
// Non-streaming agent interaction with function tools.
138+
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));
139+
140+
// Streaming agent interaction with function tools.
141+
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync("What is the weather like in Amsterdam?"))
142+
{
143+
Console.WriteLine(update);
144+
}
145+
146+
// Cleanup by agent name removes the agent version created.
147+
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
148+
105149

106-
// Define response schema
150+
// Define structured output schema for weather response
151+
[Description("Weather information for a location")]
107152
public class WeatherResponse
108153
{
109154
[JsonPropertyName("location")]
110155
public string Location { get; set; } = string.Empty;
111156

112157
[JsonPropertyName("temperature")]
113-
public double Temperature { get; set; }
114-
}
158+
public string Temperature { get; set; } = string.Empty;
115159

116-
var client = new PersistentAgentsClient(
117-
"https://<resource>.services.ai.azure.com/api/projects/<project>",
118-
new AzureCliCredential());
160+
[JsonPropertyName("condition")]
161+
public string Condition { get; set; } = string.Empty;
162+
}
163+
```
119164

120-
// Step 1: Create agent (only model, name, instructions)
121-
var agentMetadata = await client.Administration.CreateAgentAsync(
122-
model: "gpt-4o-mini", // Just for example
123-
name: "WeatherAgent",
124-
instructions: "Provide weather information");
165+
#### ❌ INCORRECT - AzureOpenAIClient Patterns to Avoid
125166

126-
// Step 2: Get agent with ChatOptions (tools, ResponseFormat, etc.)
127-
AIAgent agent = await client.GetAIAgentAsync(
128-
agentId: agentMetadata.Value.Id,
129-
new ChatOptions
130-
{
131-
Tools = [AIFunctionFactory.Create(GetWeather)], // ✅ Tools passed here
132-
ResponseFormat = ChatResponseFormat.ForJsonSchema<WeatherResponse>( // ✅ ResponseFormat passed here
133-
schemaName: "WeatherResponse",
134-
schemaDescription: "Weather data")
135-
});
167+
**Don't use explicit thread management with AzureOpenAIClient:**
168+
```csharp
136169

137-
var response = await agent.RunAsync("What's the weather in Seattle?");
170+
// Create AIAgent with AzureOpenAIClient
171+
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) // ❌ WRONG: Use AIProjectClient instead
172+
.GetChatClient(deploymentName)
173+
.CreateAIAgent(instructions: "You are a helpful assistant");
138174
```
139175

140-
#### ❌ INCORRECT - Don't Use AzureOpenAIClient Pattern with PersistentAgentsClient
176+
#### ❌ INCORRECT - Don't Use Legacy PersistentAgentsClient Pattern
141177

142178
```csharp
143-
var client = new PersistentAgentsClient(
179+
using Azure.AI.Agents.Persistent; // ❌ WRONG: Use Azure.AI.Projects instead
180+
181+
var client = new PersistentAgentsClient( // ❌ WRONG: Use AIProjectClient instead
144182
"https://<resource>.services.ai.azure.com/api/projects/<project>",
145183
new AzureCliCredential());
146-
147-
// ❌ WRONG PATTERN: Trying to pass tools at agent creation
148-
AIAgent agent = await client.Administration.CreateAgentAsync(
149-
model: "gpt-4o-mini",
150-
tools: [AIFunctionFactory.Create(GetWeather)] // ❌ Wrong: Can't pass tools here
151-
);
152184
```
185+

0 commit comments

Comments
 (0)