AIへのルール、プロンプトに書くのをやめた話

AIに同じことを何度も言い直してしまう人へ

「必ずJSON形式で返して」

プロンプトにそう書いた。最初はちゃんと守られた。でも少し複雑な指示を重ねたら、いつの間にか普通の文章で返ってきた。
また書き直す。また守られる。また崩れる。

こういう経験、ありませんか?

AIに渡すルールが、なぜか定着しない。毎回同じことを書き足している。「前も言ったのに」と思いながら、また同じ一文を追加する。

これ、プロンプトの書き方が悪いんじゃないんです。

ルールを置く場所が間違っている、というのが本当の原因でした。

この記事は以下のXを深掘りした内容になります。

なぜ「プロンプトに書いたルール」は守られなくなるのか


プロンプトに書いた指示は、AIにとって「その会話の中でのお願い」です。

会話が短ければ問題ない。でも指示が増えて、文章が長くなるにつれて、AIは全体をまんべんなく読めなくなっていきます。

研究(18種類のAIモデルを対象にした調査)によると、AIは長い文章の最初と最後には強く注意を向けるけれど、中間部分は見落としやすいという特性があります。U字型、と表現されることもある。

つまり、ルールをプロンプトの中ほどに書けば書くほど、読み飛ばされるリスクが上がる。

さらに別の問題もあります。

プロンプトに書いたルールは、会話が終わると消えます。次に新しい会話を始めたとき、また同じルールを書かないといけない。書き忘れれば、守られない。

これが「毎回書き直している」の正体です。AIが賢くなっていないのではなく、ルールを「会話の中に置く」という設計そのものに限界があった。

ルールを「プロンプトの外」に置くとどうなるか

少し視点を変えてみます。

職場のルールを例に考えると、「毎朝、口頭で今日の注意事項を伝える」方法と、「マニュアルや規則集として紙に残す」方法があります。

口頭だけだと、言い忘れた日はルールが存在しないも同然。でもマニュアルがあれば、誰も言わなくても参照できる。

AIへのルールも同じです。

プロンプトに毎回書くのは、口頭で伝えるのと同じです。言い忘れたら、ルールは消える。

一方、ルールを別の場所に置いておくと、AIが自動的に読んでくれる仕組みがあります。たとえば、AGENTS.md や CLAUDE.md というファイルをフォルダのトップに置いておくだけで、Claude や Cursor(※AIを使ったコーディングツール)は会話を始める前に自動でそのファイルを読みます。

プロンプトに書かなくても、ルールが毎回有効になる。

「そんな方法があったのか」と思うかもしれないけれど、これがハーネス設計(※AIが動く「環境」をデザインすること)の入口です。

もっと「壁」にする方法もある

AGENTS.md に書く方法は、AIが「読んで守ろうとする」ものです。ただ、それでもたまに無視されることがあります。

より確実にしたいなら、守られなかったら物理的に止まる仕組みを作ります。

たとえば、「Pythonのコードは必ずこの書き方で」というルールを linter(※コードの書き方を自動チェックするツール)に設定しておくと、AIが書いたコードがルールを破っていたとき、自動でエラーを出して止めてくれます。人間が確認するより前に、機械が検出する。

「守ってもらう」から「守られなければ通過できない」に変わる。

ここが、プロンプトにルールを書き続けることとの、一番大きな違いです。

まず何から始めるか

「linterとかCIとか、なんか難しそう」と感じた人は、まずここだけ試してみてください。

今日できる最小ステップ

  1. プロンプトに3回以上書き直したルールを1つ思い出す

  2. フォルダのトップに AGENTS.md という名前のファイルを作る

  3. そこにそのルールだけ書いて保存する

それだけでいい。ツールのインストールも設定も不要。テキストファイルを1つ作るだけで、「会話が終わると消えるルール」から「ファイルに残り続けるルール」に変わります。

有料パートでは、このステップの続きを扱っています。

どのルールをどの場所に置くかの判断フローと、AGENTS.md / linter / pre-commit hook それぞれのコピーして使える設定例を出しています。

「設定の仕方がわからない」「どこから始めればいいかわからない」という状態から、手を動かして試せるところまで持って行く内容にしました。

プロンプトに同じことを書き続けることに疲れてきたなら、続きを読んでみてください。

判断フロー:このルールはどこに置くべきか

ルールを1つ選んで、上から順に答えていく。

Q1. このセッション限りの指示か?(「今回はこの条件で」「この文体で」など)
YES → プロンプトに残す。環境に移す必要はない
NO  → Q2へ

Q2. コードや出力の「形式・書き方」に関するルールか?
  (命名規則、フォーマット、import順序、出力形式など)

YES → linter / formatter へ(→ 設定例A)
NO  → Q3へ

Q3. コミットやマージのタイミングで自動検証したいルールか?
  (「.envをコミットしない」「テストが通らなければマージしない」など)

YES → pre-commit hook / CI へ(→ 設定例B)
NO  → Q4へ

Q4. セッションをまたいで常に有効にしたいルールか?
  (「このフォルダは触らない」「関数を追加するときは必ずコメントを書く」など)

YES → AGENTS.md / CLAUDE.md へ(→ 設定例C)
NO  → プロンプトに残す。または上の分岐を見直す

迷ったときのシンプルな基準:同じルールをプロンプトに3回以上書いたことがあれば、環境に移す候補

設定例A:linter / formatter(形式・書き方のルール)

Python の場合(Ruff)

# インストール
pip install ruff

# 一度走らせてみる(エラーが出た箇所がルール化の候補)
ruff check .

設定ファイル(pyproject.toml に追記):

[tool.ruff]
line-length = 88
select = [
"E",   # スタイルエラー
"F",   # 未使用変数・インポート
"I",   # import順序
]

[tool.ruff.isort]
force-sort-within-sections = true

AIが生成したコードがこの設定に違反していると、ruff check . を走らせた瞬間にエラーになる。CIに組み込めば、pull requestを出した時点で自動検出される。

JavaScript / TypeScript の場合(ESLint)

npm install --save-dev eslint @eslint/js
npx eslint --init

.eslintrc.json の設定例:

{
"rules": {
  "camelcase": "error",
  "no-unused-vars": "error",
  "no-console": "warn"
}
}

linterを入れて最初にやること:
既存のコードに対して一度走らせ、エラーが大量に出るようなら "error" を "warn" に下げて段階的に厳しくする。最初から厳しくしすぎるとAIが修正ループを繰り返してかえって遅くなる。

設定例B:pre-commit hook(コミット前の自動検証)

pre-commit hookは「git commit を実行した瞬間に自動で走るチェック」。AIが生成したファイルをコミットしようとしたとき、基準を満たさなければコミット自体が止まる。

pip install pre-commit
pre-commit install  # リポジトリで一度だけ実行。以降は自動で走る

設定ファイル(.pre-commit-config.yaml):

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
  rev: v4.5.0
  hooks:
    - id: detect-private-key        # .envや秘密鍵の混入を防ぐ
    - id: check-added-large-files   # 大きなファイルの混入を防ぐ
    - id: no-commit-to-branch       # mainへの直接コミットを防ぐ
      args: ['--branch', 'main']
    - id: end-of-file-fixer         # ファイル末尾の改行を統一する
    - id: trailing-whitespace       # 行末の余分なスペースを除去

- repo: https://github.com/astral-sh/ruff-pre-commit
  rev: v0.3.0
  hooks:
    - id: ruff
      args: [--fix]
    - id: ruff-format

これを設定すると、git commit のたびに上記のチェックが自動で走る。AIが .env を誤ってステージングしても、コミット前に止まる。

設定例C:AGENTS.md / CLAUDE.md(セッションをまたぐルール)

Claude Code や Cursor はプロジェクトのルートに AGENTS.md(または CLAUDE.md)があれば、会話開始時に自動で読み込む。プロンプトに書かなくてもルールが毎回有効になる。

書き方のポイント:

  • 「なるべく〜」「できれば〜」は無視されやすい。「〜は禁止」「〜は必ず〜する」と断定形で書く

  • 条件がある場合は「〜の場合のみ〜してよい」と明示する

# AGENTS.md

## 変更禁止エリア
- `/legacy/` 以下のファイルは読み取りのみ。変更・削除・移動は禁止
- `config/production.yaml` は変更しない

## コーディングルール
- 新しい関数を追加する場合、必ず最初の行にその関数の目的をコメントで書く
例: # 注文IDからユーザー情報を取得して返す
- テストファイルは必ず tests/ 以下に置く。ルートに置かない
- 変数名は snake_case に統一する(JavaScript の場合は camelCase)

## コミット前の確認
- ruff check . を通してからコミットする
- 型エラーが出る場合は修正してからコミットする

linterとの使い分け:

linterで検証できるルール(形式・書き方)はlinterに任せて、AGENTS.mdには「AIの判断・行動範囲」に関するルールを書くと整理しやすい。両方に同じルールを書く必要はない。

よくある失敗パターンと対処

パターン1:linterを入れたのにCIで引っかからなかった

原因:ローカルとCIのlinterバージョンが違い、ルールの適用が異なっていた。
対処:pyproject.toml でバージョンを固定する。

[tool.ruff]
required-version = ">=0.3.0"

パターン2:AGENTS.mdのルールをAIが無視した

原因:「なるべく〜」「できれば〜」という曖昧な表現を使っていた。
対処:断定形に書き直す。「〜は禁止」「〜の場合は必ず〜する」。条件があるなら「〜の場合のみ〜してよい、それ以外は〜しない」まで書く。

パターン3:pre-commit hookが重くてcommitが遅くなった

原因:全ファイルに対してlinterを走らせていた。
対処:重いチェックはCIに移して、pre-commitは軽いものだけにする。

向かないケース・tradeoff

このアプローチが向かない場面:

  • タスクごとに内容が変わる指示(「今回はこの条件で」)→ プロンプトに残す

  • AIの創造的な判断に委ねたい部分(「最適な設計を選んで」)→ 制約にすると却って質が落ちる

  • 1人・小規模プロジェクトで整備コストが見合わない初期段階 → まず AGENTS.md だけで始める

tradeoff:

  • 設定ファイルが増えるため、初期整備に時間がかかる(最初の1時間)

  • ルールが厳しすぎると、AIが修正ループに入りかえって遅くなる。段階的に厳しくする

  • チームで使う場合、全員が pre-commit install しないと機能しない。CI側にも同じチェックを入れておくと確実

今日やる最小手順

  1. 今使っているプロンプトを開いて、「3回以上書き直したルール」を1つ探す

  2. そのルールが形式・書き方に関するなら → pip install ruff && ruff check . を一度走らせる。出たエラーが即移行候補

  3. そのルールがセッションをまたぐものなら → プロジェクトのルートに AGENTS.md を作り、そのルールだけ断定形で書く
    プロンプトからそのルールを削除して1日使う。崩れなければ成功
    1ルールずつ移していくだけで、プロンプトは短くなり、守られない回数は減っていく。

いいなと思ったら応援しよう!