Skip to main content

best-practices-prompt

Rules for writing clear, testable LLM prompts. Eliminates vagueness, enforces concrete output specs, grounding in source material, and deterministic verifiability. Gate before /review-prompt.

跳到安装

来源信息

仓库
grahama1970/agent-stack-public
最近来源活动
2026年9月24日 18:04
检测到的 SKILL.md 语言
英语
星标
0
分支
0

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
5 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
best-practices-prompt
description
Rules for writing clear, testable LLM prompts. Eliminates vagueness, enforces concrete output specs, grounding in source material, and deterministic verifiability. Gate before /review-prompt.
triggers
["best practices prompt","prompt conventions","write prompt","prompt writing","improve prompt","prompt quality","vague prompt","prompt review prep"]
license
MIT
metadata
{"prompt_types":["system prompts","skill prompts","extraction prompts","classification prompts","generation prompts"]}
provides
["best-practices-prompt"]
composes
["review-prompt","prompt-lab","agentic-evals"]
taxonomy
["prompt-engineering","llm"]
disciplines
["engineering-standards","model-ops"]
# Prompt Best Practices (Project Skill) This skill is a curated set of rules for writing LLM prompts in this repo. Every prompt — system prompts, skill prompts, extraction templates, generation instructions — MUST pass these rules before going to `/review-prompt`. **The core problem:** Agents write vague, hand-wavy prompts that sound reasonable but produce garbage output. "Analyze the document and extract relevant information" is not a prompt — it is a wish. This skill exists to kill that pattern. ## When to Apply Use this skill whenever you: - write a new system prompt or skill prompt template - modify an existing prompt in a `.txt`, `.md`, or inline Python string - build prompts for `/scillm`, `/code-runner`, `/prompt-lab`, or any LLM call - prepare a prompt for `/review-prompt` review ## Categories (priority order) 1. Clarity (CRITICAL): `clarity-` — every sentence must have one unambiguous meaning 2. Specificity (CRITICAL): `specificity-` — concrete nouns, verbs, quantities, formats 3. Output Specification (HIGH): `output-` — exact schema, format, and constraints 4. Grounding (HIGH): `grounding-` — reference real data, files, schemas, examples 5. Structure (MEDIUM): `structure-` — logical ordering, sections, progressive disclosure 6. Testability (MEDIUM): `testability-` — how do you know the output is correct? 7. Efficiency (LOW): `efficiency-` — token budget, context window management ## Compliance Prompt Rules (STOP — read these first if writing SPARTA/NIST/CWE prompts) These rules apply to ANY prompt that operates on cross-framework compliance data (evidence cases, crosswalk chains, control glossaries, QRA results). Violations cause 0% accuracy. | Rule | What it prevents | Link | |------|-----------------|------| | `grounding-match-pipeline-schema` | Prompt invents its own schema instead of using the pipeline's actual output fields. Result: model can't parse the payload. | [Rule 15](#rule-15) | | `grounding-vocabulary-control` | Prompt says "different framework" without listing valid frameworks or telling the model how to identify them. Result: model guesses wrong. | [Rule 6](#rule-6) | | `grounding-cite-source-fields` | Prompt says "use the glossary" without naming `glossary[].framework`, `glossary[].description`. Result: model uses wrong fields. | [Rule 10](#rule-10) | **Before writing a compliance prompt:** 1. Find the function that produces the payload (e.g., `_build_evidence_case()` in `runner.py`) 2. Read its output — field names, types, nesting, framework identifiers 3. Use those exact field paths in the prompt 4. Include the framework closed vocabulary: SPARTA, CWE, NIST, CAPEC, ATT&CK, D3FEND ## Prompt Type Routing Load specialized rulesets based on prompt type: | Writing a... | Load this reference | Key rules | |--------------|---------------------|-----------| | **Extraction prompt** (QRA, entity, control extraction) | [`references/extraction.md`](references/extraction.md) | 24-36: source admissibility, distinctness, modality preservation | | **Inference/filter prompt** (classification, ranking, JSON output) | [`references/inference-time.md`](references/inference-time.md) | 16-23: format anchor, anti-MCQ, gates vs ranking, Pydantic patterns | | **Any prompt** | Core rules below | 0-15: no weasel words, concrete nouns, schema, examples | | **Debugging failures** | [`references/incidents.md`](references/incidents.md) | Pattern library of past prompt failures | ## Rule S: Models Never Return Prose (NON-NEGOTIABLE, operator 2026-09-24) ### Rule: `output-json-fields-only` Every model output is a JSON object whose fields are fixed by a Pydantic model. No model ever returns a free-prose answer, narration, summary, or explanation for a consumer to display or concatenate. Required pipeline: 1. **Model → JSON fields.** The prompt specifies the exact schema (Rules 2, 3, 12, 13) with hard quantities per field (e.g. `direct_answer`: one sentence, max 20 words; `steps[].point`: one sentence, max 15 words). 2. **Pydantic validation.** The consumer validates with a strict model (`extra="forbid"`, word/sentence-count validators, closed enums). Invalid output is rejected, never repaired into prose or truncated. 3. **`$jev` judgment.** A bounded Jev choice question scores the validated fields against the supplied evidence (answers-the-question and grounded-in-source distributions). `rejected`/`uncertain`/`unavailable` stay distinct and block acceptance; they are never coerced to success. 4. **Deterministic rendering.** Only code turns fields into display or speech (headline, source chip, numbered steps). Code never glues model text into paragraphs. Observed 2026-09-24: explain-project's `ExplainerStep.spoken: str` (max 2000 chars) let the authoring model write narration; the cockpit concatenated every step into an unscannable 110-word paragraph with no source file. ## Quick Reference (Core Rules 0-15) | Rule | Code | One-liner | |------|------|-----------| | 0 | `structure-rationale-header` | Every prompt starts with Purpose/Consumer/Why header | | 1 | `clarity-no-weasel-words` | No "relevant", "appropriate", "ensure", "comprehensive" | | 2 | `specificity-name-the-format` | Exact JSON schema, not "return JSON" | | 3 | `output-show-one-example` | Full input→output example, not fragments | | 4 | `clarity-imperative-voice` | "Extract X" not "you should try to extract X" | | 5 | `structure-task-before-context` | State task, THEN provide context | | 6 | `grounding-vocabulary-control` | List ALL valid categories explicitly | | 7 | `output-rejection-criteria` | Tell model what makes output WRONG | | 8 | `specificity-concrete-nouns` | "control ID, title, page" not "the information" | | 9 | `specificity-quantity-not-quality` | "2-3 sentences" not "brief summary" | | 10 | `grounding-cite-source-fields` | Name exact field paths: `doc.lineage.entity_ids` | | 11 | `structure-one-task` | One prompt = one task, chain for complex work | | 12 | `structure-schema-last` | Output schema at END, right before generation | | 13 | `output-nothing-but` | "Return ONLY this JSON, no other text" | | 14 | `testability-deterministic-check` | Define how to verify output is correct | | 15 | `grounding-match-pipeline-schema` | Prompt schema must match pipeline payload (compliance) | | 16 | `structure-review-payload` | Every prompt dir needs `review/` with complete payload for Web LLM audit | --- ## Rule 0: Every Prompt Must Have a Rationale Header (NON-NEGOTIABLE) ### Rule: `structure-rationale-header` Every prompt file MUST begin with a rationale block that answers three questions before the prompt itself starts. This block is for humans reviewing the prompt — it is NOT sent to the LLM. ``` # RATIONALE (not sent to LLM) # Purpose: What does this prompt produce? (e.g., "Extracts CWE→SPARTA crosswalk chains from evidence cases") # Consumer: What system/skill receives the output? (e.g., "SPARTA Explorer NLG pipeline, step 4") # Why this matters: What breaks if this prompt is wrong? (e.g., "Users get hallucinated attack paths") ``` ### Why this is Rule 0 Without rationale, prompts become orphans. Six months later, nobody knows: - **What** the prompt is for — is it extraction? classification? generation? - **Who** consumes the output — a Pydantic model? a human? another LLM? - **Why** it exists — what user-facing behavior depends on it? This is how "word salad" prompts survive: nobody can tell if the prompt is wrong because nobody knows what right looks like. The rationale makes the prompt auditable — a reviewer can check "does this prompt actually produce what the rationale says it should?" ### WRONG: ``` You are a cybersecurity analyst producing actionable insights from cross-framework evidence. [... 50 lines of instructions ...] ``` ### RIGHT: ``` # RATIONALE (not sent to LLM) # Purpose: Generate structured cybersecurity analysis from SPARTA evidence cases # Consumer: SPARTA Explorer API → /api/query response → "answer" field # Why this matters: This is the user-facing answer. Bad output = user sees nonsense. # Input: EVIDENCE_CASE JSON with glossary, crosswalk_chains, prior_qra_evidence # Output: JSON with decision, answer, citations. Validated by EvidenceCaseResponse Pydantic model. # Last reviewed: 2026-04-09 by Graham You are a NIST/SPARTA cross-framework evidence analyst. Task: Given an EVIDENCE_CASE, produce a structured cybersecurity analysis... ``` ### What belongs in the rationale: - **Purpose** — one sentence: what does this prompt do - **Consumer** — what code/system receives the output (skill name, API endpoint, Pydantic model) - **Why this matters** — what breaks if the output is wrong - **Input** — what data the prompt receives (field names, not vibes) - **Output** — schema name or format spec - **Last reviewed** — date and person, so staleness is visible ### How agents should handle the rationale: When calling `run.sh review`, the rationale block (lines starting with `#`) is parsed separately and shown in the review page header — not mixed into the prompt body. When the prompt is sent to the LLM, strip lines starting with `# RATIONALE` through the first non-comment line. --- ## Rule 1: No Weasel Words (NON-NEGOTIABLE) ### Rule: `clarity-no-weasel-words` Weasel words are adjectives and adverbs that feel meaningful but carry zero information for an LLM. They are the #1 source of vague prompts. If a human reader could reasonably ask "what do you mean by that?", it is a weasel word. **Banned words and what to replace them with:** | Weasel Word | Why It Fails | Replace With | |-------------|-------------|-------------| | "relevant" | Relevant to what? | Name the specific fields or criteria | | "appropriate" | By whose standard? | State the standard explicitly | | "comprehensive" | How comprehensive? | "All X" or "at least N" | | "thorough" | Unmeasurable | Enumerate what must be checked | | "important" | Important how? | State the consequence of missing it | | "ensure" | Not an action verb | "Check that X. If not, do Y." | | "consider" | Does not commit to action | "If X, then Y. Otherwise Z." | | "properly" | Properly by what definition? | State the exact criteria | | "meaningful" | Subjective | Define the threshold | | "high-quality" | Unmeasurable | List the quality criteria explicitly | | "as needed" | Who decides? | State the condition: "if X, then Y" | | "various" | How many? Which ones? | List them or say "all" | | "leverage" | Corporate jargon for "use" | "use" | | "utilize" | Same | "use" | ### WRONG: ``` Analyze the document and extract relevant information. Ensure comprehensive coverage of important topics. Provide appropriate responses as needed. ``` ### RIGHT: ``` Extract every person name, organization, and date from the document. Return them as a JSON array of objects: {"entity": "...", "type": "person|org|date", "page": N}. If no entities are found on a page, omit that page from the output. ``` ### Why this matters On 2026-03-22, a QRA extraction prompt using "extract relevant security controls" produced 40% hallucinated controls because "relevant" gave the LLM permission to invent plausible-sounding controls. Replacing it with "extract only controls whose ID appears verbatim in the source text" dropped hallucinations to 2%. --- ## Rule 2: Name the Output Format Exactly (NON-NEGOTIABLE) ### Rule: `specificity-name-the-format` Every prompt that expects structured output MUST specify the exact format. Not "return JSON" — return the exact JSON schema with field names, types, and constraints. ### WRONG: ``` Return the results as JSON. ``` ``` Output a structured response with the key findings. ``` ### RIGHT: ``` Return a JSON object with this exact schema: { "controls": [ { "id": "string — e.g. 'AC-2', 'SI-4'. Must match regex ^[A-Z]{2}-\\d+$", "title": "string — the control title from the source, verbatim", "source_page": "integer — 1-indexed page number where this control appears", "confidence": "float 0.0-1.0 — 1.0 if quoted verbatim, 0.7 if paraphrased" } ], "document_title": "string — from the PDF metadata or first heading", "total_pages_scanned": "integer" } Do not add fields not listed above. Do not nest objects deeper than shown. If a field cannot be determined, use null — never omit the key. ``` ### Why this matters "Return JSON" gives the LLM freedom to invent any schema. Every downstream consumer then needs to handle N possible shapes. Specifying the schema upfront means the output is parseable by a fixed Pydantic model — no guessing, no `get()` with fallbacks, no "try these 3 field names". --- ## Rule 3: Show One Complete Input/Output Example (NON-NEGOTIABLE) ### Rule: `output-show-one-example` Every prompt that produces structured output MUST include at least one complete input/output example. Not a fragment — the full input and the full expected output. ### WRONG: ``` Extract entities from the text. For example, you might find names like "John Smith". ``` ### RIGHT: ``` ## Example Input text: "On March 15, 2026, Dr. Sarah Chen from NIST published SP 800-171 Rev 3." Expected output: { "entities": [ {"text": "March 15, 2026", "type": "date", "start_char": 3, "end_char": 17}, {"text": "Dr. Sarah Chen", "type": "person", "start_char": 19, "end_char": 33}, {"text": "NIST", "type": "organization", "start_char": 39, "end_char": 43}, {"text": "SP 800-171 Rev 3", "type": "document_id", "start_char": 54, "end_char": 70} ] } Note: start_char and end_char are 0-indexed byte offsets into the input string. ``` ### Why this matters Examples are worth 100 lines of instruction. The LLM learns the output shape, the level of detail expected, the naming conventions, and the edge cases from a single concrete example. Without an example, each instruction sentence is another opportunity for misinterpretation. --- ## Rule 4: Imperative Voice, Not Descriptive (HIGH) ### Rule: `clarity-imperative-voice` Prompts are instructions, not descriptions. Use imperative verbs ("extract", "return", "list", "check") not descriptive language ("you should", "it would be good to", "the system is expected to"). ### WRONG: ``` You are a helpful assistant that analyzes documents. You should try to find security controls and it would be good to return them in a structured format. The system is expected to handle edge cases appropriately. ``` ### RIGHT: ``` You are a NIST SP 800-53 control extractor. Task: Extract every security control reference from the input document. Steps:
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看