Token导航 LogoToken导航TokenDH.com
研究检索只读github未标认证来源可访问许可证需确认审计异常

prompt-engine提示引擎

Agent Skill

用于辅助提示词、系统指令、Agent 行为约束和工作流模板的整理。它适合让 Agent 规范任务边界、统一输出格式、拆分操作步骤或优化提示词可复用性。使用时需要保留真实业务约束,不要把示例当硬规则;涉及自动执行、外部工具或高风险操作时,应在提示词中明确确认步骤、权限边界和失败处理方式。

总安装

533

周安装

22

GitHub Stars

777

下载量

174
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:prompt-engine(提示引擎)
来源仓库:https://github.com/dadbodgeoff/drift
仓库路径:skills/prompt-engine
安装命令:
npx skills add https://github.com/dadbodgeoff/drift --skill prompt-engine
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dadbodgeoff/drift --skill prompt-engine

简介

用于辅助提示词、系统指令、Agent 行为约束和工作流模板的整理。

  • 适合让 Agent 规范任务边界、统一输出格式或优化提示词可复用性。
  • 通过安装命令添加,使用时需保留真实业务约束,避免将示例当硬规则。
  • 涉及自动执行或外部工具调用时,应在提示词中明确确认步骤和权限边界。
  • prompt-engine 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

AI Prompt Templating Engine

Template-based prompt building with brand consistency and security.

When to Use This Skill

  • Managing AI prompts across a codebase
  • Need brand consistency in generated content
  • Preventing prompt injection attacks
  • Optimizing token usage with compact context

Core Concepts

Prompt engineering challenges:

  1. Scattered prompts - Hard to maintain consistency
  2. Brand drift - Generated content doesn't match brand
  3. Injection attacks - User input can hijack prompts
  4. Token waste - Verbose context burns budget

Implementation

TypeScript

// Types
interface PromptTemplate {
  name: string;
  version: string;
  basePrompt: string;
  placeholders: string[];
  qualityModifiers: string[];
}

interface BrandKitContext {
  primaryColors: string[];
  accentColors: string[];
  headlineFont?: string;
  bodyFont?: string;
  tone?: string;
}

interface ResolvedBrandContext {
  primaryColor?: string;
  secondaryColor?: string;
  accentColor?: string;
  gradient?: string;
  font?: string;
  tone?: string;
  intensity: 'subtle' | 'balanced' | 'strong';
}

// Security: Input Sanitization
const MAX_INPUT_LENGTH = 500;
const SANITIZE_PATTERN = /[<>{}\[\]\\|`~]/g;

const INJECTION_PATTERNS = [
  /ignore\s+(previous|above|all)/i,
  /disregard\s+(previous|above|all)/i,
  /system\s*:/i,
  /assistant\s*:/i,
  /\[INST\]/i,
  /<<SYS>>/i,
];

function sanitizeInput(input: string): string {
  if (input.length > MAX_INPUT_LENGTH) {
    input = input.slice(0, MAX_INPUT_LENGTH);
  }

  input = input.replace(SANITIZE_PATTERN, '');

  for (const pattern of INJECTION_PATTERNS) {
    if (pattern.test(input)) {
      throw new Error('Potential prompt injection detected');
    }
  }

  return input.trim();
}

function sanitizePlaceholders(placeholders: Record<string, string>): Record<string, string> {
  const sanitized: Record<string, string> = {};
  for (const [key, value] of Object.entries(placeholders)) {
    sanitized[key] = sanitizeInput(value);
  }
  return sanitized;
}

// Brand Context Resolver
class BrandContextResolver {
  resolve(
    brandKit: BrandKitContext,
    options: {
      primaryColorIndex?: number;
      secondaryColorIndex?: number;
      accentColorIndex?: number;
      useGradient?: boolean;
      intensity?: 'subtle' | 'balanced' | 'strong';
    } = {}
  ): ResolvedBrandContext {
    const primaryColor = this.resolveColor(brandKit.primaryColors, options.primaryColorIndex ?? 0);
    const secondaryColor = this.resolveColor(brandKit.primaryColors, options.secondaryColorIndex ?? 1);
    const accentColor = this.resolveColor(brandKit.accentColors, options.accentColorIndex ?? 0);

    const gradient = options.useGradient && primaryColor && secondaryColor
      ? `${primaryColor}→${secondaryColor}`
      : undefined;

    return {
      primaryColor,
      secondaryColor,
      accentColor,
      gradient,
      font: brandKit.headlineFont,
      tone: brandKit.tone,
      intensity: options.intensity || 'balanced',
    };
  }

  private resolveColor(colors: string[], index: number): string | undefined {
    if (!colors.length) return undefined;
    return colors[Math.min(index, colors.length - 1)];
  }
}

// Compact brand block (~50-80 tokens)
function toCompactBrandBlock(ctx: ResolvedBrandContext): string {
  const parts: string[] = [];

  const colors = [ctx.primaryColor, ctx.secondaryColor, ctx.accentColor].filter(Boolean);
  if (colors.length) parts.push(`Colors: ${colors.join(', ')}`);
  if (ctx.gradient) parts.push(`Gradient: ${ctx.gradient}`);
  if (ctx.font) parts.push(`Font: ${ctx.font}`);
  if (ctx.tone) parts.push(`Tone: ${ctx.tone}`);

  if (!parts.length) return '';
  return `[BRAND: ${ctx.intensity} - ${parts.join(' | ')}]`;
}

// Template Loader with caching
const templateCache = new Map<string, PromptTemplate>();

async function loadTemplate(templateName: string): Promise<PromptTemplate> {
  if (templateCache.has(templateName)) {
    return templateCache.get(templateName)!;
  }

  // Prevent directory traversal
  const normalized = templateName.replace(/\.\./g, '').replace(/[<>:"|?*]/g, '');

  const content = await fs.readFile(`prompts/${normalized}.yaml`, 'utf-8');
  const data = yaml.load(content) as any;

  const template: PromptTemplate = {
    name: data.name || templateName,
    version: data.version || '1.0.0',
    basePrompt: data.base_prompt,
    placeholders: data.placeholders || [],
    qualityModifiers: data.quality_modifiers || [],
  };

  // Validate placeholders exist in prompt
  for (const placeholder of template.placeholders) {
    if (!template.basePrompt.includes(`{${placeholder}}`)) {
      throw new Error(`Placeholder {${placeholder}} not found in template`);
    }
  }

  templateCache.set(templateName, template);
  return template;
}

// Prompt Engine
const INTENSITY_MODIFIERS = {
  subtle: 'subtly incorporate',
  balanced: 'use',
  strong: 'prominently feature',
};

class PromptEngine {
  private brandResolver = new BrandContextResolver();

  async buildPrompt(
    templateName: string,
    placeholders: Record<string, string>,
    brandKit?: BrandKitContext,
    brandOptions?: Parameters<BrandContextResolver['resolve']>[1]
  ): Promise<string> {
    const sanitizedPlaceholders = sanitizePlaceholders(placeholders);
    const template = await loadTemplate(templateName);

    // Substitute placeholders
    let prompt = template.basePrompt;
    for (const [key, value] of Object.entries(sanitizedPlaceholders)) {
      prompt = prompt.replace(new RegExp(`\\{${key}\\}`, 'g'), value);
    }

    // Inject brand context
    if (brandKit) {
      const resolved = this.brandResolver.resolve(brandKit, brandOptions);
      const brandBlock = toCompactBrandBlock(resolved);

      if (brandBlock) {
        const modifier = INTENSITY_MODIFIERS[resolved.intensity];
        prompt = `${prompt}\n\n${modifier} the following brand guidelines:\n${brandBlock}`;
      }
    }

    // Add quality modifiers
    if (template.qualityModifiers.length) {
      prompt = `${prompt}\n\nQuality: ${template.qualityModifiers.join(', ')}`;
    }

    return prompt;
  }
}

export const promptEngine = new PromptEngine();

Python

import re
import yaml
from dataclasses import dataclass
from typing import Dict, List, Optional
from pathlib import Path

MAX_INPUT_LENGTH = 500
SANITIZE_PATTERN = re.compile(r'[<>{}\[\]\\|`~]')
INJECTION_PATTERNS = [
    re.compile(r'ignore\s+(previous|above|all)', re.I),
    re.compile(r'disregard\s+(previous|above|all)', re.I),
    re.compile(r'system\s*:', re.I),
    re.compile(r'assistant\s*:', re.I),
    re.compile(r'\[INST\]', re.I),
]

def sanitize_input(input_str: str) -> str:
    if len(input_str) > MAX_INPUT_LENGTH:
        input_str = input_str[:MAX_INPUT_LENGTH]

    input_str = SANITIZE_PATTERN.sub('', input_str)

    for pattern in INJECTION_PATTERNS:
        if pattern.search(input_str):
            raise ValueError("Potential prompt injection detected")

    return input_str.strip()

@dataclass
class PromptTemplate:
    name: str
    version: str
    base_prompt: str
    placeholders: List[str]
    quality_modifiers: List[str]

@dataclass
class BrandKitContext:
    primary_colors: List[str]
    accent_colors: List[str]
    headline_font: Optional[str] = None
    tone: Optional[str] = None

@dataclass
class ResolvedBrandContext:
    primary_color: Optional[str] = None
    secondary_color: Optional[str] = None
    accent_color: Optional[str] = None
    gradient: Optional[str] = None
    font: Optional[str] = None
    tone: Optional[str] = None
    intensity: str = "balanced"

class BrandContextResolver:
    def resolve(
        self,
        brand_kit: BrandKitContext,
        primary_index: int = 0,
        secondary_index: int = 1,
        accent_index: int = 0,
        use_gradient: bool = False,
        intensity: str = "balanced",
    ) -> ResolvedBrandContext:
        primary = self._resolve_color(brand_kit.primary_colors, primary_index)
        secondary = self._resolve_color(brand_kit.primary_colors, secondary_index)
        accent = self._resolve_color(brand_kit.accent_colors, accent_index)

        gradient = f"{primary}→{secondary}" if use_gradient and primary and secondary else None

        return ResolvedBrandContext(
            primary_color=primary,
            secondary_color=secondary,
            accent_color=accent,
            gradient=gradient,
            font=brand_kit.headline_font,
            tone=brand_kit.tone,
            intensity=intensity,
        )

    def _resolve_color(self, colors: List[str], index: int) -> Optional[str]:
        if not colors:
            return None
        return colors[min(index, len(colors) - 1)]

def to_compact_brand_block(ctx: ResolvedBrandContext) -> str:
    parts = []

    colors = [c for c in [ctx.primary_color, ctx.secondary_color, ctx.accent_color] if c]
    if colors:
        parts.append(f"Colors: {', '.join(colors)}")
    if ctx.gradient:
        parts.append(f"Gradient: {ctx.gradient}")
    if ctx.font:
        parts.append(f"Font: {ctx.font}")
    if ctx.tone:
        parts.append(f"Tone: {ctx.tone}")

    if not parts:
        return ""
    return f"[BRAND: {ctx.intensity} - {' | '.join(parts)}]"

_template_cache: Dict[str, PromptTemplate] = {}

def load_template(template_name: str) -> PromptTemplate:
    if template_name in _template_cache:
        return _template_cache[template_name]

    # Prevent directory traversal
    safe_name = template_name.replace("..", "").replace("/", "_")
    path = Path("prompts") / f"{safe_name}.yaml"

    with open(path) as f:
        data = yaml.safe_load(f)

    template = PromptTemplate(
        name=data.get("name", template_name),
        version=data.get("version", "1.0.0"),
        base_prompt=data["base_prompt"],
        placeholders=data.get("placeholders", []),
        quality_modifiers=data.get("quality_modifiers", []),
    )

    _template_cache[template_name] = template
    return template

INTENSITY_MODIFIERS = {
    "subtle": "subtly incorporate",
    "balanced": "use",
    "strong": "prominently feature",
}

class PromptEngine:
    def __init__(self):
        self._brand_resolver = BrandContextResolver()

    def build_prompt(
        self,
        template_name: str,
        placeholders: Dict[str, str],
        brand_kit: Optional[BrandKitContext] = None,
        intensity: str = "balanced",
        use_gradient: bool = False,
    ) -> str:
        # Sanitize inputs
        sanitized = {k: sanitize_input(v) for k, v in placeholders.items()}

        template = load_template(template_name)

        # Substitute placeholders
        prompt = template.base_prompt
        for key, value in sanitized.items():
            prompt = prompt.replace(f"{{{key}}}", value)

        # Inject brand context
        if brand_kit:
            resolved = self._brand_resolver.resolve(
                brand_kit, intensity=intensity, use_gradient=use_gradient
            )
            brand_block = to_compact_brand_block(resolved)

            if brand_block:
                modifier = INTENSITY_MODIFIERS[resolved.intensity]
                prompt = f"{prompt}\n\n{modifier} the following brand guidelines:\n{brand_block}"

        # Add quality modifiers
        if template.quality_modifiers:
            prompt = f"{prompt}\n\nQuality: {', '.join(template.quality_modifiers)}"

        return prompt

prompt_engine = PromptEngine()

Template Example

# prompts/thumbnail_gaming.yaml
name: thumbnail_gaming
version: "1.0.0"
base_prompt: |
  Create a {game_name} thumbnail.
  Feature {subject} with {emotion} expression.
  Style: {style}

placeholders:
  - game_name
  - subject
  - emotion
  - style

quality_modifiers:
  - ultra detailed
  - cinematic lighting
  - 8K quality

Usage Examples

const prompt = await promptEngine.buildPrompt(
  'thumbnail_gaming',
  {
    game_name: 'Cyberpunk 2077',
    subject: 'character with katana',
    emotion: 'intense',
    style: 'neon cyberpunk',
  },
  {
    primaryColors: ['#FF00FF', '#00FFFF'],
    accentColors: ['#FFFF00'],
    headlineFont: 'Orbitron',
    tone: 'edgy',
  },
  { useGradient: true, intensity: 'strong' }
);

// Result:
// Create a Cyberpunk 2077 thumbnail.
// Feature character with katana with intense expression.
// Style: neon cyberpunk
//
// prominently feature the following brand guidelines:
// [BRAND: strong - Colors: #FF00FF, #00FFFF, #FFFF00 | Gradient: #FF00FF→#00FFFF | Font: Orbitron | Tone: edgy]
//
// Quality: ultra detailed, cinematic lighting, 8K quality

Best Practices

  1. Sanitize all user inputs before substitution
  2. Use compact brand blocks to save tokens
  3. Cache templates for performance
  4. Validate placeholders exist in templates
  5. Use intensity modifiers for brand prominence

Common Mistakes

  • No input sanitization (injection vulnerability)
  • Verbose brand context (wastes tokens)
  • Hardcoded prompts (inconsistent)
  • Missing placeholder validation
  • No template caching (slow)

Related Patterns

  • ai-generation-client - Use prompts with AI APIs
  • rate-limiting - Protect AI quota
  • validation-quarantine - Validate AI outputs

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

37.2%
按下载量换算65

Claude

31.64%
按下载量换算55

Cursor

17.67%
按下载量换算31

Gemini CLI

9.72%
按下载量换算17

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

未通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills