Skip to main content
AI/MLCrestApps

orchardcore-ai-prompting

Skill for creating and managing AI prompting assets in Orchard Core. Covers prompt templates via admin UI and markdown files, the AI Prompting feature, template sources, and applying templates when creating AI Profiles. Use this skill when requests mention Orchard Core AI Prompting, Prompt Templates, Enabling AI Prompting, Creating Templates via Markdown Files, Profile Templates, SystemMessage Templates, or closely related Orchard Core implementation, setup, extension, or troubleshooting work. Strong matches include work with CrestApps.OrchardCore.AI.Prompting, OrchardCore.Entities, INamedCatalogManager, AIProfilePostSessionSettings, AIProfileDataExtractionSettings, DisplayDriver, MyCustomTemplateDriver, IDisplayResult, BuildEditorContext. It also helps with Profile Templates, SystemMessage Templates, Markdown Template Format (Profile Source), plus the code patterns, admin flows, recipe steps, and referenced examples captured in this skill.

Stars
13
Source
CrestApps/CrestApps.AgentSkills
Updated
2026-05-29
Slug
CrestApps--CrestApps.AgentSkills--orchardcore-ai-prompting
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/CrestApps/CrestApps.AgentSkills/HEAD/plugins/crestapps-orchardcore/skills/orchardcore-ai-prompting/SKILL.md -o .claude/skills/orchardcore-ai-prompting.md

Drops the SKILL.md into .claude/skills/orchardcore-ai-prompting.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

Orchard Core AI Prompting

Overview

The AI Prompting feature provides reusable prompt templates that can serve as profile templates or system message templates. They can include system messages, model parameters, connection settings, tools, agents, data sources, documents, and more.

Template Sources

Source Description
Profile Pre-fills AI Profile settings when creating new profiles. Users can select from a dropdown and click "Apply".
SystemMessage Provides reusable system message prompts that can be rendered using the render_ai_template Liquid tag.

Templates can be defined in two ways:

  1. Admin UI (runtime) — stored in the database, full CRUD support
  2. Markdown files (code) — placed in AITemplates/Profiles/ or AITemplates/SystemMessages/ folders within modules, read-only at runtime

Guidelines

  • AI Prompting extends CatalogItem and uses the INamedCatalogManager<AIProfileTemplate> pattern.
  • Templates are source-independent — the same template works with any AI provider.
  • Database templates take precedence over file-based templates with the same name.
  • Template properties are read with Entity.TryGet<T>(out var value) and written with Put<T>() (not GetSettings/AlterSettings).
  • Profile-type templates: when applied, Properties are copied to both profile.Properties and profile.Settings.
  • SystemMessage templates: rendered at runtime using render_ai_template Liquid tag.
  • Profile types supported: Chat, Utility, TemplatePrompt, Agent.
  • Agent templates must include Description and AgentMetadata with availability setting.

Enabling AI Prompting

Enable the dedicated AI Prompting feature:

{
  "steps": [
    {
      "name": "Feature",
      "enable": [
        "CrestApps.OrchardCore.AI",
        "CrestApps.OrchardCore.AI.Prompting"
      ]
    }
  ]
}

Creating Templates via Markdown Files

Profile Templates

Place .md files in your module's AITemplates/Profiles/ directory. The file name (without extension) becomes the template's technical name.

SystemMessage Templates

Place .md files in your module's AITemplates/SystemMessages/ directory. These are rendered using the render_ai_template Liquid tag.

Markdown Template Format (Profile Source)

---
Title: Customer Support Bot
Description: Template for customer support chatbots
Category: Customer Service
IsListable: true
ProfileType: Chat
ChatDeploymentName: gpt-4o
UtilityDeploymentName: gpt-4o-mini
OrchestratorName: default
WelcomeMessage: Hello! How can I help you today?
TitleType: Generated
Temperature: 0.7
TopP: 0.9
FrequencyPenalty: 0.0
PresencePenalty: 0.0
MaxOutputTokens: 800
PastMessagesCount: 10
ToolNames: web-search, knowledge-base
AgentNames: research-agent
---

You are a professional customer support agent.
Your goal is to help customers resolve issues efficiently.
Always be polite and empathetic.

The body after the front matter becomes the SystemMessage.

Markdown Template Format (SystemMessage Source)

---
Title: Agent Availability Info
Description: Provides the LLM with information about available agents
Category: System
IsListable: false
---

The following agents are available to assist you:
{% for agent in tools %}
{% if agent.Source == "Agent" %}
- **{{ agent.Name }}**: {{ agent.Description }}
{% endif %}
{% endfor %}

Front Matter Properties

Property Type Description
Title string Display name for the template
Description string Description of what the template does
Category string Grouping category for the dropdown
IsListable bool Whether the template appears in the selection dropdown
ProfileType string Chat, Utility, TemplatePrompt, or Agent
ChatDeploymentName string Chat deployment technical name to pre-select for generated profiles
UtilityDeploymentName string Utility deployment technical name to pre-select for generated profiles
OrchestratorName string Orchestrator name (default: default)
WelcomeMessage string Initial greeting shown to users (Chat profiles only)
TitleType string InitialPrompt or Generated
PromptTemplate string Liquid template for TemplatePrompt profiles
PromptSubject string Subject for the prompt
Temperature float Controls randomness (0.0 to 2.0)
TopP float Nucleus sampling threshold
FrequencyPenalty float Reduces frequent token repetition
PresencePenalty float Encourages topic diversity
MaxOutputTokens int Maximum tokens in response
PastMessagesCount int Number of history messages to include
ToolNames string Comma-separated list of AI tool names
AgentNames string Comma-separated list of agent profile names

Using render_ai_template Liquid Tag

The render_ai_template tag renders a SystemMessage template by ID, optionally passing variables:

{% render_ai_template "template-id" %}

With variables:

{% render_ai_template "agent-availability" tools %}

This passes the tools variable from the current scope to the rendered template. Variables are inherited from the parent scope.

Example: Composing Templates

You are an AI assistant with access to various tools and agents.

{% if hasAgents %}
{% render_ai_template "agent-availability" tools %}
{% endif %}

Always follow the user's instructions carefully.

Creating Agent Templates

Agent templates help users quickly create agent profiles:

{
  "steps": [
    {
      "name": "AIProfileTemplate",
      "Templates": [
        {
          "Name": "research-agent",
          "DisplayText": "Research Agent",
          "Description": "Template for creating a research agent that can gather and summarize information.",
          "Category": "Agents",
          "IsListable": true,
          "ProfileType": "Agent",
          "SystemMessage": "You are a research assistant. Gather information from available tools, verify facts, and provide comprehensive answers with sources.",
          "Temperature": 0.3,
          "MaxOutputTokens": 4096,
          "ToolNames": ["web-search"],
          "AgentNames": [],
          "Properties": {
            "AgentMetadata": {
              "Availability": "OnDemand"
            }
          }
        }
      ]
    }
  ]
}

Creating Templates via Recipes

Profile Template Recipe

{
  "steps": [
    {
      "name": "AIProfileTemplate",
      "Templates": [
        {
          "Name": "customer-support",
          "DisplayText": "Customer Support Bot",
          "Description": "Template for customer support chatbots",
          "Category": "Customer Service",
          "IsListable": true,
          "ProfileType": "Chat",
          "ChatDeploymentName": "gpt-4o",
          "UtilityDeploymentName": "gpt-4o-mini",
          "OrchestratorName": "default",
          "SystemMessage": "You are a professional customer support agent.",
          "WelcomeMessage": "Hello! How can I help you today?",
          "TitleType": "Generated",
          "Temperature": 0.7,
          "TopP": 0.9,
          "MaxOutputTokens": 800,
          "PastMessagesCount": 10,
          "ToolNames": ["web-search", "knowledge-base"],
          "AgentNames": ["research-agent"],
          "Properties": {}
        }
      ]
    }
  ]
}

Recipe with Post-Session, Data Extraction & Conversion Goals

Templates store all settings in Properties (not Settings). Here is a full recipe with post-session tasks, data extraction entries, and conversion goals:

{
  "steps": [
    {
      "name": "AIProfileTemplate",
      "Templates": [
        {
          "Name": "support-analytics",
          "DisplayText": "Support with Analytics",
          "Description": "Support template with full data processing and metrics.",
          "Category": "Customer Service",
          "ProfileType": "Chat",
          "SystemMessage": "You are a customer support agent.",
          "AgentNames": [],
          "Properties": {
            "AIProfilePostSessionSettings": {
              "EnablePostSessionProcessing": true,
              "ToolNames": [],
              "PostSessionTasks": [
                {
                  "Name": "sentiment",
                  "Type": "PredefinedOptions",
                  "Instructions": "Classify the overall sentiment of the conversation.",
                  "AllowMultipleValues": false,
                  "Options": [
                    { "Value": "positive", "Description": "Customer was happy." },
                    { "Value": "neutral", "Description": "No strong emotion." },
                    { "Value": "negative", "Description": "Customer was frustrated." }
                  ]
                },
                {
                  "Name": "summary",
                  "Type": "Semantic",
                  "Instructions": "Write a concise summary of the conversation.",
                  "AllowMultipleValues": false,
                  "Options": []
                }
              ]
            },
            "AIProfileDataExtractionSettings": {
              "EnableDataExtraction": true,
              "ExtractionCheckInterval": 1,
              "SessionInactivityTimeoutInMinutes": 30,
              "DataExtractionEntries": [
                {
                  "Name": "customer_name",
                  "Description": "The customer's full name.",
                  "AllowMultipleValues": false,
                  "IsUpdatable": true
                },
                {
                  "Name": "issue_category",
                  "Description": "The category of the issue.",
                  "AllowMultipleValues": false,
                  "IsUpdatable": true
                }
              ]
            },
            "AnalyticsMetadata": {
              "EnableSessionMetrics": true,
              "EnableAIResolutionDetection": true,
              "EnableConversionMetrics": true,
              "ConversionGoals": [
                {
                  "Name": "issue_resolved",
                  "Description": "The customer's issue was fully resolved.",
                  "MinScore": 0,
                  "MaxScore": 10
                },
                {
                  "Name": "customer_satisfaction",
                  "Description": "The customer expressed satisfaction.",
                  "MinScore": 0,
                  "MaxScore": 10
                }
              ]
            }
          }
        }
      ]
    }
  ]
}

Named Entry Merge Behavior

When re-importing templates via recipe, named entries (PostSessionTasks, DataExtractionEntries, ConversionGoals) are merged by their Name field:

Scenario Result
Entry with same name exists Updated with incoming values
Entry is new (name not found) Added to the list
Existing entry not in import Preserved (not deleted)

Entry names must be unique within each list and contain only alphanumeric characters and underscores.

Exporting Templates via Deployment

AI Templates can be exported using the deployment plan system. The deployment step AIProfileTemplate exports all or specific templates.

Creating a Display Driver for AIProfileTemplate

To extend the template editor with custom tabs (like documents, capabilities, etc.), create a DisplayDriver<AIProfileTemplate>:

public sealed class MyCustomTemplateDriver : DisplayDriver<AIProfileTemplate>
{
    public override IDisplayResult Edit(AIProfileTemplate template, BuildEditorContext context)
    {
        return Initialize<MyViewModel>("MyShape_Edit", model =>
        {
            if (!template.TryGet<MyMetadata>(out var metadata))
            {
                metadata = new MyMetadata();
            }

            model.SomeSetting = metadata.SomeSetting;
        }).Location("Content:10#MyTab;8");
    }

    public override async Task<IDisplayResult> UpdateAsync(
        AIProfileTemplate template,
        UpdateEditorContext context)
    {
        var model = new MyViewModel();

        await context.Updater.TryUpdateModelAsync(model, Prefix);

        template.Put(new MyMetadata
        {
            SomeSetting = model.SomeSetting,
        });

        return await EditAsync(template, context);
    }
}

Register the driver in Startup:

services.AddDisplayDriver<AIProfileTemplate, MyCustomTemplateDriver>();

Placement Format Reference

When specifying .Location() for display drivers, use the format:

Zone:ItemPosition#TabName;TabGroupPosition
  • :N after zone = item order WITHIN the tab (lower number = first)
  • ;N after tab name = tab order among other tabs (lower number = first)
  • CRITICAL: Use ; (semicolon) after tab name, NOT : (colon). Using : makes the number part of the tab name.

Examples:

  • Content:3#Capabilities;8 — item at position 3 within the "Capabilities" tab, tab at position 8
  • Content:5#Data Processing & Metrics;10 — item at position 5 within the "Data Processing & Metrics" tab, tab at position 10

Important Notes

  • Template drivers use template.TryGet<T>(out var value) for reads and Put<T>() for writes from OrchardCore.Entities (not GetSettings/AlterSettings).
  • Template drivers can reuse the same ViewModels and shape names as AI Profile drivers.
  • When applying a template, Properties are copied to both profile.Properties and profile.Settings.
  • Templates support document uploads — documents are cloned when applying a template to a new profile.
  • All template settings (post-session, data extraction, analytics) live in template.Properties.

Where Template Settings Live vs AI Profile Settings

Settings Type On AIProfileTemplate On AIProfile
AIProfilePostSessionSettings template.Properties via TryGet<T>(out var value)/Put<T>() profile.Settings via GetSettings/AlterSettings
AIProfileDataExtractionSettings template.Properties via TryGet<T>(out var value)/Put<T>() profile.Settings via GetSettings/AlterSettings
AnalyticsMetadata template.Properties via TryGet<T>(out var value)/Put<T>() profile.Properties via TryGet<T>(out var value)/Put<T>()
AIProfileMetadata template.Properties via TryGet<T>(out var value)/Put<T>() profile.Properties via TryGet<T>(out var value)/Put<T>()
AgentMetadata template.Properties via TryGet<T>(out var value)/Put<T>() profile.Properties via TryGet<T>(out var value)/Put<T>()

Security

  • AI Template management requires the ManageAIProfileTemplates permission.
  • Templates do not store API keys or sensitive connection details.
  • Templates reference connections by name, not by credentials.