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.

Quellinformationen

Repository
grahama1970/agent-stack-public
Letzte Quellaktivität
24. September 2026 um 18:04
Erkannte Sprache von SKILL.md
Englisch
Sterne
0
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
5 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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:
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen