lwlee2608/agent-skills

writing-system-prompts

Use when writing or editing a system prompt for any LLM API or SDK (any code passing a system= / system role parameter, or a .txt/.md file holding such a prompt).

소스 보기

사용 방법

  1. 설치 명령을 복사하고 자신의 에이전트 환경에 설치하기 전에 소스 패키지를 확인하세요.
  2. 필요한 도구, 인증 정보, 지원 환경은 원본 문서에서 확인하세요.
  3. 입력과 원하는 산출물을 설명하고 출처와 결과를 대조하세요.
npx skills add https://github.com/lwlee2608/agent-skills --skill writing-system-prompts

시작 전 확인

  • 설치에는 모델 구독, API 한도, 파일 접근 권한이 포함되지 않습니다.
  • 별점 수와 설치 수는 활동 지표이며 독립적인 품질·보안 검증이 아닙니다.
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

Writing LLM System Prompts

A well-built system prompt steers behavior across the whole conversation and — if structured for KV-cache reuse — costs a fraction of an uncached prefix on providers that offer prompt caching (Anthropic, OpenAI, Bedrock, Vertex, etc.).

Rules

  1. Put the role first, in one sentence. A single descriptive sentence in the system field (not the user turn) anchors tone and vocabulary, e.g. You are a helpful coding assistant specializing in Python. Plain prose at the top — do not wrap in markup.
  1. Order static-first, dynamic-last. Cache hits require a byte-identical prefix. Sequence: role → tools/policies → long reference docs / few-shot examples → cache breakpoint → dynamic context → user turn. Why: one changed token before the breakpoint drops you from cached-read pricing (~10% of input) to full input cost.
  1. Mark cache breakpoints explicitly when the provider supports it. Most caching is opt-in (e.g. Anthropic cache_control, Bedrock cachePoint). Place a breakpoint at the end of each stable block to reuse. Cache writes typically cost more than base input; reads a fraction of it. TTLs vary (commonly ~5 min, sometimes longer tiers). Only cache prefixes you'll reuse within the TTL — sparse traffic pays the write penalty repeatedly.
python
   # Anthropic example — adapt to your provider's syntax
   system=[
       {"type": "text", "text": ROLE_AND_POLICIES},
       {"type": "text", "text": LONG_REFERENCE_DOC,
        "cache_control": {"type": "ephemeral"}},
   ]
  1. Never put churning content at the prefix. Current time, request ID, user ID, or conversation summary at the top defeats caching for the whole prompt. Push them past the breakpoint — either a second system message (for authoritative facts like date/IDs) or the user turn (for task material like questions and documents). Both preserve cache reuse equally.
  1. Use structural delimiters for distinct sections. Wrap longform inputs and behavioral directives in clear delimiters — XML tags (<documents><document>…</document></documents>, <default_to_action>…</default_to_action>), markdown headers, or named JSON fields. Why: delimited sections survive long contexts better than walls of prose, and several model families (notably Claude) are explicitly trained on XML structure.
  1. Place longform data above instructions in the user turn. For 20k+ token inputs, docs at the top, question at the bottom — measured up to 30% quality lift on multi-document tasks across major models.
  1. Write literal, scoped instructions. Modern instruction-tuned models interpret prompts increasingly literally and won't silently generalize. If a rule applies broadly, say so: Apply this formatting to every section, not just the first one. Avoid ALL-CAPS shouting (CRITICAL, MUST) — it causes over-triggering on recent Claude models and adds little on others; use normal imperative voice.
  1. Tune verbosity, tone, tool use, and subagent spawning only when the default is wrong. Examples: Provide concise, focused responses. Skip non-essential context. / Use a warm, collaborative tone. / Spawn multiple subagents in the same turn when fanning out across items. Do not spawn a subagent for work you can complete in a single response. Override defaults only after observing a problem — don't pre-empt.

Verification procedure

After drafting or editing, check each:

  1. Role check — One-sentence role at the very top of the system field?
  2. Cache-order check — List segments top-to-bottom. Is every segment before the breakpoint stable across requests? Move per-request values below the breakpoint (second system message or user turn).
  3. Breakpoint check — Is the breakpoint on the last static block? Is the cached prefix above the provider's minimum (e.g. 1024 tokens for Anthropic Opus/Sonnet, 2048 for Haiku, 1024 for OpenAI)? Below the minimum, breakpoints are silently ignored.
  4. Structure check — Longform docs wrapped in delimiters? Behavioral blocks in named tags or sections?
  5. Literalism check — If an instruction says "format the output" but means "format every section," rewrite with explicit scope.

Common mistakes to watch for

  • Timestamp at the top. Current date: {{today}} in the role line invalidates the cache every request. Move past the breakpoint — second system message or user turn.
  • Caching a tiny prefix. A short system prompt below the provider's minimum — breakpoint silently ignored and you still pay the write surcharge. Either grow the cached block or drop the breakpoint.
  • Conversation history before the breakpoint. History grows every request, so anything after it can never be cached. Put the breakpoint before the rolling history.
  • Copy-pasted legacy `CRITICAL: YOU MUST…` shouting. Causes over-triggering on recent models. Rewrite as plain imperatives.
  • Role in the user message. You are a… in messages[0] instead of the system field weakens steering and wastes a cacheable slot.