The single source of truth for prompt-engineering best practices used by this suite. Provides a named, severity-graded rubric for reviewing prompts and a set of guidelines for authoring new ones, including where prompts belong in layered/clean architectures. Read this whenever auditing, authoring, or fixing an LLM prompt.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add assist-software/claude-code-repository --skill prompt-best-practices --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Prompt Best Practices?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/assist-software-prompt-best-practices)More formats (shields.io, HTML) on the badges page.
---
name: prompt-best-practices
description: The single source of truth for prompt-engineering best practices used by this suite. Provides a named, severity-graded rubric for reviewing prompts and a set of guidelines for authoring new ones, including where prompts belong in layered/clean architectures. Read this whenever auditing, authoring, or fixing an LLM prompt.
---
# Prompt Best Practices — Rubric & Authoring Guide
This skill is the shared standard that the `prompt-discovery`, `prompt-reviewer`,
`context-gatherer`, and `prompt-writer` subagents all rely on. Reviewing and
authoring must use the *same* rules so a prompt this suite writes would also pass
the review this suite runs.
If a `.prompt-review.yaml` config exists at the repo root, it overrides this file:
teams may disable checks, change severities, or add house rules. Always load it
first (see "Project configuration" below) and merge it over these defaults.
---
## How to use this rubric
For each prompt under review, evaluate every applicable check and emit a finding:
- **id** — the check id (e.g. `PE-03`)
- **severity** — `HIGH` | `MEDIUM` | `LOW` (after applying config overrides)
- **status** — `pass` | `fail` | `n/a`
- **evidence** — the specific line / snippet that triggered it
- **fix** — a concrete suggested rewrite (a diff), never a vague instruction
Severity meaning:
- **HIGH** — security or correctness risk. Ship-blocking. (injection, no output contract for parsed output)
- **MEDIUM** — materially hurts reliability or quality. Should fix.
- **LOW** — efficiency or style. Nice to fix.
Do not invent new severities. Do not pass a check you did not actually verify
against the prompt text.
---
## The rubric
### Security & correctness (usually HIGH)
**PE-01 — Role separation.** Stable instructions live in the system role; per-request
data lives in the user role. User-controlled text must never be concatenated into the
system instructions.
- *Fail signal:* a single f-string/template that mixes fixed instructions and user input in one role.
- *Severity:* HIGH if user input is involved, else MEDIUM.
**PE-02 — Untrusted input is delimited.** Any user- or third-party-supplied content
is wrapped in explicit delimiters (e.g. `<doc>…</doc>`, triple backticks) and the
instructions name those delimiters.
- *Severity:* HIGH when the input is user-controlled.
**PE-03 — Trust boundary stated (injection hardening).** The prompt explicitly tells
the model that delimited content is DATA, not instructions, and to ignore any
instructions found inside it.
- *Severity:* HIGH for any prompt that embeds external/user input.
**PE-04 — Output contract.** If the output is parsed by code, the prompt constrains
the output (JSON mode / tool calling / a named schema / a strict enum) rather than
hoping for a parseable shape from prose.
- *Fail signal:* code does `json.loads(response)` / regex-scrapes a free-text answer.
- *Severity:* HIGH when output is parsed; MEDIUM otherwise.
### Reliability & quality (usually MEDIUM)
**PE-05 — Specificity.** The task is concrete: it states the action, the exact output
format (count/length/structure), the audience where relevant, and constraints
(what to do AND what not to do).
- *Severity:* MEDIUM.
**PE-06 — Grounding & escape hatch.** For knowledge/extraction tasks, the prompt
supplies the source material and tells the model to answer only from it, with an
explicit "if not present, say NOT_FOUND" escape hatch to curb hallucination.
- *Severity:* MEDIUM (HIGH if the prompt is used in a factual/compliance context).
**PE-07 — Few-shot for format-sensitive tasks.** Classification, extraction, or
strict-format tasks include 2–4 examples (kept as data, not prose) when zero-shot
reliability is shaky.
- *Severity:* LOW–MEDIUM, task dependent.
**PE-08 — Determinism settings.** The call sets parameters appropriate to the task:
`temperature=0` for extraction/classification/deterministic output; `max_tokens`
bounded; not relying on provider defaults. (This is a call-site check, not prompt text.)
- *Severity:* MEDIUM.
### Engineering hygiene (usually LOW–MEDIUM)
**PE-09 — Prompts as code.** The prompt is a named, parameterized template — not a
scattered inline string literal. It is reusable, reviewable, and located in the right
place in the codebase (see "Where prompts belong").
- *Fail signal:* the same or near-duplicate prompt string appears in multiple files; prompt embedded in a controller/handler/domain entity.
- *Severity:* MEDIUM if duplicated or mislayered; LOW for a single tidy inline prompt in a small app.
**PE-10 — Evaluation reference.** There is some test/eval covering this prompt's
behavior (a golden set, snapshot test, or assertion). A prompt with no test is a
prompt that can silently regress.
- *Severity:* MEDIUM.
**PE-11 — Token & context efficiency.** No redundant boilerplate, no duplicated
instructions, no needlessly long examples. Instructions are tight.
- *Severity:* LOW.
**PE-12 — Model-appropriateness.** If the target is a small/local model, the prompt
is explicit and tightly structured (small models tolerate vague prompts poorly). If
prompts are shared across model tiers, that portability is acknowledged.
- *Severity:* LOW–MEDIUM.
---
## Where prompts belong (architecture-aware placement)
A prompt is an **infrastructure / integration concern** — it is the contract with an
external LLM provider, not business logic. Placement therefore depends on the
codebase's architecture. Detect the style first, then recommend accordingly.
**Clean / Hexagonal / Onion / DDD (common in Java & C#):**
- *Domain layer:* NO prompts. Keep it pure — entities, value objects, domain services only.
- *Application layer:* defines a **port/interface** expressing intent, e.g.
`ISummarizationService.Summarize(text)` — no prompt text, no provider details.
- *Infrastructure / Adapters layer:* the **prompt templates live here**, inside the
adapter that implements the port and talks to the LLM. Prefer a dedicated
`Prompts/` folder or externalized resources (`.resx` in C#, resource bundles or
`src/main/resources` in Java, `.jinja`/`.txt`/`.yaml` elsewhere) over hardcoded
string constants.
- *Rule of thumb:* if swapping the LLM provider would force you to touch a file, that
file belongs in infrastructure — and so does its prompt.
**Layered MVC / service-oriented (no strict clean architecture):**
- Centralize prompts in a dedicated module/package (e.g. `prompts/`, `app/prompts`,
`PromptTemplates`), referenced by name. Keep them out of controllers and views.
**Small app / script:**
- A single, well-named templates file is enough. Don't over-engineer.
**Existing convention wins.** If the repo already has an established place for prompts,
follow it and only suggest moving things if the current placement violates a layer
boundary (e.g. a prompt sitting in a domain entity).
---
## Authoring guidelines (for prompt-writer)
When creating new prompts for a feature:
1. **Understand intent first.** Use the gathered project context (READMEs, feature
docs, surrounding business logic) to state, in one sentence, what the prompt must
accomplish and how its output is consumed.
2. **Design the output contract before the words.** Decide the schema/enum/format the
calling code needs (PE-04). Write the prompt to produce exactly that.
3. **Separate roles** (PE-01), **delimit any injected data** (PE-02), and **state the
trust boundary** (PE-03) from the start.
4. **Be specific** (PE-05): role, audience, format, constraints, and an escape hatch
(PE-06) where facts are involved.
5. **Parameterize** — named variables, not concatenation. Produce it as a reusable
template (PE-09) and place it in the correct architecture layer (above).
6. **Propose an eval** (PE-10): suggest a tiny golden set or assertion alongside the prompt.
7. **Set call parameters** (PE-08): recommend temperature/max_tokens for the task.
8. Ask the developer a targeted question ONLY where business context is genuinely
missing and cannot be inferred from the codebase.
A newly authored prompt must pass its own review. Self-check it against the rubric
before presenting.
---
## Project configuration
Look for `.prompt-review.yaml` at the repo root. Shape:
```yaml
# Disable checks by id, or override severity
checks:
PE-07: { enabled: false }
PE-11: { severity: low }
# Fail the run if any finding is at or above this severity (used in CI later)
fail_threshold: high
# Extra house rules appended to the rubric (free text, evaluated like checks)
house_rules:
- "All user-facing prompts must include a brand-voice note."
target_models:
- "gpt-4o-mini"
- "llama3.1 (local)"
```
If the file is absent, use the defaults in this document and mention that no project
config was found.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!