エージェント向けシステムプロンプトの書き方 完全ガイド — Claude Codeのリバースエンジニアリングから学んだこと

Claude Codeのシステムプロンプトをデコンパイルし、DeepAgentsのソースを研究して、ゼロから独自のAIエージェントを構築した。世の中のプロンプトガイドのほとんどは、ただの「雰囲気」だ。

Feng Liu
Feng Liu
2026年3月20日·10 分で読める
エージェント向けシステムプロンプトの書き方 完全ガイド — Claude Codeのリバースエンジニアリングから学んだこと

現在、AI界隈ではちょっとした集団的な錯覚が起きている。

どのチュートリアルを見ても、まるで魔法の呪文を唱えるかのようにシステムプロンプトを書けと教えている。正しい呪文さえ見つければ、モデルは服従するのだ、と。「あなたは20年の経験を持つ、極めて優秀なシニアエンジニアです...」聞き覚えはないだろうか?

私はここ数ヶ月、深い市場調査を行いVCレベルの分析を生成するAIスタートアップアドバイザー、VibeComの構築に費やしてきた。その過程で、Claude Codeのシステムプロンプトをリバースエンジニアリングし、DeepAgentsのミドルウェアのソースコードを読み漁り、認めたくないほど大量のAPIクレジットを消費した。そこから得た最大の教訓は何か?システムプロンプトについて人々が重要だと思っていることのほとんどは、実は重要ではない。そして本当に重要なことについては、ほとんど誰も語っていないということだ。

この記事は、その完全なプレイブックだ。5分で読める概要ではなく、私が開発を始める前に誰かに教えてほしかったことのすべてをまとめている。コーヒーでも淹れて、ゆっくり読んでほしい。


1. 設計哲学:モデルを信頼する

「エージェントとはモデルのことだ。フレームワークでも、プロンプトチェーンでもない。」 — shareAI-lab/learn-claude-code

この考え方が、私にとってすべてを変えた。LLMはすでに推論、計画、実行の方法を知っている。システムプロンプトは、LLMに「考え方」を教えるものではない。LLMが働くための「環境」を整えるためのものだ。

シニアエンジニアを採用する時のことを考えてみてほしい。すべてのタスクに対して20ステップのチェックリストを渡したりはしないはずだ。「我々は何者か」「境界線はどこか」「何をもって成功とするか」を伝え、あとは彼らの邪魔をしないようにするだけだ。

システムプロンプトの役割は、正確に以下の4つだけだ:

  • 自分が何者かを伝える — 役割とアイデンティティ
  • 壁(境界)がどこにあるかを伝える — 安全性の制約
  • 何が良い結果なのかを伝える — 品質基準
  • ツールを与える — 機能と知識

これだけだ。それ以外はすべてノイズに過ぎない。

ハーネスマインドセット(環境構築の思考法)

Harness = Tools + Knowledge + Observation + Action Interfaces + Permissions

システムプロンプトは、このハーネス(制御環境)の操作マニュアルだ。厳格なパイプラインを設計するのではなく、モデルが自律的に最高の仕事ができる環境を設計しているのだ。

システムプロンプトをフローチャートのように書いてはいけない。実行順序はモデル自身が決定する。


2. プロンプトの構造とセクションの順序

推奨されるレイアウト(Claude Code v2.0.14からのリバースエンジニアリング)

┌─────────────────────────────────────────────┐
│ 1. Identity                                  │  ← 最初に読み込まれ、振る舞いの基盤となる
│ 2. Security & Safety                         │  ← 重要なマーカー、交渉の余地なし
│ 3. Tone & Style                              │  ← 出力フォーマットを制御する
│ 4. Core Workflow                             │  ← 仕事の進め方
│ 5. Tool Usage Policy                         │  ← ツール選択の優先順位
│ 6. Domain Knowledge                          │  ← 事前ロードではなく、オンデマンドで
│ 7. Environment Info                          │  ← 実行時コンテキスト、動的に注入される
│ 8. Reminders                                 │  ← 重要なルールを再提示する
├─────────────────────────────────────────────┤
│ [Tool Definitions — system-injected]         │  ← 編集不可、通常は非常に長い
├─────────────────────────────────────────────┤
│ [User Message]                               │
└─────────────────────────────────────────────┘

なぜこの順序が重要なのか

LLMの注意力はU字型のカーブを描く。プロンプトの最初と最後に最も注意を払い、中間部分では注意力が散漫になる。これは「Lost in the Middle(中間の喪失)」効果としてよく知られている現象だ。

  • トップにアイデンティティと安全性: モデルはまず役割と境界を確立する(初頭効果)。
  • 上部の中間にコアワークフロー: 最も重要なセクション。エージェントがどのように仕事をするか。
  • ツール定義はプロンプトの後にシステムから注入される: Claude Codeのツール定義は約11,438トークンを消費する。つまり、あなたが書いたカスタムコンテンツは、予想以上に「最初の方」に配置されることになる。これが指示への遵守率(Adherence)を高める
  • 最後にリマインダー: 親近効果(Recency bias)を利用して、重要なルールを強化する。

3. 各セクションの書き方

3.1 アイデンティティ — このエージェントは何者か?

目的: 1〜3文でモデルの役割を明確に固定する。

You are Claude Code, Anthropic's official CLI for Claude.
You are an interactive agent that helps users with software engineering tasks.

ガイドライン:

  • 簡潔に保つ — 最大1〜3文。
  • 役割を明示的に名付ける(モデルがコンテキストを区別しやすくなる)。
  • 曖昧な「あなたは役立つアシスタントです」ではなく、中核となる責任(「Xを支援する」)を述べる。
  • 該当する場合はSDKやプラットフォームに言及する(「AnthropicのClaude Agent SDKで構築されている」など)。

アンチパターン:

  • 「あなたは役立つ、無害で、誠実なAIアシスタントです」 — 一般的すぎて、役割の固定にならない。
  • バックストーリーや設定を長々と書く — トークンの無駄遣い。モデルにキャラクター開発は必要ない。

3.2 セキュリティと安全性 — 絶対的な境界線

目的: 決して破ってはならない行動の制約を設定する。

IMPORTANT: Assist with defensive security tasks only.
Refuse to create, modify, or improve code that may be used maliciously.
IMPORTANT: You must NEVER generate or guess URLs for the user.

ガイドライン:

  • IMPORTANT: プレフィックスを使用する — Claudeの指示階層のトレーニングでは、これに特別な重みが与えられている。
  • 絶対的な言葉を使用する:NEVER(決して〜しない)、MUST NOT(〜してはならない)、Refuse to(〜を拒否する)。
  • 許可されていることと禁止されていることの両方を述べる(双方向の制約の方が明確になる)。
  • 中間に埋もれさせず、一番上に配置する。
  • 重要な安全ルールは最後にも繰り返す — Claude Codeはまさにこれを行っている。

なぜ繰り返すのか? 初頭効果(最初)+ 親近効果(最後)= 二重の強化。Claude Codeのセキュリティ宣言は、プロンプトの最初と最後の両方に現れる。エンジニアが忘れっぽかったからではない。U字型の注意力カーブを理解しているからだ。

3.3 トーンとスタイル — 出力のコントロール

目的: 出力フォーマットとトーンを制御する。

## Tone and style

- Your responses should be short and concise.
- Only use emojis if the user explicitly requests it.
- Use Github-flavored markdown for formatting.
- NEVER create files unless absolutely necessary.

ガイドライン:

  • 曖昧な「プロフェッショナルであれ」ではなく、具体的な行動をリストアップする。
  • すべてのルールはTrue/Falseでテスト可能であるべき(「短く簡潔に」vs「なるべく手短に」)。
  • 出力フォーマットの要件を含める(Markdown?JSON?プレーンテキスト?)。
  • やってはいけないことも含める — スタイルの問題の多くは、特定の行動を禁止することで解決する。

Claude Codeの秀逸な点 — プロフェッショナルとしての客観性:

Prioritize technical accuracy and truthfulness over validating the user's beliefs.
Focus on facts and problem-solving, providing direct, objective technical info
without any unnecessary superlatives, praise, or emotional validation.

この段落は極めて重要だ。モデルの「ユーザーに迎合する(Sycophancy)」傾向をブロックしてくれる。エージェントが客観的な判断(コードレビュー、アイデアの評価、アーキテクチャの決定)を下す必要がある場合、このような条項が絶対に必要になる。

3.4 コアワークフロー — 最も重要なセクション

目的: 厳格な手順ではなく、方法論として「仕事の進め方」をモデルに教える。

これはうまく書くのが最も難しいセクションであり、正しく書けた時の影響が最も大きいセクションでもある。

核となる原則:手順ではなく、原則を与えること。

LLMに「良い出力とはどのようなものか」「なぜそれが良いのか」を伝え、そこに到達する方法はLLM自身に見つけさせよう。出力が下流のシステムで機械的に処理される場合を除き、正確なフィールド数、ステップの順序、フォーマットを規定するのは避けること。

Claude Codeのアプローチ:

## Doing tasks

The user will primarily request software engineering tasks.
For these tasks the following steps are recommended:

- Use the TodoWrite tool to plan the task if required

「推奨される(recommended)」という言葉の選択に注目してほしい。「これらの正確なステップに従わなければならない」ではない。このたった一つの言葉の選択が、モデルに適応する余地を与えている。

良いワークフロー定義の例:

1. まず理解する — 変更を加える前に既存のコードを読む
2. まず計画する — 実行する前に複雑なタスクをステップに分割する
3. 最小限の変更 — 必要な部分だけを変更し、「ついでにリファクタリング」はしない
4. 検証する — 変更が機能することを確認する(テストの実行、Lintなど)

各ルールには暗黙の「なぜ」が含まれており、モデルはその意図を理解し、新しいシナリオに一般化することができる。

アンチパターン:

  • 厳格な20ステップの手順 — モデルは機械的に実行し、予期せぬ入力でフリーズする。
  • 「まずAをして、次にBをして、次にCをする」 — それはプロンプトチェーンであり、エージェントプロンプトではない。
  • LLMがすでに得意としていることを過剰に指導する — トークンの無駄遣い。

私はVibeComの開発で、これを身をもって学んだ。初期のバージョンには10ステップのリサーチワークフローがあった。ステップ3でユーザーの質問にすでに答えている場合でも、モデルは忠実に10ステップすべてを実行しようとした。これを原則(「十分な証拠が集まるまでリサーチし、その後統合する」)に切り替えたところ、品質が向上し、トークンコストも下がった。

例外: 出力が下流のシステムで機械的に消費される場合(エージェント間通信、APIレスポンスフォーマットなど)は、厳密なフォーマットを定義するべきだ。原則は「振る舞い」のためのものであり、スキーマは「インターフェース」のためのものだ。

3.5 ツール使用ポリシー — 曖昧さの排除

目的: 複数のツールが同じことをできる場合、どのツールを優先すべきかをモデルに伝える。

## Tool usage policy

- Use specialized tools instead of bash commands:
  - Read for reading files instead of cat/head/tail
  - Edit for editing instead of sed/awk
  - Grep for searching instead of grep/rg
- You can call multiple tools in a single response. If independent, call in parallel.
- Use the Task tool for file search to reduce context usage.

ガイドライン:

  • 優先順位を表現するために「〜の代わりに(instead of)」を使用する(Bの代わりにA)。
  • なぜ特定のツールを優先するのか、その理由を説明する(「より良いUXを提供するため」「コンテキスト使用量を減らすため」)。
  • 並列処理の戦略を定義する(独立している場合は並列、依存している場合は直列)。
  • ツール使用時のセキュリティ制約をリストアップする(パスの検証、権限チェックなど)。

ツールとプロンプトの極めて重要な関係:

ツール定義は通常システムから注入され、直接編集することはできない。Claude Codeのツール定義は約11,438トークンもある。これが意味するのは:

  • ツール定義にすでに書かれている情報を繰り返さないこと。
  • システムプロンプトは戦略的なガイダンスに使用すること:各ツールをいつ使用するか、なぜ他のツールより優先するのか、優先順位付けなど。
  • ツール定義の品質はエージェントの有効性に直結する。独自のエージェントを構築する場合は、優れたツールの説明を書くことに時間を投資すること。

3.6 ドメイン知識 — 事前ロードではなく、オンデマンドで読み込む

目的: モデルのトレーニングデータに欠けている可能性のある専門知識を提供する。

核となる原則:知識のダンプ(丸投げ)ではなく、段階的開示(Progressive Disclosure)。

❌ 200個のAPIエンドポイントをすべてシステムプロンプトに貼り付ける → トークンの爆発
✅ モデルに検索するためのツールを与える → 「必要な時に知識をロードする」

この戦略は、Claude CodeのSkillsシステムやDeepAgentsのProgressive Disclosureミドルウェアでも共有されている。すべてを事前にロードするのではなく、ツール呼び出しを通じてオンデマンドで知識をロードするのだ。

実装アプローチ:

  1. システムプロンプトにポインタを置く: 「必要な場合は get_api_docs ツールを使用してドキュメントを取得すること」
  2. プロジェクトのコンテキストに CLAUDE.md / AGENTS.md を使用する — ハードコードするのではなく、実行時にロードする。
  3. 機能の発見に Skills / SKILL.md を使用する — モデルは利用可能なスキルのメニューを見て、オンデマンドで完全な仕様を取得する。

3.7 環境情報 — 実行時のコンテキスト

目的: モデルに実行環境を認識させる。

<env>
Working directory: /Users/fengliu/Desktop/tfm/vibecom
Is directory a git repo: true
Platform: darwin
Today's date: 2026-03-21
</env>
You are powered by the model named Claude Opus 4.6.

ガイドライン:

  • 動的に生成し、決してハードコードしない。
  • 含めるべきもの:作業ディレクトリ、プラットフォーム、日付、モデル名、Gitのステータス。
  • パースしやすいように構造化されたフォーマット(XMLタグやコードブロック)を使用する。
  • 日付は重要 — 情報の鮮度を判断するために、モデルは「現在」を知る必要がある。

3.8 リマインダー — 最後の念押し

目的: プロンプトの最後で、最も重要なルールを再度提示する。

Claude Codeは、安全性に関する制約とTodoWriteの要件を最後にもう一度繰り返している:

IMPORTANT: Assist with defensive security tasks only. [repeated]
IMPORTANT: Always use the TodoWrite tool to plan and track tasks. [repeated]

ガイドライン:

  • 最も重要なルールを2〜3個だけ繰り返す — すべてを複製しないこと。
  • 親近効果(Recency bias)を利用する — モデルは最近のコンテンツをより強く記憶する。
  • 最適な候補:安全性の制約、最も頻繁に違反されるルール、コアワークフローのリマインダー。

4. トークン予算とコンテキスト管理

予算配分の目安

セクション推奨トークン数備考
アイデンティティ + 安全性200-500簡潔に、しかし妥協なく
トーンとスタイル300-800ルールは具体的に、ただし長々と書かない
コアワークフロー500-2,000最も重要なセクション、投資する価値あり
ツール使用ポリシー300-1,000ツールの数に依存
ドメイン知識0-1,000オンデマンドでのロードを推奨
環境情報100-300動的に生成される
リマインダー100-300必須事項のみを繰り返す
あなたの合計1,500-6,000
ツール定義(システム)5,000-15,000コントロール不可

コンテキスト劣化のカーブ

コミュニティのテスト(Redditの u/CodeMonke_)により、実際の指示遵守率の低下がマッピングされている:

  • 80Kトークン未満: プロンプトの遵守率は安定している
  • 80K - 120Kトークン: 指示への従順さが低下し始める
  • 120Kトークン以上: 著しい低下 — モデルは初期の指示を「忘れる」
  • 180Kトークン以上: 深刻な劣化

200Kのコンテキストウィンドウ ≠ 200Kの有効なコンテキストである。これを見越して計画を立てよう。

軽減戦略:

  • システムプロンプトをスリムに保つ(自分のパートは6,000トークン未満に)。
  • 要約を使用して会話履歴を圧縮する(DeepAgentsは約80K文字でトリガーされる)。
  • 重要なルールをプロンプトの両端に配置する(U字型の注意力)。
  • 会話の途中で <system-reminder> タグを注入する(詳しくはセクション8で)。

5. ライティングの原則

5.1 手順ではなく、原則を与える

❌ 「ステップ1: ファイルを読む。ステップ2: バグを見つける。ステップ3: 修正する。ステップ4: テストを実行する。」
✅ 「変更を加える前に必ず既存のコードを理解すること。変更が機能するか検証すること。」

原則は一般化できる。手順は機械的に従うことしかできない。モデルがあなたの予期せぬ状況に遭遇したとき、原則は正しい決定を導いてくれるが、手順はそうはいかない。

例外: 出力が機械によって消費される場合(エージェント間通信、APIフォーマット)は、厳密なスキーマを定義する。

5.2 厳格な制約には絶対的な言葉を使う

強度言葉遣い用途
絶対的な禁止NEVER, MUST NOT安全性、不可逆的な操作
強い要件ALWAYS, MUSTコアワークフローのルール
推奨recommended, prefer例外のあるベストプラクティス
提案consider, you may任意の最適化

Claude Codeの例:

  • NEVER update the git config — 絶対的な禁止
  • ALWAYS prefer editing an existing file — 強い要件だが、例外は存在する
  • The following steps are recommended — 推奨されるワークフロー

5.3 説明の代わりに例を使う

## Code References

When referencing specific functions or pieces of code include
the pattern `file_path:line_number`.

<example>
user: Where are errors from the client handled?
assistant: Clients are marked as failed in the `connectToServer`
function in src/services/process.ts:712.
</example>

1つの例は、100語の説明よりも多くのことを教えてくれる:

  • モデルは抽象的な説明よりも、例からパターンを確実に学習する。
  • ルールと区別するために <example> タグで囲む。
  • 肯定的な例(「こうする」)と否定的な例(「こうしない」)の両方を提供する。
  • 「foo/bar」のようなプレースホルダーではなく、具体的でリアルな例を使用する。

5.4 双方向の制約

✅ 「専用ツールを使用すること:ファイルの読み込みにはRead、編集にはEdit。」
✅ 「ファイル操作にbashを使用しないこと(cat, head, tail, sed, awk)。」

「これをしろ」とだけ言う → モデルはいつそれを「してはいけない」のか分からない。 「これをするな」とだけ言う → モデルは代替案が分からない。 双方向 → 明確で曖昧さがない。

5.5 「何を」だけでなく「なぜ」を説明する

❌ 「git commit --amend を使用しないこと。」
✅ 「git commit --amend は避けること。--amend を使用するのは以下のいずれかの場合のみ:
   (1) ユーザーが明示的に amend を要求した
   (2) pre-commit フックからの編集を追加する
   理由:amend は他人のコミットを上書きする可能性があるため。」

なぜを説明することで、モデルはエッジケースでも正しい判断を下せるようになる。Claude CodeのGitセーフティプロトコルはまさにマスタークラスだ。すべてのルールにその根拠が示されている。

5.6 散文よりも構造を

  • Markdownヘッダー (##, ###) — モデルは階層を認識する
  • 段落よりも箇条書き — 各ルールを独立してテスト可能にする
  • 特別なコンテンツにはXMLタグ<example>, <env>, <system-reminder>
  • 比較やマッピングにはテーブル
  • 構造化されていないテキストをそのまま投げ込まない — 遵守率のテストにおいて、構造化されたプロンプトは常に自然言語の散文を上回る。

6. トークンを無駄にするアンチパターン

エージェントを装ったプロンプトチェーン

「まずツールAを呼び出してデータを取得する。
次にその結果を使ってツールBを呼び出す。
次に出力をJSONとしてフォーマットする。
次にファイルに保存する。」

これはエージェントプロンプトではない。パイプラインスクリプトだ。モデルは機械的に実行し、自律的な計画能力を失ってしまう。

解決策: モデルに目標と制約を伝える。ステップはモデル自身に決定させる。

おだてエンジニアリング(Flattery Engineering)

「あなたは20年の経験を持つ、極めて優秀で信じられないほど経験豊富な
シニアソフトウェアエンジニアです...」

褒め言葉や最上級の表現は、出力の品質を向上させない。モデルには自尊心などないのだ。その15トークンは、実際のルールのために節約しよう。

知識のダンプ(丸投げ)

「ここに当社の200個のエンドポイントの完全なAPIドキュメントがあります...」

これはコンテキストウィンドウを食い潰し、コンテキストの劣化を加速させる。オンデマンドでのロードに置き換えよう:

「必要な場合は get_api_docs ツールを使用してAPIドキュメントを取得すること。」

ツールの説明の繰り返し

ツール定義にすでに「Readツールはファイルシステムからファイルを読み込む」と書かれているなら、システムプロンプトでそれを繰り返さないこと。ツール定義でカバーされていない戦略的なガイダンス(いつ使うべきか、なぜ優先すべきか、優先順位など)のみを追加しよう。

エラーハンドリングの欠如

明示的なガイダンスがないと、モデルは失敗したツール呼び出しを無限ループで再試行してしまう。常に以下を含めること:

「ツール呼び出しが拒否された場合、全く同じ呼び出しを再試行しないこと。
なぜ拒否されたのかを考え、アプローチを調整すること。」

コンテキストウィンドウの劣化を無視する

200Kのコンテキストウィンドウ ≠ 200Kの有効なコンテキスト。実際のテストでは、80Kから劣化が始まることが示されている。要約戦略が必要だ。


7. 注入ポイントと優先順位

Claude Codeの3つのカスタマイズ方法

メソッド置き換える対象配置場所最適な用途
Output Styles"Tone and style" + "Doing tasks" セクションツール定義の直前インタラクションスタイルの変更
--append-system-promptなし(追加)出力スタイルの後、ツール定義の前特定の振る舞いの追加
--system-promptシステムプロンプト全体ツール定義 + 1行のアイデンティティは保持完全なカスタマイズ(最終手段)

複数使用する場合の順序:Output Style → Append Prompt → Tool Definitions

指示の階層

Claudeは、指示の階層を理解するように特別にトレーニングされている:

1. ユーザーの明示的な指示(CLAUDE.md、直接のリクエスト)  ← 最優先
2. カスタムシステムプロンプトの追加分                               ← 高
3. デフォルトのシステムプロンプト                                        ← 中
4. ツール定義                                             ← リファレンスレベル

これが意味するのは:

  • CLAUDE.mdのルールは、デフォルトのシステムプロンプトの振る舞いを上書きする。
  • ユーザーの直接のリクエストは、すべてを上書きする。
  • あなたのカスタムプロンプトは、デフォルトのプロンプトを上書きする。

動的な注入メカニズム

  • <system-reminder> — 会話の途中で任意のメッセージに注入し、重要なルールをモデルに思い出させる。
  • CLAUDE.md / AGENTS.md — 実行時にファイルから読み込まれ、システムプロンプトに追加される。
  • Skills / SKILL.md — ツール呼び出しを通じてオンデマンドで読み込まれ、システムプロンプトのフットプリントをゼロにする。

8. 会話途中での注入 — 秘密兵器

システムプロンプトは、メッセージ配列の一番最初に一度だけ表示される。しかし、LLMは(ユーザー / アシスタント / ツールのメッセージが交互に並ぶ)完全なメッセージ配列を入力として受け取るため、ユーザーメッセージやツールの結果にもプロンプトを注入することができる。 Claude Codeは本番環境でこのテクニックを多用している。

なぜ必要なのか

コンテキストの劣化と戦うため。 会話が長くなるにつれて、システムプロンプトの指示に対するモデルの遵守率は低下する(80Kトークン以上で顕著になる)。会話の途中でリマインダーを注入する = 親近効果によってルールをリフレッシュするということだ。

メンタルモデル:

  • システムプロンプト = 憲法(一度だけ制定され、長期的な権威を持つ)
  • ユーザーメッセージのリマインダー = メモ/通達(定期的に送信され、執行を維持する)

メッセージ配列における3つの注入ポイント

Messages Array:
┌─────────────────────────────────────┐
│ System Prompt                       │ ← 一度だけ表示される、初頭効果
│   (identity, safety, workflow...)   │
├─────────────────────────────────────┤
│ User Message 1                      │
│ Assistant Message 1                 │
│ User Message 2 + <system-reminder>  │ ← 会話途中での注入
│ Assistant Message 2                 │
│ Tool Result + <system-reminder>     │ ← ツールの結果にも注入可能
│ ...                                 │
│ User Message N + <system-reminder>  │ ← 最新のメッセージ、最も強い親近効果
└─────────────────────────────────────┘
場所利点欠点
システムプロンプト初頭効果、最初に読まれる一度しか表示されず、長い会話では「忘れられる」
ユーザーメッセージへの注入親近効果、定期的なリフレッシュ注入のたびにトークンを消費する
ツールの結果への注入最も自然な注入ポイントツールが呼び出された時にしか機能しない

Claude Codeは実際にどう使っているか

前提条件 — システムプロンプトでタグを宣言する:

Tool results and user messages may include <system-reminder> tags.
<system-reminder> tags contain useful information and reminders.
They are automatically added by the system, and bear no direct
relation to the specific tool results or user messages in which they appear.

このステップは極めて重要だ。これらのタグがユーザーの発言ではなく、システムから注入されたものであることをモデルに伝える役割を果たす。

用途1:行動のリマインダー(定期的なルールのリフレッシュ)

<system-reminder>
The task tools haven't been used recently. If you're working on tasks
that would benefit from tracking progress, consider using TaskCreate...
</system-reminder>

Claude Codeはこれを使用して、TodoWriteで計画を立てるようモデルに思い出させている。なぜなら、モデルは計画を立てることを「忘れ」、すぐにコーディングを始めてしまう傾向があるからだ。

用途2:モードの切り替え(プランモード)

<system-reminder>
Plan mode is active. The user indicated that they do not want you to
execute yet -- you MUST NOT make any edits, run any non-readonly tools,
or otherwise make any changes to the system.
</system-reminder>

プランモードはシステムプロンプトには実装されていない。次のユーザーメッセージに注入されるタグなのだ。これにより、システムプロンプトを変更することなく、動的にモードを切り替えることができる。見事な手法だ。

用途3:ファイル変更の通知

<system-reminder>
Note: /path/to/file.ts was modified, either by the user or by a linter.
This change was intentional, so make sure to take it into account.
</system-reminder>

外部プロセス(リンター、フォーマッター、手動編集)がファイルを変更した際、システムはリマインダーを通じてモデルに通知する。これにより、古いファイルの内容に基づいた判断を防ぐことができる。

用途4:動的なコンテキスト(日付、プロジェクトのルール)

<system-reminder>
Today's date is 2026-03-21.
Current branch: dev
claudeMd: [CLAUDE.md content injected here]
</system-reminder>

実行時のコンテキスト(日付、Gitのステータス、プロジェクトのルール)は、システムプロンプトにハードコードされるのではなく、ユーザーメッセージを通じて注入される。

リマインダーを書くためのガイドライン

  • XMLタグで囲む (<system-reminder>) — モデルはシステムからの注入とユーザーの発言を区別できる。
  • システムプロンプトでタグを事前宣言する — そうしないと、モデルがリマインダーに返答しようとする可能性がある。
  • すべてのメッセージに注入しない — 注入のたびにトークンを消費するため、必要な時だけ注入する。
  • 短く保つ — リマインダーは2つ目のシステムプロンプトではない。1〜2個の重要なルールにとどめる。
  • システムプロンプトと矛盾させない — リマインダーは補完と強化のためのものであり、上書きするものではない。
  • 動的な切り替えに使用する — プランモード、読み取り専用モード、機能フラグなどに活用する。

システムプロンプトとユーザーメッセージリマインダーの使い分け

シナリオシステムプロンプトユーザーメッセージリマインダー
役割の定義
安全性の制約✅ 最初の宣言✅ 定期的な繰り返し
ワークフローの方法論
モードの切り替え(プランモード)
ファイル変更の通知
日付 / 環境情報✅ 初期値✅ 更新された値
振る舞いの修正
ツール使用のリマインダー✅ ルールの定義✅ 実行の促進

9. プロンプトキャッシュ — 反復トークンを90%節約する

Anthropicのプロンプトキャッシュを使用すると、メッセージ配列の**静的なプレフィックス(先頭部分)**をキャッシュできる。後続のリクエストが同じプレフィックスを共有している場合、キャッシュがヒットし、コストとレイテンシを削減できる。

エージェントにとって、これは非常に重要だ。会話中のすべてのLLM呼び出しにおいて、システムプロンプトとツール定義を毎回再送信しているからだ。

重要な数値

指標
キャッシュヒットのコスト通常価格の10%(90%の節約)
キャッシュ書き込みのコスト通常価格の125%(初回書き込み時に25%の割増)
キャッシュのTTL(有効期間)5分(リクエストがないと期限切れ)
最小キャッシュ可能長1,024トークン(Claude 3.5以降)
キャッシュの粒度プレフィックスマッチング — 先頭からマークされたブレークポイントまで
最大ブレークポイント数4

これがプロンプト設計をどう変えるか

核となる原則:静的なコンテンツを先に、動的なコンテンツを後に。

✅ キャッシュフレンドリーなレイアウト:
  System prompt (static)      ← キャッシュブレークポイント 1
  Tool definitions (static)   ← キャッシュブレークポイント 2
  CLAUDE.md / project rules   ← キャッシュブレークポイント 3(時々変更される)
  Conversation history         ← ローリングウィンドウ用のブレークポイント 4

❌ キャッシュを破壊するレイアウト:
  System prompt
  DYNAMIC TIMESTAMP            ← リクエストごとに変更されるため、これ以降はすべてキャッシュミスになる
  Tool definitions
  Conversation history

誰も警告してくれない罠: システムプロンプトの途中に動的なタイムスタンプを入れると、それ以降のすべてがキャッシュミスになる。毎回の。すべての。リクエストでだ。間違った場所にタイムスタンプを1つ置くだけで、何千ものトークンにフルプライスを支払うことになる。

APIの使用方法

const response = await anthropic.messages.create({
  model: "claude-sonnet-4-6",
  system: [
    {
      type: "text",
      text: "You are a startup advisor...",
      cache_control: { type: "ephemeral" }  // ← キャッシュブレークポイントをマーク
    }
  ],
  messages: [...]
});

マルチブレークポイント戦略

ブレークポイント 1: システムプロンプト           ← ほとんど変更されない
ブレークポイント 2: ツール定義         ← ほとんど変更されない
ブレークポイント 3: プロジェクトルール / CLAUDE.md ← 時々変更される
ブレークポイント 4: 最初のN個の履歴メッセージ  ← ローリングウィンドウキャッシュ

会話履歴が変更された場合でも、最初の3つのブレークポイントはヒットし続ける。10ターンの会話で、入力トークンコストを約40〜60%節約できる。

設計の推奨事項

  • システムプロンプトに高頻度で変動する動的な値を入れない — 日付は問題ない(日次で変わるため)が、正確なタイムスタンプはNG。
  • 動的なコンテキスト(Gitのステータスなど)はユーザーメッセージに注入する — システムプロンプトに入れるとキャッシュが破壊される。
  • ツール定義を安定させる — 実行時に動的にツールを追加/削除しない。
  • 会話履歴にローリングウィンドウを使用する — 最初のN個のメッセージをキャッシュし、最新のメッセージのみをキャッシュミスにする。

10. チェックリスト

システムプロンプトを書いた後、このチェックリストで確認しよう:

構造

  • アイデンティティは一番上に配置されているか?
  • 安全性の制約には IMPORTANT とマークし、最後にも繰り返しているか?
  • ヘッダーを使用してセクションを明確に分離しているか?
  • 例は <example> タグで囲まれているか?

トークン予算

  • 自分のパートは6,000トークン未満に収まっているか?
  • ツール定義にすでに書かれている情報を繰り返していないか?
  • ドメイン知識は事前ロードではなく、オンデマンドで読み込まれるようになっているか?
  • 冗長な設定やキャラクターのバックストーリーはないか?

ルールの品質

  • すべてのルールはTrue/Falseでテスト可能か?
  • 厳格な制約には絶対的な言葉(NEVER/MUST)を使用しているか?
  • 緩やかな提案には推奨の言葉(recommended/prefer)を使用しているか?
  • 重要なルールは「何を」だけでなく「なぜ」を説明しているか?
  • 双方向の制約(これをする + これをしない)になっているか?

エージェントの振る舞い

  • 厳格なステップバイステップの手順ではなく、原則を与えているか?
  • 「ツール呼び出しが拒否された」シナリオを処理しているか?
  • 「障害に遭遇した」場合の戦略(力任せに再試行しない)を処理しているか?
  • コンテキスト管理戦略(要約のしきい値など)は用意されているか?

やってはいけないこと

  • おだてや最上級の形容詞を使っていないか?
  • 「あなたは役立つAIです」といった冗長な宣言はないか?
  • プロンプトチェーンのように書かれていないか?
  • オーバーエンジニアリング(誰も求めていない機能)になっていないか?

もし今日、私がゼロから始めるなら

私なら、正確に以下のことを行う:

  1. 最初の3行でアイデンティティと安全性を設定する。 エージェントが何者であるかを2文で。NEVER/MUSTを使った厳格な制約。安全ルールは最後にも繰り返す。

  2. コアワークフローはステップではなく原則として書く。 最大4〜5個の箇条書き。緩いルールには「recommended」や「prefer」を、厳格なルールには「NEVER」や「MUST」を使う。

  3. 自分のパートの予算を1,500〜6,000トークンにする。 ツール定義でさらに5,000〜15,000トークンが追加される。もし6Kを超えているなら、オンデマンドで読み込むべき知識をダンプしてしまっている可能性が高い。

  4. すべてを構造化する。 Markdownのヘッダー、箇条書き、例のためのXMLタグ。構造化されたプロンプトは、常に自然言語の散文を上回る。

  5. 初日から会話途中でのリマインダーを組み込む。 システムプロンプトで <system-reminder> を宣言する。重要なルール、モードの切り替え、コンテキストの更新のためにリマインダーを注入する。

  6. キャッシュを前提に設計する。 静的なコンテンツを先に、動的なコンテンツを後に。変化する値をシステムプロンプトの本文に絶対に入れない。


これだけの作業をしておいて皮肉なことだが、最高のシステムプロンプトは短い。Claude Codeのカスタム指示(ツール定義を除く)は驚くほど簡潔だ。すべての行が、そこに存在する意味を持っている。

以前は、プロンプトエンジニアリングとは気の利いたトリックを見つけることだと思っていた。しかし今は、それは「規律」の問題だと考えている。語る言葉を減らし、正確に伝え、あとはモデルが自分で答えを出してくれると信頼することだ。モデルはあなたのプロンプトよりも賢い。振る舞いではなく、環境を設計しよう。


参考文献

ソース重要な洞察
Claude Code v2.0.14 System Prompt本番環境のエージェントプロンプト構造の完全なリファレンス
Reddit: Understanding Claude Code's 3 System Prompt MethodsOutput Styles / --append / --system-prompt の詳細、コンテキスト劣化の実際のデータ
shareAI-lab/learn-claude-code「モデルこそがエージェントである」という哲学、ハーネスエンジニアリングの方法論
Anthropic Prompt Engineering Docs公式のプロンプトベストプラクティス
DeepAgents Framework要約ミドルウェア、スキルの段階的開示(Progressive Disclosure)
ai agent system promptsprompt engineering guideclaude code system promptbuilding ai agentsllm prompt optimization

シェア

Feng Liu

執筆者 Feng Liu

shenjian8628@gmail.com

エージェント向けシステムプロンプトの書き方 完全ガイド — Claude Codeのリバースエンジニアリングから学んだこと | Feng Liu