ハーネスエンジニアリングとは?AIエージェントの「足場」を作って安全に任せる方法
AIエージェントが暴走しない理由はモデルの賢さではなく「ハーネス(足場)」。とは何か、なぜ要るのか、safePathの門番から検証ループまで、コピペで動く最小例でやさしく解説。
「このリポジトリ、いい感じに整理しといて」
そう頼んだ翌朝、AIは“いい感じ”に40ファイルを書き換えていました。動くコードもちゃんとあった。でも、消したらまずい設定ファイルまで、きれいさっぱり“整理”されていたんです。
ヒヤッとした経験、ありませんか。
賢いはずのAIが、なぜ平気で事故を起こすのか。理由はシンプルで、「賢いこと」と「安全に働けること」はまったく別物だからです。テストでは満点なのに、初めてのバイトでレジを壊す新人。あれと同じです。能力の問題じゃなくて、足場の問題なんですね。
その足場のことを、最近は ハーネス(harness) と呼びます。この記事では「ハーネスエンジニアリングとは何か」を、専門用語をなるべく使わずに、コピペで動く最小例つきで解説します。
この記事の要点
- ハーネスエンジニアリングとは、AIエージェントの「外側」に足場(読む範囲・使える道具・止める条件・確かめ方)を組む技術。プロンプトを磨く話ではない。
- AIが事故るのは賢さ不足ではなく足場の不在。命綱や補助輪と同じで、能力はそのままに「落ちないようにする」のが役目。
- 足場の心臓部は門番(ガードレール)。作業フォルダの外に出たら止める
safePathが1つあるだけで、冒頭の40ファイル事故は起きない。 - 作るときは最小から育てる。読む範囲を狭く→ゴールを明確に→確認はコマンドに→危険操作は人間承認、の順。
- 仕上げは検証ループ。「できました」を鵜呑みにせず、機械で測れる門番(ビルド・テスト・文字数・リンク切れ)で必ず確かめる。
ハーネスエンジニアリングとは?要するに何の技術か
ハーネスは、AIの「外側」に置く小さなプログラムです。
イメージしやすいのは、工事現場の安全帯(命綱)や、子ども用の自転車の補助輪。本人の能力はそのままに、落ちないようにする仕組みのことです。AIエージェントでいえば、こんな役割を持ちます。
- 何を読ませるか決める(全部は見せない)
- 何を作らせるか決める(ゴールをはっきりさせる)
- どこまで勝手にやらせ、どこで人間に確認させるか決める
- できあがったものが壊れていないか、機械的にチェックする
ハーネスエンジニアリングとは、この4つを設計する仕事です。「いいプロンプトを書く」のは、このうちのほんの一部にすぎません。プロンプトばかり磨いても事故が減らないのは、補助輪なしで一輪車の練習をしているようなものだからです。
道具にも向き不向きがあります。包丁とハサミを思い浮かべてください。紙はハサミ、野菜は包丁。AIに渡す道具も同じで、「ファイルを読む」「検索する」くらいの安全な道具と、「削除する」「本番DBに書く」「課金する」みたいな危ない道具は、扱いを分けるべきです。後者はそもそも渡さない、渡すなら必ず人間の承認をはさむ。これが足場づくりの基本姿勢です。
なぜ今、AIエージェントの足場が要るのか
少し前まで、AIに頼むことといえば「文章を書いて」「コードを書いて」くらいでした。出てきたものを人間が読んで判断すればよかった。
ところが今は、AIに作業そのものを任せ始めています。ファイルを読む、既存の記事と被らないネタを選ぶ、変更点を確認する、外部サービスに登録する、失敗したら原因を報告する——ここまで来ると、間に人間が毎回挟まれません。だから「勝手にやって事故る」リスクが一気に上がったわけです。
Claude Codeの評判がいいのも、モデルが賢いからというより、この足場がよくできているからです。ファイルを読む道具、検索する道具、危険な操作を止める仕組み、プロジェクトのルールを覚えさせる仕組み。そういう「地味な周辺」がしっかりしている。流行っているのは魔法のプロンプトではなく、その地味な周辺なんです。考え方の一次情報は Claude Agent SDK の公式ドキュメント にまとまっています。
足場のあり/なしで、何がどう変わるのか。表にするとこうです。
| 観点 | 足場なし(プロンプトだけ) | 足場あり(ハーネス) |
|---|---|---|
| 読む範囲 | リポジトリ全部を丸ごと | 必要なフォルダだけに限定 |
| 危険な操作 | AIの判断にお任せ | 門番で停止/人間が承認 |
| 失敗時 | それっぽく直して進む | 止まって原因を報告 |
| 品質チェック | 人間が最後に目視 | コマンドで機械的に判定 |
| 事故ったとき | どこで壊れたか不明 | どの門番で止まったか分かる |
まず動かしてみる:30行の最小ハーネス
説明より、動かしたほうが早いです。AIに「読み書き」だけを許し、決めたフォルダの外には絶対に手を出させない、最小の足場を作ってみましょう。Node.jsとAnthropicのAPIキー(ANTHROPIC_API_KEY)があれば動きます。
まず準備します。
mkdir harness-demo && cd harness-demo
npm init -y
npm install @anthropic-ai/sdk
mkdir sandbox
echo "# メモ" > sandbox/note.md
次に「許可リスト」を書きます(policy.json)。これがハーネスの心臓部です。sandbox の外は触らせない、やり直しは6回まで、という宣言です。
{
"workspace": "./sandbox",
"maxSteps": 6
}
そして本体(harness.mjs)。覚えてほしいのは1か所だけ。safePath が「フォルダの外に出ようとしたら止める」門番です。これがあるだけで、冒頭の“40ファイル事故”は起きません。
import Anthropic from "@anthropic-ai/sdk";
import { readFile, writeFile } from "node:fs/promises";
import path from "node:path";
const client = new Anthropic();
const policy = JSON.parse(await readFile(new URL("./policy.json", import.meta.url), "utf8"));
const root = path.resolve(policy.workspace);
// 門番:作業フォルダの外に出ようとしたら、その場で止める
function safePath(p) {
const resolved = path.resolve(root, p);
if (resolved !== root && !resolved.startsWith(root + path.sep)) {
throw new Error(`${p} は作業フォルダの外です。sandbox の中だけ触れます。`);
}
return resolved;
}
const tools = [
{ name: "read_file", description: "sandbox内のテキストを読む",
input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
{ name: "write_file", description: "sandbox内にテキストを書く",
input_schema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] } },
];
async function useTool(name, input) {
if (name === "read_file") return await readFile(safePath(input.path), "utf8");
if (name === "write_file") { await writeFile(safePath(input.path), input.content, "utf8"); return "書き込みOK"; }
throw new Error(`知らない道具: ${name}`);
}
const messages = [{ role: "user", content: process.argv.slice(2).join(" ") || "note.md を読んで、要約を summary.md に書いて。" }];
for (let step = 0; step < policy.maxSteps; step++) {
const res = await client.messages.create({
model: process.env.ANTHROPIC_MODEL || "claude-sonnet-4-6",
max_tokens: 1024,
tools,
system: "あなたは慎重なファイル係です。必要なときだけ道具を使い、作業はsandbox内に限ります。",
messages,
});
messages.push({ role: "assistant", content: res.content });
const calls = res.content.filter((b) => b.type === "tool_use");
if (calls.length === 0) { console.log(res.content.find((b) => b.type === "text")?.text ?? ""); break; }
const results = [];
for (const c of calls) {
try { results.push({ type: "tool_result", tool_use_id: c.id, content: String(await useTool(c.name, c.input)).slice(0, 4000) }); }
catch (e) { results.push({ type: "tool_result", tool_use_id: c.id, is_error: true, content: e.message }); }
}
messages.push({ role: "user", content: results });
}
実行はこれだけ。
node harness.mjs
試しに node harness.mjs "../package.json を読んで" と、わざとフォルダの外を指定してみてください。AIは safePath に弾かれ、「作業フォルダの外です」とエラーを受け取って、おとなしく sandbox の中だけで動き直します。これが門番のある暮らしです。
たった数十行ですが、もう「AI本体」「使える道具」「許可の範囲」「やり直しの上限」「壊れたら止まる仕組み」が分かれています。これがハーネスの骨格です。あとはここに、検索・テスト実行・承認待ち・通知を足していくと、Claude Codeのような形に育っていきます。
こんな場面で効く(具体例3つ)
1. 記事や資料の“量産チェック” 「ブログ書いて」で終わらせると、AIは平気で薄い記事や“ほぼ同じネタ”を量産します。そこでハーネスに「既存タイトルを読む→被らない切り口を選ぶ→本文を書く→文字数とリンクを機械チェック」と段取りを持たせる。すると、出来の良し悪しを人が悩む前に、門番が薄い記事を弾いてくれます。僕はこれで、公開前に止まる下書きが月に何本も出るようになりました。止まってくれてありがたい、という感覚です。
2. 問い合わせの仕分け 「来た問い合わせを読んで、商談になりそうなものだけ教えて」。読むのは自動でいい。でも、顧客リストへの登録は人間がボタンを押すまで保留にする。読み取りは自動、書き込みは下書き(dry-run)、最終登録だけ人間。この3段を強制すると、誤分類したお客さんを本番のデータベースに勝手に突っ込む事故が消えます。
3. デプロイ前のひと呼吸 公開ボタンを押す前に、ビルドが通るか・環境変数が揃っているか・差分が想定どおりか・戻す手順があるか、を必ず確認させる。AIは失敗ログの“最後の行”だけ見て見当違いを直しがちなので、「どこを見るか」を先に決めておくのがコツです。ログは全部渡さず、関係する数十行に絞る。これだけで的外れな修正がぐっと減ります。
検証ループ:「できました」を鵜呑みにしない
ハーネスでいちばん効くのに、いちばん抜けがちなのが検証ループです。AIは平気で「修正しました」「テスト通りました」と言います。でも、本当に通ったかは別問題です。
ここで効くのが機械で測れる門番です。人間の目はその日の体調で揺れますが、コマンドの結果は揺れません。たとえばこんな門番を1本ずつ足していきます。
- ビルドが通るか(
npm run buildの終了コード) - テストが緑か(
npm test) - 型エラーがないか(
tsc --noEmit) - 文字数が基準を満たすか/リンク切れがないか
実装の段取りは ビルド→スモークテスト→自動修正を回す足場の作り方 に手順を分けて書きました。さらに「本当に確かめた証拠」を残す運用は 検証レシートで証拠を残すワークフロー にまとめています。コマンドの終了コードと出力を“レシート”として保存しておくと、後から「どの門番で止まったか」を一目で追えます。
コツは、検証をAIの善意に頼らないこと。**「テストを書いて」ではなく「テストを実行して、結果のレシートを見せて」**まで足場側で強制します。ここまでやって初めて、夜中に走らせても安心して眠れる足場になります。
僕がやらかした失敗3つ
正直に書きます。最初のハーネスは事故だらけでした。
ひとつ目は、道具を渡しすぎたこと。便利だろうと30個くらい用意したら、AIが「どれ使えば?」と迷って、変な選択を連発しました。今は最初5〜10個に絞っています。包丁もハサミもドライバーも全部出すより、今日の作業に要る2〜3本だけ机に置く。そのほうが手が早い。
ふたつ目は、エラーメッセージが不親切だったこと。Error: failed とだけ返していたら、AIは何も直せません。README.md が見つかりません。sandbox には note.md だけあります のように、原因と次の一手まで書いて返したら、急に自己解決し始めました。門番は「止める」だけでなく「次にどうすればいいか」を教える役でもあるんです。
みっつ目は、確認を人間の目だけに頼ったこと。「最後に僕がチェックすればいい」は、忙しい日に必ず破綻します。文字数・リンク切れ・型エラーみたいな機械でわかる門番を置いてからは、夜中の確認がぐっと減りました。
始めるなら、ここから(育て方の順番)
いきなり「全自動の賢いエージェント」を作らないでください。失敗しても戻せる、小さい仕事をひとつ選ぶ。下書き記事のチェック、PRの一次レビュー、問い合わせの仕分け、ステージング公開前の確認。このくらいがちょうどいいです。
順番はいつも同じです。
- 読ませる範囲を狭く決める(リポジトリ全部ではなく、対象フォルダだけ)
- ゴール(成果物)をはっきりさせる(「整理して」ではなく「未使用importを消して」)
- 確認はできるだけコマンドにやらせる(目視ではなくビルド・テスト・型チェック)
- 危ない操作は最初は全部「人間に聞く」にする(削除・本番DB・課金・force push)
安全だと分かった操作だけ、あとから自動に格上げする。この順番を守るだけで、事故は驚くほど減ります。
権限の決め方は Claude Code権限設定ガイド に、チームで使うときの土台づくりは CLAUDE.mdベストプラクティス にまとめています。長い作業を別の担当に逃がしたいなら サブエージェント活用パターン も合わせてどうぞ。
よくある質問
Q. ハーネスエンジニアリングと、プロンプトエンジニアリングは何が違うの? プロンプトはAIへの「指示の出し方」、ハーネスはAIの「外側の足場」です。指示が完璧でも、読む範囲・止める条件・確かめ方が無ければ事故ります。プロンプトは足場の一部品にすぎません。
Q. Claude Codeを使えば、自分で足場を作らなくていい? 日々の開発はそれで十分です。Claude Codeはよくできた既製の足場だからです。自分で作るのは、独自の業務(記事の量産チェック、問い合わせ仕分けなど)をAIに任せるとき。そのときもClaude Codeの設計をお手本に“盗む”のが近道です。
Q. どんな操作を「人間の承認待ち」にすべき?
戻せない操作と、戻すのが高くつく操作です。具体的には、ファイル/レコードの削除、本番データベースへの書き込み、課金、git push --force、外部への公開・送信。逆に「読む・検索する・下書きを作る」は自動でかまいません。
Q. 最小ハーネスから、どこまで育てればいい? 任せたい仕事が安定して回るところまで、です。まず読み書き+門番、次に検証コマンド、次に承認待ち、最後に通知。一気に足さず、1本ずつ足して様子を見ます。途中で事故ったら、その手前に門番を1つ追加するのが鉄則です。
Q. AIが「テスト通りました」と言うのに失敗します。なぜ? AIの自己申告を信じているからです。検証はAIに任せず、足場側でコマンドを実行し、終了コードと出力(レシート)を確認しましょう。検証レシートのワークフロー が具体的です。
実際に試した結果
冒頭の“40ファイル事故”以来、僕は「AIを信じるかどうか」で悩むのをやめました。代わりに見るのは、どの門番で止まったかです。最小ハーネスに safePath を1つ足しただけで、フォルダ外の事故はゼロになりました。文字数とリンクの自動チェックを足したら、薄い記事が公開前に止まるようになりました。検証レシートを残すようにしてからは、「できました」の真偽で消耗することもなくなりました。賢いAIを探すより、転んでもケガしない足場を先に作る。遠回りに見えて、これがいちばん速い、というのが今の実感です。
まとめ
ハーネスエンジニアリングとは、プロンプトを飾る技術ではありません。AIエージェントに何を見せ、何をさせ、どこで止め、どう確かめるかを設計する技術です。まずは上の30行を動かして、自分の仕事に「門番」をひとつ足すところから始めてみてください。AIの仕事の質は、モデルの賢さより、その外側の足場で決まります。
もっと体系的に、自分の業務へAIを安全に組み込みたい人は 教材・テンプレート一覧 を、チーム全体で権限・レビュー・検証まで整えたい人は 研修・導入相談 をのぞいてみてください。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Codeに1ファイルだけ直させる指示文のつくり方
「もっと良くして」で40行も変えられた失敗から学んだ、触る範囲・検証・戻し方をセットにしたClaude Code用の依頼文テンプレートを紹介します。
Claude Code の権限拒否から復旧する: 止まった理由を次の安全手順に変える
Claude Code のコマンドが拒否されたとき、焦って許可を広げずに、拒否理由、代替手順、証拠コマンド、再試行条件へ分解する方法。
Claude Codeにビルド→スモークテスト→自動修正を回させる足場の作り方
最小スモークテストの選び方、失敗ログを食わせて直させるループ、回数上限と確認ゲートで暴走を止める方法を、コピペで動くコード付きで紹介します。