AIに「絶対するな」が通じない理由 「Claude Code」の意図しない動作を防ぐ7つのTIPS:Anthropicが「ハーネスエンジニアリング」の基本を解説
AIの意図しない挙動やプロンプトによる指示の「無視」を防ぐにはどうすべきなのか。Anthropicは「Claude Code」における7つの制御手法とそれぞれの実践的な使い分け、アンチパターンを解説した。
企業におけるAIの業務利用が定着しつつある一方で、大きな課題となっているのが「ハルシネーション」や「意図しない動作」による品質のばらつきだ。プロンプトで「絶対に〜しないでください」と命令していても、複雑なタスクや長い会話の中でAIが指示を「無視」してしまうことがある。
AIの利用が本格化する中で、成果物の品質をいかに安定させ、AIを目的通りに制御できるかどうかが活用のカギを握る。こうした背景から「ハーネスエンジニアリング」と呼ばれる、AIを制御するための取り組みが注目されている。システム構成や制約の仕組みによって外側からAIの挙動をコントロールするという考え方だ。
では、AIの意図しない挙動を防ぎ、思い通りの出力を得るためにはどのようなハーネスエンジニアリングの手段があり、どう使い分ければよいのか。Anthropicは公式ブログで「Claude Code」におけるLLM(大規模言語モデル)の「Claude」の制御を題材に、AIの振る舞いを確実にコントロールする7つの手法と、それぞれの使い分け、アンチパターンを整理して解説した。
AIの「迷走」を防ぐ仕組み 7つの手法を比較
この7つの手法とは、「CLAUDE.mdファイル」「ルール」「スキル」「サブエージェント」「フック」「出力スタイル」「システムプロンプトへの追記」だ。
Anthropicは、Claudeに「どの指示をどの方法で与えるべきか」を判断するフレームワークとして、各手法を以下の3つの評価軸で分類し、7つの手法を次のように比較している。
- 指示がコンテキストウィンドウに読み込まれるタイミング
- 指示が長いセッションを通じてClaude Codeのコンパクション(※)後も保持されるかどうか
- 指示が持つ権限の大きさ
※会話履歴の圧縮。長い会話を圧縮して領域を空けるClaude Codeの処理であり、方法ごとに挙動が異なる。
| 方法 | 読み込まれるタイミング | コンパクション時の挙動 | コンテキストコスト | 主な用途 |
|---|---|---|---|---|
| CLAUDE.md(ルート) | セッション開始時。セッション全体を通じて保持 | コンパクション後に再読み込み(キャッシュは破棄) | 高い。全行が常にトークンを消費 | ビルドコマンド、ディレクトリ構成、モノレポ構造、コーディング規約、チーム規範 |
| CLAUDE.md(サブディレクトリ) | 当該サブディレクトリ内のファイル読み込み時 | 当該サブディレクトリが再度参照されるまで失われる | 低い。当該作業時のみ消費 | サブディレクトリ固有の規約 |
| ルール | スコープ指定がないルールはセッション開始時。パスでスコープが指定されたルールは該当ファイル操作時 | コンパクション時に再注入 | 中。パス指定がない場合は常時有効 | 特定の制約や規約 |
| スキル | 名前と説明はセッション開始時、本体はスキル起動時 | 呼び出されたスキルは共有予算の範囲内で再注入、古い順に破棄 | 低い。スキル起動時のみ本体が読み込まれ、スキル間の共有トークン予算の対象となる | 手順型のワークフロー(デプロイ、リリースチェックリスト) |
| サブエージェント | 名前、説明、ツール一覧はセッション開始時、本体はAgentツール経由の呼び出し時 | 最終メッセージ(要約とメタデータ)のみを返す | 低い。呼び出しまでゼロ。独立したコンテキストで実行 | 並列実行や、要約のみ返す補助タスク(ディープリサーチ、ログ解析、依存関係監査など) |
| フック | Claude Codeのライフサイクルの特定イベント発生時 | コンパクションの影響を受けない | 低い。構成はコンテキストの外部で実行される(一部の出力が返る場合あり) | 決定論的な自動化(linter実行、Slack通知、コマンドのブロック、履歴のバックアップなど) |
| 出力スタイル | セッション開始時。システムプロンプトに注入 | コンパクションされない | 高い。既定のシステムプロンプトを上書き | 役割の大きな変更(コーディングアシスタントから汎用〈はんよう〉アシスタントへ、など) |
| システムプロンプトへの追記 | セッション開始時。CLI(コマンドラインインタフェース)のフラグとして渡す | コンパクションされない。当該の呼び出しにのみ適用 | 中程度。初回リクエスト後にキャッシュ | トーン、応答の長さ、書式の設定 |
| Claude CodeでClaudeに指示する7つの方法(提供:Anthropic) | ||||
それぞれの手法の特徴と使い分け
1.CLAUDE.mdファイル
CLAUDE.mdは、プロジェクトのルートに置くMarkdownファイルだ。セッション開始時に読み込まれ、セッション全体を通じてコンテキストに保持される。ビルドコマンド、ディレクトリ構成、モノレポ構造、チームの規約など、プロジェクト全体の基本ルールを記述する場所として適している。
種類は2つあり、読み込まれ方が異なる。ルートにあるCLAUDE.mdは常に読み込まれ、会話がコンパクションされるたびに再読み込みされる。一方、サブディレクトリにあるCLAUDE.mdは、Claudeがそのディレクトリ配下のファイルを読んだときにのみ、必要に応じて読み込まれる。
共有リポジトリでCLAUDE.mdが肥大化すると、トークンの浪費や指示追従性の低下といったリスクが生じる。Anthropicは「200行以内」に抑え、手順は「スキル」へ、特定の規約は「ルール」に移すことが望ましいとしている。
2.ルール(.claude/rules)
ルールは、「.claude/rules/」に置くMarkdownファイルだ。Claudeに特定の制約や規約を与える。スコープを指定しないルールはCLAUDE.mdと同様に動作し、セッション開始時に読み込まれ、コンパクション時に再注入される。
ルールは「paths:」フィールドを用いてスコープを指定できる。pathsフィールドを用いてAPIのディレクトリに限定したルールは、ドキュメントのみの作業中はコンテキストに入らず、APIのディレクトリ内のコードを読み込むときにのみ適用される。
3.スキル(.claude/skills)
スキルは、「.claude/skills/」内にフォルダとして配置される。指示、スクリプト、リソースを収めており、Claudeによって動的に読み込まれる。スキルフォルダごとに置く「SKILL.md」に、スキルの名前、説明、本体を記述する。
セッション開始時は、スキルの名前と説明のみが読み込まれ、必要になったタイミングでスキル本体が読み込まれる。スキルの起動は、「/code-review」のようなスラッシュコマンドか、タスクとの自動的なマッチングにより実行される。
この仕組みにより、コンテキストコストは低く抑えられ、デプロイ(展開)やリリースチェックリストといった手順型の内容は、必要なときにのみコンテキストに入る。
なお、Claude Codeはカスタムスキルの作成にも対応している。
サブエージェント(.claude/agents)
サブエージェントは、「.claude/agents/」に置くMarkdownファイルだ。特定のサブ(補助)タスク向けに独立したアシスタントを定義する。名前、説明、ツール一覧はセッション開始時に読み込まれるが、本体は自動では起動されず、ClaudeがAgentツール経由で呼び出す。
サブエージェントは独立した新しいコンテキストウィンドウで分離実行され、最終メッセージとメタデータのみをメインセッションに返す。最大5階層までネストでき、「動的ワークフロー」によって数十から数百のバックグラウンドエージェントをオーケストレーション(管理)できる。
この分離が、スキルではなくサブエージェントを選ぶ主な理由だ。ディープリサーチや依存関係監査のように、中間結果がメインで会話を煩雑にする副次的なタスクには、サブエージェントが適している。一方、各ステップを確認、制御できるように、手順をメインスレッド内で実行させたい場合は、スキルを使用する。
5.フック(hook)
フックは、ユーザーが定義するコマンド、HTTPエンドポイント、またはプロンプトだ。Claude Codeのライフサイクルにおける特定のイベント(ファイル編集、ツール呼び出し、セッション開始など)に応じて起動し、Claudeの動作を決定論的に制御する。
フックのコンテキストコストは低い。構成や指示がメインのコンテキストウィンドウの外部にあるためだ。
Anthropicは、コード編集後のlinter実行や、特定コマンドの実行前のブロックなど、決定論的に実行すべき処理にフックを使用することを推奨する。「PreToolUse」というフックは、ツール呼び出しを検査し、ブロックできる。
6.出力スタイル(.claude/output-styles/)
出力スタイルは、「.claude/output-styles/」にあるファイルだ。システムプロンプトに指示を注入するため、これまでに挙げた方法の中で最も強く指示に従わせる効果を持つ。
ただし、出力スタイルを変更すると、デフォルト(既定)の出力スタイルが上書きされてしまう。これを防ぐには、スタイルのフロントマターで「keep-coding-instructions: true」を設定する必要がある。
これを設定しない場合、Claude Codeのソフトウェアエンジニアリング向けの動作が失われ、汎用アシスタントのように振る舞う恐れがあるという。
Anthropicは、カスタム出力スタイルを作成する前に、まず組み込みの「Proactive」「Explanatory」「Learning」というスタイルを確認するよう推奨している。
7.システムプロンプトへの追記
システムプロンプトへの追記は、「append-system-prompt」フラグによって、デフォルトのシステムプロンプトの末尾にカスタムテキストを追加する形式だ。
これは呼び出し時に渡され、その呼び出しにのみ適用される。セッションをまたいでファイルとして永続化されるわけではない。
プロンプトの「絶対にしないで」はなぜ失敗する?
Anthropicは以下の例を挙げつつ、多くの開発者が陥りがちな「プロンプト依存」のアンチパターンとその見直し策を、次のように示している。
CLAUDE.md内の「Xが発生するたびに、常にYを実行する」という記述
動作を確実に実行する必要がある場合は、「settings.json」によるフックを使用する。
CLAUDE.md内の「絶対に●●をしてはならない」という記述
Claudeは多くの場合指示に従うが、長いセッション、複雑なコンテキスト、あるいはタスクの一部としてアクセスしたファイルに潜む「プロンプトインジェクション」の影響などにより、プロンプトで定義した指示を無視してしまう可能性がある。
本当の「ガードレール」を構築するには、フックやパーミッションなどプログラムとして強制される“決定論的な手法”に頼る必要がある。
例として「PreToolUse」フックで危険なコマンドの実行を検知したら実行を強制終了することができる。ユーザーのローカル設定を上書きできるManaged settingsを用いれば、組織全体でガードレールを確実に強制することも可能だとした。
CLAUDE.md内の30行のプロシージャ
プロシージャはスキルとして、「claude/skills/」に配置すべきだとした。
パスの指定がないAPI固有のルール
ルールが「src/api/**」にのみ適用される場合、「paths:」でスコープを限定すれば、無関係な作業中にそのルールがコンテキストに混入するのを防げるとした。
プロジェクトレベルのCLAUDE.mdファイルへの個人設定の記述
個人設定にはローカルファイルを使用する。プロジェクトレベルのファイルには、チーム全体で共有されるが、特定のコードベースに固有の設定を保存する。
Anthropicは、同社の公式ドキュメント「Claude Codeのベストプラクティス」で解説されている環境設定(CLAUDE.md、パーミッション、フック、スキル、サブエージェントなど)を試し、それらが有効に機能したら、プラグインとしてまとめ、チームメイトやプロジェクト間で共有することを推奨している。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
「Claude Code」は開発の司令塔に 常識を一変させた5つの進化
コード補完を超え、自律的に調査・実行・検証を回せるようになった「Claude Code」。本連載の初回は、この1年でソフトウェア開発の「常識」が一変したClaude Codeの5つの進化を解説。AIを「開発の司令塔」として生かすために押さえておくべきポイントを紹介します。
【入門】.claudeフォルダの構造と使い方 Claude Codeを思い通りに動かそう
Claude Codeを使い始めたものの、プロジェクト内に生成される「.claude」フォルダをそのままにしていませんか? 実はこのフォルダこそが、Claude Codeの振る舞いを決定づける重要なポイントです。このフォルダの構造と役割を整理し、初心者の方でも理解できるように解説します。
「Claude Codeでトークン浪費」の原因 Anthropicが明かす「サブエージェント」5つの使い所と止め所
Anthropicは、同社のCLI型AIコーディングツール「Claude Code」のサブエージェントにおけるベストプラクティスやアンチパターンなどを解説したブログ記事を公開した。
「Claude Code」がプラグインをサポート AIエージェントやツールをまとめて配布可能に
Anthropicは、エージェント型コーディングツール「Claude Code」がプラグインでカスタマイズできるようになったと発表した。これによって「スラッシュコマンド」「サブエージェント」「MCPサーバ」「フック」など、機能拡張のための仕組みを一つのパッケージにまとめて共有できるようになるという。


