@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.
- package/README.md +368 -368
- package/claude-plugin.json +14 -14
- package/docs/CHEATSHEET.md +199 -199
- package/docs/QUICKSTART.md +200 -200
- package/framework/CLAUDE.md +1 -1
- package/framework/MORPH.md +4 -1
- package/framework/agents.json +132 -127
- package/framework/rubrics/backend.json +41 -36
- package/framework/rules/ai-agents-standards.md +45 -15
- package/framework/rules/neon-standards.md +25 -26
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +3 -1
- package/framework/skills/core/morph-stack-scan/SKILL.md +3 -3
- package/framework/standards/STANDARDS.json +1729 -1133
- package/framework/standards/ai-agents/agent-session.md +160 -0
- package/framework/standards/ai-agents/batching.md +193 -0
- package/framework/standards/ai-agents/context-providers.md +188 -0
- package/framework/standards/ai-agents/mcp-server.md +250 -0
- package/framework/standards/ai-agents/mcp-tools.md +197 -0
- package/framework/standards/ai-agents/middleware-patterns.md +207 -0
- package/framework/standards/ai-agents/modalities-image-gen.md +173 -0
- package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -0
- package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -0
- package/framework/standards/ai-agents/modalities-vision.md +201 -0
- package/framework/standards/ai-agents/multi-agent-patterns.md +155 -0
- package/framework/standards/ai-agents/production.md +114 -258
- package/framework/standards/ai-agents/prompts-in-db.md +214 -0
- package/framework/standards/ai-agents/providers/model-registry.md +158 -0
- package/framework/standards/ai-agents/rag-custom-pgvector.md +243 -0
- package/framework/standards/ai-agents/service-tier-flex.md +135 -0
- package/framework/standards/ai-agents/setup.md +142 -316
- package/framework/standards/ai-agents/structured-output.md +249 -0
- package/framework/standards/ai-agents/sweet-spot.md +109 -0
- package/framework/standards/ai-agents/workflows.md +114 -284
- package/framework/standards/architecture/vertical-slice/vertical-slice.md +439 -429
- package/framework/standards/backend/api/validation.md +92 -88
- package/framework/standards/backend/database/postgresql/database.md +336 -332
- package/framework/standards/backend/database/vector-search-rag.md +599 -541
- package/framework/standards/backend/dotnet/fluent-validation-vsa.md +4 -0
- package/framework/standards/backend/dotnet/result-pattern.md +4 -0
- package/framework/standards/backend/dotnet/scalar-ui.md +176 -172
- package/framework/standards/backend/dotnet/scrutor.md +4 -0
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +310 -274
- package/framework/standards/backend/integrations/asaas/asaas-api.md +260 -216
- package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +354 -350
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +30 -19
- package/framework/standards/backend/integrations/resend/resend-email.md +400 -385
- package/framework/standards/data/nosql/cache/redis.md +106 -97
- package/framework/standards/data/nosql/cosmos-db.md +127 -118
- package/framework/standards/data/vector-search/rag-chunking.md +113 -104
- package/framework/standards/frontend/design-system/ai-image-generation.md +4 -0
- package/framework/standards/frontend/design-system/animations.md +164 -160
- package/framework/standards/frontend/design-system/naming.md +68 -64
- package/framework/standards/frontend/gsap/gsap-core.md +14 -8
- package/framework/standards/frontend/gsap/gsap-plugins.md +26 -21
- package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +9 -7
- package/framework/standards/frontend/nextjs/app-router.md +127 -123
- package/framework/standards/frontend/nextjs/components.md +136 -132
- package/framework/standards/frontend/nextjs/data-fetching.md +130 -126
- package/framework/standards/frontend/nextjs/forms.md +134 -128
- package/framework/standards/frontend/nextjs/motion-patterns.md +328 -322
- package/framework/standards/frontend/nextjs/naming-conventions.md +71 -67
- package/framework/standards/frontend/nextjs/nextjs-patterns.md +229 -225
- package/framework/standards/frontend/nextjs/project-structure.md +106 -102
- package/framework/standards/frontend/nextjs/state-management.md +76 -72
- package/framework/standards/frontend/nextjs/testing.md +115 -111
- package/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -192
- package/framework/standards/infrastructure/neon/neon-pgrag.md +6 -2
- package/framework/standards/infrastructure/neon/neon-pgvector.md +4 -0
- package/framework/standards/infrastructure/neon/neon-setup.md +5 -1
- package/framework/standards/integration/mcp/mcp-tools.md +471 -462
- package/framework/templates/CLAUDE.md.core.template +1 -1
- package/framework/templates/REGISTRY.json +1745 -1239
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -0
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -0
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -0
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -0
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -0
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -0
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -0
- package/framework/templates/code/dotnet/backend/repository.cs +3 -10
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -0
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -0
- package/package.json +89 -83
- package/src/core/templates/template-registry.js +289 -256
- package/src/lib/generators/context-generator.js +516 -518
- package/src/lib/generators/scaffold-generator.js +23 -26
- package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +0 -310
- package/framework/templates/integrations/semantic-kernel-neon.cs +0 -125
|
@@ -1,157 +1,71 @@
|
|
|
1
|
-
# Microsoft Agent Framework
|
|
1
|
+
# Microsoft Agent Framework — Production Patterns
|
|
2
2
|
|
|
3
|
-
> **Scope:**
|
|
4
|
-
> **Layer:**
|
|
5
|
-
> **Keywords:** middleware,
|
|
6
|
-
> **
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 1 (on-keyword)
|
|
5
|
+
> **Keywords:** middleware, observability, telemetry, mcp, a2a, caching, anti-hallucination, production agent
|
|
6
|
+
> **Read by Claude in:** implement (when wiring middleware/telemetry/MCP into an agent)
|
|
7
7
|
|
|
8
|
-
**
|
|
9
|
-
|
|
10
|
-
Middleware, A2A protocol, MCP integration, caching, and observability for production agents.
|
|
8
|
+
**Verified against:** MAF 1.0 GA. Last-verified: 2026-05-19.
|
|
11
9
|
|
|
12
10
|
---
|
|
13
11
|
|
|
14
12
|
## Middleware Pipeline
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
Três tipos de middleware interceptam o comportamento do agent em camadas distintas:
|
|
17
15
|
|
|
18
|
-
|
|
|
16
|
+
| Tipo | Intercepts | Use Case |
|
|
19
17
|
|------|-----------|----------|
|
|
20
|
-
| **Agent Run** |
|
|
21
|
-
| **Function Calling** |
|
|
22
|
-
| **IChatClient** |
|
|
23
|
-
|
|
24
|
-
### Agent Run Middleware
|
|
25
|
-
|
|
26
|
-
```csharp
|
|
27
|
-
async Task<AgentResponse> LoggingMiddleware(
|
|
28
|
-
IEnumerable<ChatMessage> messages,
|
|
29
|
-
AgentSession? session,
|
|
30
|
-
AgentRunOptions? options,
|
|
31
|
-
AIAgent innerAgent,
|
|
32
|
-
CancellationToken cancellationToken)
|
|
33
|
-
{
|
|
34
|
-
Console.WriteLine($"Input messages: {messages.Count()}");
|
|
35
|
-
var response = await innerAgent.RunAsync(messages, session, options, cancellationToken);
|
|
36
|
-
Console.WriteLine($"Output messages: {response.Messages.Count}");
|
|
37
|
-
return response;
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Function Calling Middleware (Error Handling)
|
|
42
|
-
|
|
43
|
-
```csharp
|
|
44
|
-
async ValueTask<object?> ErrorHandlingMiddleware(
|
|
45
|
-
AIAgent agent,
|
|
46
|
-
FunctionInvocationContext context,
|
|
47
|
-
Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next,
|
|
48
|
-
CancellationToken cancellationToken)
|
|
49
|
-
{
|
|
50
|
-
try
|
|
51
|
-
{
|
|
52
|
-
Console.WriteLine($"Calling: {context.Function.Name}");
|
|
53
|
-
var result = await next(context, cancellationToken);
|
|
54
|
-
Console.WriteLine($"Result: {result}");
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
catch (Exception ex)
|
|
58
|
-
{
|
|
59
|
-
// Return error message the agent can understand
|
|
60
|
-
return $"Error calling {context.Function.Name}: {ex.Message}. Try a different approach.";
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
```
|
|
18
|
+
| **Agent Run** | Invocação completa do agent | Logging, auth, rate limiting |
|
|
19
|
+
| **Function Calling** | Chamadas individuais de tools | Error handling, validação, auditoria |
|
|
20
|
+
| **IChatClient** | Chamadas brutas ao LLM | Telemetry, caching, content filtering |
|
|
64
21
|
|
|
65
|
-
|
|
22
|
+
O **tratamento canônico** de middleware — código dos 3 níveis, registro via `.AsBuilder().Use(...)`,
|
|
23
|
+
e os patterns de telemetria, resilência (retry + rate-limit) e anti-hallucination — está em
|
|
24
|
+
**`ai-agents-middleware-patterns`**. Não duplicado aqui.
|
|
66
25
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
ChatOptions? options,
|
|
71
|
-
IChatClient innerChatClient,
|
|
72
|
-
CancellationToken cancellationToken)
|
|
73
|
-
{
|
|
74
|
-
var sw = Stopwatch.StartNew();
|
|
75
|
-
var response = await innerChatClient.GetResponseAsync(messages, options, cancellationToken);
|
|
76
|
-
sw.Stop();
|
|
77
|
-
|
|
78
|
-
Console.WriteLine($"LLM call: {sw.ElapsedMilliseconds}ms, Tokens: {response.Usage?.TotalTokenCount}");
|
|
79
|
-
return response;
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Registering Middleware
|
|
84
|
-
|
|
85
|
-
```csharp
|
|
86
|
-
// On an existing agent
|
|
87
|
-
var middlewareAgent = originalAgent
|
|
88
|
-
.AsBuilder()
|
|
89
|
-
.Use(runFunc: LoggingMiddleware, runStreamingFunc: LoggingStreamingMiddleware)
|
|
90
|
-
.Use(ErrorHandlingMiddleware) // Function calling
|
|
91
|
-
.Build();
|
|
92
|
-
|
|
93
|
-
// On the chat client (before agent creation)
|
|
94
|
-
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
|
95
|
-
.GetChatClient(deploymentName)
|
|
96
|
-
.AsIChatClient()
|
|
97
|
-
.AsBuilder()
|
|
98
|
-
.Use(getResponseFunc: TelemetryMiddleware, getStreamingResponseFunc: null)
|
|
99
|
-
.Build();
|
|
100
|
-
|
|
101
|
-
// Via factory method on AsAIAgent
|
|
102
|
-
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
|
103
|
-
.GetChatClient(deploymentName)
|
|
104
|
-
.AsAIAgent("You are a helpful assistant.", clientFactory: (chatClient) => chatClient
|
|
105
|
-
.AsBuilder()
|
|
106
|
-
.Use(getResponseFunc: TelemetryMiddleware, getStreamingResponseFunc: null)
|
|
107
|
-
.Build());
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
**Important:** If only non-streaming middleware is provided, streaming calls run in non-streaming mode.
|
|
26
|
+
> Em produção: registre `ResilientToolMiddleware` (ou equivalente) em qualquer agent que chame
|
|
27
|
+
> APIs externas, e um middleware de telemetria no `IChatClient`. Ver `ai-agents-middleware-patterns`
|
|
28
|
+
> para o código e a decision tree de qual nível usar.
|
|
111
29
|
|
|
112
30
|
---
|
|
113
31
|
|
|
114
32
|
## A2A Protocol (Agent-to-Agent)
|
|
115
33
|
|
|
116
|
-
|
|
34
|
+
Exponha agents como serviços web interoperáveis via protocolo A2A padronizado.
|
|
117
35
|
|
|
118
|
-
|
|
36
|
+
**Package (GA):**
|
|
119
37
|
|
|
120
38
|
```xml
|
|
121
|
-
|
|
122
|
-
<!-- <PackageReference Include="Microsoft.Agents.AI.Hosting.A2A.AspNetCore" Version="1.0.0-preview.*" /> -->
|
|
39
|
+
<PackageReference Include="Microsoft.Agents.AI.A2A" Version="1.0.*" />
|
|
123
40
|
```
|
|
124
41
|
|
|
125
|
-
|
|
126
|
-
> The patterns below reflect the expected API surface. Until GA, implement A2A manually via HTTP endpoints.
|
|
127
|
-
|
|
128
|
-
### Expose Agent via A2A
|
|
42
|
+
### Expor um agent via A2A
|
|
129
43
|
|
|
130
44
|
```csharp
|
|
131
45
|
// Program.cs
|
|
46
|
+
using Microsoft.Agents.AI;
|
|
47
|
+
using Microsoft.Agents.AI.A2A;
|
|
48
|
+
using Microsoft.Extensions.AI;
|
|
49
|
+
|
|
132
50
|
var builder = WebApplication.CreateBuilder(args);
|
|
133
51
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
.GetChatClient(deploymentName)
|
|
137
|
-
.AsIChatClient();
|
|
52
|
+
// Registrar agent via Model Registry
|
|
53
|
+
IChatClient chatClient = /* from ModelRegistry singleton */;
|
|
138
54
|
builder.Services.AddSingleton(chatClient);
|
|
139
55
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
var historyAgent = builder.AddAIAgent("history", instructions: "You are a history expert.");
|
|
56
|
+
builder.AddAIAgent("math", instructions: "You are a math expert.");
|
|
57
|
+
builder.AddAIAgent("history", instructions: "You are a history expert.");
|
|
143
58
|
|
|
144
59
|
var app = builder.Build();
|
|
145
60
|
|
|
146
|
-
|
|
147
|
-
app.MapA2A(mathAgent, path: "/a2a/math", agentCard: new()
|
|
61
|
+
app.MapA2A("math", path: "/a2a/math", agentCard: new()
|
|
148
62
|
{
|
|
149
63
|
Name = "Math Agent",
|
|
150
64
|
Description = "Expert in mathematics and calculations.",
|
|
151
65
|
Version = "1.0"
|
|
152
66
|
});
|
|
153
67
|
|
|
154
|
-
app.MapA2A(
|
|
68
|
+
app.MapA2A("history", path: "/a2a/history", agentCard: new()
|
|
155
69
|
{
|
|
156
70
|
Name = "History Agent",
|
|
157
71
|
Description = "Expert in world history.",
|
|
@@ -161,103 +75,80 @@ app.MapA2A(historyAgent, path: "/a2a/history", agentCard: new()
|
|
|
161
75
|
app.Run();
|
|
162
76
|
```
|
|
163
77
|
|
|
164
|
-
###
|
|
165
|
-
|
|
166
|
-
```
|
|
167
|
-
GET /a2a/math/v1/card → Returns agent metadata (name, description, capabilities)
|
|
168
|
-
POST /a2a/math/v1/message:stream → Send message, get streaming response
|
|
169
|
-
```
|
|
78
|
+
### Consumir um agent A2A remoto
|
|
170
79
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
| Feature | Description |
|
|
174
|
-
|---------|-------------|
|
|
175
|
-
| Agent Discovery | Standardized Agent Cards with metadata |
|
|
176
|
-
| Cross-Framework | .NET agent can talk to Python agent and vice versa |
|
|
177
|
-
| Context Persistence | `contextId` maintains conversation across messages |
|
|
178
|
-
| Streaming | Server-Sent Events for real-time responses |
|
|
179
|
-
| Long-Running Tasks | Async task support for extended operations |
|
|
80
|
+
```csharp
|
|
81
|
+
using Microsoft.Agents.AI.A2A;
|
|
180
82
|
|
|
181
|
-
|
|
83
|
+
// Wrap a remote A2A endpoint as a local AIAgent
|
|
84
|
+
AIAgent remoteAgent = new A2AClient(new Uri("https://agents.example.com/a2a/math"))
|
|
85
|
+
.AsAIAgent();
|
|
182
86
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Connect agents to external tools and data sources via MCP servers.
|
|
87
|
+
var response = await remoteAgent.RunAsync("What is the integral of x^2?");
|
|
88
|
+
```
|
|
186
89
|
|
|
187
|
-
###
|
|
90
|
+
### Agent Card Discovery
|
|
188
91
|
|
|
189
|
-
```
|
|
190
|
-
|
|
92
|
+
```
|
|
93
|
+
GET /a2a/math/v1/card → metadata (name, description, capabilities)
|
|
94
|
+
POST /a2a/math/v1/message:stream → send message, get streaming response
|
|
191
95
|
```
|
|
192
96
|
|
|
193
|
-
|
|
97
|
+
| Feature A2A | Descrição |
|
|
98
|
+
|-------------|-----------|
|
|
99
|
+
| Agent Discovery | Agent Cards com metadados padronizados |
|
|
100
|
+
| Cross-Framework | Agent .NET pode conversar com agent Python |
|
|
101
|
+
| Context Persistence | `contextId` mantém conversa entre mensagens |
|
|
102
|
+
| Streaming | Server-Sent Events para respostas em tempo real |
|
|
194
103
|
|
|
195
|
-
|
|
196
|
-
using ModelContextProtocol;
|
|
197
|
-
using ModelContextProtocol.Client;
|
|
104
|
+
---
|
|
198
105
|
|
|
199
|
-
|
|
200
|
-
await using var mcpClient = await McpClientFactory.CreateAsync(
|
|
201
|
-
new StdioClientTransport(new()
|
|
202
|
-
{
|
|
203
|
-
Name = "GitHubServer",
|
|
204
|
-
Command = "npx",
|
|
205
|
-
Arguments = ["-y", "--verbose", "@modelcontextprotocol/server-github"],
|
|
206
|
-
}));
|
|
106
|
+
## MCP Integration (Model Context Protocol)
|
|
207
107
|
|
|
208
|
-
|
|
209
|
-
|
|
108
|
+
Agents MAF podem consumir tools de **MCP servers externos** (GitHub, filesystem, Postgres,
|
|
109
|
+
servidores internos) e expor capacidades do projeto **como** um MCP server.
|
|
210
110
|
|
|
211
|
-
|
|
212
|
-
AIAgent agent = chatClient.AsAIAgent(
|
|
213
|
-
instructions: "You answer questions about GitHub repositories.",
|
|
214
|
-
tools: [.. mcpTools.Cast<AITool>()]);
|
|
111
|
+
Esses dois casos têm tratamento canônico em standards dedicados — **não duplicado aqui**:
|
|
215
112
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
113
|
+
| Caso | Standard |
|
|
114
|
+
|------|----------|
|
|
115
|
+
| Agente MAF consome um MCP server externo | `ai-agents-mcp-tools` (`McpClientFactory.CreateAsync`, transports, `await using`) |
|
|
116
|
+
| Projeto expõe capacidades como MCP server | `ai-agents-mcp-server` (`[McpServerTool]`, `AddMcpServer`, stdio/HTTP) |
|
|
219
117
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
| Server | Purpose |
|
|
223
|
-
|--------|---------|
|
|
224
|
-
| `@modelcontextprotocol/server-github` | GitHub repos, issues, PRs |
|
|
225
|
-
| `@modelcontextprotocol/server-filesystem` | File system operations |
|
|
226
|
-
| `@modelcontextprotocol/server-sqlite` | SQLite database access |
|
|
227
|
-
| Azure MCP Server | Azure resource management |
|
|
118
|
+
> Em produção, lembre: MCP client sempre com `await using` (dispose do transporte); MCP server
|
|
119
|
+
> exposto via HTTP exige autenticação. Detalhes nos standards acima.
|
|
228
120
|
|
|
229
121
|
---
|
|
230
122
|
|
|
231
|
-
## Caching Patterns
|
|
123
|
+
## Caching Patterns
|
|
232
124
|
|
|
233
125
|
### Semantic Caching (Redis)
|
|
234
126
|
|
|
235
|
-
Cache LLM
|
|
127
|
+
Cache de respostas LLM por similaridade semântica — evita inferências repetidas.
|
|
128
|
+
|
|
129
|
+
> **Illustrative pseudo-code** — the exact Redis vector-search calls depend on your Redis client. For a complete, working semantic-search implementation see `ai-agents-rag-custom-pgvector` (Onda 2). The point of this section is the *pattern*: embed the query, vector-search a cache, return on a similarity hit.
|
|
236
130
|
|
|
237
131
|
```csharp
|
|
238
132
|
public async Task<string?> GetCachedResponseAsync(string question)
|
|
239
133
|
{
|
|
240
134
|
var questionEmbedding = await _embedding.GenerateAsync(question);
|
|
241
135
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"PARAMS", "2", "vec", questionEmbedding.ToByteArray(),
|
|
246
|
-
"SORTBY", "score", "DIALECT", "2");
|
|
136
|
+
// pseudo-code: perform a KNN vector search against the cache index
|
|
137
|
+
var (similarityScore, cachedResponse) = await VectorSearchCacheAsync(
|
|
138
|
+
"idx:semantic_cache", questionEmbedding);
|
|
247
139
|
|
|
248
|
-
if (
|
|
249
|
-
return
|
|
140
|
+
if (similarityScore >= 0.95) // cosine similarity: higher = more similar
|
|
141
|
+
return cachedResponse;
|
|
250
142
|
|
|
251
|
-
return null; //
|
|
143
|
+
return null; // cache miss
|
|
252
144
|
}
|
|
253
145
|
```
|
|
254
146
|
|
|
255
|
-
**Cost savings:**
|
|
147
|
+
**Cost savings:** embedding ~$0.0001/1K tokens vs inferência ~$0.01-0.03/1K tokens = **100-300x savings**.
|
|
256
148
|
|
|
257
149
|
### Hybrid Cache (L1 + L2)
|
|
258
150
|
|
|
259
151
|
```csharp
|
|
260
|
-
// Program.cs
|
|
261
152
|
builder.Services.AddHybridCache(options =>
|
|
262
153
|
{
|
|
263
154
|
options.DefaultEntryOptions = new HybridCacheEntryOptions
|
|
@@ -267,7 +158,7 @@ builder.Services.AddHybridCache(options =>
|
|
|
267
158
|
};
|
|
268
159
|
});
|
|
269
160
|
|
|
270
|
-
//
|
|
161
|
+
// Uso num tool
|
|
271
162
|
[Description("Gets weather for a location")]
|
|
272
163
|
public async Task<WeatherResponse> GetWeatherAsync(
|
|
273
164
|
string location, string date, CancellationToken ct)
|
|
@@ -284,17 +175,16 @@ public async Task<WeatherResponse> GetWeatherAsync(
|
|
|
284
175
|
| L1 | Process memory | Fastest | Per instance |
|
|
285
176
|
| L2 | Redis | Very fast | Distributed |
|
|
286
177
|
|
|
287
|
-
### MCP Tool Routing Cache
|
|
288
|
-
|
|
289
|
-
Store tool description embeddings in Redis. On user query, find relevant tools by vector similarity — reduces tokens sent to LLM.
|
|
290
|
-
|
|
291
178
|
---
|
|
292
179
|
|
|
293
|
-
## Observability
|
|
294
|
-
|
|
295
|
-
### OpenTelemetry Integration
|
|
180
|
+
## Observability / OpenTelemetry
|
|
296
181
|
|
|
297
182
|
```csharp
|
|
183
|
+
using OpenTelemetry;
|
|
184
|
+
using OpenTelemetry.Trace;
|
|
185
|
+
using OpenTelemetry.Metrics;
|
|
186
|
+
using Microsoft.Agents.AI;
|
|
187
|
+
|
|
298
188
|
// Enable on individual agents
|
|
299
189
|
agent.WithOpenTelemetry();
|
|
300
190
|
|
|
@@ -302,39 +192,31 @@ agent.WithOpenTelemetry();
|
|
|
302
192
|
builder.Services.AddOpenTelemetry()
|
|
303
193
|
.WithTracing(tracing =>
|
|
304
194
|
{
|
|
305
|
-
tracing.AddSource(
|
|
195
|
+
tracing.AddSource(AgentOpenTelemetryConsts.DefaultSourceName); // MAF 1.0 GA source
|
|
306
196
|
tracing.AddSource(builder.Environment.ApplicationName);
|
|
307
197
|
tracing.AddAspNetCoreInstrumentation();
|
|
308
198
|
tracing.AddHttpClientInstrumentation();
|
|
199
|
+
tracing.AddOtlpExporter();
|
|
309
200
|
})
|
|
310
201
|
.WithMetrics(metrics =>
|
|
311
202
|
{
|
|
312
|
-
metrics.AddMeter(
|
|
203
|
+
metrics.AddMeter(AgentOpenTelemetryConsts.DefaultSourceName); // MAF 1.0 GA meter
|
|
313
204
|
metrics.AddAspNetCoreInstrumentation();
|
|
314
205
|
metrics.AddHttpClientInstrumentation();
|
|
315
206
|
metrics.AddRuntimeInstrumentation();
|
|
316
207
|
});
|
|
317
|
-
|
|
318
|
-
// Enable sensitive data in development
|
|
319
|
-
builder.AddAzureChatCompletionsClient("chat", settings =>
|
|
320
|
-
{
|
|
321
|
-
settings.EnableSensitiveTelemetryData = builder.Environment.IsDevelopment();
|
|
322
|
-
});
|
|
323
208
|
```
|
|
324
209
|
|
|
210
|
+
> **Source name:** sempre `AgentOpenTelemetryConsts.DefaultSourceName` de `Microsoft.Agents.AI`.
|
|
211
|
+
> **NÃO usar** o source string `"Experimental.[pacote-antigo].*"` — pertence à família `Microsoft.Extensions.AI 9.x`, incompatível com MAF 1.0 GA.
|
|
212
|
+
|
|
325
213
|
### Aspire Dashboard
|
|
326
214
|
|
|
327
|
-
|
|
328
|
-
-
|
|
215
|
+
Visualiza traces de agents incluindo:
|
|
216
|
+
- Fluxo completo de conversas entre agents
|
|
329
217
|
- Tool call cycles (Model → Tool → Model)
|
|
330
|
-
- Token usage
|
|
331
|
-
- Error traces
|
|
332
|
-
|
|
333
|
-
```csharp
|
|
334
|
-
// AppHost/Program.cs
|
|
335
|
-
var redis = builder.AddAzureRedisEnterprise("cache");
|
|
336
|
-
var api = builder.AddProject<Projects.Api>().WithReference(redis);
|
|
337
|
-
```
|
|
218
|
+
- Token usage e latência por chamada
|
|
219
|
+
- Error traces e retry patterns
|
|
338
220
|
|
|
339
221
|
### What to Monitor
|
|
340
222
|
|
|
@@ -348,72 +230,46 @@ var api = builder.AddProject<Projects.Api>().WithReference(redis);
|
|
|
348
230
|
|
|
349
231
|
---
|
|
350
232
|
|
|
351
|
-
##
|
|
352
|
-
|
|
353
|
-
### Centralized via Middleware
|
|
354
|
-
|
|
355
|
-
```csharp
|
|
356
|
-
// Function calling middleware catches tool errors
|
|
357
|
-
async ValueTask<object?> ResilientToolMiddleware(
|
|
358
|
-
AIAgent agent,
|
|
359
|
-
FunctionInvocationContext context,
|
|
360
|
-
Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next,
|
|
361
|
-
CancellationToken cancellationToken)
|
|
362
|
-
{
|
|
363
|
-
try
|
|
364
|
-
{
|
|
365
|
-
return await next(context, cancellationToken);
|
|
366
|
-
}
|
|
367
|
-
catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
|
|
368
|
-
{
|
|
369
|
-
// Rate limit — return friendly message so agent can retry
|
|
370
|
-
return "Service is temporarily busy. Please try again in a moment.";
|
|
371
|
-
}
|
|
372
|
-
catch (TimeoutException)
|
|
373
|
-
{
|
|
374
|
-
return $"Tool '{context.Function.Name}' timed out. Try a simpler query.";
|
|
375
|
-
}
|
|
376
|
-
catch (Exception ex)
|
|
377
|
-
{
|
|
378
|
-
// Log and return error context to agent
|
|
379
|
-
return $"Error in {context.Function.Name}: {ex.Message}";
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
### HAX Framework Principles for Production
|
|
233
|
+
## Security Checklist (verifiable by morph-eval)
|
|
385
234
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
235
|
+
- [ ] API keys nunca em `appsettings.json` no repositório — bind de environment variables ou secret store
|
|
236
|
+
- [ ] Variáveis de provider (`OpenAI__ApiKey`, `Google__ApiKey`, `Anthropic__ApiKey`) em env vars / Docker secrets
|
|
237
|
+
- [ ] Input validation middleware registrado em agents públicos (PII detection, injection prevention)
|
|
238
|
+
- [ ] Output filtering / guardrails para conteúdo prejudicial
|
|
239
|
+
- [ ] Rate limiting middleware em agents expostos publicamente
|
|
240
|
+
- [ ] Endpoints A2A protegidos com autenticação
|
|
241
|
+
- [ ] Structured output usado para respostas — evita parsing de texto livre
|
|
242
|
+
- [ ] OpenTelemetry com `AgentOpenTelemetryConsts.DefaultSourceName` configurado
|
|
392
243
|
|
|
393
244
|
---
|
|
394
245
|
|
|
395
|
-
##
|
|
246
|
+
## Production Checklist (verifiable by morph-eval)
|
|
396
247
|
|
|
397
|
-
- [ ]
|
|
398
|
-
- [ ]
|
|
399
|
-
- [ ]
|
|
400
|
-
- [ ]
|
|
401
|
-
- [ ]
|
|
402
|
-
- [ ]
|
|
403
|
-
- [ ] A2A endpoints
|
|
248
|
+
- [ ] `Microsoft.Agents.AI` 1.0.* no `.csproj`; nenhum pacote `Experimental.*` ou SK
|
|
249
|
+
- [ ] Middleware registrado via `.AsBuilder().Use(...)` antes de `Build()`
|
|
250
|
+
- [ ] `ResilientToolMiddleware` (ou equivalente) em agents que chamam APIs externas
|
|
251
|
+
- [ ] Semantic cache configurado se o agent recebe queries repetitivas
|
|
252
|
+
- [ ] OpenTelemetry source = `AgentOpenTelemetryConsts.DefaultSourceName`
|
|
253
|
+
- [ ] Dados sensíveis de telemetry desabilitados em produção (`EnableSensitiveTelemetryData = false`)
|
|
254
|
+
- [ ] A2A endpoints com `MapA2A` protegidos por auth se expostos na internet
|
|
255
|
+
- [ ] MCP client `await using` para dispose correto do transporte
|
|
404
256
|
|
|
405
257
|
---
|
|
406
258
|
|
|
407
259
|
## References
|
|
408
260
|
|
|
261
|
+
- `ai-agents-setup` — pacotes, DI, quick start
|
|
262
|
+
- `ai-agents-sweet-spot` — decisão de arquitetura antes de middleware
|
|
263
|
+
- `ai-agents-providers-model-registry` — Model Registry para `_modelRegistry.GetChatClient(...)`
|
|
264
|
+
- `ai-agents-middleware-patterns` — **tratamento canônico** de middleware (código dos 3 níveis, telemetria, resilência, anti-hallucination)
|
|
265
|
+
- `ai-agents-mcp-tools` — agente MAF consumindo MCP servers externos
|
|
266
|
+
- `ai-agents-mcp-server` — projeto expondo capacidades como MCP server
|
|
267
|
+
- `ai-agents-rag-custom-pgvector` — implementação completa de busca semântica (referida em Caching)
|
|
409
268
|
- [Agent Middleware](https://learn.microsoft.com/agent-framework/user-guide/agents/agent-middleware)
|
|
410
269
|
- [A2A Integration](https://learn.microsoft.com/agent-framework/user-guide/hosting/agent-to-agent-integration)
|
|
411
270
|
- [Using MCP Tools](https://learn.microsoft.com/agent-framework/user-guide/model-context-protocol/using-mcp-tools)
|
|
412
271
|
- [MCP C# SDK](https://github.com/modelcontextprotocol/csharp-sdk)
|
|
413
|
-
- [Build MCP Server in C#](https://devblogs.microsoft.com/dotnet/build-a-model-context-protocol-mcp-server-in-csharp/)
|
|
414
|
-
- `setup.md` — Core setup
|
|
415
|
-
- `workflows.md` — Orchestration patterns
|
|
416
272
|
|
|
417
273
|
---
|
|
418
274
|
|
|
419
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
275
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/production.md v2.1 (2026-05-19)*
|