一键导入
koan-bootstrap
Auto-registration via KoanAutoRegistrar, minimal Program.cs, "Reference = Intent" pattern
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Auto-registration via KoanAutoRegistrar, minimal Program.cs, "Reference = Intent" pattern
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Chat endpoints, embeddings, RAG workflows, vector search
Aggregate boundaries, relationships, lifecycle hooks, value objects
Entity<T> patterns, GUID v7 auto-generation, static methods vs manual repositories
Transparent L1/L2 caching for Entity<T>, [Cacheable] attribute, cross-node coherence, per-request opt-out
Run a mandatory pre-implementation exploration workflow before writing production code in Koan (.NET/C#). Use when a task requires code changes and Codex must first map concerns/layers, read relevant files and docs, check existing constants and types, identify the closest existing pattern, plan exact code placement, and confirm architectural guardrails.
EntityController<T>, custom routes, payload transformers, auth policies
基于 SOC 职业分类
| name | koan-bootstrap |
| description | Auto-registration via KoanAutoRegistrar, minimal Program.cs, "Reference = Intent" pattern |
services.AddKoan() is the ONLY line needed in Program.cs. The framework discovers and registers everything through auto-registration. No manual service registration. No manual configuration. Just add package references and everything wires up automatically.
Adding a package reference automatically enables functionality:
<!-- Add MongoDB connector -->
<PackageReference Include="Koan.Data.Connector.Mongo" Version="0.6.3" />
<!-- Now MongoDB is discovered, configured, and available automatically -->
<!-- Add AI capabilities -->
<PackageReference Include="Koan.AI" Version="0.6.3" />
<!-- Now AI services are auto-registered and ready to use -->
No manual registration in Program.cs. The framework handles everything.
using Koan.Core;
var builder = WebApplication.CreateBuilder(args);
// ONE LINE - framework handles all dependencies
builder.Services.AddKoan();
var app = builder.Build();
// Middleware auto-configured by framework
app.Run();
That's it. 8 lines total. No manual service registration. No manual middleware configuration. The framework discovers:
Invoke this skill when:
KoanAutoRegistrar is how you register application-specific services (not framework services - those auto-register). Create one per application/module.
Create KoanAutoRegistrar when you have:
// File: /Initialization/KoanAutoRegistrar.cs
using Koan.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace MyApp.Initialization;
public sealed class KoanAutoRegistrar : IKoanAutoRegistrar
{
public string ModuleName => "MyApp";
public string? ModuleVersion =>
typeof(KoanAutoRegistrar).Assembly.GetName().Version?.ToString();
public void Initialize(IServiceCollection services)
{
// Register application-specific services here
services.AddScoped<ITodoService, TodoService>();
services.AddScoped<IEmailService, EmailService>();
services.AddSingleton<ICacheService, RedisCacheService>();
services.AddHostedService<BackgroundCleanupWorker>();
}
public void Describe(ProvenanceModuleWriter module, IConfiguration cfg, IHostEnvironment env)
{
module.Describe(ModuleVersion, "Application services");
module.AddNote("Application services registered");
module.AddNote($"Environment: {env.EnvironmentName}");
}
}
As of ARCH-0086, extend KoanModule instead of implementing IKoanAutoRegistrar directly. A KoanModule
is an IKoanAutoRegistrar (discovered + ordered identically), but gives one self-describing surface plus a
real, ordered startup lifecycle:
// File: /Initialization/MyAppModule.cs
using Koan.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace MyApp.Initialization;
public sealed class MyAppModule : KoanModule
{
public override string Id => "MyApp";
public override void Register(IServiceCollection services) // was Initialize
{
services.AddScoped<ITodoService, TodoService>();
services.AddSingleton<ICacheService, RedisCacheService>();
}
public override Task Start(IServiceProvider sp, CancellationToken ct) // one-time, ordered startup
{
// Replaces the "register a bootstrap IHostedService in Initialize" idiom.
// DI is available; ordered against other modules by [Before]/[After].
return Task.CompletedTask;
}
public override void Report(ProvenanceModuleWriter module, IConfiguration cfg, IHostEnvironment env) // was Describe
=> module.Describe(Version);
}
Register ⇐ Initialize, Report ⇐ Describe, plus a new Start for one-time ordered startup work.IKoanBackgroundService family. Code that registers services
or must run before the container is built belongs in Register, not Start.IKoanAutoRegistrar above still works via the bridge — migration is opportunistic.[KoanDiscoverable]Don't hand-roll an AppDomain assembly scan to find plug-ins. Mark the interface [KoanDiscoverable] and
read implementers from the registry:
[KoanDiscoverable]
public interface IMyPlugin { }
// inside Register():
foreach (var t in KoanRegistry.GetDiscoveredImplementors(typeof(IMyPlugin)))
services.TryAddEnumerable(ServiceDescriptor.Scoped(typeof(IMyPlugin), t));
The source generator (build time) + RegistryManifestLoader (runtime) populate KoanRegistry, so discovery
is fast and never misses lazily-loaded assemblies. (Used by IKoanAuthEventContributor / IKoanAuthFlowHandler.)
The framework automatically discovers IKoanAutoRegistrar implementations:
IKoanAutoRegistrarInitialize()Describe() to populate boot reportYou don't call it. The framework finds and executes it automatically.
var builder = WebApplication.CreateBuilder(args);
// ❌ DON'T DO THIS - breaks auto-registration pattern
builder.Services.AddScoped<ITodoRepository, TodoRepository>();
builder.Services.AddDbContext<MyDbContext>();
builder.Services.AddScoped<ITodoService, TodoService>();
builder.Services.AddKoan(); // Too late, order matters
Why wrong?
// Program.cs stays minimal
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKoan();
var app = builder.Build();
app.Run();
// Application services in KoanAutoRegistrar
public sealed class KoanAutoRegistrar : IKoanAutoRegistrar
{
public void Initialize(IServiceCollection services)
{
services.AddScoped<ITodoService, TodoService>();
}
}
// ❌ DON'T DO THIS
builder.Services.AddKoan();
builder.Services.AddKoanData(); // Redundant
builder.Services.AddKoanWeb(); // Redundant
builder.Services.AddKoanAI(); // Redundant
Why wrong? AddKoan() already discovers and registers ALL Koan modules automatically.
builder.Services.AddKoan(); // Discovers and registers everything
// In Development environment
if (KoanEnv.IsDevelopment)
{
var logger = app.Services.GetRequiredService<ILogger<Program>>();
KoanEnv.DumpSnapshot(logger);
}
Output shows:
[INFO] Koan:discover postgresql: server=localhost;database=myapp... OK
[INFO] Koan:modules data→postgresql
[INFO] Koan:modules web→controllers
[INFO] Koan:modules ai→openai
[INFO] Koan:modules MyApp v1.0.0
The Describe method receives a ProvenanceModuleWriter — a fluent writer with the following API:
| Method | Purpose |
|---|---|
module.Describe(version, description) | Set module version and description text |
module.AddNote(message) | Append a plain-text note (extension method) |
module.SetStatus(status, detail) | Set operational status ("ok", "degraded", "error") |
module.ClearStatus() | Reset status to default |
module.SetSetting(key, builder) | Add a structured setting entry with source tracking |
module.SetNote(key, builder) | Add a structured note entry |
module.AddTool(name, route, description) | Register an exposed tool/endpoint in the report |
public void Describe(ProvenanceModuleWriter module, IConfiguration cfg, IHostEnvironment env)
{
// Set version and description
module.Describe(ModuleVersion, "Application services");
// Add informational notes
module.AddNote("Services registered: TodoService, EmailService");
module.AddNote($"Data source: {cfg["Koan:Data:Sources:Default:Adapter"]}");
// Add a structured setting with source information
module.SetSetting("Environment", b => b.Value(env.EnvironmentName));
// Report degraded status when optional config is missing
if (!cfg.GetSection("Email:Smtp").Exists())
{
module.SetStatus("degraded", "Email configuration missing — notifications disabled");
}
}
Note: There is no
AddWarning()orAddModule(). UseSetStatus("degraded", detail)to signal non-fatal configuration issues. The module identity is set viamodule.Describe(version, description).
Use KoanEnv for environment-aware logic:
public void Initialize(IServiceCollection services)
{
// Development-only services
if (KoanEnv.IsDevelopment)
{
services.AddScoped<ISeedService, DevelopmentSeedService>();
}
// Production-only services
if (KoanEnv.IsProduction)
{
services.AddSingleton<IEmailService, SendGridEmailService>();
}
// Container-specific configuration
if (KoanEnv.InContainer)
{
services.AddSingleton<IHealthCheckService, ContainerHealthCheck>();
}
// Dangerous operations gated by flag
if (KoanEnv.AllowMagicInProduction)
{
services.AddScoped<IAdminService, AdminService>();
}
}
Use framework configuration helpers:
public void Initialize(IServiceCollection services)
{
var sp = services.BuildServiceProvider();
var cfg = sp.GetRequiredService<IConfiguration>();
// Read with fallback chain: setting → env var → default
var apiKey = Configuration.Read(
cfg,
defaultValue: "dev-key",
"App:ApiKey", // Config path
"APP_API_KEY" // Environment variable
);
services.AddSingleton(new ExternalApiClient(apiKey));
}
System.InvalidOperationException: Unable to resolve service for type 'ITodoService'
Cause: KoanAutoRegistrar not discovered or not registering service
Solution:
/Initialization/KoanAutoRegistrar.csIKoanAutoRegistrarpublic and not internal[ERROR] Koan:discover mongodb: connection failed
[INFO] Koan:modules data→json (fallback)
Cause: Provider package referenced but connection failed
Solution:
appsettings.json[WARNING] Koan:modules MyModule not discovered
Cause: Assembly not referenced or not loaded at startup
Solution:
<ProjectReference> or <PackageReference> existsvar assembly = Assembly.Load("MyModule");
templates/Program.cs.template - Minimal Program.cstemplates/KoanAutoRegistrar.cs.template - Complete registrar templatetemplates/KoanAutoRegistrar-with-options.cs.template - Registrar with configuration optionstemplates/appsettings.json.template - Koan configuration structuredocs/guides/deep-dive/bootstrap-lifecycle.mddocs/guides/troubleshooting/bootstrap-failures.mddocs/guides/deep-dive/auto-provisioning-system.mdsamples/S0.ConsoleJsonRepo/Program.cs (Minimal 20-line bootstrap)samples/S1.Web/Program.cs (Web bootstrap with lifecycle)Modules load in this order:
KoanAutoRegistrarDependencies are resolved automatically. You never need to specify order manually.
public void Initialize(IServiceCollection services)
{
var sp = services.BuildServiceProvider();
var cfg = sp.GetRequiredService<IConfiguration>();
// Feature flags
if (cfg.GetValue<bool>("Features:EmailNotifications"))
{
services.AddScoped<INotificationService, EmailNotificationService>();
}
else
{
services.AddScoped<INotificationService, NoOpNotificationService>();
}
// Provider-specific services
var dataProvider = cfg["Koan:Data:Sources:Default:Adapter"];
if (dataProvider == "mongodb")
{
services.AddSingleton<IMongoIndexManager, MongoIndexManager>();
}
}
Bootstrap patterns are mandatory in Koan Framework:
AddKoan() for all framework registrationKoanAutoRegistrar for application servicesAddDbContext, AddControllers, etc. manuallyThe framework handles everything through auto-discovery.