@polymorphism-tech/morph-spec 7.5.0 → 7.6.0
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 +2 -2
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/agents.json +1 -1
- package/framework/commands/morph-preflight.md +10 -5
- package/framework/rules/infrastructure-standards.md +4 -4
- package/framework/skills/core/create-umbraco-lp/SKILL.md +22 -2
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +84 -5
- package/framework/skills/core/morph-apply/SKILL.md +1 -1
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +1 -1
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +1 -1
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +80 -8
- package/framework/standards/ai-agents/durable-workflows-hitl.md +191 -0
- package/framework/standards/ai-agents/rag-custom-pgvector.md +246 -243
- package/framework/standards/ai-agents/setup.md +3 -0
- package/framework/standards/ai-agents/vector-data-extensions.md +170 -0
- package/framework/standards/ai-agents/workflows.md +190 -187
- package/framework/standards/infrastructure/docker/{easypanel-deploy.md → coolify-deploy.md} +49 -20
- package/framework/templates/README.md +7 -7
- package/framework/templates/REGISTRY.json +14 -14
- package/framework/templates/context/CONTEXT.md +3 -3
- package/framework/templates/docs/proposal.md +2 -2
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +1 -1
- package/framework/templates/infrastructure/docker/coolify.template.json +49 -0
- package/framework/templates/infrastructure/github/README.md +6 -6
- package/framework/templates/infrastructure/github/workflows/deploy-coolify.yml.hbs +33 -0
- package/package.json +1 -1
- package/framework/templates/infrastructure/docker/easypanel.template.json +0 -46
- package/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Microsoft.Extensions.VectorData & DataIngestion — Official Vector Store Abstractions
|
|
2
|
+
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 1 (on-keyword)
|
|
5
|
+
> **Keywords:** microsoft extensions vectordata, vectorstorecollection, vector store abstraction, data ingestion, ingestion pipeline, semantic kernel connectors exception, pgvector connector, vectorstorewriter
|
|
6
|
+
> **Read by Claude in:** plan (when choosing a RAG storage backend) + implement (when deciding whether to adopt VectorData over custom pgvector)
|
|
7
|
+
|
|
8
|
+
**Verified against:** Microsoft.Extensions.VectorData.Abstractions GA (`dotnet/extensions`, transferred from the Semantic Kernel repo) + Microsoft.Extensions.DataIngestion 10.0.1-preview.1.25571.5 + Microsoft.SemanticKernel.Connectors.PgVector 1.74.0-preview. Last-verified: 2026-07-06.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## O que é
|
|
13
|
+
|
|
14
|
+
`Microsoft.Extensions.VectorData.Abstractions` is the official, GA, provider-agnostic abstraction over vector stores — the vector-store equivalent of `IChatClient` for chat models. Core API:
|
|
15
|
+
|
|
16
|
+
```csharp
|
|
17
|
+
VectorStoreCollection<TKey, TRecord> collection = new SomeVectorStore<TKey, TRecord>(...);
|
|
18
|
+
|
|
19
|
+
await collection.CreateCollectionAsync();
|
|
20
|
+
await collection.UpsertAsync(record);
|
|
21
|
+
|
|
22
|
+
await foreach (var result in collection.SearchAsync(queryText, top: 5))
|
|
23
|
+
{
|
|
24
|
+
var record = result.Record;
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
A single `VectorStoreCollection<TKey, TRecord>` shape works identically whether the backing store is in-memory, SQLite, Postgres (pgvector), Qdrant, Azure AI Search, Cosmos DB, or SQL Server — switching backends is a constructor swap, not a rewrite.
|
|
29
|
+
|
|
30
|
+
`Microsoft.Extensions.DataIngestion` is a companion library (still **preview**) that provides the ETL building blocks around it: `IngestionDocumentReader` (Markdown/MarkItDown/Markdig), `IngestionChunker<T>` (header, section, `SemanticSimilarityChunker`), chunk/document enrichers (`SummaryEnricher`, `SentimentEnricher`, `KeywordEnricher`, `ImageAlternativeTextEnricher`), and `VectorStoreWriter<T>` — chained together via `IngestionPipeline<T>`.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## A pegadinha de nomenclatura (crítico — leia antes de tudo)
|
|
35
|
+
|
|
36
|
+
The concrete vector-store **connectors** — the packages that actually implement `VectorStoreCollection` against a real backend — ship under `Microsoft.SemanticKernel.Connectors.*` package names (`Microsoft.SemanticKernel.Connectors.PgVector`, `.Qdrant`, `.SqlServer`, `.CosmosNoSQL`, `.InMemory`, etc.), even though `Microsoft.Extensions.VectorData.Abstractions` itself has been transferred out of the Semantic Kernel repo into `dotnet/extensions` and is fully independent of SK orchestration.
|
|
37
|
+
|
|
38
|
+
Microsoft's own docs are explicit about this:
|
|
39
|
+
|
|
40
|
+
> "Despite the inclusion of 'SemanticKernel' in the package names, these providers have nothing to do with Semantic Kernel and are usable anywhere in .NET, including Agent Framework." — [Data ingestion - .NET | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/ai/conceptual/data-ingestion)
|
|
41
|
+
|
|
42
|
+
**Exceção explícita à regra "Forbidden" de `ai-agents-setup`:** the ban on `Microsoft.SemanticKernel.*` in `ai-agents-setup` §1/§7 targets the SK **orchestration** surface — `Kernel`, `KernelFunction`, `[KernelFunction]`, `ChatHistory`, `Kernel.InvokePromptAsync()`. It does **not** apply to `Microsoft.SemanticKernel.Connectors.*` packages when used purely as `Microsoft.Extensions.VectorData` backend connectors — those carry zero SK orchestration code. Never import the `Microsoft.SemanticKernel` core package itself; that remains forbidden.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Maturidade atual (verificado 2026-07-06)
|
|
47
|
+
|
|
48
|
+
| Package | Status |
|
|
49
|
+
|---------|--------|
|
|
50
|
+
| `Microsoft.Extensions.VectorData.Abstractions` | **GA** |
|
|
51
|
+
| `Microsoft.Extensions.AI` / `Microsoft.Extensions.AI.Abstractions` | **GA** |
|
|
52
|
+
| `Microsoft.SemanticKernel.Connectors.PgVector` (Postgres/pgvector connector) | **Prerelease** (1.74.0-preview, requires `--prerelease`) |
|
|
53
|
+
| `Microsoft.SemanticKernel.Connectors.InMemory` / other connectors | Verify current status via context7/NuGet before adding — connector GA timing lags the abstractions package |
|
|
54
|
+
| `Microsoft.Extensions.DataIngestion` | **Preview** (10.0.1-preview.1.25571.5) |
|
|
55
|
+
|
|
56
|
+
Preview packages are subject to breaking API changes before GA (see the May 2025 rename `PostgresVectorStoreRecordCollection` → `PostgresCollection` as precedent).
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Decision matrix — custom pgvector vs VectorData
|
|
61
|
+
|
|
62
|
+
| Situation | Use |
|
|
63
|
+
|-----------|-----|
|
|
64
|
+
| Default production RAG on Neon/Postgres (this framework's default stack) | **`ai-agents-rag-custom-pgvector`** — GA-quality, zero preview dependencies, framework-owned raw SQL, already the checklisted default |
|
|
65
|
+
| Project needs genuine portability across >1 vector backend (e.g., a client contract requires swapping Postgres for Qdrant or Azure AI Search later) | `Microsoft.Extensions.VectorData` with the relevant connector — document the choice in `decisions.md` |
|
|
66
|
+
| Prototyping, tests, or demos where an in-memory GA-quality store is enough | `Microsoft.Extensions.VectorData` + an in-memory/SQLite connector |
|
|
67
|
+
| Team explicitly accepts a preview dependency for the Postgres connector today | Allowed, but record the acceptance + a revisit-at-GA note in `decisions.md`; do not silently swap the default |
|
|
68
|
+
|
|
69
|
+
Do not migrate the existing `ai-agents-rag-custom-pgvector` implementation to the preview PgVector connector as a default — that would trade a working, GA-quality, framework-owned implementation for an unstable dependency, contradicting this framework's no-preview-by-default stance (see `ai-agents-setup` §1).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Exemplo mínimo (backend GA — sem depender de pacote preview)
|
|
74
|
+
|
|
75
|
+
```csharp
|
|
76
|
+
using Microsoft.Extensions.AI;
|
|
77
|
+
using Microsoft.Extensions.VectorData;
|
|
78
|
+
|
|
79
|
+
// embeddingGenerator wired via the project's Model Registry `embeddings` alias
|
|
80
|
+
// (see ai-agents-providers-model-registry) — any IEmbeddingGenerator works here.
|
|
81
|
+
IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator = /* from Model Registry */;
|
|
82
|
+
|
|
83
|
+
VectorStoreCollection<string, KnowledgeChunk> collection =
|
|
84
|
+
new SomeGaBackedVectorStore<string, KnowledgeChunk>(
|
|
85
|
+
connectionOptions,
|
|
86
|
+
"kb_chunks",
|
|
87
|
+
new VectorStoreCollectionOptions { EmbeddingGenerator = embeddingGenerator });
|
|
88
|
+
|
|
89
|
+
await collection.EnsureCollectionExistsAsync();
|
|
90
|
+
await collection.UpsertAsync(chunk);
|
|
91
|
+
|
|
92
|
+
await foreach (var result in collection.SearchAsync(question, top: 5))
|
|
93
|
+
{
|
|
94
|
+
Console.WriteLine(result.Record.Content);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public sealed record KnowledgeChunk
|
|
98
|
+
{
|
|
99
|
+
[VectorStoreKey] public required string Id { get; init; }
|
|
100
|
+
[VectorStoreData] public required string Content { get; init; }
|
|
101
|
+
[VectorStoreVector(1536)] public required ReadOnlyMemory<float> Embedding { get; init; }
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
> Replace `SomeGaBackedVectorStore` with the connector matching the chosen backend — verify its current package name and GA/preview status via context7 before adding it to a project, per the maturity table above.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Microsoft.Extensions.DataIngestion (preview) — pipeline pattern para adoção futura
|
|
110
|
+
|
|
111
|
+
Not adopted as default today (preview), but documented so a future migration is straightforward once it reaches GA:
|
|
112
|
+
|
|
113
|
+
```csharp
|
|
114
|
+
IngestionDocumentReader reader = new MarkdownReader();
|
|
115
|
+
|
|
116
|
+
IngestionChunker<string> chunker = new SemanticSimilarityChunker(
|
|
117
|
+
embeddingGenerator,
|
|
118
|
+
new IngestionChunkerOptions(TiktokenTokenizer.CreateForModel("gpt-5")));
|
|
119
|
+
|
|
120
|
+
using VectorStoreWriter<string> writer = new(vectorStore, dimensionCount: 1536);
|
|
121
|
+
|
|
122
|
+
using IngestionPipeline<string> pipeline = new(reader, chunker, writer)
|
|
123
|
+
{
|
|
124
|
+
ChunkProcessors = { summaryEnricher },
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
await foreach (var result in pipeline.ProcessAsync(new DirectoryInfo("./knowledge-base"), searchPattern: "*.md"))
|
|
128
|
+
{
|
|
129
|
+
Console.WriteLine($"Completed '{result.DocumentId}'. Succeeded: {result.Succeeded}.");
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
This maps conceptually onto the existing custom pattern: `IngestionDocumentReader` ≈ the project's document loading step, `IngestionChunker<T>` ≈ the strategies in `data-vector-search-rag-chunking`, `VectorStoreWriter<T>` ≈ `EmbeddingService` + the `kb_embeddings` insert in `ai-agents-rag-custom-pgvector`. `IngestionPipeline<T>.ProcessAsync` returns `IAsyncEnumerable<IngestionResult>` — a single document failure does not abort the whole run (partial success by design).
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Anti-patterns
|
|
138
|
+
|
|
139
|
+
| Anti-pattern | Why it's wrong | Right way |
|
|
140
|
+
|--------------|----------------|-----------|
|
|
141
|
+
| Refusing to add `Microsoft.SemanticKernel.Connectors.PgVector` because of the "Forbidden: Microsoft.SemanticKernel.*" rule | The rule targets SK orchestration, not VectorData connectors — see the naming-trap section above | Read this standard's exception note before treating any `Microsoft.SemanticKernel.Connectors.*` package as forbidden |
|
|
142
|
+
| Migrating the working custom pgvector implementation to VectorData "because it's official" | The Postgres connector is still prerelease — trades a stable implementation for an unstable one with no functional gain by default | Keep `ai-agents-rag-custom-pgvector` as the default; adopt VectorData only per the decision matrix |
|
|
143
|
+
| Treating `Microsoft.Extensions.DataIngestion` as production-ready | It ships as `10.0.1-preview.1` — breaking changes are expected before GA | Track it for future adoption; do not wire it into a shipped feature today |
|
|
144
|
+
| Importing `Microsoft.SemanticKernel` (the core orchestration package) to "just get the vector store types" | Pulls in the full SK orchestration surface this framework has deliberately moved away from | Import only `Microsoft.Extensions.VectorData.Abstractions` + the specific `*.Connectors.*` package needed |
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Checklist (verifiable by morph-eval)
|
|
149
|
+
|
|
150
|
+
- [ ] If `Microsoft.SemanticKernel.Connectors.*` appears in a `.csproj`, it is used only for `VectorStoreCollection`/`VectorStore` types — no `Kernel`, `KernelFunction`, or `ChatHistory` usage anywhere in the project.
|
|
151
|
+
- [ ] No plain `Microsoft.SemanticKernel` (core) package reference.
|
|
152
|
+
- [ ] If VectorData was chosen over custom pgvector, the reason is recorded in `decisions.md` per the decision matrix.
|
|
153
|
+
- [ ] If a preview package (`Microsoft.SemanticKernel.Connectors.*` or `Microsoft.Extensions.DataIngestion`) was adopted, `decisions.md` records the preview-acceptance and a revisit-at-GA note.
|
|
154
|
+
- [ ] Embedding model/dimensions consistent between the `VectorStoreVector(N)` attribute and the chosen embedding model.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## References
|
|
159
|
+
|
|
160
|
+
- `ai-agents-rag-custom-pgvector` — the default, GA-quality custom RAG implementation this standard complements
|
|
161
|
+
- `ai-agents-setup` — the `Microsoft.SemanticKernel.*` "Forbidden" rule this standard carves an exception into
|
|
162
|
+
- `ai-agents-providers-model-registry` — `embeddings` alias, `IEmbeddingGenerator` wiring
|
|
163
|
+
- `data-vector-search-rag-chunking` — chunk strategies (conceptual counterpart to `IngestionChunker<T>`)
|
|
164
|
+
- Data ingestion - .NET | Microsoft Learn: https://learn.microsoft.com/en-us/dotnet/ai/conceptual/data-ingestion
|
|
165
|
+
- AI and Vector Data Extensions GA announcement: https://devblogs.microsoft.com/dotnet/ai-vector-data-dotnet-extensions-ga/
|
|
166
|
+
- Introducing Data Ingestion Building Blocks (Preview): https://devblogs.microsoft.com/dotnet/introducing-data-ingestion-building-blocks-preview/
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/vector-data-extensions.md v1.0 (2026-07-06)*
|
|
@@ -1,187 +1,190 @@
|
|
|
1
|
-
# Microsoft Agent Framework — Workflow Orchestration
|
|
2
|
-
|
|
3
|
-
> **Scope:** stacks=["dotnet"]
|
|
4
|
-
> **Layer:** 1 (on-keyword)
|
|
5
|
-
> **Keywords:** workflow, orchestration, fan-in, fan-out, multi-agent workflow, sequential workflow
|
|
6
|
-
> **Read by Claude in:** plan (only when a genuine fan-in/out or long-running need appears)
|
|
7
|
-
|
|
8
|
-
**Verified against:** MAF 1.0 GA. Last-verified: 2026-05-19.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Quando NÃO usar um Workflow
|
|
13
|
-
|
|
14
|
-
Leia `ai-agents-sweet-spot` antes de continuar. A regra:
|
|
15
|
-
|
|
16
|
-
> "Tudo que Workflows fazem, código C# normal faz com menos complexidade."
|
|
17
|
-
> — pesquisa sweet-spot (2026-05-18)
|
|
18
|
-
|
|
19
|
-
Checklist de desqualificação — se qualquer item for verdadeiro, **não use Workflow**:
|
|
20
|
-
|
|
21
|
-
- [ ] A feature tem **um tópico + uma decisão** → single agent com tools resolve
|
|
22
|
-
- [ ] O fan-in pode ser escrito como `foreach` + `LINQ Aggregate` sobre os resultados → escreva o `foreach`
|
|
23
|
-
- [ ] Você quer "dividir responsabilidade" entre 2 agents → use **Agent-as-Tool** (ver `ai-agents-multi-agent-patterns` — Onda 2)
|
|
24
|
-
- [ ] O workflow seria Sequential de 2 etapas → é só `await agent.RunAsync(await step1.RunAsync(input))`
|
|
25
|
-
|
|
26
|
-
Workflows adicionam: classes extras, configuração de edges, streaming de eventos, coordenação de supersteps. Adicione esse custo somente quando os critérios abaixo se aplicarem.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Quando um Workflow É justificado
|
|
31
|
-
|
|
32
|
-
| Critério | Exemplo realista |
|
|
33
|
-
|----------|------------------|
|
|
34
|
-
| **Fan-in genuíno sobre N inputs** | Relatório mensal que agrega análises de N documentos em paralelo |
|
|
35
|
-
| **Fan-out para > 2 agents especializados independentes** | Code review: security + perf + readability ao mesmo tempo |
|
|
36
|
-
| **Long-running com human-in-the-loop (HITL)** | Fluxo de aprovação onde um humano intervém entre etapas |
|
|
37
|
-
|
|
38
|
-
Se sua feature não se encaixa nesses critérios, volte ao single agent.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
using Microsoft.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
builder.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
builder.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
builder.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
await
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
- `
|
|
130
|
-
-
|
|
131
|
-
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
|
142
|
-
|
|
143
|
-
| **
|
|
144
|
-
| **
|
|
145
|
-
| **
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
|
157
|
-
|
|
158
|
-
| `InProcessExecution.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
- [ ] `
|
|
169
|
-
- [ ]
|
|
170
|
-
- [ ] `
|
|
171
|
-
- [ ]
|
|
172
|
-
- [ ]
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
- `ai-agents-
|
|
181
|
-
- `ai-agents-
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
1
|
+
# Microsoft Agent Framework — Workflow Orchestration
|
|
2
|
+
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 1 (on-keyword)
|
|
5
|
+
> **Keywords:** workflow, orchestration, fan-in, fan-out, multi-agent workflow, sequential workflow
|
|
6
|
+
> **Read by Claude in:** plan (only when a genuine fan-in/out or long-running need appears)
|
|
7
|
+
|
|
8
|
+
**Verified against:** MAF 1.0 GA. Last-verified: 2026-05-19.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Quando NÃO usar um Workflow
|
|
13
|
+
|
|
14
|
+
Leia `ai-agents-sweet-spot` antes de continuar. A regra:
|
|
15
|
+
|
|
16
|
+
> "Tudo que Workflows fazem, código C# normal faz com menos complexidade."
|
|
17
|
+
> — pesquisa sweet-spot (2026-05-18)
|
|
18
|
+
|
|
19
|
+
Checklist de desqualificação — se qualquer item for verdadeiro, **não use Workflow**:
|
|
20
|
+
|
|
21
|
+
- [ ] A feature tem **um tópico + uma decisão** → single agent com tools resolve
|
|
22
|
+
- [ ] O fan-in pode ser escrito como `foreach` + `LINQ Aggregate` sobre os resultados → escreva o `foreach`
|
|
23
|
+
- [ ] Você quer "dividir responsabilidade" entre 2 agents → use **Agent-as-Tool** (ver `ai-agents-multi-agent-patterns` — Onda 2)
|
|
24
|
+
- [ ] O workflow seria Sequential de 2 etapas → é só `await agent.RunAsync(await step1.RunAsync(input))`
|
|
25
|
+
|
|
26
|
+
Workflows adicionam: classes extras, configuração de edges, streaming de eventos, coordenação de supersteps. Adicione esse custo somente quando os critérios abaixo se aplicarem.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quando um Workflow É justificado
|
|
31
|
+
|
|
32
|
+
| Critério | Exemplo realista |
|
|
33
|
+
|----------|------------------|
|
|
34
|
+
| **Fan-in genuíno sobre N inputs** | Relatório mensal que agrega análises de N documentos em paralelo |
|
|
35
|
+
| **Fan-out para > 2 agents especializados independentes** | Code review: security + perf + readability ao mesmo tempo |
|
|
36
|
+
| **Long-running com human-in-the-loop (HITL)** | Fluxo de aprovação onde um humano intervém entre etapas |
|
|
37
|
+
|
|
38
|
+
Se sua feature não se encaixa nesses critérios, volte ao single agent.
|
|
39
|
+
|
|
40
|
+
Para o critério de HITL/long-running acima, a implementação (`RequestPort`, `CheckpointManager`, resume após restart) está em `ai-agents-durable-workflows-hitl` — leia esse standard antes de escrever o código de aprovação humana ou de checkpoint.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Packages
|
|
45
|
+
|
|
46
|
+
Workflow APIs (`AgentWorkflowBuilder`, `WorkflowBuilder`, `InProcessExecution`) estão no pacote GA principal:
|
|
47
|
+
|
|
48
|
+
```xml
|
|
49
|
+
<PackageReference Include="Microsoft.Agents.AI" Version="1.0.*" />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Para DI helpers (`AddAIAgent`):
|
|
53
|
+
|
|
54
|
+
```xml
|
|
55
|
+
<PackageReference Include="Microsoft.Agents.AI.Hosting" Version="1.0.*" />
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
> Sem pacotes "preview" separados. Sem `Microsoft.Extensions.AI 9.x`. As APIs de Workflow são parte do `Microsoft.Agents.AI` 1.0 GA.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Exemplo canônico — Fan-In Concurrent
|
|
63
|
+
|
|
64
|
+
Caso realista: analisar o mesmo documento com 3 agents especializados em paralelo, depois agregar.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
[Input] ──┬→ [SecurityAnalyst] ──┐
|
|
68
|
+
├→ [PerfAnalyst] ──┤→ [Aggregator]
|
|
69
|
+
└→ [QualityAnalyst] ──┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```csharp
|
|
73
|
+
using Microsoft.Agents.AI;
|
|
74
|
+
using Microsoft.Agents.AI.Workflows;
|
|
75
|
+
using Microsoft.Extensions.AI;
|
|
76
|
+
|
|
77
|
+
// --- 1. Agents (via Model Registry — nunca hardcode o modelo) ---
|
|
78
|
+
IChatClient chatClient = _modelRegistry.GetChatClient("text-default");
|
|
79
|
+
|
|
80
|
+
AIAgent securityAnalyst = chatClient.AsAIAgent(
|
|
81
|
+
instructions: "Analyze code for security vulnerabilities. Be concise.",
|
|
82
|
+
name: "SecurityAnalyst");
|
|
83
|
+
|
|
84
|
+
AIAgent perfAnalyst = chatClient.AsAIAgent(
|
|
85
|
+
instructions: "Analyze code for performance bottlenecks. Be concise.",
|
|
86
|
+
name: "PerfAnalyst");
|
|
87
|
+
|
|
88
|
+
AIAgent qualityAnalyst = chatClient.AsAIAgent(
|
|
89
|
+
instructions: "Analyze code for readability and maintainability. Be concise.",
|
|
90
|
+
name: "QualityAnalyst");
|
|
91
|
+
|
|
92
|
+
AIAgent aggregator = chatClient.AsAIAgent(
|
|
93
|
+
instructions: "You receive multiple analysis reports. Produce a unified summary with key findings.",
|
|
94
|
+
name: "Aggregator");
|
|
95
|
+
|
|
96
|
+
// --- 2. Build fan-out / fan-in workflow ---
|
|
97
|
+
WorkflowBuilder builder = new(securityAnalyst);
|
|
98
|
+
builder.AddEdge(securityAnalyst, aggregator);
|
|
99
|
+
|
|
100
|
+
builder.AddInputEdge(perfAnalyst); // also receives the original input
|
|
101
|
+
builder.AddEdge(perfAnalyst, aggregator);
|
|
102
|
+
|
|
103
|
+
builder.AddInputEdge(qualityAnalyst);
|
|
104
|
+
builder.AddEdge(qualityAnalyst, aggregator);
|
|
105
|
+
|
|
106
|
+
builder.WithOutputFrom(aggregator);
|
|
107
|
+
Workflow workflow = builder.Build();
|
|
108
|
+
|
|
109
|
+
// --- 3. Run with streaming events ---
|
|
110
|
+
string codeSnippet = /* input from request */;
|
|
111
|
+
await using StreamingRun run =
|
|
112
|
+
await InProcessExecution.RunStreamingAsync(workflow, codeSnippet);
|
|
113
|
+
|
|
114
|
+
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
|
|
115
|
+
{
|
|
116
|
+
switch (evt)
|
|
117
|
+
{
|
|
118
|
+
case AgentResponseUpdateEvent update:
|
|
119
|
+
Console.WriteLine($"[{update.Update.AuthorName}] {update.Update.Text}");
|
|
120
|
+
break;
|
|
121
|
+
case WorkflowErrorEvent error:
|
|
122
|
+
Console.Error.WriteLine($"Workflow error: {error.Exception?.Message}");
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Key points:**
|
|
129
|
+
- `AddInputEdge(agent)` — agent recebe o input original (fan-out)
|
|
130
|
+
- `AddEdge(from, to)` — conecta um executor ao próximo
|
|
131
|
+
- `WithOutputFrom(aggregator)` — define quem produz o output final
|
|
132
|
+
- O Aggregator só executa após todos os analysts completarem (superstep boundary)
|
|
133
|
+
- Agents criados via Model Registry alias — não hardcode modelo ou provider
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Outros padrões — tabela de referência rápida
|
|
138
|
+
|
|
139
|
+
Use esta tabela para decidir qual padrão pesquisar. Não escreva código de todos aqui.
|
|
140
|
+
|
|
141
|
+
| Padrão | Topologia | Quando usar |
|
|
142
|
+
|--------|-----------|-------------|
|
|
143
|
+
| **Sequential** | Cadeia linear | Pipeline simples onde cada etapa depende da anterior. Muitas vezes substituível por chamadas encadeadas. |
|
|
144
|
+
| **Handoff** | Mesh dinâmico | Roteamento dinâmico — agents passam controle conforme o contexto. Ver `ai-agents-multi-agent-patterns` (Onda 2). |
|
|
145
|
+
| **GroupChat** | Estrela (manager) | Refinamento iterativo entre agents com rodadas fixas. `AgentWorkflowBuilder.CreateGroupChatBuilderWith(...)`. |
|
|
146
|
+
| **Magentic** | Estrela (planner LLM) | Variante de GroupChat onde o manager é um LLM que decide dinamicamente quem age. |
|
|
147
|
+
| **Agent-as-Tool** | Ferramental | **Não é um Workflow** — o agent chama outro como tool via `AIFunctionFactory`. Opção mais simples; cobre 80% dos casos multi-agent. Ver `ai-agents-multi-agent-patterns` (Onda 2). |
|
|
148
|
+
|
|
149
|
+
Para Sequential simples, `AgentWorkflowBuilder.BuildSequential(agent1, agent2)` é suficiente.
|
|
150
|
+
Para Handoff, `AgentWorkflowBuilder.CreateHandoffBuilderWith(entryAgent)` + `.WithHandoffs(...)`.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Executando um Workflow (resumo da API)
|
|
155
|
+
|
|
156
|
+
| Método | Retorno | Quando usar |
|
|
157
|
+
|--------|---------|-------------|
|
|
158
|
+
| `InProcessExecution.RunStreamingAsync(workflow, input)` | `StreamingRun` | Input conhecido de antemão, streama eventos |
|
|
159
|
+
| `InProcessExecution.OpenStreamingAsync(workflow)` | `StreamingRun` | Input enviado depois via `TrySendMessageAsync` (ex: chat interativo) |
|
|
160
|
+
| `InProcessExecution.RunAsync(workflow, input)` | `Run` | Sem streaming, acumula todos os eventos |
|
|
161
|
+
|
|
162
|
+
Sempre use `await using` no `StreamingRun` / `Run` — é `IAsyncDisposable`.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Checklist (verifiable by morph-eval)
|
|
167
|
+
|
|
168
|
+
- [ ] Foi verificado que um `foreach` ou single agent não resolve o problema?
|
|
169
|
+
- [ ] O critério de fan-in/out genuíno ou HITL está documentado em `decisions.md`?
|
|
170
|
+
- [ ] `Microsoft.Agents.AI` 1.0.* presente no `.csproj` (sem pacotes preview separados)?
|
|
171
|
+
- [ ] Agents referenciando alias do Model Registry (não model strings hardcoded)?
|
|
172
|
+
- [ ] `await using` no `StreamingRun` / `Run`?
|
|
173
|
+
- [ ] `WorkflowErrorEvent` tratado no loop de eventos?
|
|
174
|
+
- [ ] OpenTelemetry habilitado para rastrear chamadas inter-agent?
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## References
|
|
179
|
+
|
|
180
|
+
- `ai-agents-setup` — pacotes, `ChatClientAgent`, tools
|
|
181
|
+
- `ai-agents-sweet-spot` — decisão single agent vs workflow
|
|
182
|
+
- `ai-agents-multi-agent-patterns` (Onda 2) — Agent-as-Tool, Handoff patterns
|
|
183
|
+
- `ai-agents-providers-model-registry` — Model Registry para alias de provider
|
|
184
|
+
- `ai-agents-durable-workflows-hitl` — `RequestPort`, `CheckpointManager`, resume após restart
|
|
185
|
+
- MAF Workflows docs: https://learn.microsoft.com/agent-framework/
|
|
186
|
+
- MAF Workflow samples: https://github.com/microsoft/agent-framework/tree/main/dotnet/samples/03-workflows
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/workflows.md v2.0 (2026-05-19)*
|