@polymorphism-tech/morph-spec 7.0.0 → 7.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +368 -368
  2. package/claude-plugin.json +14 -14
  3. package/docs/CHEATSHEET.md +199 -199
  4. package/docs/QUICKSTART.md +200 -200
  5. package/framework/CLAUDE.md +1 -1
  6. package/framework/MORPH.md +4 -1
  7. package/framework/agents.json +132 -127
  8. package/framework/rubrics/backend.json +41 -36
  9. package/framework/rules/ai-agents-standards.md +45 -15
  10. package/framework/rules/neon-standards.md +25 -26
  11. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  12. package/framework/skills/core/morph-plan/SKILL.md +3 -1
  13. package/framework/skills/core/morph-stack-scan/SKILL.md +3 -3
  14. package/framework/standards/STANDARDS.json +1729 -1133
  15. package/framework/standards/ai-agents/agent-session.md +160 -0
  16. package/framework/standards/ai-agents/batching.md +193 -0
  17. package/framework/standards/ai-agents/context-providers.md +188 -0
  18. package/framework/standards/ai-agents/mcp-server.md +250 -0
  19. package/framework/standards/ai-agents/mcp-tools.md +197 -0
  20. package/framework/standards/ai-agents/middleware-patterns.md +207 -0
  21. package/framework/standards/ai-agents/modalities-image-gen.md +173 -0
  22. package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -0
  23. package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -0
  24. package/framework/standards/ai-agents/modalities-vision.md +201 -0
  25. package/framework/standards/ai-agents/multi-agent-patterns.md +155 -0
  26. package/framework/standards/ai-agents/production.md +114 -258
  27. package/framework/standards/ai-agents/prompts-in-db.md +214 -0
  28. package/framework/standards/ai-agents/providers/model-registry.md +158 -0
  29. package/framework/standards/ai-agents/rag-custom-pgvector.md +243 -0
  30. package/framework/standards/ai-agents/service-tier-flex.md +135 -0
  31. package/framework/standards/ai-agents/setup.md +142 -316
  32. package/framework/standards/ai-agents/structured-output.md +249 -0
  33. package/framework/standards/ai-agents/sweet-spot.md +109 -0
  34. package/framework/standards/ai-agents/workflows.md +114 -284
  35. package/framework/standards/architecture/vertical-slice/vertical-slice.md +439 -429
  36. package/framework/standards/backend/api/validation.md +92 -88
  37. package/framework/standards/backend/database/postgresql/database.md +336 -332
  38. package/framework/standards/backend/database/vector-search-rag.md +599 -541
  39. package/framework/standards/backend/dotnet/fluent-validation-vsa.md +4 -0
  40. package/framework/standards/backend/dotnet/result-pattern.md +4 -0
  41. package/framework/standards/backend/dotnet/scalar-ui.md +176 -172
  42. package/framework/standards/backend/dotnet/scrutor.md +4 -0
  43. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +310 -274
  44. package/framework/standards/backend/integrations/asaas/asaas-api.md +260 -216
  45. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +354 -350
  46. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +30 -19
  47. package/framework/standards/backend/integrations/resend/resend-email.md +400 -385
  48. package/framework/standards/data/nosql/cache/redis.md +106 -97
  49. package/framework/standards/data/nosql/cosmos-db.md +127 -118
  50. package/framework/standards/data/vector-search/rag-chunking.md +113 -104
  51. package/framework/standards/frontend/design-system/ai-image-generation.md +4 -0
  52. package/framework/standards/frontend/design-system/animations.md +164 -160
  53. package/framework/standards/frontend/design-system/naming.md +68 -64
  54. package/framework/standards/frontend/gsap/gsap-core.md +14 -8
  55. package/framework/standards/frontend/gsap/gsap-plugins.md +26 -21
  56. package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +9 -7
  57. package/framework/standards/frontend/nextjs/app-router.md +127 -123
  58. package/framework/standards/frontend/nextjs/components.md +136 -132
  59. package/framework/standards/frontend/nextjs/data-fetching.md +130 -126
  60. package/framework/standards/frontend/nextjs/forms.md +134 -128
  61. package/framework/standards/frontend/nextjs/motion-patterns.md +328 -322
  62. package/framework/standards/frontend/nextjs/naming-conventions.md +71 -67
  63. package/framework/standards/frontend/nextjs/nextjs-patterns.md +229 -225
  64. package/framework/standards/frontend/nextjs/project-structure.md +106 -102
  65. package/framework/standards/frontend/nextjs/state-management.md +76 -72
  66. package/framework/standards/frontend/nextjs/testing.md +115 -111
  67. package/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -192
  68. package/framework/standards/infrastructure/neon/neon-pgrag.md +6 -2
  69. package/framework/standards/infrastructure/neon/neon-pgvector.md +4 -0
  70. package/framework/standards/infrastructure/neon/neon-setup.md +5 -1
  71. package/framework/standards/integration/mcp/mcp-tools.md +471 -462
  72. package/framework/templates/CLAUDE.md.core.template +1 -1
  73. package/framework/templates/REGISTRY.json +1745 -1239
  74. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -0
  75. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -0
  76. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -0
  77. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -0
  78. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -0
  79. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -0
  80. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -0
  81. package/framework/templates/code/dotnet/backend/repository.cs +3 -10
  82. package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -0
  83. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -0
  84. package/package.json +89 -83
  85. package/src/core/templates/template-registry.js +289 -256
  86. package/src/lib/generators/context-generator.js +516 -518
  87. package/src/lib/generators/scaffold-generator.js +23 -26
  88. package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +0 -310
  89. package/framework/templates/integrations/semantic-kernel-neon.cs +0 -125
@@ -1,418 +1,244 @@
1
- # Microsoft Agent Framework - Setup Guide (.NET 10)
1
+ # Microsoft Agent Framework — Setup Guide (.NET 10)
2
2
 
3
- > **Scope:** universal
4
- > **Layer:** 0 (always load)
5
- > **Keywords:** agent, ai, openai, setup, microsoft agents, chatclient
6
- > **Load When:** always
3
+ > **Scope:** stacks=["dotnet"]
4
+ > **Layer:** 0 (always-load via persona maf-expert)
5
+ > **Keywords:** maf setup, microsoft agents ai, chatclient, ai agent, agent framework, agent dotnet, AsAIAgent
6
+ > **Read by Claude in:** plan (pra citar pacote em tasks.json) + implement (pra escrever .csproj e Program.cs)
7
7
 
8
- **IMPORTANT:** MORPH-SPEC uses **exclusively** Microsoft Agent Framework.
9
- Semantic Kernel is superseded. Do NOT use `Kernel`, `KernelFunction`, or `InvokePromptAsync`.
8
+ **Verified against:** Microsoft.Agents.AI 1.0 GA (abril/2026). Last-verified: 2026-05-19.
10
9
 
11
10
  ---
12
11
 
13
- ## Packages
12
+ ## Provider philosophy — direct models always
14
13
 
15
- ```xml
16
- <!-- .csproj -->
17
- <!-- Microsoft.Extensions.AI — STABLE abstractions for IChatClient, AIFunctionFactory, tools -->
18
- <PackageReference Include="Microsoft.Extensions.AI" Version="9.5.0" />
19
- <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.3.0-preview.*" />
14
+ This framework is **provider-agnostic**. There is no "primary" provider hardcoded. Every model is reached as a **direct model** (you call the model API directly) — never via a hosted agent service. Hosted services lag 6-9 months on models and remove control.
20
15
 
21
- <!-- For Azure OpenAI -->
22
- <PackageReference Include="Azure.AI.OpenAI" Version="2.*" />
23
- <PackageReference Include="Azure.Identity" Version="1.*" />
16
+ First-class providers: **OpenAI, Google (Gemini), Anthropic (Claude), Ollama** (local/on-prem).
17
+ Azure OpenAI is also a direct model but is **not a default** — see note in §3.4.
24
18
 
25
- <!-- For A2A protocol hosting (when GA) -->
26
- <!-- <PackageReference Include="Microsoft.Agents.AI.Hosting.A2A.AspNetCore" Version="1.0.0-preview.*" /> -->
27
- ```
19
+ The concrete model choice lives in the project's Model Registry, not in this standard. See `ai-agents-providers-model-registry`.
20
+
21
+ ## Decision tree (when reading this in plan phase)
28
22
 
29
- > **Note:** The Microsoft Agent Framework (MAF) packages (`Microsoft.Agents.AI.*`) are **not yet published on NuGet**.
30
- > Use `Microsoft.Extensions.AI` as the primary package — it provides `IChatClient`, `AIFunctionFactory`,
31
- > and all abstractions shown in this guide. The MAF `ChatClientAgent`, `AsAIAgent()`, and `AgentWorkflowBuilder`
32
- > APIs documented here reflect the expected GA surface. Until MAF ships, implement agents using `IChatClient` directly.
23
+ ```
24
+ Está adicionando um agente AI a um projeto .NET?
25
+ ├─ Sim → use este standard + ai-agents-sweet-spot + ai-agents-providers-model-registry
26
+ │ ├─ Projeto tem >1 modelo ou >1 provider? → SEMPRE use Model Registry
27
+ │ ├─ Provider OpenAI? → §3.1
28
+ │ ├─ Provider Ollama (local)? → §3.2
29
+ │ ├─ Provider Google / Anthropic? → §3.3
30
+ │ └─ Provider Azure OpenAI (data residency)? → §3.4 (nota, não default)
31
+ └─ Não → este standard não se aplica
32
+ ```
33
33
 
34
34
  ---
35
35
 
36
- ## Quick Start (Minimal Agent)
36
+ ## 1. Packages (NuGet)
37
37
 
38
- ```csharp
39
- using Azure.AI.OpenAI;
40
- using Azure.Identity;
41
- using Microsoft.Extensions.AI;
42
-
43
- AIAgent agent = new AzureOpenAIClient(
44
- new Uri("https://your-resource.openai.azure.com/"),
45
- new AzureCliCredential())
46
- .GetChatClient("gpt-4o-mini")
47
- .AsAIAgent(instructions: "You are a helpful assistant.");
38
+ **Required for any MAF project:**
48
39
 
49
- Console.WriteLine(await agent.RunAsync("Analyze this order."));
40
+ ```xml
41
+ <PackageReference Include="Microsoft.Agents.AI" Version="1.0.*" />
50
42
  ```
51
43
 
52
- ---
53
-
54
- ## Setup by Provider
44
+ **Provider-specific (escolha conforme o Model Registry do projeto):**
55
45
 
56
- ### Azure OpenAI (Production)
46
+ ```xml
47
+ <!-- OpenAI direct -->
48
+ <PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.0.*" />
49
+ <PackageReference Include="OpenAI" Version="2.*" />
57
50
 
58
- ```csharp
59
- using Azure.AI.OpenAI;
60
- using Azure.Identity;
61
- using Microsoft.Extensions.AI;
51
+ <!-- Ollama (local / on-prem) — usa o mesmo OpenAI-compatible client -->
52
+ <PackageReference Include="OpenAI" Version="2.*" />
62
53
 
63
- builder.Services.AddSingleton<IChatClient>(sp =>
64
- {
65
- var cfg = sp.GetRequiredService<IConfiguration>();
66
- return new AzureOpenAIClient(
67
- new Uri(cfg["AzureOpenAI:Endpoint"]!),
68
- new DefaultAzureCredential()) // Managed Identity
69
- .GetChatClient(cfg["AzureOpenAI:DeploymentName"] ?? "gpt-4o-mini")
70
- .AsIChatClient();
71
- });
54
+ <!-- Google Gemini — SDK verificado no standard model-registry.md -->
55
+ <!-- Anthropic Claude — SDK verificado no standard model-registry.md -->
56
+ <!-- Azure OpenAI (somente se data residency exigir) — Azure.AI.OpenAI 2.* + Azure.Identity 1.* -->
72
57
  ```
73
58
 
74
- ### GitHub Models (Development)
59
+ > The `.AsIChatClient()` extension on `OpenAI.ChatClient` comes from `Microsoft.Agents.AI.OpenAI`. The `IChatClient` abstraction itself lives in `Microsoft.Extensions.AI` (a transitive dependency of `Microsoft.Agents.AI`) — code that uses `IChatClient` needs `using Microsoft.Extensions.AI;`.
75
60
 
76
- ```csharp
77
- using OpenAI;
78
- using Microsoft.Extensions.AI;
61
+ > Os pacotes de Google e Anthropic mudam de nome/versão com frequência. O standard `ai-agents-providers-model-registry` mantém a lista verificada com data. Não trave SDK aqui.
79
62
 
80
- builder.Services.AddSingleton<IChatClient>(sp =>
81
- {
82
- var cfg = sp.GetRequiredService<IConfiguration>();
83
- return new ChatClient(
84
- "gpt-4o-mini",
85
- new ApiKeyCredential(cfg["GitHub:Token"]!),
86
- new OpenAIClientOptions { Endpoint = new Uri("https://models.github.ai/inference") })
87
- .AsIChatClient();
88
- });
89
- ```
63
+ **Optional (only when feature requires):**
90
64
 
91
- ### Ollama (Local)
65
+ ```xml
66
+ <!-- Hosting helpers (AddAIAgent, AddSequentialWorkflow) -->
67
+ <PackageReference Include="Microsoft.Agents.AI.Hosting" Version="1.0.*" />
92
68
 
93
- ```csharp
94
- builder.Services.AddSingleton<IChatClient>(sp =>
95
- new ChatClient("llama3.2:3b",
96
- endpoint: new Uri("http://localhost:11434"))
97
- .AsIChatClient());
69
+ <!-- A2A protocol -->
70
+ <PackageReference Include="Microsoft.Agents.AI.A2A" Version="1.0.*" />
98
71
  ```
99
72
 
100
- ---
73
+ **Forbidden in new MAF projects:**
101
74
 
102
- ## Agent Pattern (Required)
75
+ - `Microsoft.SemanticKernel.*` — superseded by MAF, do not introduce.
76
+ - `Microsoft.Extensions.AI.OpenAI` 9.* — replaced by `Microsoft.Agents.AI.OpenAI` in GA.
77
+ - Hosted agent services (Foundry Agent Service, etc.) — use direct models.
103
78
 
104
- ### Using ChatClientAgent
79
+ ---
80
+
81
+ ## 2. Quick Start (canonical minimal agent)
105
82
 
106
83
  ```csharp
84
+ using Microsoft.Agents.AI;
107
85
  using Microsoft.Extensions.AI;
86
+ using OpenAI;
87
+ using OpenAI.Chat;
108
88
 
109
- public class OrderAnalysisAgent
110
- {
111
- private readonly IChatClient _chatClient;
112
- private readonly ILogger<OrderAnalysisAgent> _logger;
113
-
114
- public OrderAnalysisAgent(IChatClient chatClient, ILogger<OrderAnalysisAgent> logger)
115
- {
116
- _chatClient = chatClient;
117
- _logger = logger;
118
- }
119
-
120
- public async Task<string> AnalyzeAsync(Order order, CancellationToken ct = default)
121
- {
122
- var agent = new ChatClientAgent(
123
- _chatClient,
124
- new ChatClientAgentOptions
125
- {
126
- Name = "OrderAnalyzer",
127
- Instructions = """
128
- You are an e-commerce order analyst.
129
- Analyze the order and return:
130
- 1. Summary
131
- 2. Upsell suggestions
132
- 3. Cancellation risk (low/medium/high)
133
- Be concise.
134
- """
135
- });
136
-
137
- _logger.LogInformation("Analyzing order {OrderNumber}", order.OrderNumber);
138
-
139
- var response = await agent.RunAsync(
140
- $"Order: {order.OrderNumber}, Total: {order.Total:C}, Items: {order.Items.Count}",
141
- cancellationToken: ct);
142
-
143
- return response.Text;
144
- }
145
- }
146
- ```
147
-
148
- ### Using AsAIAgent (Shorthand)
149
-
150
- ```csharp
151
- AIAgent agent = chatClient.AsAIAgent(
152
- instructions: "You are a helpful assistant.",
153
- name: "MyAgent");
89
+ AIAgent agent = new ChatClient(model: "gpt-4o-mini", apiKey: "<from-config>")
90
+ .AsIChatClient()
91
+ .AsAIAgent(instructions: "You are a helpful assistant.");
154
92
 
155
- var response = await agent.RunAsync("Hello!", cancellationToken: ct);
93
+ var response = await agent.RunAsync("Analyze this order.");
156
94
  Console.WriteLine(response.Text);
157
95
  ```
158
96
 
97
+ This snippet is the baseline. In a real project you never hardcode the model — use the Model Registry (`ai-agents-providers-model-registry`). Anything more complex (DI, tools, structured output, RAG) layers on top via the other ai-agents standards.
98
+
159
99
  ---
160
100
 
161
- ## Tools (Function Calling)
101
+ ## 3. Setup by Provider
102
+
103
+ > In any project with >1 model or >1 provider, **do not register `IChatClient` directly** — use the Model Registry (`ai-agents-providers-model-registry`). The snippets below show the raw client construction the registry wraps.
162
104
 
163
- ### Define Tools with AIFunctionFactory
105
+ ### 3.1 OpenAI direct (most common)
164
106
 
165
107
  ```csharp
108
+ using OpenAI;
109
+ using OpenAI.Chat;
166
110
  using Microsoft.Extensions.AI;
167
111
 
168
- public class WeatherFunctions
112
+ builder.Services.AddSingleton<IChatClient>(sp =>
169
113
  {
170
- private readonly IWeatherService _weatherService;
171
-
172
- public WeatherFunctions(IWeatherService weatherService) => _weatherService = weatherService;
173
-
174
- [Description("Gets current weather for a city")]
175
- public async Task<string> GetWeatherAsync(
176
- [Description("City name")] string city,
177
- CancellationToken ct = default)
178
- {
179
- var weather = await _weatherService.GetCurrentAsync(city, ct);
180
- return $"Temp: {weather.Temperature}°C, Condition: {weather.Condition}";
181
- }
182
-
183
- [Description("Gets weather forecast for upcoming days")]
184
- public async Task<string> GetForecastAsync(
185
- [Description("City name")] string city,
186
- [Description("Number of days")] int days = 3,
187
- CancellationToken ct = default)
188
- {
189
- var forecast = await _weatherService.GetForecastAsync(city, days, ct);
190
- return string.Join("\n", forecast.Select(f => $"{f.Date:dd/MM}: {f.Temperature}°C"));
191
- }
192
- }
114
+ var cfg = sp.GetRequiredService<IConfiguration>();
115
+ return new ChatClient(
116
+ model: cfg["OpenAI:Model"] ?? "gpt-4o-mini",
117
+ apiKey: cfg["OpenAI:ApiKey"]!)
118
+ .AsIChatClient();
119
+ });
193
120
  ```
194
121
 
195
- ### Register Agent with Tools
122
+ ### 3.2 Ollama (local dev / on-prem)
123
+
124
+ Ollama exposes an OpenAI-compatible endpoint — use the same `ChatClient`:
196
125
 
197
126
  ```csharp
198
- var weatherFunctions = new WeatherFunctions(weatherService);
199
-
200
- var agent = new ChatClientAgent(
201
- chatClient,
202
- new ChatClientAgentOptions
203
- {
204
- Name = "WeatherAssistant",
205
- Instructions = "You help with weather questions. Use available tools.",
206
- ChatOptions = new ChatOptions
207
- {
208
- Tools =
209
- [
210
- AIFunctionFactory.Create(weatherFunctions.GetWeatherAsync),
211
- AIFunctionFactory.Create(weatherFunctions.GetForecastAsync)
212
- ]
213
- }
214
- });
127
+ using OpenAI;
128
+ using OpenAI.Chat;
129
+ using System.ClientModel;
130
+ using Microsoft.Extensions.AI;
131
+
132
+ builder.Services.AddSingleton<IChatClient>(sp =>
133
+ new ChatClient(
134
+ model: "llama3.2:3b",
135
+ credential: new ApiKeyCredential("ollama"), // any non-empty string
136
+ options: new OpenAIClientOptions { Endpoint = new Uri("http://localhost:11434/v1") })
137
+ .AsIChatClient());
215
138
  ```
216
139
 
217
- ### Static Function Tools
140
+ > Models < 3B params often fail tool calling. Use Ollama only for non-tool agents in dev.
218
141
 
219
- ```csharp
220
- [Description("Gets the current date and time")]
221
- static string GetCurrentDateTime() => DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
142
+ ### 3.3 Google (Gemini) / Anthropic (Claude)
222
143
 
223
- var agent = chatClient.AsAIAgent(
224
- instructions: "You are a helpful assistant.",
225
- tools: [AIFunctionFactory.Create(GetCurrentDateTime)]);
226
- ```
144
+ Both are first-class providers reached as direct models. The exact NuGet SDK and client construction are documented (with verification date) in `ai-agents-providers-model-registry` §providers — that standard is the single source of truth for provider SDKs, since they change names/versions often.
145
+
146
+ ### 3.4 Azure OpenAI (note — not a default)
147
+
148
+ Azure OpenAI is also a direct model, but requires an Azure resource + deployment per model. It is **not a default provider** in this framework — projects deploy to VPS, not Azure. Add an Azure branch to the Model Registry only when a client explicitly requires data residency in a specific Azure region. The pattern: `new AzureOpenAIClient(endpoint, credential).GetChatClient(deployment).AsIChatClient()`.
227
149
 
228
150
  ---
229
151
 
230
- ## Dependency Injection (Web API / Blazor)
152
+ ## 4. DI Registration (keyed agents)
231
153
 
232
- ### Register Agents with Keyed Services
154
+ > The `builder.AddAIAgent(...)` extension requires the `Microsoft.Agents.AI.Hosting` package (see §1 Optional). For projects that register agents manually without `AddAIAgent`, the base `Microsoft.Agents.AI` package is enough.
233
155
 
234
156
  ```csharp
235
157
  // Program.cs
236
158
  builder.AddAIAgent("OrderAnalyzer", (sp, key) =>
237
159
  {
238
160
  var chatClient = sp.GetRequiredService<IChatClient>();
239
- var orderFunctions = sp.GetRequiredService<OrderFunctions>();
240
-
241
161
  return new ChatClientAgent(
242
162
  chatClient,
243
163
  name: key,
244
- instructions: "You are an order analysis expert.",
245
- tools:
246
- [
247
- AIFunctionFactory.Create(orderFunctions.GetOrderAsync),
248
- AIFunctionFactory.Create(orderFunctions.CalculateDiscountAsync)
249
- ]);
164
+ instructions: "You are an order analysis expert.");
250
165
  });
251
-
252
- // Simple agent (no tools)
253
- builder.AddAIAgent(
254
- name: "Editor",
255
- instructions: "You are an editor who improves text quality.");
256
166
  ```
257
167
 
258
- ### Inject in Controllers / Blazor Components
168
+ Inject by key:
259
169
 
260
170
  ```csharp
261
- // Controller
262
171
  public class AgentController(
263
- [FromKeyedServices("OrderAnalyzer")] AIAgent orderAgent) : ControllerBase
264
- {
265
- [HttpPost("analyze")]
266
- public async Task<IActionResult> Analyze(OrderRequest request)
267
- {
268
- var response = await orderAgent.RunAsync(request.Prompt);
269
- return Ok(response.Text);
270
- }
271
- }
272
-
273
- // Blazor component
274
- @inject IServiceProvider ServiceProvider
275
- @code {
276
- private AIAgent _agent = default!;
277
-
278
- protected override void OnInitialized()
279
- {
280
- _agent = ServiceProvider.GetRequiredKeyedService<AIAgent>("OrderAnalyzer");
281
- }
282
- }
283
- ```
284
-
285
- ---
286
-
287
- ## Streaming
288
-
289
- ```csharp
290
- await foreach (var update in agent.RunStreamingAsync(
291
- "Write a detailed analysis.",
292
- cancellationToken: ct))
293
- {
294
- if (update is AgentResponseUpdateEvent e)
295
- {
296
- Console.Write(e.Data);
297
- }
298
- }
172
+ [FromKeyedServices("OrderAnalyzer")] AIAgent orderAgent) : ControllerBase { ... }
299
173
  ```
300
174
 
301
- ---
302
-
303
- ## Recommended Models
304
-
305
- | Use Case | Model | Provider | Cost (per 1M input tokens) |
306
- |----------|-------|----------|---------------------------|
307
- | Simple tasks (default) | gpt-4o-mini | Azure OpenAI | $0.15 |
308
- | Complex analysis | gpt-4o | Azure OpenAI | $2.50 |
309
- | Embeddings | text-embedding-3-small | Azure OpenAI | $0.02 |
310
- | Local development | llama3.2:3b | Ollama | Free |
311
- | Cloud development | gpt-4o-mini | GitHub Models | Free (preview) |
312
-
313
- **MORPH-SPEC default:** `gpt-4o-mini` for production.
175
+ For agents with tools and structured output, see `ai-agents-multi-agent-patterns` and `ai-agents-structured-output` (Onda 2).
314
176
 
315
177
  ---
316
178
 
317
- ## Security
318
-
319
- ### API Keys in Azure Key Vault
179
+ ## 5. OpenTelemetry
320
180
 
321
181
  ```csharp
322
- if (builder.Environment.IsProduction())
323
- {
324
- var keyVaultUri = new Uri(builder.Configuration["KeyVault:Uri"]!);
325
- builder.Configuration.AddAzureKeyVault(keyVaultUri, new DefaultAzureCredential());
326
- }
327
- ```
182
+ using OpenTelemetry;
183
+ using OpenTelemetry.Trace;
184
+ using Microsoft.Agents.AI;
328
185
 
329
- ### Managed Identity (Recommended)
186
+ using var tracerProvider = Sdk.CreateTracerProviderBuilder()
187
+ .AddSource(AgentOpenTelemetryConsts.DefaultSourceName)
188
+ .AddOtlpExporter()
189
+ .Build();
330
190
 
331
- ```csharp
332
- // Use DefaultAzureCredential — works with Managed Identity in production,
333
- // AzureCliCredential in development
334
- var client = new AzureOpenAIClient(
335
- new Uri(config["AzureOpenAI:Endpoint"]!),
336
- new DefaultAzureCredential());
191
+ // Wrap any agent (e.g. the `agent` from §2)
192
+ var instrumented = agent.WithOpenTelemetry();
337
193
  ```
338
194
 
339
- ---
340
-
341
- ## Observability
342
-
343
- ```csharp
344
- // Enable OpenTelemetry on agents
345
- agent.WithOpenTelemetry();
346
-
347
- // Program.cs — Aspire Dashboard integration
348
- builder.Services.AddOpenTelemetry()
349
- .WithTracing(tracing =>
350
- {
351
- tracing.AddSource("Experimental.Microsoft.Extensions.AI.*");
352
- tracing.AddAspNetCoreInstrumentation();
353
- })
354
- .WithMetrics(metrics =>
355
- {
356
- metrics.AddMeter("Experimental.Microsoft.Extensions.AI.*");
357
- metrics.AddAspNetCoreInstrumentation();
358
- });
359
- ```
195
+ > **Note:** Source name is `AgentOpenTelemetryConsts.DefaultSourceName` from `Microsoft.Agents.AI`. **Do NOT** use the old `Experimental.Microsoft.Extensions.AI.*` source — it belongs to a previous package family.
360
196
 
361
197
  ---
362
198
 
363
- ## Limitations & Troubleshooting
199
+ ## 6. Security checklist
364
200
 
365
- | Problem | Cause | Solution |
366
- |---------|-------|----------|
367
- | Tool calling fails | Model < 3B params | Use gpt-4o-mini minimum |
368
- | Rate limit errors | Too many requests | Add retry middleware (see production.md) |
369
- | Tools not invoked | Missing `[Description]` | Add `[Description]` to method AND parameters |
370
- | Agent returns empty | No instructions | Always set `Instructions` in agent options |
201
+ - [ ] API keys never in source. Bind from environment variables / secret store (the VPS deploy uses env vars; Docker secrets or a vault are fine too).
202
+ - [ ] `appsettings.json` checked into git never contains real keys — only placeholder/empty values.
203
+ - [ ] Provider keys (`OpenAI:ApiKey`, `Google:ApiKey`, `Anthropic:ApiKey`) bound from environment.
204
+ - [ ] No agent receives raw user input without input-validation middleware (see `ai-agents-middleware-patterns` — Onda 2).
371
205
 
372
206
  ---
373
207
 
374
- ## Checklist
208
+ ## 7. What NOT to do (anti-patterns)
375
209
 
376
- - [ ] `Microsoft.Extensions.AI` + `Microsoft.Extensions.AI.OpenAI` installed
377
- - [ ] `IChatClient` registered as singleton via DI
378
- - [ ] Agents created with `ChatClientAgent` or `AsAIAgent()`
379
- - [ ] Agents registered with `builder.AddAIAgent()` (keyed services)
380
- - [ ] Tools use `AIFunctionFactory.Create()` + `[Description]`
381
- - [ ] API keys in Key Vault (production)
382
- - [ ] Managed Identity configured
383
- - [ ] gpt-4o-mini as default model
384
- - [ ] OpenTelemetry enabled on agents
385
- - [ ] Error handling via middleware (see `production.md`)
210
+ | Wrong | Right |
211
+ |-------|-------|
212
+ | `using Microsoft.SemanticKernel` | `using Microsoft.Agents.AI` |
213
+ | `Kernel.InvokePromptAsync()` | `agent.RunAsync()` |
214
+ | `[KernelFunction]` | `[Description]` on method + parameters; register via `AIFunctionFactory.Create()` |
215
+ | `ChatHistory` | `IEnumerable<ChatMessage>` |
216
+ | Hardcoded model strings spread across codebase | Single source via Model Registry (see `ai-agents-providers-model-registry`) |
217
+ | `Microsoft.Extensions.AI.OpenAI` 9.* | `Microsoft.Agents.AI.OpenAI` 1.* GA |
218
+ | Hosted agent service "to simplify" | Direct models always |
386
219
 
387
220
  ---
388
221
 
389
- ## What NOT To Do
222
+ ## 8. Checklist (verifiable by morph-eval)
390
223
 
391
- | Wrong | Correct |
392
- |-------|---------|
393
- | `using Microsoft.SemanticKernel` | `using Microsoft.Extensions.AI` |
394
- | `Kernel.InvokePromptAsync()` | `agent.RunAsync()` |
395
- | `[KernelFunction]` | `AIFunctionFactory.Create()` |
396
- | `[AgentTool]` attribute | `[Description]` + `AIFunctionFactory` |
397
- | `AgentTool.FromMethod()` | `AIFunctionFactory.Create(method)` |
398
- | `_chatClient.CreateAgent()` | `new ChatClientAgent()` or `.AsAIAgent()` |
399
- | `agent.CreateThreadAsync()` | Use session/conversation management |
400
- | `ChatHistory` | `IEnumerable<ChatMessage>` |
401
- | Hardcoded API keys | Key Vault / Managed Identity |
402
- | Models < 3B for tools | gpt-4o-mini minimum |
224
+ - [ ] `Microsoft.Agents.AI` package present in `.csproj`
225
+ - [ ] No `Microsoft.SemanticKernel.*` references
226
+ - [ ] `IChatClient` registered (either directly or via Model Registry)
227
+ - [ ] At least one `AIAgent` created via `AsAIAgent()` or `new ChatClientAgent()`
228
+ - [ ] OpenTelemetry source name is `AgentOpenTelemetryConsts.DefaultSourceName` (if telemetry wired)
229
+ - [ ] Models reference Model Registry alias when project has >1 model use case
403
230
 
404
231
  ---
405
232
 
406
- ## References
233
+ ## 9. References
407
234
 
408
- - [Agent Framework Quick Start](https://learn.microsoft.com/agent-framework/tutorials/quick-start)
409
- - [Agent Tools](https://learn.microsoft.com/agent-framework/user-guide/agents/agent-tools)
410
- - [Microsoft.Extensions.AI](https://learn.microsoft.com/dotnet/ai/ai-extensions)
411
- - [GitHub: microsoft/agent-framework](https://github.com/microsoft/agent-framework)
412
- - `workflows.md` — Orchestration patterns
413
- - `production.md` — Middleware, A2A, MCP, caching
414
- - `blazor-ui.md` — Natural Language First UI patterns
235
+ - `ai-agents-sweet-spot` — when to use agents vs workflows
236
+ - `ai-agents-providers-model-registry` — provider-agnostic pattern
237
+ - `ai-agents-structured-output` (Onda 2) — typed responses
238
+ - `ai-agents-middleware-patterns` (Onda 2) — telemetry, retry, anti-hallucination, streaming agent responses
239
+ - Microsoft.Agents.AI docs: https://learn.microsoft.com/agent-framework/
240
+ - Verified packages list (context7 /microsoft/agent-framework): retrieved 2026-05-19
415
241
 
416
242
  ---
417
243
 
418
- *MORPH-SPEC by Polymorphism Tech*
244
+ *MORPH-SPEC by Polymorphism Tech — ai-agents/setup.md v2.0 (2026-05-19)*