Summary
Build a C# source generator that compiles .prompty files into typed C# classes at build time. This replaces the need for runtime YAML parsing and file loading entirely.
Motivation
Currently, using a .prompty file in C# requires:
var agent = PromptyLoader.Load("path/to/chat.prompty");
var result = await Pipeline.InvokeAgentAsync(agent, inputs: new Dictionary<string, object?> {
["firstName"] = "Jane",
["question"] = "What is the meaning of life?",
});
With a source generator, the same .prompty file would produce a typed class at build time:
// Auto-generated from chat.prompty
var result = await ChatPrompty.RunAsync(firstName: "Jane", question: "What is the meaning of life?");
This gives you IntelliSense, compile-time validation, and no runtime YAML parsing — the same pattern as Razor pages, gRPC stubs, and protobuf.
Scope
Phase 1: Basic source generator
- Read
.prompty files from the project (MSBuild AdditionalFiles or a custom <Prompty> item group)
- Parse frontmatter at build time
- Emit a typed class per
.prompty file with:
- Strongly-typed input parameters from
inputSchema.properties
- Typed return value from
outputSchema (or string default)
- Static
RunAsync() / PrepareAsync() methods that delegate to the runtime pipeline
- The raw prompty content embedded as a string constant (no file I/O at runtime)
Phase 2: Tracing attributes
- Auto-generate OpenTelemetry
Activity spans from prompty metadata (name, description, model info)
- Emit
[ActivitySource] registration and span creation in the generated code
- Map prompty execution stages (render → parse → execute → process) to child spans
- Include prompty metadata as span attributes (model ID, provider, template kind)
Phase 3: Validation and diagnostics
- Emit compiler warnings/errors for:
- Invalid YAML frontmatter
- Missing required
inputSchema properties without defaults
- Unknown
model.provider values
${env:VAR} references (informational: "resolved at runtime")
- Roslyn analyzer companion for IDE squiggles
Design Questions
- Should the generated class name come from the
name field or the filename?
- Should we generate interfaces for testability (e.g.,
IChatPrompty)?
- How should
${env:VAR} and ${file:path} references work in codegen context? (They're inherently runtime — the generator can embed them as deferred resolution)
- NuGet packaging:
Prompty.SourceGenerator as a separate analyzer package?
Supersedes
References
Summary
Build a C# source generator that compiles
.promptyfiles into typed C# classes at build time. This replaces the need for runtime YAML parsing and file loading entirely.Motivation
Currently, using a
.promptyfile in C# requires:With a source generator, the same
.promptyfile would produce a typed class at build time:This gives you IntelliSense, compile-time validation, and no runtime YAML parsing — the same pattern as Razor pages, gRPC stubs, and protobuf.
Scope
Phase 1: Basic source generator
.promptyfiles from the project (MSBuildAdditionalFilesor a custom<Prompty>item group).promptyfile with:inputSchema.propertiesoutputSchema(orstringdefault)RunAsync()/PrepareAsync()methods that delegate to the runtime pipelinePhase 2: Tracing attributes
Activityspans from prompty metadata (name,description, model info)[ActivitySource]registration and span creation in the generated codePhase 3: Validation and diagnostics
inputSchemaproperties without defaultsmodel.providervalues${env:VAR}references (informational: "resolved at runtime")Design Questions
namefield or the filename?IChatPrompty)?${env:VAR}and${file:path}references work in codegen context? (They're inherently runtime — the generator can embed them as deferred resolution)Prompty.SourceGeneratoras a separate analyzer package?Supersedes
Load(Stream)) — codegen eliminates the need for stream-based loadingReferences