- Published on
AI harness 解剖 — モデルを agent に変える scaffolding(loop・tool・context、そして自作する)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
プロローグ — 同じモデル、違う harness、違う結果
2026 年によく見る光景: 2 つのチームが同じ frontier モデルを使っている。あるチームの agent はチケットを受け取って PR を開き、もう一方のチームの agent は 30 分間同じファイルを空回りしている。
違いはモデルではない。harness だ。
モデルは engine だ。harness は車だ。 同じ engine をレーシングシャーシに載せるか、壊れたトラックに載せるかで、走行体験はまったく変わる。
2023〜2024 年の AI engineering は「どのモデルを使うか」だった。2026 年の AI engineering はほとんどが**「そのモデルをどう取り囲むか」**だ。モデル提供者は数社に収束したが、harness は爆発的に多様化した — Claude Code、Cursor、Codex CLI、Aider、OpenClaw… これらは同じモデル API を呼ぶ。違うのは harness だ。
この記事は harness を解剖する。agent loop、tool execution 層、context 管理、System Prompt、制御フロー、失敗モード。そして40 行の最小 harness を自作し、harness をどう評価するかまで見る。
1章 · harness とは何か
harness = LLM を取り囲み、それを「agent」に変えるすべてのコード。
LLM 自体は無状態関数だ — テキストが入ればテキストが出てくる。それだけだ。ファイルを読むことも、コマンドを実行することも、記憶することもできない。harness がそのすべてをやる。
┌──────────────────────────────────────┐
│ harness │
│ ┌────────────┐ ┌────────────────┐ │
│ │ System │ │ context 管理 │ │
│ │ Prompt │ │ (window・圧縮) │ │
│ └────────────┘ └────────────────┘ │
│ ┌────────────┐ ┌────────────────┐ │
│ │ agent │──▶│ モデル (LLM) │ │
│ │ loop │◀──│ = engine │ │
│ └─────┬──────┘ └────────────────┘ │
│ ▼ │
│ ┌────────────┐ ┌────────────────┐ │
│ │ tool │ │ 制御フロー・hook・│ │
│ │ execution │ │ 権限ゲート │ │
│ └────────────┘ └────────────────┘ │
└──────────────────────────────────────┘
harness が所有するもの:
- loop — モデルを 1 回ではなく繰り返し呼ぶ。
- tool — モデルが「行動」できるようにする。
- context — 何をモデルに見せるかを決める。
- System Prompt — モデルのアイデンティティとルール。
- 制御フロー — いつ止め、いつ人を呼び、いつ並列化するか。
- 安全装置 — 無限 loop・コスト暴走・誤った tool 呼び出しを防ぐ。
モデルを変えると推論の質が変わる。harness を変えると agent の行動そのものが変わる。 だから両者を分けて考えなければならない。
2章 · agent loop — harness の心臓
harness の核心は驚くほど単純だ。while loop だ。
1. モデルを呼ぶ (現在のメッセージ群を渡す)
2. モデルの応答を見る:
- 最終回答か? → loop 終了
- tool 呼び出しか? → 3 へ
3. tool を実行する
4. tool 結果をメッセージに追加する
5. 1 に戻る
これが ReAct パターンの本質だ — think → act → observe を繰り返す。モデルが「思考」(推論)し、「行動」(tool 呼び出し)し、harness が「観察」(結果の注入)を与える。
終了条件 — loop は必ず止まらなければならない
while で最も重要なのは脱出だ。終了条件が弱いと agent は永遠に回る。
| 終了条件 | 意味 |
|---|---|
| 最終回答 | モデルが tool なしでテキストのみ返す |
| step cap | N 回繰り返したら強制終了 (例: 40) |
| トークン予算 | 累積トークンが上限を超えたら終了 |
| 明示的シグナル | モデルが done のような終了 tool を呼ぶ |
| エラー | 復旧不能な失敗 |
| 人の介入 | ユーザーが中断 |
step cap とトークン予算は選択肢ではない。 この 2 つがない harness はコスト爆弾だ。
3章 · tool execution 層
モデルは「行動」できない。モデルがやるのは**「この tool をこの引数で呼び出したい」という構造化された出力を出すこと**だけだ。実際の実行は harness がやる。
tool 呼び出しのライフサイクル
1. harness がモデルに「tool 一覧」を伝える (名前・説明・引数 schema)
2. モデルが tool 呼び出しブロックを出力する (tool 名 + 引数)
3. harness がそのブロックを parse する
4. harness が引数を検証する (schema 違反 → エラーをモデルに返す)
5. harness が tool を実行する (多くは sandbox 内で)
6. harness が結果(stdout・stderr・戻り値・エラー)を捕捉する
7. harness が結果を「tool 結果」メッセージにして会話に追加する
8. loop に戻ってモデルを再び呼ぶ
核心: モデルは tool の存在を「説明」でしか知らない。 tool の説明が貧弱ならモデルは tool を誤って使う。tool 定義は事実上 prompt の一部だ。
tool execution で harness が責任を持つもの
- 検証 — モデルが送った引数が schema に合うか。合わなければ実行せずエラーを返す(モデルに自己修正させる)。
- sandboxing — tool 実行は隔離された環境で。ホスト・本番と分離する。
- エラー捕捉 — tool が死んでも harness は死なない。エラーを捕まえてモデルに「観察」として与える。
- タイムアウト — すべての tool 呼び出しにタイムアウト。止まった tool に loop を止めさせるな。
- 結果のフォーマット — 巨大な出力(ログ 10 万行)をそのまま入れると context が破裂する。切り詰めるか要約する。
MCP — tool 層の標準
2026 年には tool を harness ごとに新しく実装しない。**MCP(Model Context Protocol)**サーバーが「tool の束」を標準インターフェースとして公開し、どの harness もそれに接続する。harness の tool 層は次第に「MCP クライアント」になっている。
4章 · context 管理 — 最も難しい部分
モデルの context window は有限だ。そして agent loop は毎 step メッセージを積み上げる — tool 呼び出し、tool 結果、推論。100 step の作業は context を圧倒する。
何を入れ何を抜くかを決めることが harness の最も難しい責任だ。
Context Rot — context は腐る
context が長くなるほどモデルの性能はただ「維持」されるわけではない — 低下する。古い tool 結果、破棄された計画、無関係な探索の痕跡が積もると、モデルは信号と雑音を区別しにくくなる。これを **context rot(context の腐敗)**と呼ぶ。
window に「入る」からといってすべて同じではない。前方・後方が中間よりよく使われる。 だから harness は単に「全部入れる」ではなく、何を、どこに置くかを設計しなければならない。
context を扱う技法
| 技法 | 説明 |
|---|---|
| Pruning | 古い・無関係なメッセージを切り捨てる |
| Compaction | 古い会話を要約版に圧縮する |
| Retrieval | 必要なときだけ外部から関連する断片を取ってくる (RAG) |
| Sub-agent 隔離 | 下位作業を別 context で回して本文を汚染しない |
| 構造化 | tool 結果を原文ではなく構造化・要約された形で |
| 外部メモリ | ファイル・DB に状態を置き、context にはポインタだけ |
核心の洞察: context window は RAM ではなく作業台だ。 無限に積む場所ではなく、今の作業に必要なものだけを載せておく場所だ。harness の仕事はこの作業台をきれいに保つことだ。
5章 · System Prompt — harness の憲法
System Prompt は harness がモデルに与える憲法だ。毎 loop ごとにモデルが見る、変わらない土台。
ここに入るもの:
- アイデンティティ — 「お前は何で、何のために存在するのか」。
- ルール・制約 — 絶対にやらないこと、常にやること。
- tool 使用の指針 — tool をいつ・どう使うか。
- 出力形式 — 応答の構造。
- 安全境界 — 拒否すべきリクエスト、人を呼ぶべき状況。
ここにcontext ファイル(CLAUDE.md、AGENTS.md など)が加わる — プロジェクトごとのルール・アーキテクチャ・慣習。System Prompt が「harness の憲法」なら context ファイルは「このプロジェクトの地域法」だ。
核心: 同じモデル + 同じ tool でも、System Prompt が違えばまったく違う agent だ。 System Prompt は harness がモデルの「性格」を形作る場所だ。
6章 · 制御フロー — loop の上のオーケストレーション
基本 loop(2章)の上に、成熟した harness は制御フローを載せる。
Sub-agent — context 隔離
下位作業を新しい context で回す別の agent。「このディレクトリ構造を調査して」のような探索作業を sub-agent に任せれば、数十回のファイル読み込みが本文 context を汚染しない。 sub-agent は結果の要約だけを返す。context rot 防御の核心ツール。
Hook — 決定論的な割り込み
agent loop の特定の地点(tool 実行前、応答後など)で回る決定論的なコード。モデルの判断ではなく固定されたルール。例:「どの tool でも実行前に linter を回す」「commit 前にテストを強制する」。
権限ゲート — 行動する前に止まる
高リスクの tool(ファイル削除、デプロイ、外部送信)は実行前にポリシー検査または人の承認を経る。harness は「読み取り tool は自動、書き込み tool はゲート」のようなポリシーを強制する。
並列化
互いに依存性のない tool 呼び出しは同時に。独立したファイル読み込み 3 つを直列にする理由はない。ただし、状態を触る呼び出しは直列で。
Human-in-the-loop
取り返しのつかない決定の前で harness は止まり、人に尋ねる。自律性と安全のダイヤルは harness が握っている。
7章 · 失敗モードと復元
成熟した harness とデモ harness の違いは失敗をどう扱うかで分かれる。
| 失敗モード | 症状 | harness の防御 |
|---|---|---|
| 無限 loop | 同じ行動を繰り返す、進展なし | step cap、loop 検知(反復行動の探知) |
| tool エラー | tool が死ぬ、400 応答 | エラーを捕まえてモデルに「観察」として伝える、リトライ上限 |
| 幻覚された tool | 存在しない tool 名を呼ぶ | レジストリと照合、モデルに「そんな tool はない」と返す |
| Context rot | 長くなった context で品質低下 | 圧縮、sub-agent 隔離、pruning |
| コスト暴走 | トークンが静かに積もる | トークン予算、自己修正回数の上限 |
| 誤った自信 | 間違った答えを確信を持って | 検証 tool(テスト・型チェック)を loop に |
| スコープ逸脱 | 指示された以上のことをやる | System Prompt の制約、権限ゲート |
核心原則: agent は失敗する — harness がその失敗を吸収し、復旧可能なら復旧し、そうでなければきれいに止まらなければならない。 失敗を防ぐのではなく、失敗を扱うのが harness の仕事だ。
8章 · 実際の harness たち — 何が違うのか
同じモデル API を呼んでいるのに、体験が違う。harness が違うからだ。
| harness | 表面 | 特徴 |
|---|---|---|
| Claude Code | CLI | sub-agent、hook、skill、MCP、権限モード、CLAUDE.md |
| Cursor | IDE | エディタがそのまま harness の表面、background agent、diff 中心 |
| Codex CLI | CLI | sandbox 実行、AGENTS.md |
| Aider | CLI | git ネイティブ、repo map、commit 中心 |
| OpenClaw | メッセージングアプリ | ローカル gateway、Skills/ClawHub、マルチチャネル |
| Claude Agent SDK | ライブラリ | harness 自体を作るためのツール |
これらの違いはほぼすべてharness の設計判断だ:
- 表面(CLI vs IDE vs メッセージング)
- context ファイルの慣習(
CLAUDE.mdvsAGENTS.md) - tool execution モデル(sandbox の強度)
- 制御フロー(sub-agent・hook のサポート有無)
- 権限モデル(どれだけ自律的か)
Claude Agent SDK が特に興味深い — それは完成された harness ではなく、harness を作るためのライブラリだ。loop・tool・context 管理を提供し、あなたはその上に自分の harness を建てる。
9章 · 自作する — 40 行の最小 harness
harness の本質は単純だ。最小 harness を自作してみると明確になる。
import anthropic
client = anthropic.Anthropic()
# tool 定義 — モデルはこの「説明」でしか tool を知らない
TOOLS = [{
"name": "run_bash",
"description": "Run a bash command and return its output.",
"input_schema": {
"type": "object",
"properties": {"command": {"type": "string"}},
"required": ["command"],
},
}]
def execute_tool(name, args):
# 実際の実行 — 現実では sandbox 内で
import subprocess
if name == "run_bash":
r = subprocess.run(args["command"], shell=True,
capture_output=True, text=True, timeout=30)
return (r.stdout + r.stderr)[:4000] # 結果を切り詰めて context を保護
return f"Unknown tool: {name}" # 幻覚された tool への防御
def agent_loop(task, max_steps=20): # step cap = 終了保証
messages = [{"role": "user", "content": task}]
for step in range(max_steps):
resp = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
system="You are a coding agent. Use tools to complete the task.",
tools=TOOLS,
messages=messages,
)
messages.append({"role": "assistant", "content": resp.content})
# tool 呼び出しがなければ → 最終回答 → loop 終了
tool_uses = [b for b in resp.content if b.type == "tool_use"]
if not tool_uses:
return resp.content
# tool を実行し結果をメッセージに注入
results = []
for tu in tool_uses:
output = execute_tool(tu.name, tu.input)
results.append({
"type": "tool_result",
"tool_use_id": tu.id,
"content": output,
})
messages.append({"role": "user", "content": results})
return "Step limit reached" # fail-closed
これがすべてだ。while loop + tool execution + メッセージ注入。 Claude Code も Cursor も、この骨格の上に — context 管理、sub-agent、hook、権限、より良い tool、より良い System Prompt を — 載せたものだ。
上の 40 行で抜けているものこそが「プロダクション harness」の仕事だ: context 圧縮(4章)、権限ゲート(6章)、失敗復元(7章)、ストリーミング UX、可観測性、コスト追跡。
10章 · harness を評価する — モデル eval とは違う
「このモデルは良い?」はモデル eval だ。「この harness は良い?」は別の問いだ。
harness eval の核心: モデルを固定し、harness だけを変えて測定する。
モデル eval: harness 固定、モデル A vs モデル B
harness eval: モデル固定、harness A vs harness B
測定する指標:
- 作業完了率 — 同じ作業の束を harness A/B で回したときの成功比率。
- step 数 — 完了まで何回の loop か? 少ないほど効率的。
- 作業あたりのコスト — トークン・時間。harness が context をうまく管理すれば安くなる。
- エラー復旧率 — tool が失敗したとき harness が復旧させる比率。
- 逸脱率 — スコープを外れたり無限 loop に陥る比率。
同じ frontier モデルでも harness が悪ければ、弱いモデル + 良い harness より実務作業で負ける。 だから harness eval はモデル eval と同じくらい重要だ — ところがほとんどの場合測定されていない。
11章 · harness がモデルと同じくらい重要な理由
整理しよう。2026 年に「AI engineering」と呼ぶ仕事のほとんどはharness engineering だ。
- モデル提供者は少数に収束した — モデルは事実上**コモディティ(commodity)**に近づいた。
- 差別化はそのモデルをどう取り囲むかから生まれる — loop、tool、context、制御フロー。
- 同じモデル、違う harness → 一方は PR を開き、一方は空回りする。
- frontier モデル + 悪い harness < 弱いモデル + 良い harness(実務作業の基準で)。
これは 1章の比喩に戻る。engine(モデル)は次第に似てくる。レースは車(harness)で分かれる。
そして良い知らせ: harness はengineering 可能だ。モデルはあなたが変えられない。しかし loop、終了条件、tool の説明、context 管理、権限ゲート、失敗復元 — これは全部あなたが設計するコードだ。AI engineer が実際にコントロールできる表面こそが harness だ。
エピローグ — harness を意識せよ
この記事の一文要約: モデルを選ぶときと同じくらい harness を意識せよ。
ツールを使うときは「この harness が loop をどう回すか、context をどう管理するか、失敗をどう扱うか」を見る。harness を作るときは — 40 行の骨格の上に — context 管理・権限・復元を載せる。harness を評価するときはモデルを固定し harness だけを測る。
次の 10 年の AI engineering はより大きなモデルを待つことではない。より良い harness を建てることだ。
12項目チェックリスト
- harness の agent loop に終了条件が明確か(step cap・トークン予算)?
- tool の引数を実行前に検証するか?
- tool execution が sandbox 内で回るか?
- すべての tool 呼び出しにタイムアウトがあるか?
- 巨大な tool 出力を切り詰めるか要約するか?
- context 圧縮・pruning の戦略があるか?
- 探索的な下位作業を sub-agent で隔離するか?
- 高リスクの tool に権限ゲートがあるか?
- 無限 loop 検知(反復行動の探知)があるか?
- 幻覚された tool 名をレジストリで弾くか?
- 自己修正 loop に回数の上限があるか?
- harness を(モデルを固定して)別途評価するか?
アンチパターン 10 個
- 終了条件のない loop — コスト爆弾。
- tool の引数を検証なしで実行。
- tool execution をホストで直接(sandbox なし)。
- 巨大な出力を context にそのまま注入。 5.「全部入れる」context 戦略 — context rot。
- 探索作業を本文 context で — 汚染。
- 高リスクの tool に権限ゲートなし。
- tool エラーで harness が一緒に死ぬ。
- モデルだけ評価して harness は評価しない。
- harness を「モデル呼び出しラッパー」としてだけ扱う — そこで止まる。
次の記事の予告
次の記事の候補: sub-agent オーケストレーション — マルチ agent harness の設計、context 圧縮の深掘り — 何を捨て何を残すか、harness eval スイートの構築 — モデルを固定して harness を測定する。
「モデルは engine だ。だがレースは車で分かれる。2026 年 AI engineering の重心はモデルではなく harness だ。」
— AI harness 解剖、おわり。