ハーネスエンジニアリング完全ガイド|Claude Codeに学ぶAIエージェントの作り方
プロンプトだけでLLMは使いこなせない。ツール・文脈・制御ループを束ねる「ハーネス」を、動くコードで解説。Claude Code実装例から自作エージェントまで。
「ChatGPTにプロンプトを投げるだけ」の時代は終わりました。 2025年以降、AIエンジニアリングの焦点は急速に ハーネスエンジニアリング (harness engineering) に移っています。Anthropic の社内ブログでも、OpenAI のエージェント研究でも、最も頻繁に登場するキーワードの一つです。
でも「ハーネス」って何?と聞かれて即答できる人はまだ少ない。この記事では 動くコード と Claude Code 自体の設計 を題材に、ハーネスエンジニアリングをじっくり解説します。読み終わる頃には、自分のエージェントをゼロから組めるようになっているはずです。
ハーネスとは「AIの足場」である
ハーネス (harness) は元々「馬具」や「安全帯」を意味する英単語です。ソフトウェア業界では「テストハーネス (test harness)」のように 「何かを動かすための外側の仕組み」 を指します。
AI の文脈では、LLM を取り巻くラッパー層 のことです。もう少し具体的に言うと、LLM が実世界のタスクをこなすために必要な以下の要素を束ねたものです。
- ツール群: ファイルを読む、コマンドを実行する、APIを叩く…
- 文脈管理: 何を記憶し、何を忘れ、何を圧縮するか
- 制御ループ: いつ呼び、いつ止め、いつ再試行するか
- 権限と安全装置: 破壊的操作を勝手にやらせない仕組み
- メモリ: セッションをまたいで保持する知識
プロンプトは、このハーネスに投入する「1つの入力」に過ぎません。ハーネスが貧弱だと、どんなに巧妙なプロンプトを書いても性能は頭打ち です。これが近年「プロンプトエンジニアリングだけでは足りない」と言われる理由です。
なぜハーネスが重要なのか: OODAループで考える
LLM 単体でできるのは「テキストの続きを生成する」ことだけ。実世界のタスクを解くには、軍事戦略でいう OODAループ (Observe → Orient → Decide → Act) を回す必要があります。
| フェーズ | 内容 | 担当 |
|---|---|---|
| Observe (観測) | 環境の状態を取得する (ファイル読み、DB問い合わせ) | ハーネス |
| Orient (状況判断) | 取得情報を整理してLLMに渡す | ハーネス |
| Decide (決定) | 次に何をするか判断する | LLM |
| Act (実行) | 決めたことをやる (コマンド実行、API呼び出し) | ハーネス |
ご覧の通り 4フェーズ中3フェーズがハーネスの担当 です。LLM が得意なのは Decide だけ。残りを支える足場の品質が、エージェント全体の品質を決めます。
実例で理解する: 「3つのハーネスレベル」
同じ「ブログ記事を生成して」というタスクを、3段階のハーネスで解いてみます。
レベル1: 素のAPI呼び出し (ハーネスほぼなし)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const res = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
messages: [{ role: "user", content: "ブログ記事を書いて" }],
});
console.log(res.content[0].text);
結果: 汎用的で中身のないテキスト が返ってくるだけ。トピックも構造も毎回バラバラ。
レベル2: ツールを与える (中レベルハーネス)
const tools = [
{
name: "read_existing_posts",
description: "既存ブログ記事の一覧とタイトルを取得",
input_schema: { type: "object", properties: {} },
},
{
name: "write_post",
description: "MDXファイルを書き出す",
input_schema: {
type: "object",
properties: {
slug: { type: "string" },
frontmatter: { type: "object" },
body: { type: "string" },
},
required: ["slug", "frontmatter", "body"],
},
},
];
async function runAgent(userGoal: string) {
let messages = [{ role: "user", content: userGoal }];
while (true) {
const res = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
tools,
messages,
});
if (res.stop_reason === "end_turn") break;
// ツール呼び出しをハーネスが実行
const toolUse = res.content.find((c) => c.type === "tool_use");
const result = await executeTool(toolUse.name, toolUse.input);
messages.push({ role: "assistant", content: res.content });
messages.push({
role: "user",
content: [{ type: "tool_result", tool_use_id: toolUse.id, content: result }],
});
}
}
結果: 既存記事と重複しないトピックで、正しい形式のMDXが生成される。ツールを与えただけで品質が激変します。
レベル3: Claude Code 並みの完全ハーネス
- 自動ループ (ユーザー承認、エラー再試行)
- 文脈圧縮 (長い会話を要約してトークン節約)
- サブエージェント委譲 (翻訳は別コンテキストで)
- プロンプトキャッシング (固定部分は再送しない)
- Hooks (コミット前に自動 lint)
これらを自前で組むのは大変。だからこそ Claude Code を「実装の見本」として研究する価値があります。
Claude Code のハーネス構造を分解する
Claude Code は Anthropic 社内で最も磨かれたエージェントハーネス です。以下の5層で理解できます。
第1層: ツール設計
Read / Edit / Write / Bash / Glob / Grep / Agent などが用意されています。注目すべきは ツールの粒度。
Grepは単なるgrepではなく ripgrep のラッパー。正確で高速Editは全文書き換えではなく 特定文字列の置換。差分が最小Agentはサブエージェントを spawn し、コンテキストを隔離
ツール品質がエージェント品質に直結します。「動けば何でもいい」ではダメで、冪等性・明確なエラーメッセージ・最小責務 を意識して設計する必要があります。
第2層: 文脈の階層化
~/.claude/CLAUDE.md ← グローバル規約
./CLAUDE.md ← プロジェクト規約 (自動ロード)
~/.claude/memory/ ← 長期記憶 (複数セッション横断)
├── user_profile.md
├── feedback_xxx.md
└── project_xxx.md
会話履歴 ← 直近のやり取り
タスク/プラン ← 現セッションの進捗
寿命と役割が違うので、書き込み先を間違えると情報がすぐ失われたり、逆に古い情報が残り続けたりします。「このセッションだけ」はタスク、「何度も使う」はメモリ と使い分けましょう。
第3層: サブエージェント委譲
Agent ツールで別コンテキストのエージェントを spawn できます。
# メインは指示だけ、重労働は subagent に
Agent(
subagent_type: "general-purpose",
prompt: "blog/harness.mdx を英語+8言語に翻訳し、
各 blog-{lang}/ に保存して完了報告"
)
こうすると メインの文脈が詳細ログで汚れない。長時間のビルドログ、翻訳の中間結果、検索結果など「成果物だけ欲しい作業」を丸投げできます。
第4層: Hooks (決定論的処理)
.claude/settings.json でツール呼び出しの前後にシェルコマンドを差し込めます。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "npx tsc --noEmit" }
]
}
]
}
}
ファイル編集後に自動で型チェックが走ります。「毎回LLMに頼むより決定論的に処理すべきこと」 はフックで吸収するのが定石です。
第5層: 権限モード
{
"permissions": {
"allow": ["Read", "Grep", "Glob"],
"deny": ["Bash(rm -rf*)", "Bash(git push --force*)"],
"ask": ["Write", "Edit", "Bash"]
}
}
破壊的コマンドを明示的に拒否し、書き込み系は承認を求める。事故は「勝手に実行された時」に起きる ので、ここの設計が運用の安全性を決めます。
落とし穴5選
1. ツールを増やしすぎる 30個のツールを与えると、モデルが選択に迷い精度が落ちます。5-15個に絞る のが経験則。足りない機能はサブエージェント側に持たせましょう。
2. プロンプトキャッシュを活かせていない
Claude API の cache_control を使わないと、長い system prompt を毎回フルで送って課金が跳ねます。5分TTLを意識して、変わらない部分はキャッシュ に。
messages: [{
role: "system",
content: [
{ type: "text", text: longStaticInstructions,
cache_control: { type: "ephemeral" } }, // ← これ
{ type: "text", text: dynamicContext },
],
}]
3. エラーメッセージが LLM に読めない形式
ツールが Error: undefined とだけ返すと、モデルは自己修復できません。「何が悪くて、どう直せば良いか」まで書く。
throw new Error(
`ファイル '${path}' が存在しません。` +
`scripts/ ディレクトリのファイル一覧は: ${list.join(", ")}`
);
4. 人間の承認を省略する 破壊的操作 (削除、force push、DB更新) を自動承認すると、ある日必ず事故ります。「書き込み系は ask、削除系は deny」 をデフォルトに。
5. メモリを整理しない
時間経過で古くなった情報が残ると、エージェントが間違った前提で動きます。メモリも 定期的に断捨離 が必要です (Claude Code なら /compact や手動編集)。
自作ミニハーネスを動かしてみよう
最後に、ブラウザで動く最小ハーネスを置いておきます。Node.js + TypeScript。
// mini-harness.ts
import Anthropic from "@anthropic-ai/sdk";
import { readFileSync, writeFileSync } from "fs";
const client = new Anthropic();
const tools = [
{ name: "read_file",
description: "テキストファイルを読む",
input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
{ name: "write_file",
description: "テキストファイルを書き出す",
input_schema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] } },
];
const executors = {
read_file: ({ path }) => readFileSync(path, "utf-8"),
write_file: ({ path, content }) => { writeFileSync(path, content); return `written ${path}`; },
};
async function loop(goal: string, maxSteps = 10) {
const messages: any[] = [{ role: "user", content: goal }];
for (let i = 0; i < maxSteps; i++) {
const res = await client.messages.create({
model: "claude-opus-4-6", max_tokens: 4096, tools, messages,
});
messages.push({ role: "assistant", content: res.content });
if (res.stop_reason === "end_turn") return res.content;
const toolUse = res.content.find((c: any) => c.type === "tool_use") as any;
if (!toolUse) return res.content;
const result = executors[toolUse.name](toolUse.input);
messages.push({
role: "user",
content: [{ type: "tool_result", tool_use_id: toolUse.id, content: String(result) }],
});
}
}
await loop("README.md を読んで TL;DR.md に3行で要約して保存して");
これだけで 「既存ファイルを読み、新しいファイルを書き出す」 ミニエージェントが完成します。ここに Grep ツール、Bash ツール、Agent ツールを足していけば、Claude Code の縮小版が作れます。
実務でハーネスを設計するときの判断基準
ハーネスエンジニアリングで失敗しやすいのは、最初から「何でもできる万能エージェント」を作ろうとすることです。実務では逆で、狭く、測れて、戻せる範囲から始めるほうが成功します。
私が Claude Code を記事運用や開発作業に使うときは、最初に次の4つを決めます。
| 判断項目 | 最初に決めること | 決めないと起きる失敗 |
|---|---|---|
| 入力 | どのファイル、ログ、URLだけを読ませるか | 不要な文脈を読みすぎて判断がぼやける |
| 出力 | MDX、PR、レポートなど何を成果物にするか | それっぽい説明だけで終わる |
| 検証 | build、lint、公開URL確認など何で合格にするか | 生成しただけで壊れたまま公開される |
| 権限 | 自動でよい操作、人間確認が必要な操作を分ける | deploy、削除、課金変更を誤って実行する |
例えばブログ記事生成なら、いきなり「良い記事を書いて」ではなく、既存記事一覧を読む → 重複しないテーマを選ぶ → MDXを書く → コードフェンスを検査する → buildする → 公開URLを見る までをハーネスにします。LLMの文章力よりも、どこで止まり、何を証拠として残すかが品質を決めます。
開発チームで使うなら、さらに git diff、テスト結果、レビュー観点、ロールバック手順まで含めます。ここまで入れると、Claude Code は「返事がうまいAI」ではなく、作業の入口から出口までを支える実行環境になります。
この記事をどう活かすか
まず自分で試すなら、この記事のミニハーネスをそのまま動かし、次に Claude Code 権限設定ガイド で危険操作の線引きを決めてください。知識管理まで含めたい場合は Claude Code × Obsidian 連携ガイド が次の読み物です。
手元に置く資料としては、無料の Claude Code Quick Reference Cheatsheet から始めるのが軽いです。チーム導入、記事運用、開発ワークフローまで含めて「自分の業務用ハーネス」を設計したい場合は、導入相談 で現状の権限・検証・収益導線を一緒に整理できます。
この記事で紹介した内容を実際に試した結果
このサイトの運用では、記事生成、翻訳、コードフェンス検査、build、Cloudflare Pages へのデプロイ確認までを小さなハーネスとして分けています。最初はプロンプトだけで記事を増やしていましたが、コードブロック崩れやデプロイ失敗を見逃しました。いまは check-code-fences、localized content check、公開URL確認を挟むことで、少なくとも「壊れた記事をそのまま出す」事故は減らせています。ハーネスは理論ではなく、失敗した場所から順番に足していく実務の安全装置です。
まとめ: プロンプトを書く人から、ハーネスを設計する人へ
| 従来の視点 | これからの視点 |
|---|---|
| 良いプロンプトを書けば良い出力 | 良いハーネスがあれば良い出力 |
| モデルを選ぶ | モデル + ツール + 文脈 + 権限を設計 |
| 単発の質問 | 継続的なループ運用 |
Claude Code は、この視点の転換を体感するのに最適な教材です。使うだけでなく、仕組みを分解して自分のエージェントに取り入れる。これが 2026 年以降のAIエンジニアに求められる姿勢です。
まずは上のミニハーネスをコピペして動かしてみてください。10分後には、あなた専用のエージェントの第一歩が踏み出せます。
関連記事
参考資料
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Code検証レシート運用: AIの変更をビルド、公開URL、CTAまで確認する
Claude Codeで変更後に差分、ビルド、公開URL、CTA、スクショを1枚の検証レシートへ残す実務手順。
Claude CodeのPermission Budget Loop: 毎回承認せず安全に進める権限設計
Claude Codeで承認疲れを起こさず、危険な操作だけ止めるpermission budgetの作り方とチーム運用例。
Claude Codeプロンプトライブラリの育て方: 使い捨て指示を資産に変える
Claude Codeのプロンプトを命名、検証、再利用し、無料PDFからテンプレート集購入へつながる導線を作ります。