ハーネスエンジニアリングとは:AI開発を支える3層設計
この記事で学べること
- 継続的なAI作業で、会話だけでは品質が安定しない理由
- ルール・作業手順・検証を統合するハーネスエンジニアリングの考え方
- このサイトの3層構造を参考に、自分のプロジェクトへ仕組みを配置する方法
ハーネスエンジニアリングはルール・手順・検証を統合する
本記事では、ハーネス(AI作業を支えるルール、手順、検証の仕組み)を設計する実践を「ハーネスエンジニアリング」と呼びます。このサイトでは、会話だけで同じ前提を渡す方法から、共有ルール、Skills(特定の作業の手順や資料)、自動検査を役割別に管理する方法へ移りました。製品の公式機能とサイト独自の3層設計を分けると、自分のプロジェクトで追加すべき仕組みを判断できます。
最後まで読むと、「ハーネスエンジニアリングは何を設計し、製品機能とどう分けるのか」という問いを、自分の状況に照らして判断するための材料を持ち帰れます。
ハーネスをルール・手順・検証の3層で設計する
AIを個人的な質問への回答に使う場合と、プロジェクトに継続的に組み込んで使う場合では、直面する問題が異なります。
プロジェクトでAIを使い始めると、次のような状況が繰り返し起きます。先週AIに依頼して設定した内容を、今週また別の会話で依頼すると、異なる方法で実装される。ルールを守ってほしいと一度伝えても、次の会話では守られていない。
基盤モデルは、別セッションの内容を自動的に恒久保存しているわけではありません。製品側の履歴、Memory、プロジェクト設定、外部ファイルなどが利用できない場合、前回のルールや判断は次のセッションへ自動的には引き継がれません。Claude Codeでは、CLAUDE.md のようなメモリファイルを使ってプロジェクト文脈を渡す仕組みが公式に説明されています。[1]
指示、ツール、権限、環境、検証、フィードバックを一体として設計する考え方は、エージェントハーネスやHarness Engineeringと表現される場合があります。目的は、AIエージェントを安定して動かすことです。
本記事では、この考え方をAI Learning Playgroundへ適用した独自の3層構造を紹介します。
本サイトでは、AIに同じ品質で作業してもらうためのルール、設定、検証、引き継ぎ、レビューの仕組みをまとめて「ハーネスエンジニアリング」と呼んでいます。この用語が指す範囲と3層への分け方は、本サイトでの実践を説明するための整理です。特定ベンダーの公式機能名や、共通の3層仕様として扱うものではありません。
ハーネスはAIの動きを制約・接続・検証する役割から名付けられた
ハーネス(harness)は馬具を指し、力を正しい方向へ制御する道具です。AIにも、プロジェクトの目的に沿って一貫して動くための制御を組み合わせます。この役割を表すために、ハーネスという名前を使っています。
AIそのものを変えるのではなく、AIが参照する設定・ルール・手順を整えることで、プロジェクト全体での動作を安定させることが目的です。
公式仕様とこのサイトの設計を分ける
Claude Codeの公式仕様として確認できる要素は4つあります。CLAUDE.mdによるプロジェクトメモリ、許可・権限・実行環境の設定、Hooks、Skillsです。[1][2][3][4]
Hooks(実行前後などの決まったタイミングで自動処理を動かす仕組み)と、特定タスク向けの手順や資料をまとめるSkillsを組み合わせます。
「ハーネスエンジニアリング」という呼び方、shared/への共通ルール集約、CLAUDE.md・shared/・教訓ログの3層構造は、このサイト独自の整理です。公式機能を利用していますが、Claude Codeがこの3層構造を公式パターンとして定義しているわけではありません。
| 観点 | 位置づけ |
|---|---|
CLAUDE.md をプロジェクト文脈として使う | Claude Code公式仕様に基づく |
| 設定、権限、Hooks、Skillsを組み合わせて使う | Claude Code公式機能に基づく |
shared/ を共通ルールの一次情報源にする | AI Learning Playground独自の設計 |
| 本記事での「ハーネスエンジニアリング」の範囲 | 本サイトの実践を説明する整理 |
| 3層構造として整理すること | このサイトの運用パターン |
このサイトでは初期指示ファイル・共有ルール・教訓の3層へ情報を配置する
このサイトでは、上記の公式機能と独自設計を組み合わせ、情報を次の3層へ配置しています。初期指示ファイルから、必要な共有ルールや作業手順へ案内し、過去の失敗は教訓ログへ残します。自動検査は別のスクリプトとして動き、3層に書いた制約の一部を実行時に確認します。検証だけを第3層に閉じ込める構成ではありません。
1. プロジェクト設定(CLAUDE.md)
AIがプロジェクトを開始するときに最初に読む設定ファイルです。「このプロジェクトでは何をしてはいけないか」「どのディレクトリに何があるか」「使ってよいコマンドはどれか」といった基本方針を記述します。新入社員に渡す「オリエンテーション資料」に相当します。
2. ルール・スキル集(shared/ディレクトリ)
具体的な作業ごとの手順や制約をまとめたファイル群です。たとえば「コンテンツの書き方」「デプロイ手順」「レビューの基準」などが該当します。プロジェクトの「業務マニュアル」です。AIはタスクに応じて該当するファイルを参照します。
3. 教訓ログ(lessons.md)
過去に発生した問題と対処方法を記録するファイルです。製品側の履歴やMemoryに依存できない場合、同じ問題が繰り返されることがあります。教訓ログをAIが読むことで、過去に解決済みの問題を再現しにくくするための情報を提供します。
教訓ログと変更履歴で確認できる不具合修正
見出しリンクの不具合を設定と検査で直す
教訓ログには、見出しにカーソルを合わせたとき、本文に重なる大きな壊れたリンクプレビューが表示された問題を記録しています。2026年9月5日の記録は、見た目をCSSで隠すだけではリンク要素が残るため、リンクの生成設定を変える方針を示しています。
ログ内のMarkdownは、行頭の#で見出し、-で箇条書きを表す文章形式です。次は、実際のshared/workflow/lessons.mdにある「ルール」欄の抜粋です。設定名と検査名は、同じ対策を再現するときに必要なため残しています。
Docs、Blog、AboutのMarkdown見出しは
idと目次リンクを維持しつつ、Starlightのホバー用パーマリンク生成をmarkdown.headingLinks: falseで無効化する。verify-ui-invariants.mjsはこの設定をdev:check、harness:check、prebuildで検査し、設定の削除、trueへの変更、Starlight設定外への誤記を拒否する。
この一件を3層へ対応させると、初期指示ファイルが共有ルールの参照先を示し、共有ルールが既存UIを守る制約と確認方法を定め、教訓ログが症状・理由・適用場面を残します。さらに自動検査が、設定の削除、trueへの変更、設定場所の誤りを検出します。記録を読むことと、違反を機械的に止めることは別の役割です。
リポジトリには、この3種類の設定変更を拒否するテストもあります。これは再発条件を検出する仕組みの実装例です。運用中に何回止めたか、読者に届く不具合を何件防いだかは集計していないため、防止件数や削減率は示せません。記録の使い方はlessons.mdの記事でも扱っています。
画面と検査で同じ表示ルールを使う
別の修正例は、2026年6月14日に保存された変更記録0ec777d8です。学習情報を画面に表示する条件と、その条件を検査する処理が別々に書かれ、古い検査が仕様に合う表示を拒否していました。教訓ログにも、この不一致で公開用ファイルの生成が失敗したことが記録されています。
この修正は5ファイルを変更し、画面と検査が、学習情報を表示するかを決める同じルールを使う形へ改めています。トップ、トピック一覧、セクション一覧、記事、ブログの5種類について、学習情報を表示するかを検査する処理も加えました。保存された変更前後のコードから、別々に書いていた条件を共通の処理へまとめたことを確認できます。ただし、この変更による手戻り時間の短縮や、その後の防止件数は測っていません。
実装抜粋:共通の表示条件と設定違反のテスト
現在のsrc/components/page-title-learning-info.mjsは次の実装です。entryIdはページの識別子で、ja/ai/securityのように言語と階層を表します。showLearningInfoがtrueなら学習情報を表示します。ブログとプロフィールでは表示せず、学習ページの階層から表示対象を決めます。
export function getPageTitleLearningInfoState(entryId) {
const idSegments = entryId.split('/').filter(Boolean);
const isBlogPage = idSegments[1] === 'blog';
const isAboutPage = idSegments[1] === 'about';
const isSectionOrArticle = idSegments.length >= 3;
return {
lang: idSegments[0] === 'en' ? 'en' : 'ja',
showLearningInfo: isSectionOrArticle && !isBlogPage && !isAboutPage,
};
}画面側と検査側がこの関数を読み込み、同じ条件を使います。検査入力と期待する表示は次の5件です。2026年10月13日の検査では、この5件すべてで実装が返す値と期待値が一致しました。
| 入力 | ページの種類 | 学習情報の表示 |
|---|---|---|
ja | 言語別トップ | しない |
en/ai | トピック一覧 | しない |
ja/ai/security | セクション一覧 | する |
en/ai/security/prompt-injection | 記事 | する |
ja/blog/example-post | ブログ | しない |
見出しリンクには、設定を意図的に戻して検査が問題を見つけるかを確かめるテストがあります。次はscripts/verify-ui-invariants.test.mjsの実物の抜粋です。assert.matchは、検査結果に「見出しリンクを無効にすべき」という指摘が含まれるかを確認します。
test('rejects re-enabling Starlight heading hover links', () => {
const source = `
starlight({
title: 'AI Learning Playground',
markdown: {
headingLinks: true,
},
plugins: [],
})
`;
assert.match(getUiInvariantViolations(source).join('\n'), /headingLinks to false/);
});実行コマンドはnode --test scripts/verify-ui-invariants.test.mjsです。2026年10月13日の実行では8件すべてが合格し、その中で、設定の削除、trueへの変更、設定場所の誤りを拒否する3種類のテストも通りました。これは指定した条件で検査が動くことの確認です。本番での防止件数やAIモデルの性能測定ではありません。コミット履歴だけでは、各行を私が書いたかAIが生成したかまでは特定できません。
ハーネスは業務ルールと確認手順から設計できる
業務ルールや作業手順は、Markdownテキストファイルで整理できます。ルールの整理を始めるうえで、プログラミングの知識は必須ではありません。一方、自動検査にはスクリプトやテストの実装が必要です。「どんなルールを守ってほしいか」「何をしてはいけないか」「どういう手順で作業してほしいか」を言葉で整理できれば、ハーネスを設計できます。
逆に言えば、この設計なしにAIをプロジェクトに組み込むと、会話のたびにルールを再説明する手間が発生し、AIの判断が会話ごとにばらつくという状況が続きます。
まとめ:公式機能と独自設計を分け、必要な3層だけを配置する
ハーネスエンジニアリングは、AIを継続的かつ一貫して動かすため、ルール、作業手順、検証を周囲に配置する設計です。CLAUDE.md、設定、Hooks、Skillsという公式機能と、shared/への集約や3層構造というこのサイト固有の設計を分けると、製品へ期待する範囲とプロジェクトで補う範囲を判断できます。
最初の対象は、AIへ毎回説明している前提を1つ選び、ルール、手順、検証のどこへ置くか決めることです。3層構造は再利用できる整理方法ですが、すべての製品に共通する公式構成ではありません。
参考文献
- Anthropic, How Claude remembers your project, Claude Code Docs
- Anthropic, Claude Code settings, Claude Code Docs
- Anthropic, Hooks reference, Claude Code Docs
- Anthropic, Extend Claude with skills, Claude Code Docs
最新のリリースやアップデートの詳細は、公式サイト・公式ドキュメントを確認してください。