AIコーディングにおけるプロンプトの良し悪しとは、文章のうまさではなく、自分が書いた制約が出力に何個反映されたかで測れるものです。制約を箇条書きにして数え、出力のどの行がそれを満たしているかを指せた数を数える。指せなかったぶんが、そのプロンプトの欠落です。
「プロンプト次第で出力が変わる」という話はよく見かけます。ただ、その差を実際に並べて見せている記事はあまりありません。そこでこの記事では、まったく同じ課題を「丸投げの1行」と「制約を7つ書いたプロンプト」の2種類で、それぞれ3回ずつ投げた結果を先に出します。数字は筆者が実際に取ったもので、条件も限界も後述します。
結果を先に書いておくと、丸投げ側は3回とも「作られた機能そのもの」が違いました。そのうち1回にはメールアドレスの変更機能が混ざっており、「アバターURLはhttpsだけ許可する」という条件は3回とも入りませんでした。一方で制約を書いた側は、7項目すべてが3回とも反映されました。それでも、プロンプトをどれだけ丁寧に書いても直らなかったズレが1つ残りました。そこが、この記事の後半で扱う「検証手段」の話につながります。
この記事が扱うのは「指示の技術」と「その良し悪しの測り方」です。どのツールでAIコーディングを始めるかという話は扱いません。ツール選びから知りたい場合はAIにコードを書かせる開発スタイル(vibe coding)の全体像を先に読んでください。
同じ課題を、2つのプロンプトで投げて比べた
まず実測から示します。主張の根拠を、読んだ人が同じ手順で再現できる形にしておくためです。
検証の条件
2026年8月2日に実施しました。条件は次のとおりです。
| 課題(両方共通) | ログイン中のユーザーが、自分のプロフィール(表示名・自己紹介文・アバターURL)を更新できるようにする |
| プロンプトA | 「プロフィール編集機能を作って」の1行だけ |
| プロンプトB | 環境・やりたいこと・制約7項目・出力形式を書いたもの(下に全文を載せます) |
| 試行回数 | A・Bそれぞれ3回ずつ、合計6回 |
| 投げ方 | 毎回まっさらな状態から1回だけ投げる。追加指示・やり直しはせず、1回目の出力だけを採点する |
| 使ったAI | Claude の Sonnet 系モデル。Web検索は使わせていない |
先に限界を書いておきます。3回は統計ではありません。傾向を見るための回数です。また、実行環境には共通のコーディング規約(命名や不変性のルール)があらかじめ読み込まれていました。これは丸投げ側に有利に働く条件です。それでも下の結果になった、という読み方をしてください。
投げた2つのプロンプト(そのまま貼れます)
プロンプトA(丸投げ)。これだけです。
プロフィール編集機能を作ってプロンプトB(5つの要素を書いたもの)。制約に番号を振っているのは、あとで採点するためです。
【環境】
- Next.js 16(App Router)
- TypeScript 5
- Prisma 7 + PostgreSQL
- 認証は next-auth(セッションから user.id が取れる)
【やりたいこと】
ログイン中のユーザーが、自分のプロフィール(表示名・自己紹介文・アバターURL)を更新できるようにしたい。
【制約】
1. 更新処理は Server Actions で書く
2. バリデーションは Zod 4 を使う
3. 表示名は1〜30文字
4. 自己紹介文は0〜200文字
5. アバターURLは https のみ許可する
6. 他人のプロフィールを書き換えられないようにする
7. 新しいライブラリは追加しない
【出力形式】
1. Zodスキーマ
2. Server Action本体
3. 想定されるエラーケースの一覧結果:丸投げは3回とも「違う機能」を作った
最初に目についたのは、出力の質より前の段階でした。プロンプトAは、3回とも「何を編集できる機能なのか」自体が違いました。
| 回 | AIが自分で決めた編集項目 | 表示名の上限 | 自己紹介の上限 | アバターURLをhttpsに限定 |
|---|---|---|---|---|
| 1回目 | 名前・メールアドレス・自己紹介・アバターURL | 50字 | 200字 | していない |
| 2回目 | 表示名・自己紹介・アバターURL | 50字 | 500字 | していない |
| 3回目 | 名前・自己紹介・Webサイト・X(Twitter)ユーザー名 | 50字 | 200字 | していない |
「プロフィール編集」という言葉から何を連想するかが毎回違うので、当然そうなります。問題はここからです。1回目にはメールアドレスの変更機能が入っていました。メールアドレスの変更は本来、確認メールによる本人確認を伴う操作です。それが、表示名や自己紹介と同じ1つのフォームに、同じ扱いで並んで出てきました。
3回目には、頼んでいないWebサイトURLとXのユーザー名の欄が増え、代わりにアバターURLが消えました。丸投げで返ってくるのは「足りないコード」ではなく、頼んでいない範囲まで含んだ、毎回輪郭の違うコードです。
対してプロンプトBは、3回とも指定した3項目だけを扱い、制約7項目がすべて反映されました。
| 測定項目 | A(丸投げ)3回 | B(制約7項目)3回 |
|---|---|---|
| プロンプトに書いた制約の数 | 0 | 7 |
| 出力に反映された制約の数 | 採点対象なし(何も書いていないため) | 3回とも 7 / 7 |
| アバターURLをhttpsに限定した | 0回 / 3回 | 3回 / 3回 |
| 依頼していない機能・項目が混ざった | 2回 / 3回 | 0回 / 3回 |
| 更新対象をサーバー側のセッションIDに固定した | 3回とも実施(ただし理由の明示なし) | 3回とも実施+「クライアント由来のidは使わない」と明記 |
| 想定エラーケースの列挙 | 0件 | 8件・11件・13件 |
予想外だった点:出力が多いのは丸投げのほう
1回目の出力を保存して行数を数えたところ、丸投げが311行、制約を書いたほうが108行でした。丸投げのほうが約2.9倍多く出力しています。丸投げ側はスキーマ・APIルート・フォーム・ページの4ファイルを一式生成し、制約を書いた側は指定した3項目(スキーマ・処理本体・エラーケース一覧)だけを返したためです。
この行数の比較は1回目の1組についてのみ実測した数字です(残り2組は生成物を保存していないため、行数は測っていません)。ただ傾向としては3回とも同じで、丸投げは毎回4ファイル分のコードを返しました。
ここから言えるのは1つだけです。出力の量は品質の指標になりません。「AIがたくさん書いてくれた」は、うまくいった証拠ではなく、こちらが決めていない部分をAIが埋めた量です。
なぜ同じAIで出力が変わるのか
「AIは指示された通りに出力する」だけでは、上の結果は説明できません。実際に起きているのは、その手前の段階です。
書かれていない仕様は、空欄のまま出てこない
コードは「未定」のまま書けません。表示名の上限を決めなければ入力欄は作れず、URLをどこまで許すかを決めなければバリデーションは書けません。だからAIは、書かれていない項目を必ず何かで埋めます。上の実測で表示名の上限が毎回50字になり、自己紹介が200字だったり500字だったりしたのは、その埋め方が毎回決め直されているからです。
Anthropicの公式ドキュメントは、この状況を「Claudeを、優秀だが自社の慣習やワークフローを知らない新入社員だと考えること」と表現しています。新入社員は、決められていない仕様を勝手に空欄にはしません。もっともらしい値を置いて先に進みます。
埋められた仕様は、頼んでいない機能として現れる
埋められるのは値だけではありません。機能の範囲も埋められます。「プロフィール編集」に何が含まれるかを書かなければ、メールアドレス変更が含まれる回もあれば、SNSアカウント欄が含まれる回もあります。
ここが危険なのは、増えた機能はレビューで目立たない点です。足りない機能は動かしたときに気づきます。増えた機能は動いてしまいます。「メールアドレスも編集できるようになっていた」ことに気づくのは、本人確認を伴わないメール変更が問題になったあとです。
公式ドキュメントはこれを何と呼んでいるか
Anthropicの「Best practices for Claude Code」は、よくある失敗パターンの1つとして the trust-then-verify gap(信用してから検証する、という順序のずれ)を挙げ、次のように書いています。
Claude produces a plausible-looking implementation that doesn’t handle edge cases. Fix: Always provide verification (tests, scripts, screenshots). If you can’t verify it, don’t ship it.
Anthropic「Best practices for Claude Code」(2026年8月2日取得)
もっともらしく見える実装が返ってくること自体は、想定内の挙動として扱われています。実務で「動くか」より「運用できるか」が問われるのは、この性質があるからです。運用できるとは、レビュー・テスト・デプロイ・保守という複数の段階に耐えられることです。
なお、指示が甘くなる原因はコーディングに限りません。何を作るのかを自分が言語化できていない場合、プロンプトの書式を整えても中身は埋まりません。この論点はAIへの指示が甘くなる原因を業務理解の側から整理した記事で扱っています。
プロンプトに入れる5つの要素
上の実測でプロンプトBに書いたのは、次の5つです。それぞれ「何を埋められないようにするための項目か」という観点で見てください。
コンテキスト(環境・バージョン・既存の書き方)
言語・フレームワーク・バージョン・ORM・認証方式を書きます。バージョンを書かないと、AIは学習時点で一般的だった書き方を選びます。上の実測でプロンプトAが返したコードは、Zod 4 でトップレベルへ移された文字列フォーマットを旧来の z.string().url() の形で呼び、認証やDBクライアントについては「存在すると仮定した独自ユーティリティ」を import していました。
そして最も強いコンテキストは、文章ではなく既存コードそのものです。「この書き方に合わせて」と言って実物を渡せば、命名も構造も揃います。この効き方が最も分かりやすいのがCSSアニメーションで、言葉で動きを説明するより動くコードを1つ渡してから指示するほうが速いという具体例をまとめています。
目的(何をもって完成とするか)
「ログイン機能を作って」ではなく「メールアドレスとパスワードで認証し、セッションを発行するところまで」と書きます。範囲の終わりを書かないと、上の実測のように範囲が毎回変わります。
Anthropicの公式ドキュメントは、この項目について次の判定基準を「Golden rule」として挙げています。
Show your prompt to a colleague with minimal context on the task and ask them to follow it. If they’d be confused, Claude will be too.(そのタスクの背景をほとんど知らない同僚にプロンプトを見せて、その通りに作業してもらう。同僚が困惑するなら、Claudeも困惑する)
Anthropic「Prompting best practices」(2026年8月2日取得)
制約条件(あとで数えられる形で書く)
ここがこの記事で最も重要な項目です。制約は、番号を振った箇条書きで書いてください。散文の中に混ぜて書くと、あとで「何個書いたか」が数えられなくなり、採点できなくなります。
数えられる制約とは、出力を見たときに「満たしている行はここ」と指させるものです。次の対比が目安になります。
| 数えられない書き方 | 数えられる書き方 |
|---|---|
| 安全に作って | 更新対象のユーザーIDは、リクエストの値ではなくサーバー側のセッションから取得すること |
| バリデーションをしっかり | 表示名は1〜30文字、自己紹介文は0〜200文字で検証すること |
| 変な画像URLを弾いて | アバターURLは https で始まるものだけを許可すること |
| 既存の構成に合わせて | 新しいライブラリを追加しないこと |
| 余計なことはしないで | 依頼した3つのファイル以外は変更しないこと |
Anthropicの公式ドキュメントも、明確な指示の条件として「望む出力形式と制約について具体的であること(Be specific about the desired output format and constraints)」を挙げています。制約は出力形式と同格の項目として扱われています。
出力形式(禁止形ではなく指示形で書く)
何を、どの順で出してほしいかを書きます。ここで効くのが書き方の向きです。Anthropicの公式ドキュメントは、出力形式の制御について最初に Tell Claude what to do instead of what not to do(してはいけないことではなく、してほしいことを伝える)を挙げています。
| 禁止形(効きにくい) | 指示形(効きやすい) |
|---|---|
| 説明を長く書かないで | コードを先に出し、解説は最後に3行以内でまとめる |
| マークダウンを使わないで | 本文は段落で書く |
| 省略しないで | ファイルごとに全文を出す。差し替える行だけの提示はしない |
例示(3〜5個・内容を散らす・タグで囲む)
入力と期待する出力の例を添えると、仕様の認識ズレを防げます。ここで個数の目安が問題になります。Anthropicの公式ドキュメントは Include 3–5 examples for best results(最良の結果を得るには例を3〜5個含める)と明記しており、1〜2個では足りないという立場です。
同ドキュメントは、例に求める条件も3つ挙げています。
| 条件 | 公式の記述 | 実務での意味 |
|---|---|---|
| Relevant | Mirror your actual use case closely | 架空のサンプルではなく、実際に扱うデータに近い例を使う |
| Diverse | Cover edge cases and vary enough that Claude doesn’t pick up unintended patterns | エッジケースを含め、内容を散らす。似た例を並べると意図しない共通点を規則として学ばれる |
| Structured | Wrap examples in <example> tags so Claude can distinguish them from instructions | 例は <example> で囲み、指示文と見分けがつくようにする |
書き方はこうなります。
<examples>
<example>
入力: { "email": "user@example.com" }
出力: { "valid": true }
</example>
<example>
入力: { "email": "user@example" }
出力: { "valid": false, "reason": "TLDがない" }
</example>
<example>
入力: { "email": "" }
出力: { "valid": false, "reason": "未入力" }
</example>
</examples>3つ目までで「成功・形式エラー・未入力」と系統を散らしている点が Diverse にあたります。同じ成功例を3つ並べても、この条件は満たしません。
5つの要素と、公式ドキュメントの対応
この5要素は筆者が独自に決めたものではなく、主要なベンダーの公式ガイドで扱われている項目と対応します。
| この記事の要素 | Anthropic「Prompting best practices」の該当項目 | OpenAI「Prompt engineering」の該当項目 |
|---|---|---|
| コンテキスト | Add context to improve performance / 「lacks context on your norms and workflows」 | Context |
| 目的 | Be clear and direct / Golden rule | Identity |
| 制約条件 | Be specific about the desired output format and constraints | Instructions |
| 出力形式 | Control the format of responses / Tell Claude what to do instead of what not to do | Instructions |
| 例示 | Use examples effectively(3〜5個・Relevant / Diverse / Structured) | Examples |
OpenAIのガイドは開発者向けメッセージの構成として Identity / Instructions / Examples / Context の4区分を挙げています。ベンダーが違っても、埋めるべき欄はほぼ同じです。
シーン別プロンプトテンプレート(コピペして使う)
ここから先は、そのままコピーして使えるテンプレートです。〈 〉で囲んだ部分が、自分の値に置き換える箇所です。具体的なバージョン番号をテンプレート側に書き込んでいないのは、書き込んだ瞬間に古くなるからです。参考までに、この記事の執筆時点(2026年8月2日、npmレジストリ実測)の最新版は Next.js 16.2.12 / React 19.2.8 / Zod 4.4.3 / Prisma 7.9.1 です。
新規機能の実装
【環境】
- フレームワーク: 〈名前とメジャーバージョン〉
- 言語: 〈名前とバージョン〉
- DB / ORM: 〈名前とバージョン〉
- 認証: 〈方式。サーバー側でユーザーIDが取れるかどうかも書く〉
- 既存の書き方: 〈参考にしてほしい既存ファイルのパス、または該当コードを貼る〉
【やりたいこと】
〈誰が・何を・どうできるようになるのかを1文で書く〉
【制約】
1. 〈使う技術・使わない技術〉
2. 〈数値の上限と下限。文字数・件数・サイズ〉
3. 〈セキュリティ上、絶対に成立させたい条件〉
4. 〈このプロジェクト固有のルール〉
5. 依頼したこと以外のファイル・機能は変更しない
【出力形式】
1. 〈最初に出してほしいもの〉
2. 〈次に出してほしいもの〉
3. 想定されるエラーケースの一覧制約の5番目を固定で入れているのは、上の実測で範囲が勝手に広がったためです。この1行があると、依頼していないファイルへの変更が減ります。
バグ修正
【現象】
〈何をすると、何が起きるか〉
【期待する動作】
〈本来どうなってほしいか〉
【再現手順】
1. 〈操作〉
2. 〈操作〉
3. 〈このとき何が表示されるか。エラーメッセージは全文を貼る〉
【環境】
- 〈フレームワークとバージョン〉
- 〈関連ライブラリとバージョン〉
【該当コード】
〈コードを貼る。呼び出し元も一緒に貼る〉
【制約】
1. 原因の説明を先に出し、そのあとで修正コードを出す
2. 依頼した箇所以外は変更しない
3. 〈変えてはいけない関数のシグネチャや公開API〉
【検証方法】
〈このコマンドが通れば直ったと判断してよい、を書く〉【検証方法】の欄を最後に置いているのは、ここが空欄だと修正の合否を自分で判定できなくなるからです。書けないなら、修正を依頼する前に検証手段のほうを先に用意します。
コードレビュー依頼
【このコードの役割】
〈何をするコードか。どこから、どのくらいの頻度で呼ばれるか〉
【レビューしてほしい観点】
1. セキュリティ上の問題(認証・認可・入力検証)
2. エラーハンドリングの漏れ
3. エッジケースの考慮漏れ(null・空配列・境界値)
4. パフォーマンス(N+1・不要な再レンダリング)
5. 〈このプロジェクト固有のルールへの違反〉
【制約】
1. 指摘は重大度の高い順に並べる
2. 「良くなる」ではなく、何がどう壊れるかを書く
3. 修正案はコード全体でなく差分だけを示す
【コード】
〈コードを貼る〉
【出力形式】
問題点ごとに「重大度 / 何が起きるか / 修正案」の3点をセットで出すリファクタリング
【現在の問題】
1. 〈計測できる形で書く。例: 1つの関数が200行ある〉
2. 〈例: 同じ処理が3箇所に重複している〉
3. 〈例: テストを書こうとすると外部APIに接続してしまう〉
【方針】
1. 〈どの基準で分割するか〉
2. 〈共通処理をどこへ切り出すか〉
3. 〈依存をどう差し替え可能にするか〉
【変えてはいけないもの】
1. 外部から見た振る舞い
2. 〈公開している関数のシグネチャ〉
3. 依頼した範囲以外のファイル
【検証方法】
〈このテスト・型チェック・ビルドが、変更前と変更後の両方で通ることを確認する〉
【コード】
〈コードを貼る〉テンプレートを自分のプロジェクト用に直す手順
テンプレートは、そのまま毎回書き直すものではありません。1回だけ手を入れて、自分用の定型文にします。
- 【環境】欄を、いま触っているプロジェクトの実際の値で埋める。バージョンは
package.jsonやロックファイルから写す(記憶で書かない) - 【制約】欄に、そのプロジェクトで毎回言っていることを固定で足す。テスト方針、命名規則、使ってはいけないライブラリなど
- 埋めた状態をエディタのスニペットやメモに保存する。次回からは【やりたいこと】と可変の制約だけを書き換える
- ライブラリを更新したら【環境】欄も更新する。ここが古いと、AIは古い書き方に合わせにいく
曖昧な指示が正解になる場面もある
ここまで読むと「曖昧な指示は常に悪い」と受け取れますが、それは正確ではありません。公式ドキュメントは明確に否定しています。
成果物を作らせるとき:曖昧さはコストになる
この記事の前半で見たとおりです。作らせる対象が決まっているとき、書かなかった仕様はAIが埋め、埋め方は毎回変わります。手戻りの量がそのままコストになります。
探索するとき:曖昧さが発見を生む
一方、まだ何が問題か分かっていない段階では、話が逆になります。
Vague prompts can be useful when you’re exploring and can afford to course-correct. A prompt like “what would you improve in this file?” can surface things you wouldn’t have thought to ask about.(曖昧なプロンプトは、探索していて、かつ軌道修正のコストを払える状況では有用なことがある。「このファイルで改善できる点は?」のようなプロンプトは、自分では思いつかなかった論点を浮かび上がらせる)
Anthropic「Best practices for Claude Code」(2026年8月2日取得)
同ドキュメントは別の箇所でも「制約をかける前に、Claudeがその問題をどう解釈するかを見たいときは、曖昧なプロンプトがまさに正しいこともある」と書いています。制約を書くという行為は、自分がすでに知っている枠にAIを収める行為でもあります。枠の外を見たいときには邪魔になります。
判断軸は「やり直しのコストを払えるか」
| 状況 | やり直しのコスト | 推奨 |
|---|---|---|
| 既存コードに手を入れる/このあと本番に出す | 高い(既存の振る舞いを壊す) | 制約を数えられる形で書く |
| 何が問題か分かっていない/捨てる前提の下見 | 低い(結果を捨てるだけ) | あえて曖昧に投げる |
| 設計方針を決めたい | 低い(まだコードを書いていない) | 曖昧に投げて選択肢を出させ、そのあと制約を書く |
ついでに、もう1つ更新が必要な通説があります。「複数の要求を一度に出すと全部中途半端になるから機能ごとに分けろ」という話です。Anthropicの公式ドキュメントは、現行のモデルについてこう書いています。
With adaptive thinking and subagent orchestration, Claude handles most multistep reasoning internally. Explicit prompt chaining … is still useful when you need to inspect intermediate outputs or enforce a specific pipeline structure.(適応的な思考とサブエージェントの制御により、Claudeは多段階の推論の大半を内部で処理する。明示的なプロンプト連鎖が今も有用なのは、中間の出力を検査したい場合や、特定のパイプライン構造を強制したい場合である)
Anthropic「Prompting best practices」(2026年8月2日取得)
つまり分割する理由は「AIが処理しきれないから」ではなく「人間が途中を確認して方向を変えられるようにするため」です。理由が変わると打ち手も変わります。「AIの限界に合わせて刻む」のではなく、「自分がレビューしたい単位で区切る」ことになります。
自分のプロンプトを採点する(制約反映率チェック)
ここからが本題です。「良いプロンプト」は主観になりますが、「制約が何個反映されたか」は数えられます。自分のプロンプト1本を、いま手元にある出力だけで採点します。追加のツールも課金も要りません。
手順
| 手順 | やること | 具体的に |
|---|---|---|
| 1 | 制約に番号を振る | プロンプトから「〜すること」「〜は使わない」「〜以内」にあたる記述を抜き出して箇条書きにする。この個数を N とする |
| 2 | 出力を受け取る | 修正指示は出さない。1回目の出力だけを採点対象にする |
| 3 | 制約ごとに、満たしている場所を指す | 「制約3は、この関数のこの行」と、行番号か関数名で指す。「たぶん満たしている」は不可 |
| 4 | 指せた数を数える | これが反映数 M。あわせて、依頼していないファイル・機能が増えていないかも見る |
手順3が要点です。指させないものは、反映されていません。「全体的にちゃんとしている」は採点になりません。
合否ライン
| 反映数 M(制約 N 個中) | 判定 | 意味 |
|---|---|---|
| N 個すべて | 合格 | このプロンプトは定型文として保存してよい |
| N − 1 個 | 条件付き合格 | 落ちた1個だけを下の分岐表で直す。全体は書き直さない |
| N − 2 個以下 | 不合格 | プロンプトの構造が原因。語尾や言い回しの調整では戻らない |
| 反映数にかかわらず、依頼していない機能・ファイルが増えていたら不合格。範囲を書いていないことが原因で、最も気づきにくい失敗 | ||
この記事の実測をこの基準で採点すると、プロンプトBは3回とも 7 / 7 で合格、プロンプトAは制約が0個なので採点以前(範囲が毎回変わっているので、そもそも不合格の条件に当たる)となります。
外れたときの分岐表
落ちた制約について、外れ方を1つ選び、対応する1手だけを打ちます。ここから先へは分岐しません。
| 外れ方 | 考えられる原因 | 次の1手 |
|---|---|---|
| 出力に痕跡がない(無視された) | プロンプトが長くて埋もれた、または禁止形で書いた | その制約だけを指示形に書き直す(「マークダウンを使うな」→「本文は段落で書く」) |
| 別の意味で実装された(誤解された) | プロジェクト固有の用語を、AIが一般的な意味で取った | その用語の定義を1文足す。または既存コードの該当箇所を貼って「この書き方に合わせて」と指す |
| 依頼していない機能が増えた | 範囲を書いていない | 「依頼したこと以外のファイル・機能は変更しない」を制約に固定で入れる |
| 反映はされたが、書き方が古い/使ったAPIが非推奨 | モデルが持つライブラリ知識のラグ。プロンプトでは直らない | ここで打ち止め。プロンプトの修正をやめ、型チェック・テスト・ビルドを走らせて結果を読ませる |
最終行の実例:丁寧に書いても残ったズレ
分岐表の最終行は、この記事の実測でも実際に起きました。制約7項目を書いたプロンプトBは3回とも 7 / 7 で合格しています。それでも、3回とも同じ古い書き方が混ざっていました。
入力エラーの整形に error.flatten() を使っていた点です。Zod の公式移行ガイドは、ZodError の .flatten() と .format() を非推奨とし、トップレベルの z.treeifyError() に置き換えたと明記しています。zod 4.4.3 を実際にインストールして確認したところ、次の状態でした(2026年8月2日実測)。
zod version: 4.4.3
z.string().url() は http:// を通すか -> true
z.url() は http:// を通すか -> true
z.url({ protocol: /^https$/ }) は http:// を通すか -> false
z.url({ protocol: /^https$/ }) は https:// を通すか -> true
error.flatten の型 -> function(残ってはいるが非推奨)
z.treeifyError の型 -> function非推奨のメソッドはまだ動きます。動くので、レビューでも気づきません。プロンプトを丁寧に書くことでは、この種のズレは埋まりません。制約反映率が満点でも残るからです。
ついでに分かったこともあります。「アバターURLは https のみ」という制約は3回とも守られましたが、その実装方法は3回とも違いました。1回目は z.string().url() に .refine() を足す形、3回目は Zod 4 のトップレベル z.url({ protocol: /^https$/ }) です。上の実測のとおり z.string().url() も z.url() も、単体では http:// を通します。「httpsのみ」と書かなければ、URL検証を入れても静かに http が通ります。プロンプトAが3回ともこの状態でした。
打ち止めのあとにやること:検証手段を渡す
プロンプトで埋まらない領域に入ったら、AIに「自分で結果を確かめる手段」を渡します。Anthropicの公式ドキュメントは、この項目を独立した見出し(Give Claude a way to verify its work)として置いています。渡す対象は、テスト・型チェック・ビルド・スクリーンショットなど、実行すると結果が返ってくるものです。
ここで注意点が1つあります。同ドキュメントは「テストを通すことに寄りすぎる」挙動も警告しています。テストを通すためにハードコードしたり、特定の入力だけで成立する回避策を書いたりする挙動です。そのため、「まず動くものを出させる」という進め方は勧められません。順序は逆で、先に合否の判定手段を決め、そのうえで実装させます。
同ドキュメントに載っている、この挙動を防ぐための定型文がこちらです。
Implement a solution that works correctly for all valid inputs, not just
the test cases. Do not hard-code values or create solutions that only work
for specific test inputs. Instead, implement the actual logic that solves
the problem generally.
(テストケースだけでなく、すべての妥当な入力に対して正しく動く解を実装すること。
値をハードコードしたり、特定のテスト入力でだけ動く解を作ったりしないこと。
問題を一般的に解く実際のロジックを実装すること)検証手段そのものを整えるのはエディタ側の仕事です。型チェックとリンタが保存のたびに走る状態になっていれば、非推奨APIはその場で赤くなります。環境の作り方はAIが出したコードを機械的に検証するエディタ環境の作り方にまとめています。
投げる直前に1回だけやる確認
採点は出力が返ってきたあとの話です。投げる前にできる確認は1つだけあります。書いたプロンプトを、そのタスクの背景をほとんど知らない人に見せて、その通りに作業してもらえるかを考えることです。困惑されるなら、AIも同じところで困惑します。
実際に誰かに見せる必要はありません。次の5つに自分で答えられるかで代用できます。
- いま作るものは何か、30秒で説明できるか
- なぜこの実装方法を選ぶのか、理由を書けるか
- できあがったコードを、他人がレビューできる状態か
- 半年後の自分が見て理解できるか
- 完成したかどうかを、何を見て判定するか決まっているか
5つ目が最も飛ばされます。Anthropicのプロンプトエンジニアリング概説は、そもそもプロンプトを工夫する前段として「成功基準の明確な定義」と「その基準に対して経験的にテストする手段」の2つを先に用意せよ、と書いています。判定手段が決まっていないプロンプトは、返ってきた出力の合否も決められません。
まとめ
同じ課題を丸投げと制約明示の2種類で3回ずつ投げた結果、丸投げは3回とも違う機能を作り、そのうち1回はメールアドレス変更という別の重みを持つ操作を混ぜてきました。「httpsのみ許可」は3回とも入りませんでした。制約を7項目書いた側は、3回とも7項目すべてが反映されました。
そこから引き出せる基準は、次の3つに絞れます。
- 制約は、あとで数えられる形(番号付きの箇条書き)で書く。数えられない制約は採点できず、採点できないプロンプトは改善もできない
- 出力の量を成果と読み替えない。量が多いのは、こちらが決めなかった部分をAIが埋めた量である
- 制約反映率が満点でも残るズレがある。そこから先はプロンプトを磨かず、検証手段を渡す側へ切り替える
この記事はAI時代のWeb制作完全ガイドの一部です。AIコーディングからAI検索最適化まで、関連記事を体系的にまとめています。
参照した一次ソース
引用はいずれも英語版の原文を正としています(すべて2026年8月2日取得。取得時にリダイレクト先まで追い、最終的な実体URLを記載しています)。
- Anthropic|Prompting best practices — Golden rule、出力形式と制約、Tell Claude what to do instead of what not to do、例は3〜5個と Relevant / Diverse / Structured、Chain complex prompts、Avoid focusing on passing tests and hardcoding
- Anthropic|Best practices for Claude Code — Give Claude a way to verify its work、the trust-then-verify gap、Vague prompts can be useful when you’re exploring
- Anthropic|Prompt engineering overview — プロンプトを工夫する前に成功基準とその検証手段を用意すること
- OpenAI|Prompt engineering — 開発者向けメッセージの構成(Identity / Instructions / Examples / Context)
- Zod|Migration guide(v4 changelog) —
ZodErrorの.flatten()/.format()を非推奨としz.treeifyError()へ移行したこと - npm registry — 記事中のバージョン(Next.js 16.2.12 / React 19.2.8 / Zod 4.4.3 / Prisma 7.9.1)の取得元。同じ形式で
react/zod/prismaも参照できます
よくある質問(FAQ)
Q. プロンプトが良いかどうかは、何で判断すればいいですか?
文章のうまさではなく、書いた制約が出力に何個反映されたかで判断してください。プロンプトの制約を箇条書きにして数え(N個)、出力のどの行が各制約を満たしているかを実際に指せた数(M個)を数えます。MがNに満たない場合、または依頼していない機能やファイルが増えていた場合は、そのプロンプトは作り直しの対象です。
Q. 丸投げのプロンプトでは、具体的に何が起きるのですか?
コードが足りなくなるのではなく、作られる機能そのものが毎回変わります。同じ課題を「プロフィール編集機能を作って」の1行で3回投げたところ、編集できる項目が3回とも異なり、1回はメールアドレスの変更機能が混ざり、別の1回は頼んでいないWebサイト欄とSNS欄が増えました。アバターURLをhttpsに限定する処理は3回とも入っていません。
Q. 例示はいくつ入れるのが適切ですか?
Anthropicの公式ガイドは3〜5個を推奨しています。数だけでなく、実際のユースケースに近いこと(Relevant)、エッジケースを含めて内容を散らすこと(Diverse)、<example>タグで囲んで指示文と区別すること(Structured)の3点を満たすと効果が上がります。似た例を並べると、AIが意図しない共通点をパターンとして拾ってしまいます。
Q. 曖昧な指示は常に避けるべきですか?
いいえ、場面によります。成果物を作らせるときは曖昧さがそのまま手戻りになりますが、まだ何が問題か分かっていない探索の段階では、あえて曖昧に投げたほうが自分では思いつかなかった論点が出てきます。Anthropicの公式ドキュメントも「軌道修正のコストを払える探索段階では曖昧なプロンプトが有用なことがある」と明記しています。判断軸は、やり直しのコストを払えるかどうかです。
Q. プロンプトを丁寧に書けば、AIの出力をそのまま使えますか?
使えません。プロンプトで防げるのは要件の取りこぼしまでで、ライブラリの新しいバージョンで非推奨になった書き方が混ざる、といったズレは残ります。この記事の実測でも、制約7項目がすべて反映された出力に、非推奨になったエラー整形メソッドが3回とも含まれていました。型チェック・テスト・ビルドのように、AIが自分で走らせて結果を読める検証手段を必ず用意してください。
Q. 一度に複数の機能をまとめて頼んではいけませんか?
現行のモデルは多段階の推論の大半を内部で処理するため、「AIが処理しきれないから分ける」という理由はもう当てはまりません。Anthropicの公式ドキュメントは、明示的に分割する意味があるのは中間の出力を検査したい場合や特定の処理順を強制したい場合だと書いています。つまり分ける基準は、自分がレビューして方向を変えたい単位です。
Q. テンプレートにバージョン番号を書き込んでおくべきですか?
テンプレート側には書かず、使うときにプロジェクトの実際の値を写してください。バージョンを書くこと自体は必要です(書かないとAIは学習時点で一般的だった書き方を選びます)。ただしテンプレートに固定値を焼き付けると、更新した瞬間に古い指示を出し続けることになります。値の出どころは記憶ではなく package.json やロックファイルにしてください。
