プロンプト設計の基本——構成要素とプロンプトキャッシュによるコスト削減
プロンプト設計は「センスの良い言い回しを見つける職人芸」だと思われがちですが、業務システムに組み込む段階では話が変わります。毎回思いつきで書くのではなく、決まった構成要素を意識して組み立てることで、出力の再現性を上げ、後から見直せる設計にできます。この記事では、業務用途のプロンプトを組み立てる際の基本要素と、AIエージェントの記事・MCPサーバーの記事で紹介したような、繰り返し実行されるループでコストを抑えるためのプロンプトキャッシュの使い方を扱います。
プロンプトを構成する4つの要素
業務システム向けのプロンプトは、おおむね次の4つに分解して考えると設計しやすくなります。
- 役割・振る舞いの定義: 「あなたは在庫管理を支援するアシスタントです」のように、システムプロンプトでモデルの立場と守るべき制約を明示する
- タスクの具体化: 「何を」「どの粒度で」実行してほしいのかを、抽象的な指示ではなく具体的な作業として書く
- 出力フォーマットの指定: 自由文で返してほしいのか、箇条書きか、特定のJSON構造かを明示する。フォーマットを指定しないと、同じ指示でも実行のたびに体裁が変わり、後続処理でパースできなくなる
- 例示(few-shot): 期待する入出力のペアを1〜2個プロンプトに含めておくと、フォーマット遵守率が体感できるほど上がる。特に日本語の業務文書は言い回しの幅が広いため、例示なしで安定した形式を期待するのは難しい
const system = `あなたは見積依頼メールから金額・納期を抽出するアシスタントです。
出力は必ず次のJSON形式のみで返してください。説明文は含めないでください。
{ "amount_yen": number, "due_date": "YYYY-MM-DD" | null }
例:
入力: 「予算は50万円くらいで、来月末までにお願いしたいです」
出力: { "amount_yen": 500000, "due_date": "2026-08-31" }
`;曖昧さを持ち込まない
プロンプト設計でもう1つ重要なのが、「モデルに解釈の余地を残さない」ことです。特に日本語の数値・日付表現は曖昧になりやすく、この曖昧さがそのままプロンプトに残っていると、モデルの出力もぶれます。この点は実際に業務データの取り違えにつながりやすい問題なので、LLM出力の非決定性とどう付き合うかで詳しく扱っています。プロンプト設計の時点でできることは、「金額は必ず円単位の数値で出力し、単位が読み取れない場合はnullを返して確認を促す」のように、曖昧なケースの扱い方まで指示に書き込んでおくことです。
プロンプトはコードと同じように扱う
プロンプトの文言を変更すると出力の傾向が変わるため、コードの変更と同様にバージョン管理し、変更前後で同じ入力セットに対する出力を見比べる習慣をつけておくと安全です。プロンプトをソースコードとは別のテキストファイルや設定値として切り出しておくと、この比較や差分レビューがしやすくなります。
プロンプトキャッシュでコストを削減する
ここまでの要素を満たそうとすると、システムプロンプトはどうしても長くなりがちです。役割定義・出力フォーマット・few-shot例・ツール定義(AIエージェントの記事で見たtools配列など)をまとめると、数百〜数千トークンになることも珍しくありません。
問題は、エージェントの実行ループでは、この長いシステムプロンプトとツール定義を毎回のAPI呼び出しでそのまま送り直すことになる点です。会話が続くほど、同じ内容を繰り返し送信するコストが積み上がっていきます。これを解決するのが、Claude APIのプロンプトキャッシュです。
プロンプトの中で「毎回変わらない部分」にcache_controlを付けてキャッシュ対象としてマークしておくと、2回目以降の同一内容のリクエストでは、その部分の処理をキャッシュから再利用し、通常の入力トークンよりも大幅に安いコストで済ませられます。
const response = await client.messages.create({
model: 'claude-sonnet-5',
max_tokens: 1024,
system: [
{
type: 'text',
text: longSystemPromptWithRulesAndExamples, // 役割定義・出力フォーマット・few-shot例など
cache_control: { type: 'ephemeral' },
},
],
tools,
messages,
});cache_control: { type: 'ephemeral' }を付けた箇所までの内容が、キャッシュのブレークポイントとして扱われます。挙動として押さえておくべき点は次の通りです。
- キャッシュは先頭からの一致で判定される: 「システムプロンプト・ツール定義」のような固定部分を前方に、ユーザーごとに変わる会話履歴を後方に置く順序を守る必要があります。固定部分の途中に可変な内容を混ぜると、そこから後ろは毎回キャッシュミスになります
- 有効時間は短い: 既定のキャッシュ有効時間は5分です。エージェントのループのように短い間隔で同じシステムプロンプトを繰り返し送るケースでは、この時間内に十分ヒットします
- 最低トークン数がある: キャッシュ対象にするには一定量以上のトークン数が必要なため、数行程度の短いシステムプロンプトでは恩恵が出ません。長い出力フォーマット指定・few-shot例・ツール定義をまとめて持つ構成でこそ効果が出ます
- 書き込みコストは通常より高い: 初回(キャッシュ未作成時)の呼び出しは、キャッシュを作成する分だけ通常の入力より割高になります。同じ内容を複数回使い回すことで初めてトータルで得になるため、1回しか呼ばない使い捨てのプロンプトには向きません
エージェントの実行ループは、まさに「同じシステムプロンプト・ツール定義を短時間に何度も送る」典型的なユースケースなので、プロンプトキャッシュとの相性が良い構成です。プロンプトの設計段階から、固定部分と可変部分を意識して分けておくと、後からキャッシュを導入する際にも手を入れやすくなります。