Claude Code エージェンティックエンジニアリング完全ガイド|CLAUDE.md、rules、skills、agents...どこに何を書けばAIエージェントは正しく動くのか?
2026年3月のある夜、Claude Codeのセッションをじっと眺めていた。
40個以上のスキルファイル、7種類のルールファイル、条件分岐で構造化されたCLAUDE.md。数ヶ月かけて育ててきた自分のリポジトリだ。
その夜、新しいスキルを3つ追加した。経済ニュースとx投稿分析の手順を標準化したかった。リサーチの精度を上げたかった。エージェントの判断基準をもっと細かく定義したかった。
結果は散々だった。
エージェントの応答が遅くなった。判断に迷うようになった。それまで一発で通っていたタスクが、2回、3回とリトライを要求してくる。
(...スキルとデータを足してるのに、なんで悪くなるんだ)
3つのスキルを全部外したら、AIエージェントがまた軽やかに動き始めた。
問題はツールの性能ではなかった。エージェントに渡す「情報」の設計が問題だった。何を渡して、何を渡さないか。どこに書いて、いつ読ませるか。この設計をミスると、どんな高性能なモデルも力を発揮できない。
本稿では、私のリポジトリで数ヶ月かけて試行錯誤してきたAIエージェントを正しく動かすのための手法と設計、「エージェンティックエンジニアリング」について、Anthropicの公式文書と付き合わせながら改善していった実践知を書く。Claude Codeを前提にしているが、原則はCodexでも他のエージェントCLIでも変わらない。
前半の無料部分では、エンジニアから投資家まで、プログラマーから非技術者まで、Claude Codeを使うすべての人が、AIエージェントを正しく動かすのための手法と設計、「エージェンティックエンジニアリング」を理解し、AIエージェントの能力を100%引き出せるようになることを目指した私の知見と2026年3月現在の最新設計を盛り込んだ完全ガイドになる。
後半のサブスクメンバー限定セッションでは、私が実際に使っているCLAUDE.md、rules、skills、agentsなどのファイルの中身を公開する。また、本稿で述べる「エージェンティックエンジニアリング9原則」を自動で検証する監査用スキルを提供する。「理解した」を「実践できている」に変えるための、具体的な道具立てとなっている。
完全ガイドの3万文字をさらに超える4万字超えの非常に長いnote記事となったが、これを読んで実際に実践していただければ、あなたも AIエージェントマスターになれるはずだ。本稿があなたのAIエージェントたちを効率よく動かすための助けになれば幸いだ。
Part 1: みんな同じところでハマっている
Xを開くと、毎日のように誰かが「Claude Codeで○○を作った」「Claude Codeで△△を自動化した」と投稿している。
デモ動画は華やかだ。プロンプト一発でアプリが立ち上がり、テストが通り、デプロイまで完了する。
(なぜか、みんな3分ぐらい動画。BGMはローファイ)
そして、その横で私は、エージェントが生成したコードのバグを手動で直している。
(...ロケットを飛ばしてる人がいるのに、自分は石を積んでいる。BGMはメタル)
この焦燥感、開発者なら覚えがあるんじゃないかと思う。
焦ると、ツールを足したくなる。ハーネスを入れよう。プラグインを追加しよう。拡張パッケージで機能を増やそう。足せば足すほど賢くなるはずだ。
でも実際は逆だ。
足すほど、パフォーマンスは落ちる。
理由は2つある。
1つ目は、フロンティア企業自身が最大のエージェントユーザーだという構造的事実。OpenAIのHarness Engineeringチームは、5ヶ月間で手書きコード0行、約100万行のコード、約1,500件のPRをエージェントにマージさせた(出典)。Anthropicも自社のClaude Codeを開発プロセスの中核に据えている。この規模で使い込んでいる人たちが「これは便利だ」と判断した機能は、本体に取り込まれる。
実際に起きたことを振り返る。
skills: 以前はサードパーティのスキル管理フレームワークが必要だった。今はClaude Code本体がカスタムスキルの読み込みをネイティブサポートしている
memory: 外部のメモリ拡張ツールが流行った時期があった。今はClaude Code自体にメモリ機能が組み込まれている
planning: タスク計画を外部で管理するツールがあった。今はエージェント自身が計画を立て、実行し、検証するフローが組み込まれている
subagents: サブエージェントの管理も、以前は自前で実装するしかなかった。今はTask機能としてネイティブに提供されている。さらにPreview段階だが、複数エージェントが協調するTeam機能まで登場し始めている
パターンは一貫している。外部ソリューションが先行し、有用性が証明されると、本体に吸収される。サードパーティのツールを山ほど積むのは、時間の投資として非効率だ。6ヶ月後にはその機能が本体に入っている可能性が高い。
2つ目は、ツールを足すとエージェントの判断リソースが分散するという問題。ツールの選択肢が増えると、「どのツールを使うか」の判断にトークンを消費する。その分、本来のタスクに使えるトークンが減る。
引き算は、怖い。でも、引いた瞬間にエージェントの動きが軽くなる。この体感を一度味わうと、もう戻れない。

Part 2: CLAUDE.mdの正体を理解する
ここから本題に入る。
エージェントのパフォーマンスを決めているのは、「どこに何を書くか」の設計だ。そしてその設計を間違える最大の原因は、CLAUDE.mdの正体を誤解していることにある。
CLAUDE.mdはSystem Promptではない
多くの開発者が、CLAUDE.mdをSystem Promptのようなものだと思っている。「ここに書いたことはClaudeの振る舞いのベースになる」と。
公式ドキュメントにはこう書かれている。
CLAUDE.mdの内容は、Claude Codeのデフォルトのシステムプロンプトに続くユーザーメッセージとして追加される。
CLAUDE.mdの内容はSystem Promptではなく、セッションの最初のUser Messageとして注入される。私がClaude Codeに投げるプロンプトと同じ扱いで、会話の中の一つのメッセージにすぎない。
さらに、公式のMemory managementページにはこうある。
Claudeはこれらをコンテキストとして扱う。強制的な設定としてではない。

この違いは見た目以上に大きい。
セッション後半で効かなくなる問題
System Promptは会話のメッセージとは別の領域で管理されている。どれだけ会話が長くなっても、Claudeにとっての重要度は変わらない。
一方、User Messageとして注入されたCLAUDE.mdの内容は、会話が進むにつれて古いメッセージになっていく。10ターン、20ターンと会話が続けば、CLAUDE.mdに書いたことの影響力は薄れる。
(...そういうことか)
私のリポジトリで起きていた現象に、急に説明がついた。
セッションの序盤はルールを守る。でも後半になると、CLAUDE.mdに書いた禁止事項を平気で破る。「テストを必ず書け」と書いているのに、セッション終盤のコミット直前でテストを省略する。「コミットメッセージは日本語で」と書いているのに、英語で書く。
Claudeがルールを無視しているんじゃない。User Messageとしてのルールが、会話の中に埋もれているだけだ。
CLAUDE.mdは「Session Start Hook」である
ここまでの事実を踏まえると、CLAUDE.mdの本質はSession Start Hookだと考えるとすっきりする。
Session Start Hook。セッションが開始されるたびに実行される初期化処理のことだ。
CLAUDE.mdもまったく同じ構造になっている。セッションが始まるたびに、最初のUser Messageとして内容が注入される。コンパクションが発生してセッションが圧縮された後も、再度読み込まれる。
Hookの役割は「起動時に必要な初期化処理を行うこと」であって、「アプリケーション全体を通じて守るべきルールを定義すること」ではない。
ルールを書きたいなら、別の場所がある。
Part 3: どこに何を書くべきか
エージェント設計のアーキテクチャは、3つの層で構成される。
CLAUDE.md、.claude/rules/、そしてskills。この3層の使い分けが、エージェントのパフォーマンスを決める。
第1層: CLAUDE.md に書くもの
CLAUDE.mdに書くべきものの基準はシンプルだ。「セッション開始時の作業を助ける情報か?」だ。
Claude Codeの作業は多岐にわたる。開発、調査、設計、レビュー、記事執筆。これらすべての用途において、セッションの最初に知っておくべき情報は何か。
私のリポジトリのCLAUDE.mdには、3つのカテゴリだけを書いている。
プロジェクトの概要:何のためのリポジトリで、何をしているのか。これはどの用途でも、セッションの最初にClaudeが把握しておくべき情報だ。
モジュール構成:ディレクトリ名だけでは各モジュールの役割がわかりにくい場合、その説明を書く。Claude Codeはどんな作業でもまずディレクトリ構造を探索するところから始まる。名前から推測しにくいモジュールの説明があれば、その探索を助けられる。
スキル一覧のディレクトリ:「記事を書くときはwriting-articlesを使え」「銘柄分析するときはscreening-equitiesを使え」のように、状況に応じてどのスキルを読むかの分岐表を書いている。CLAUDE.mdを条件分岐のディレクトリとして設計する。中身は書かない。「どこに中身があるか」だけを書く。
これだけだ。ルールもレシピも、CLAUDE.mdには書かない。
CLAUDE.mdに書くべきでないもの
逆に、以下はCLAUDE.mdに書いても効果が薄い。
セッション全体を通じて守らせたいルール:「テストは必ず書くこと」「エラーを握りつぶすな」。これらはUser Messageとして注入される以上、セッション後半では埋もれる。特にセッション終盤で初めて必要になるルールが厄介だ。コミット直前の検証手順や、PR作成時のフォーマット指定など、CLAUDE.mdのメッセージが最も古くなったタイミングで守ってほしいルールほど効きにくい。
特定の用途でしか使わない情報:「開発時はfeatureブランチを切ること」「レビュー時はセキュリティ観点を重視すること」。開発の情報を書けば調査時にはノイズになるし、レビューの情報を書けば開発時には邪魔になる。
量の多い情報:50行のルールをCLAUDE.mdに書くのは、毎回のセッションで50行分のコンテキストを無条件に消費するのと同じだ。常に渡す情報は最小限にする。
@importの罠:CLAUDE.mdには@path/to/fileという構文でファイルをインポートできる。便利だが、これが落とし穴になる。私のリポジトリでは、一時期CLAUDE.mdにこう書いていた。
コーディングガイドは @.claude/rules/coding/coding-guides.md を参照。このファイルは.claude/rules/に置かれているから、ルールとして自動的に読み込まれる。それに加えて、@importでCLAUDE.mdの一部としても展開される。同じ内容が二重にコンテキストを消費していた。
「参照」のつもりで書いた@importが、実際には「全文展開」として動作する。coding-guides.mdは70行あるファイルだ。@importで展開されれば70行分がCLAUDE.mdに追加され、さらにルールとしても別途読み込まれる。140行分のコンテキストを無駄に消費していた計算だ。同じことを複数のルールファイルでやれば、無駄は何百行にも膨れ上がる。
修正は単純だった。@importを外し、プレーンテキストの参照に変えた。
「ルールは.claude/rules/に任せる。CLAUDE.mdはどこにルールがあるかだけ示す」。これが「ディレクトリ」としてのCLAUDE.mdの正しい姿だ。
第2層: .claude/rules/ に書くもの
ルールを書くべき場所は.claude/rules/だ。

ここに置いたMarkdownファイルには2つの種類がある。常時読み込みルールと、条件付きルールだ。
常時読み込みルール:YAML frontmatterにpathsフィールドを持たないファイル。セッション開始時に無条件で読み込まれる。CLAUDE.mdと同じタイミングで注入されるが、コンテンツをCLAUDE.mdから分離できる点で有用だ。基本原則やコミュニケーション形式のような「すべてのタスクに適用される汎用ルール」はここに置く。
条件付きルール:pathsフィールドを持つファイル。マッチするファイルをClaudeが初めて扱ったタイミングで注入される。
---
paths:
- "src/**"
description: コーディング時の基本ルール
---
# コーディングガイド
- 既存コードのパターンを踏襲する
- エラーを握りつぶさない(catchして何もしないは禁止)
- 変更した機能に対するテストを追加するsrc/配下のファイルを触るときだけ、このルールが適用される。記事を書いているときには読み込まれない。
条件付きルールにProgressive Disclosure(段階的開示)の原理が効いてくる。
CLAUDE.mdはセッション開始時にすべての情報を一括で渡す。一方、条件付きルールは該当するファイルを初めて扱ったタイミングで注入される。必要な情報を必要なタイミングで渡すことで、ルールがより新しいメッセージとして届く。
セッションの30ターン目で初めてTypeScriptファイルを編集したとする。そのタイミングで注入されたルールは、セッション開幕に注入されたCLAUDE.mdよりも新しいメッセージだ。新しいメッセージのほうが効く。
同じUser Messageでも、いつ注入されるかでルールとしての実効性は大きく変わる。

私のリポジトリでは、.claude/rules/を3つのカテゴリに分けて管理している。
meta/: 実行ワークフロー、コミュニケーション形式、基本原則。pathsなしで常時読み込み
coding/: コーディングルール。paths: ["src/**", "apps/**"]で条件付き読み込み
writing/: 文章執筆ルール。paths: ["articles/**", "docs/**"]で条件付き読み込み
coding配下のルールは、ソースコードを触るときだけ読み込まれる。writing配下のルールは、記事を触るときだけ。meta配下のルールは常に読み込まれるが、CLAUDE.md本体からは分離されている。
こうすることで、記事を書いているときに「エラーを握りつぶすな」というコーディングルールを読む無駄がなくなる。
第3層: skills に書くもの
ルールは分かった。なら、スキルは?
スキルは「レシピ」だ。
スキルには、特定のタスクを実行するための具体的な手順を書く。手順が確立されているタスク、つまり「毎回同じフローで進めたい作業」をスキル化する。
私のリポジトリには40以上のスキルがある。
writing-articles: 10,000文字以上の投資論考記事を6フェーズで執筆する手順
generating-thumbnails: 記事サムネイル画像を生成する手順
analyzing-earnings: 決算発表を構造的に分析する手順
スキルの重要な特性は、CLAUDE.mdから参照されるが、呼び出されるまでコンテキストを消費しないこと。CLAUDE.mdには「記事を書くときはwriting-articlesスキルを使え」とだけ書いておく。エージェントが記事を書くタスクを受けたときに初めて、そのスキルファイルを読みに行く。
ルールでもスキルでもどちらに何を書くか判断に迷うことがある。
私の基準はこうだ。
「行動を縛る」のはルール。「やり方を教える」のはスキル。
「〜をするな」はルール。「こうやれ」はスキル。
例えば、「エラーを握りつぶすな」はルール。「決算分析はこの5ステップで進めろ」はスキル。こうやって整理するとシンプルになる。
3層アーキテクチャの全体像
まとめると、こうなる。
CLAUDE.md: セッション開始時の地図。プロジェクト概要、モジュール構成、スキルへの分岐表。量は最小限に
.claude/rules/: 状況に応じて注入されるルール。pathsで適用範囲を絞る。Progressive Disclosureで必要なタイミングに届く
skills: タスクの実行手順(レシピ)。呼び出されるまでコンテキストを消費しない
このアーキテクチャの核心は、CLAUDE.mdに全部書かないことだ。CLAUDE.mdはディレクトリであり、コンテンツではない。コンテンツは.claude/rules/とskillsに分散させ、必要なときに必要な分だけ読ませる。

自動メモリ — Claudeが書く記憶
ここまでの3層はすべて「基本的に人間とAIのどちらも書く」ものだ。CLAUDE.mdを書く、ルールを書く、スキルを書く。
もう1つ、Claudeのみが自分で書く記憶がある。自動メモリだ。
Claude Codeにはセッション中に学んだことを自分でメモする機能がある。ビルドコマンドの発見、デバッグ中に見つけたパターン、ユーザーのコーディングスタイルの好み。これらを~/.claude/projects/{プロジェクト名}/memory/にマークダウンファイルとして保存し、次のセッションで自動的に読み込む。
~/.claude/projects/{プロジェクト名}/memory/
├── MEMORY.md # インデックス(最初の200行がセッション開始時に読まれる)
├── debugging.md # デバッグパターンの詳細メモ
├── api-conventions.md # API設計の決定
└── ... # Claudeが必要に応じて作成するトピックファイルMEMORY.mdの最初の200行だけがセッション開始時に読み込まれる。200行を超えた部分は切り捨てられる。トピックファイルはセッション中にClaudeが必要に応じてオンデマンドで読む。ここにもProgressive Disclosureが効いている。
CLAUDE.mdとの違いは明確だ。CLAUDE.mdは人間がClaudeに「こうしろ」と伝えるための設計書。自動メモリはClaudeが自分用に「こうだった」と書き残すメモ帳。指示と学習は、書く主体が違う。
自動メモリに適しているもの:「このプロジェクトではnpmではなくpnpmを使う」「テスト実行前にローカルRedisが必要」「この関数名はこういう命名規則」。Claudeが作業中に発見したパターンだ。毎回発見し直すのは無駄だから、一度学んだら覚えておくのが合理的だ。
自動メモリに書くべきでないもの:ルールや設計指針だ。「テストは必ず書け」を自動メモリに任せてはいけない。それはルールだ。ルールは.claude/rules/に書く。自動メモリはClaudeのメモ帳であって、設計ドキュメントではない。
自動メモリの運用にも「ディレクトリ原則」が適用される。MEMORY.mdは200行の制限があるから、簡潔なインデックスに留めて、詳細は別のトピックファイルに分ける。CLAUDE.mdと同じだ。インデックスは軽くして、中身は外に出す。
メモリアーキテクチャの全体像
ここまでの情報を1つの地図にまとめる。何が、いつ、どこで、どのような粒度で読まれるのか。

一つの原則が全層を貫いている。「インデックスは軽く、中身は必要なときに読み込む」。CLAUDE.mdはスキルへの分岐表。ルールはpathsで絞る。スキルはトリガーされるまで読まれない。自動メモリのMEMORY.mdは200行のインデックス。すべてが同じ設計原則に従っている。
Part 4: スキルは小さなソフトウェアになる
Part 3でスキルを「レシピ」と書いた。確立された手順を定義し、毎回同じフローで進めたい作業を型化したもの。
最初はそれで十分だった。私のwriting-articlesスキルも、最初は「こういう順番で書け」という手順書にすぎなかった。情報を集めろ、構成を考えろ、書け、検証しろ。シンプルだ。
使い込んでいくうちに、このスキルは育った。リサーチの並列分割が加わった。ファクトチェック用のサブエージェントが必要になった。検証フェーズでは外部スクリプトが呼ばれるようになった。
気づいたら、スキルが「レシピ」の域を超えていた。
(...いやもうこれ、ソフトウェアの設計と一緒だ)
SKILL.mdはオーケストレーターにする
スキルが複雑になると、最初にぶつかる壁はSKILL.mdの肥大化だ。
手順、判断基準、出力フォーマット、エラー処理、サブエージェントへの指示。全部1つのファイルに書くと、1000行を超えることがある。1000行のプロンプトをコンテキストに載せるのは、それだけでかなりの圧迫になる。
解決策は、SKILL.mdをオーケストレーターにすることだ。SKILL.md自身は「何をするか」を記述しない。「いつ・誰に・何を任せるか」だけを記述する。専門処理はサブエージェント用のプロンプトファイルに、ドメイン知識はreferences/に、確定的処理はscripts/に。
SKILL.md(フロー制御)
├── agents/ # サブエージェント用プロンプト
├── references/ # データ契約・ドメイン知識
├── scripts/ # 確定的処理
└── examples/ # 入出力のサンプル私のリポジトリの記事執筆スキルもこの構造に進化した。SKILL.md本体はフェーズの流れと分岐条件だけ。リサーチエージェントへの指示、検証エージェントへの指示、ファクトチェックの基準は、それぞれ別ファイルに分離している。
これはPart 3で書いた3層アーキテクチャの再帰だ。SKILL.mdがスキル内部のCLAUDE.mdになる。ディレクトリとして機能し、詳細は外部ファイルに委ねる。Progressive Disclosureがスキルの内部設計にまで貫通する。

判断はエージェントに、計算はスクリプトに
スキルの中で最も効果が大きい分業は、「判断」と「計算」の分離だ。
エージェントは判断が得意だ。文脈を理解し、曖昧な指示を解釈し、創造的な出力を生成する。
でも、エージェントにはどうしても苦手なことがある。正確な数値計算。並列処理のループ制御。ファイルの一括操作。入力が同じなら出力も同じでなければならない、確定的な処理だ。
確定的処理をエージェントに任せると、たまに間違える。集計値がずれる。ファイル名を間違える。ループの終了条件を見落とす。エージェントの出力は本質的に確率的だから、100%の再現性を要求するタスクには向いていない。
だからスクリプトに追い出す。判断・分析・文章生成はエージェントに。ループ・集計・ファイル操作はスクリプトに。この線引きをスキルの中で明確にしておく。
スキーマ契約
エージェントとスクリプトを連携させるとき、必ず問題になるのが出力フォーマットのブレだ。
エージェントに「結果をJSONで出力しろ」と指示する。大抵はうまくいく。でもたまにフィールド名が変わる。configurationがconfigになる。ネストの深さが変わる。スクリプト側は厳密なパースを前提に書かれているから、フォーマットが1文字ずれただけで壊れる。
対処法は、references/にJSONスキーマを明記することだ。「このフィールド名を使え。この構造で出力しろ」。
SKILL.mdからは「references/schemas.mdのフォーマットに従え」と参照するだけ。
これはPart 7で書く「テストを契約として使う」思想と同根だ。テストが実装の契約なら、スキーマはエージェントとスクリプトの契約。契約書があるから、双方が独立して動ける。
理由で導く
スキルの中でルールを書くとき、2つのスタイルがある。
「必ずバリデーションを実行しろ」
これはMust-driven。
「バリデーションを省くと、APIエラーが返ってトークンを無駄にし、ユーザーを苛立たせるので、バリデーション実行する」。
これがWhy-driven。
必ず、絶対、禁止など、強い言葉を並べたくなる気持ちはわかる。でも、理由なしの強制ルールは脆い。未知のケースに対応できない。理由がわかっていれば、エージェントは指示されていない状況でも適切に判断できる。ルールの網羅性に頼る必要がなくなる。
ただし例外がある。スキーマのフィールド名の一致やセキュリティに関わる箇所のように、1文字の違いが致命的になる制約は、理由ではなく明示的な「必ず」で書く。
崖の近くにはガードレールを置く。平原では理由で導く。
descriptionは存在証明
スキル設計で最も見落とされがちなのが、descriptionフィールドだ。
Claude Codeのシステムプロンプトに常時注入されるのは、スキルのnameとdescriptionだけ。SKILL.mdの本体は、スキルがトリガーされて初めて読み込まれる。
つまり、descriptionが的確でなければ、スキルは永遠に呼ばれない。どれだけ精巧なSKILL.mdを書いても、存在しないのと同じだ。
Claudeにはスキルを「使わなすぎる」傾向がある。だからdescriptionは少し押し強めに書く。私のスキルでは、3つの要素を入れている。
What: 何をするか(「複数手法で適正株価レンジを算出する」)
When: どういうリクエストで使うか(「バリュエーションは?」「適正株価は?」「割高?割安?」等)
How: 主要な機能(「PER/PBR相対比較、DCF絶対評価、複数手法クロスチェック」)
「バリュエーション分析するときに使う」ではなく「バリュエーションは?、適正株価は?、割高?割安?、と聞かれたら使う」と、トリガーすべき表現を複数列挙する。
descriptionの最適化は、スキルのイテレーションで最もROIが高い投資だ。
レシピからソフトウェアへ
スキルの成熟を整理するとこうなる。
Phase 1: レシピ — SKILL.mdに手順を書くだけ。シンプルで十分
Phase 2: 分離 — SKILL.md + references/。手順とドメイン知識を分ける
Phase 3: オーケストレーション — SKILL.md + agents/ + references/ + scripts/。SKILL.mdはフロー制御に徹し、専門処理を外部に委譲する
Phase 1から始めるのが正しい。最初からPhase 3で設計するのは過剰設計だ。スキルを使い込んで、「ここはサブエージェントに分けたほうがいい」「ここはスクリプトのほうが安定する」と肌で感じてから、段階的に進化させる。

これもPart 9で書く「育てて、整えて、また育てる」のサイクルだ。スキルもまた、育てるものだ。
Part 5: コンテキストという酸素
3層アーキテクチャの設計思想を支えているのが、コンテキスト管理という原則だ。
エージェントにとってコンテキストウィンドウは、人間にとっての作業机のようなものだ。机の上に資料を積みすぎると、今やるべき作業が埋もれる。必要な資料がすぐに見つからない。手が止まる。
エージェントに必要な情報だけを渡し、それ以外は渡さない。「情報を足す」のではなく、「情報を絞る」。これがコンテキスト設計の本質だ。
リサーチと実装を分離する
私のリポジトリでは、記事を書くときにリサーチと執筆を完全に分離している。
rules に置いた execution-workflow.mdにこう書いてある。
Web検索を伴うリサーチは、1エージェントに集中させずに並列分割する。1エージェントあたりの検索回数を抑えることで、コンテキスト枯渇による停止を防ぐ。
具体的にはこうだ。3つのリサーチエージェントを並列で走らせる。1つは財務データ、1つは業界動向、1つは技術トレンド。それぞれが結果をファイルに書き出す。全員が終わったら、執筆エージェントがそのファイルだけを読んで書く。
執筆中にWeb検索はさせない。リサーチと執筆は別のセッション、別のエージェントだ。
リサーチと実装を混ぜると、リサーチで得た大量の情報がコンテキストを埋め尽くし、実装の精度が落ちる。これは記事執筆だけの話じゃない。コードの設計検討と実装も分けるべきだし、バグの調査と修正も分けるべきだ。
コンテキスト枯渇への対処
長いセッションで避けられないのが、コンパクションによる情報喪失だ。セッションの前半で読み込んだファイルの内容が、後半では圧縮されて消えている。エージェントが「さっき読んだはずのファイル」の内容を忘れている。
対処法は「ファイルに書き出す」ことだ。
execution-workflow.mdにこう書いている。
エージェントへのプロンプトに「途中成果物は必ずファイルに書き出せ」と指示する。これにより max_turns 到達時でも成果物が残る。
エージェントの頭の中(コンテキスト)は揮発性だが、ファイルは永続する。大事な情報はファイルに逃がしておく。コンパクションが起きても、ファイルを読み直せばいい。
この「ファイルをインターフェースにする」という発想は、Unix哲学に通じる。プロセス間でパイプやファイルを介してデータを受け渡す。各プロセスは自分の仕事だけをやる。エージェント設計も同じ構造になる。

もう一つ実践で学んだことがある。execution-workflow.mdの「Context Window 衛生管理」セクションに、こう書いた。
stdoutにはサマリーのみ流す。詳細はファイルに書き出す。
テストの出力が何千行もコンテキストに流れ込むと、それだけでエージェントの判断品質が落ちる。テスト結果のサマリーだけを表示して、詳細はログファイルに退避する。コマンドの出力もエージェントにとってはコンテキストだ。必要な分だけ見せる。この原則はどこにでも適用できる。
Part 6: 迎合するエージェントとの正しい付き合い方
AIエージェントには、構造的な弱点がある。
sycophancy(迎合)。
つまり、おべっか。ユーザーの期待に沿おうとする傾向のことだ。
「バグを探せ」とエージェントに言うと、エージェントはバグを「見つけなければならない」と解釈する。見つからなくても、何かをバグとして報告する。存在しないバグをでっち上げることすらある。
(...これには身に覚えがありすぎる)
私の失敗談を書く。
ある日、記事の下書きをエージェントに渡して「改善点を探してくれ」と頼んだ。エージェントは嬉々として12個の改善提案を返してきた。構成の変更、比喩の差し替え、データの追加、表現の修正。
全部やったら、記事が別物になった。元の文体が消え、冗長になり、読み返すと自分の声が聞こえない。
「改善点を探せ」と言ったから、エージェントは改善点を探した。12個も。実際に改善が必要だったのは、せいぜい2つか3つだった。残りは「改善点を見つけた」という成果を出すためのノイズだった。
ニュートラルなプロンプトの技法
対処法は、ニュートラルなプロンプトを使うことだ。
「バグを探せ」ではなく「ロジックを追って報告しろ」。
「改善点を探せ」ではなく「構成と論理展開を検証しろ」。
違いは微妙だが、効果は大きい。前者は「問題がある」という前提を含んでいる。後者は「問題があるかもしれないし、ないかもしれない」という中立的な立場だ。
エージェントは、プロンプトに含まれる前提を忠実に実行する。前提が偏っていれば、結果も偏る。
この話は以前、鏡と計器のnote記事で書いたことにも通じる。私が学んだことについて詳しく書いてあるので、もしよければ読んでみてほしい。

ルールでsycophancyをガードする
プロンプトの工夫だけでは限界がある。そこで.claude/rules/が活きてくる。
私のリポジトリでは、communication-standards.mdに「Push Back」のルールを入れている。
問題のある指示には代替案を提示する義務がある。盲目的な同意は失敗。
エージェントに「何でも従え」と言うのではなく、「問題があると思ったら反論しろ」と指示する。このルールは.claude/rules/meta/に置いてある。pathsなしの常時読み込みだから、すべてのタスクで有効だ。CLAUDE.md本体に書くのではなく、ルールファイルとして分離している点がポイントになる。CLAUDE.mdが肥大化するのを防ぎつつ、ルールの所在を明確にする。
もう一つ。.claude/rules/meta/core-principles.mdに「ハルシネーション禁止」の基本方針を書いている。
すべての事実をソース(Web検索、公式ドキュメント、コード)で検証。未確認の数値・日付・固有名詞を使用禁止。不明点は必ず質問せよ。
「わからないことはわからないと言え」
エージェントは「知らない」と言いたがらない。知らなくても、それらしい回答を生成してしまう。だから明示的に「不明なら質問しろ」と書く。指示しなければ、エージェントは推測で穴を埋める。
sycophancyを逆手に取る: 対立エージェントパターン
もっと構造的にsycophancyを活用する方法もある。対立エージェントパターンだ。
bug-finder agent:バグを見つけることだけに特化したエージェント。見つけたバグの重要度でスコアリングする。低が+1、中が+5、高が+10。バグを多く見つけるほどスコアが上がるから、迎合の力で「バグの superset」が出来上がる。本物のバグも含まれているが、偽陽性も多い。
adversarial agent:bug-finderの報告を否定することに特化したエージェント。「それはバグじゃない」と正しく指摘できたらスコアが上がる。ただし、本物のバグを見逃すと-2倍のペナルティ。迎合の力で「否定できるものは否定する」方向に動くから、「バグの subset」が出来上がる。本当に否定できないものだけが残る。
referee agent:中立の審判役。「自分は正解を持っている」と伝えた状態で、bug-finderとadversarialの主張をジャッジする。正解を持っていると信じているから、より慎重に判断する。
supersetとsubset。その重なりが、真のバグに近づく。
迎合を「バグ」として排除するのではなく、「設計材料」として使う。敵の力を利用する柔術のような発想だ。
この3つのエージェントを1つのスキルとして組み合わせて使うのが効果的だ。スキルのSKILL.mdがオーケストレーターとなり、bug-finder → adversarial → refereeの順に実行を制御する。
具体例1: コードのバグ検出
PRレビューでこのパターンを使う場面を考えてみる。
bug-finder agentに「このPRの変更差分を読んで、バグを探せ」と投げる。バグを見つけるほどスコアが上がるから、ありとあらゆる可能性を報告してくる。「この変数名がシャドウイングしている」「エラーハンドリングが不足している」「競合状態の可能性がある」。10件報告してきたとする。そのうち本物のバグは3件かもしれない。でも、見逃しはほぼない。
adversarial agentに「bug-finderの報告を検証しろ。誤報を正しく否定できたらスコアが上がる。ただし本物のバグを見逃したら-2倍のペナルティだ」と投げる。否定できるものは否定する方向に動くから、「変数のシャドウイングはスコープが異なるので問題ない」「このエラーは上位で捕捉されている」と7件を却下する。残った3件が、真のバグの候補だ。
最後にreferee agentが、bug-finderとadversarialの主張を中立の立場からジャッジする。両者の根拠を比較し、最終的なバグリストを確定させる。
エージェントの定義はスキル内部に配置する。
---
name: bug-finder
description: PRの変更差分からバグ・潜在的問題を網羅的に発見する。発見数でスコアリングされるため、見逃しを最小化する方向に動作する。
tools: ["Read", "Grep", "Glob", "Bash"]
---
あなたはbug-finder agentです。
## ミッション
渡されたコード差分からバグ・潜在的問題を可能な限り多く発見すること。
## スコアリング(あなたの評価基準)
- 低リスクのバグ発見: +1
- 中リスクのバグ発見: +5
- 高リスク(データ損失・セキュリティ)のバグ発見: +10
- 合計スコアが高いほど優秀な成果
## 検証観点
1. ロジックエラー(境界条件、off-by-one、null/undefined)
2. エラーハンドリング漏れ(catch なし、エラー握りつぶし)
3. 競合状態・データ整合性
4. セキュリティ(インジェクション、認証・認可漏れ)
5. パフォーマンス(N+1クエリ、不要な再レンダリング)
6. 型安全性(any型、型アサーション)
7. リソースリーク(未クローズのハンドル、イベントリスナー)
## 出力形式
必ず以下のJSON形式でファイルに書き出すこと:
```json
{
"findings": [
{
"id": "BUG-001",
"file": "path/to/file.ts",
"line": 42,
"severity": "high",
"category": "error-handling",
"title": "問題の要約(1行)",
"detail": "何が問題で、どういう条件で発生するか",
"evidence": "根拠となるコードスニペットや論理"
}
],
"score": 0,
"summary": "全体サマリー"
}
```
## 制約
- 推測ではなく、コードの事実に基づいて報告すること
- 各発見には必ず「evidence」(根拠)を含めること
- severity は low / medium / high のいずれか
---
name: adversarial-reviewer
description: bug-finderの報告を検証し、偽陽性を排除する。誤報の却下でスコアリングされるが、本物のバグ見逃しには2倍のペナルティがあるため、慎重に判定する。
tools: ["Read", "Grep", "Glob", "Bash"]
---
あなたはadversarial-reviewer agentです。
## ミッション
bug-finderの報告を検証し、偽陽性(誤報)を排除すること。
## スコアリング(あなたの評価基準)
- 誤報を正しく却下: +3
- 本物のバグを見逃し: -6(却下スコアの-2倍)
- 偽陽性の却下率が高く、かつ本物のバグを見逃さないことが最高評価
## 判定基準
各報告に対して以下を検証:
1. 報告されたコードパスは実際に到達可能か?
2. 上位・下位のコードで既に対処されていないか?
3. フレームワーク・ランタイムが保証している動作ではないか?
4. テストで既にカバーされていないか?
5. evidence(根拠)は具体的なコード事実に基づいているか?
## 出力形式
必ず以下のJSON形式でファイルに書き出すこと:
```json
{
"verdicts": [
{
"id": "BUG-001",
"verdict": "DISMISS",
"reason": "上位の try-catch で捕捉されており、エラーハンドリング漏れではない",
"evidence": "src/handler.ts:15 で try-catch が存在"
},
{
"id": "BUG-002",
"verdict": "CONFIRM",
"additional_context": "さらに、関連する箇所にも同種の問題がある"
}
],
"score": 0,
"statistics": {
"total": 0,
"dismissed": 0,
"confirmed": 0
}
}
```
## 制約
- DISMISSには必ず具体的なコード根拠を示すこと(「一般的には問題ない」はNG)
- 判断に迷った場合はCONFIRM寄りに判定すること(-6ペナルティ回避)
- bug-finderの evidence と自分の evidence を照合すること---
name: review-referee
description: bug-finderとadversarial-reviewerの判定結果を最終ジャッジし、対応が必要なバグリストを確定する。
tools: ["Read"]
---
あなたはreview-referee agentです。正解の判定基準を持っています。
## ミッション
bug-finderとadversarial-reviewerの主張を最終ジャッジし、実際に対応が必要なバグリストを確定すること。
## 判定ルール
1. 両者が一致(CONFIRM)→ 採用
2. bug-finderが報告、adversarialがDISMISS → 両者の根拠を比較し判定:
- adversarialの反論に具体的なコード根拠がある → DISMISS優先
- adversarialの反論が一般論にとどまる → CONFIRM優先
3. severity の再評価: 文脈を踏まえて severity を上げ下げする
## 出力形式
以下の形式でレビュー結果をまとめること:
```markdown
## セルフレビュー結果
### 確定バグ(要修正)
| # | severity | ファイル | 問題 | 推奨修正 |
|---|----------|---------|------|---------|
| 1 | high | path:line | 問題の要約 | 修正方針 |
### 却下した報告
| # | 元ID | 理由 |
|---|------|------|
| 1 | BUG-003 | adversarialの根拠が妥当(上位でハンドリング済み) |
### 統計
- bug-finder報告数: N件
- 確定バグ: N件
- 却下: N件
- 確定率: N%
```
## 制約
- 確定バグには必ず「推奨修正」を含めること
- 0件でも正直に報告すること(問題なしも正当な結論)
ポイントは、各エージェントに「スコアリング」を伝えていること。エージェントはスコアを最大化しようとする。これが迎合の方向を制御するハンドルになる。bug-finderは「見つける方向」に、adversarialは「否定する方向」に、それぞれの迎合が向く。refereeは中立の審判として、両者のバイアスを相殺する。
具体例2: 記事のハルシネーション・論理破綻検知
私が記事を書くときにも、似たパターンを使っている。
記事執筆後にfact-checker agentを走らせる。記事に含まれるすべての事実・数値・日付・固有名詞を検証するエージェントだ。検出数でスコアが上がるから、少しでも怪しいものは片っ端からフラグを立てる。「この数値のソースが見つからない」「この引用は原文と微妙に異なる」「この因果関係の論拠が不十分」。
次にlogic-defender agentを走らせる。fact-checkerのフラグを検証し、正当な記述を防衛するエージェントだ。「この数値は公式ドキュメントのこのページに記載がある」「この引用は要約であり、原意は保持されている」と、正当な記述を守る。ただし、本物のハルシネーションを見逃すと-2倍のペナルティ。
最後にverification-referee agentが、両者の主張を中立にジャッジし、最終的な検証結果を確定させる。
これら記事チェックエージェントたちは、Part 10で中身を公開している。
このパターンの本質は、「1つのエージェントに正確性を求める」のではなく、「3つの偏りをぶつけて真実に近づく」ことだ。1つのエージェントに「バグを探せ、でも偽陽性は出すな」と言っても、その微妙なバランスは取れない。だったら、「全力で探す係」と「全力で否定する係」と「中立にジャッジする係」を分けて、その衝突から真実を浮かび上がらせる方が構造的に安定する。

Part 7: 始め方を知っている、終わり方を知らない
エージェントにタスクを渡す。エージェントはすぐに動き始める。ファイルを読み、コードを書き、テストを走らせる。
と、始めるのは分かった…問題は、終わり方にもあった。
関数のスタブ実装を書いて「完了」と宣言する。テストを通すために本質的でない回避策を入れて「完了」と宣言する。ビルドが通ったら「完了」と宣言する。
でも、ビルドが通ることと、仕様を満たすことは別だ。
私のリポジトリでも、これには痛い目に遭った。サブエージェントにUIコンポーネントの実装を任せた。エージェントは「実装完了」と報告してきた。確認すると、型定義は正しいが中身が空だった。関数は存在するが、何もしない。NO-OP実装。テストもないからバレない。
それ以降、execution-workflow.mdに明記した。
テストを先に書かせる。検証手段のないタスクを自律実行させない。
テストを「契約」として使う
テストを「契約」として扱う。テストが全部パスするまで、タスクは未完了。そしてエージェントにテスト自体を編集させない。
テストを先に書き、エージェントにはそのテストをパスする実装を書かせる。テストが契約書で、実装が納品物。契約書を書き換えて「納品完了」とするのは許さない。

これもルールファイルに書く内容だ。CLAUDE.mdではなく.claude/rules/coding/に。コーディング中にこのルールが注入されれば、セッション後半でもテストスキップを防げる。
完了条件を明文化する
タスクごとに完了条件を明文化する方法もある。
`npm run test` が全パス
TypeScriptのコンパイルエラーが0
新規追加した関数にすべてJSDocがある
スクリーンショットで視覚的に確認済み
スクリーンショット検証は特に有効だ。CSSの問題やレイアウト崩れは、テストだけでは捉えられない。エージェントにブラウザのスクリーンショットを撮らせ、期待通りの表示かどうかを確認させる。
私のリポジトリでは、communication-standards.mdにこう書いている。
作業完了時に、何を行い何を行わなかったかを報告する。
CHANGES MADE、NOT TOUCHED、CONCERNS。何を変えた、何を変えなかった、何が心配か。この3つを強制することで、「やりました」だけの報告を防いでいる。
さらに、定量化のルールも入れている。
「いくつか生成しました」は禁止。「28枚のスライド画像を生成しました(slide-01.png ~ slide-28.png)」と書かせる。「ドキュメントを書きました」は禁止。「12,500文字のドキュメントを書きました(見出し8セクション)」と書かせる。
数値で報告させると、曖昧な「完了」宣言が消える。コードでも、3ファイル、+47行の追加という数字を見れば、「それは妥当な規模か?」と判断できる。3ファイルの変更を+10行の修正タスクで返してきたら、何か間違っている?と自律的に疑うことができる。

Part 8: 1契約、1セッション
24時間セッション。
Claude Codeを長時間走らせて、一気に大量のタスクをこなす。効率的に見える。
でも、長時間セッションはコンテキスト汚染の温床だ。セッションが長くなると、過去のタスクの残滓がコンテキストに蓄積する。タスクAで読み込んだファイルの内容が、タスクBの判断に干渉する。古い情報と新しい情報が混ざり合い、エージェントの判断精度が落ちる。
24時間セッション1本より、100個の短いセッションのほうがいい。
推奨は「1契約1セッション」。1つのタスク契約を、1つのセッションで完了させる。完了したらセッションを閉じる。次のタスクは新しいセッションで。
サブエージェントの設計
execution-workflow.mdに、サブエージェント戦略を明記している。
原則は「1タスク = 1サブエージェント」。複数タスクを1つに詰め込まない。
サブエージェントの種類ごとに、max_turnsとモデルを指定している。記事の検証は15ターン。記事の執筆は40ターン。テスト作成は15ターン。それぞれが自分の担当だけに集中する。
リサーチの並列分割も同じ思想だ。
1エージェントで10回検索させると、コンテキストが枯渇して品質が落ちてくる、最悪、途中停止する。3エージェントに分けて各3-4回検索させれば、軽量に完了する。結果はファイルに集約して、次のフェーズに渡す。
ファイルが「セッション間のインターフェース」になる。エージェントAの出力ファイルが、エージェントBの入力になる。コンテキストは各セッション内で閉じているが、ファイルを通じて情報は受け渡される。
max_turns到達時のリカバリ手順もexecution-workflow.mdに書いている。エージェントがmax_turnsに達して停止したとき、途中成果物がファイルにあれば、新しいエージェントにそのファイルを渡して続きをやらせる。コンテキストを引き継ぎたい場合はresumeで再開する。リセットしたい場合は新規起動する。
選択肢を事前に設計しておくことで、「止まったらどうしよう」という不安がなくなる。

Part 9: 育てて、整えて、また育てる
ルールとスキルの運用は、育てっぱなしでは破綻する。
最初は何もない状態から始まる。エージェントを使い始めて、失敗するたびにルールを追加する。「エラーを握りつぶすな」。「テストなしで機能を追加するな」。「勝手に機能を追加するな」。
成功パターンが見えたら、スキルとして定義する。「記事を書くときはこの6フェーズで進めろ」。「決算を分析するときはこのデータを取得しろ」。「サムネイルを作るときはこのデザインシステムに従え」。
段階的に育てていく。これは正しい。
ただし、「育て続けるだけ」は危ない。
ルールを追加し続けると、ルール同士が矛盾し始める。「コードは簡潔に書け」と「すべてのエッジケースを処理しろ」が同居する。「自律的に判断しろ」と「勝手な判断をするな」が両立を求められる。
スキルも同じだ。似たようなスキルが増えて、エージェントがどれを使えばいいかわからなくなる。コンテキストの肥大化にもつながる。
定期的な棚卸し
定期的にルールとスキルを棚卸しして、整理・統合・矛盾解消をする。
私のリポジトリでも、正直に書くと矛盾は起きていた。実はこの記事を書いている最中に、自分のリポジトリを棚卸しする羽目になった。
記事の中で「CLAUDE.mdにはルールを書くな」「CLAUDE.mdはディレクトリだ」と偉そうに書いている。でも自分のCLAUDE.mdを見返したら、「基本原則」「禁止事項」「レポート形式」というルールがしっかり直書きされていた。@importで3つのルールファイルをCLAUDE.mdに全文展開してもいた。
棚卸しで見つかった不整合は5つあった。基本原則をCLAUDE.mdからcore-principles.mdに移動した。@importをプレーンテキスト参照に変えた。各種外部APIの運用情報をスキルに移した。コーディングガイドにpathsフロントマターを追加して条件付きルールにした。レポート形式をcommunication-standards.mdに統合した。
execution-workflow.mdには「計画してから実行」と書いてある。一方で、特定のスキルの中には「すぐに実行に移れ」というニュアンスの指示がある。今回の棚卸しによって、エージェントがどちらに従うかは、タイミングとコンテキスト次第になった。
coding-guides.mdには「PRレビューから学んだルールを蓄積する」仕組みがある。レビュー指摘履歴のセクションに、過去の失敗パターンを追記していく。これは「育てる」フェーズだ。ただ、このファイル自体が肥大化していけば、いずれ整理が必要になる。
ルールとスキルの粒度
最初のうちは、粗い粒度で十分だ。「テストを書け」「計画してから実行しろ」。これで十分回る。
でも実務で使い込んでいくと、例外が出てくる。「テストを書け」だけでは、ユニットテストなのかE2Eテストなのかが曖昧になる。スキルの中で「このケースではユニットテストを書け、このケースではE2Eを書け」と条件分岐が始まる。
この条件分岐が増えすぎると、スキルファイル自体が巨大になる。巨大なスキルファイルはコンテキストを圧迫する。
解決策は、スキルを分割することだ。1つの巨大なスキルを、条件ごとに独立したスキルに分ける。「ユニットテスト作成」と「E2Eテスト作成」を別スキルにする。エージェントは状況に応じて適切なスキルだけを読み込む。
これはPart 3で書いた3層アーキテクチャの原則と同じだ。ルールとスキルの運用にも、コンテキスト設計の原則が貫通している。
育てる。整える。また育てる。このサイクルを止めない。

エージェンティックエンジニアリング9原則
CLAUDE.mdに全部書くな。ディレクトリにしろ。
CLAUDE.mdはSession Start Hook。ルールは .claude/rules/ に書け。
3層+自動メモリのアーキテクチャを設計しろ。何が、いつ、どこで読まれるかを把握しろ。
スキルはレシピから始めて、ソフトウェアに育てろ。
コンテキストは酸素だ。必要な分だけ渡せ。
sycophancy(迎合)は設計材料にしろ。
終わり方を契約で定義しろ。
1契約、1セッション。
育てて、整えて、また育てる。
ここまでのPartが、私が自身のリポジトリで数ヶ月かけて学んだエージェント設計の原則だ。
ただ、原則を知っているのと、実践できているかは別の話だ。
次のPartからは、私が実際に使っているCLAUDE.md、rules、skills、agentsなどのファイルの中身を公開する。また、上記「エージェンティックエンジニアリング9原則」を自動で検証する監査用スキルを提供する。「理解した」を「実践できている」に変えるための、具体的な道具立てとなっている。
この内容を参考にして、あなただけのエージェント作成に挑戦して見て欲しい。
ここから先は
この記事が気に入ったらチップで応援してみませんか?
