How to Create Custom Prompt Plugins for OpenDeepWiki AI Code Analysis
To create custom prompt plugins for OpenDeepWiki AI code analysis, implement the IPromptPlugin interface and register your implementation in the dependency injection container to replace the default FilePromptPlugin.
OpenDeepWiki is an open-source AI-powered code analysis tool that generates documentation by feeding source code into Large Language Models (LLMs). The system uses a pluggable prompt architecture that allows developers to create custom prompt plugins for OpenDeepWiki AI code analysis, enabling prompts to be loaded from databases, APIs, or embedded resources instead of the default file system.
Understanding the IPromptPlugin Interface
Core Interface Definition
The prompt plugin system centers on a single abstraction located at src/OpenDeepWiki/Services/Prompts/IPromptPlugin.cs. This interface defines the contract for loading and processing prompt templates:
public interface IPromptPlugin
{
Task<string> LoadPromptAsync(
string promptName,
Dictionary<string, string>? variables = null,
CancellationToken ct = default);
}
The LoadPromptAsync method accepts a promptName (typically corresponding to a template identifier), an optional dictionary of variables for placeholder substitution, and a cancellation token. It returns the processed prompt string ready for LLM consumption.
Default File-Based Implementation
OpenDeepWiki ships with FilePromptPlugin located at src/OpenDeepWiki/Services/Prompts/FilePromptPlugin.cs. This default implementation:
- Reads prompt templates from a configurable directory on disk
- Expects templates to use
{{variableName}}syntax for placeholders - Uses the static method
FilePromptPlugin.SubstituteVariablesto perform regex-based replacement
The default registration occurs in src/OpenDeepWiki/Program.cs (lines 266-277), where the plugin is configured to read from a Prompts subdirectory of the application root.
Implementing Custom Prompt Plugins
Database-Driven Prompt Plugin
For scenarios requiring dynamic prompt management or multi-tenant configurations, implement a database-backed plugin. This example assumes an Entity Framework PromptDbContext with a Prompts table:
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using OpenDeepWiki.Services.Prompts;
public class DbPromptPlugin : IPromptPlugin
{
private readonly PromptDbContext _db;
public DbPromptPlugin(PromptDbContext db) => _db = db;
public async Task<string> LoadPromptAsync(
string promptName,
Dictionary<string, string>? variables = null,
CancellationToken ct = default)
{
var entity = await _db.Prompts.FindAsync(
new object[] { promptName },
ct);
if (entity == null)
throw new FileNotFoundException(
$"Prompt \"{promptName}\" not found in DB.");
var template = entity.Content;
return variables == null || variables.Count == 0
? template
: FilePromptPlugin.SubstituteVariables(template, variables);
}
}
This implementation maintains consistency with the default behavior by reusing FilePromptPlugin.SubstituteVariables for placeholder replacement, ensuring {{variable}} syntax works identically across storage backends.
In-Memory Hardcoded Plugin
For testing scenarios or lightweight deployments where prompts rarely change, embed templates directly in code:
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using OpenDeepWiki.Services.Prompts;
public class InMemoryPromptPlugin : IPromptPlugin
{
private static readonly IReadOnlyDictionary<string, string> Templates =
new Dictionary<string, string>
{
["Summarize"] = "You are a concise summarizer. Summarize the following text:\n{{content}}",
["CodeReview"] = "You are a code reviewer. Analyze the code and give suggestions:\n{{code}}"
};
public Task<string> LoadPromptAsync(
string promptName,
Dictionary<string, string>? variables = null,
CancellationToken ct = default)
{
if (!Templates.TryGetValue(promptName, out var tmpl))
throw new FileNotFoundException(
$"Prompt \"{promptName}\" not defined.");
var result = variables == null || variables.Count == 0
? tmpl
: FilePromptPlugin.SubstituteVariables(tmpl, variables);
return Task.FromResult(result);
}
}
This approach eliminates external dependencies and ensures prompts are version-controlled alongside application code.
Registering Your Plugin in the DI Container
To activate your custom implementation, replace the default registration in src/OpenDeepWiki/Program.cs. The original registration (lines 266-277) configures FilePromptPlugin like this:
builder.Services.AddSingleton<IPromptPlugin>(sp =>
{
var env = sp.GetRequiredService<IHostEnvironment>();
var promptsDir = Path.Combine(env.ContentRootPath, "Prompts");
return new FilePromptPlugin(promptsDir);
});
Replace this with your custom implementation. For the in-memory plugin:
builder.Services.AddSingleton<IPromptPlugin, InMemoryPromptPlugin>();
For the database plugin (assuming PromptDbContext is already registered):
builder.Services.AddScoped<IPromptPlugin, DbPromptPlugin>();
The service lifetime should match your storage backend: singleton for in-memory or file-based, scoped for database contexts that should align with request lifecycles.
How WikiGenerator Uses Your Plugin
The WikiGenerator class located at src/OpenDeepWiki/Services/Wiki/WikiGenerator.cs (lines 68-84) consumes the prompt plugin during the documentation generation pipeline:
public class WikiGenerator : IWikiGenerator
{
private readonly IPromptPlugin _promptPlugin;
// ... other dependencies injected
private async Task<string> BuildPromptAsync(
string promptName,
Dictionary<string, string> variables,
CancellationToken ct)
{
var prompt = await _promptPlugin.LoadPromptAsync(
promptName,
variables,
ct);
// prompt is then sent to the configured LLM backend
return prompt;
}
}
Because WikiGenerator depends on the abstraction IPromptPlugin rather than concrete implementations, your custom plugin integrates seamlessly without modifying the core generation logic. The system resolves the registered implementation at runtime, whether it loads from disk, database, or memory.
Summary
- Implement
IPromptPlugin: Create a class implementing the single-method interface located atsrc/OpenDeepWiki/Services/Prompts/IPromptPlugin.csto define how prompt templates are retrieved and processed. - Reuse variable substitution: Leverage
FilePromptPlugin.SubstituteVariablesto maintain consistent{{variable}}placeholder replacement across custom storage backends. - Register in DI: Replace the default
FilePromptPluginregistration insrc/OpenDeepWiki/Program.cs(lines 266-277) with your implementation usingAddSingletonorAddScopeddepending on your storage requirements. - Zero core changes:
WikiGeneratorautomatically uses your plugin through constructor injection ofIPromptPlugin, requiring no modifications to the AI analysis pipeline.
Frequently Asked Questions
What is the default prompt plugin in OpenDeepWiki?
OpenDeepWiki uses FilePromptPlugin as the default implementation, located at src/OpenDeepWiki/Services/Prompts/FilePromptPlugin.cs. This plugin reads prompt templates from a configurable directory on disk, expects Markdown files, and performs variable substitution using the {{variableName}} syntax.
Can I use multiple prompt plugins simultaneously?
The current architecture in src/OpenDeepWiki/Program.cs registers a single IPromptPlugin implementation in the dependency injection container. To use multiple sources simultaneously, you would need to create a composite plugin that implements IPromptPlugin and internally delegates to multiple backends (file, database, memory) based on prompt naming conventions or fallback logic.
How do I handle variable substitution in custom plugins?
Custom plugins should support the same {{variable}} placeholder syntax as the default implementation to ensure compatibility with existing templates. You can reuse the static helper method FilePromptPlugin.SubstituteVariables(string template, Dictionary<string, string> variables) located in src/OpenDeepWiki/Services/Prompts/FilePromptPlugin.cs, or implement your own regex-based replacement using the pattern \{\{(\w+)\}\}.
Where should I register my custom prompt plugin?
Register your custom implementation in src/OpenDeepWiki/Program.cs by replacing the default registration found at lines 266-277. Use builder.Services.AddSingleton<IPromptPlugin, YourCustomPlugin>() for stateless or file-based implementations, or builder.Services.AddScoped<IPromptPlugin, YourDbPlugin>() if your plugin depends on database contexts that should align with HTTP request lifecycles.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →