AIハーネス(エージェントハーネス)は、LLMをエージェントとして動かすために、モデルの外側で「ループを回す・ツールを実行させる・止める・記録する」を受け持つ実行時の部品一式です。LangChainは2026年3月の解説で「Agent = Model + Harness」と式にし、ハーネスを「モデル以外のすべてのコード、設定、実行ロジック」と定義しました。本記事では、ハーネスという言葉が指す範囲を整理したうえで、制御基盤を6つの部品に分け、Claude Agent SDK・OpenAI Agents SDK・Deep Agents・Strands Agentsがそれぞれをどの設定名で持っているかを対応表にします。最後に、APIキー無しで動かせるハーネスのテストコードを載せます。
まとめ:ハーネスはモデル以外でエージェントを動かし止める部品一式
- AIハーネスは、ループ制御・ツール実行と権限・実行環境・コンテキストと状態・ガードレールとフック・トレースの6部品で見ると設計の抜けが分かります。
- 「LLM ハーネス」は、エージェントの実行基盤のほかに、モデルの性能を測る評価ハーネス(lm-evaluation-harness)を指す場合があります。
- 主要SDKはハーネスを内蔵済みです。ただし既定値が安全側とは限らず、Claude Agent SDKの
max_turnsとmax_budget_usdは既定で未設定、OpenAI Agents SDKのトレースは既定で有効です。 - 業務システムに組み込むなら、ループを自作せず既製SDKのハーネスに載せ、停止条件・権限・トレース送信先の3点を明示的に設定するのが基本です。
以下、言葉の整理から部品ごとの設計判断、SDKの対応表、テストコードの順に解説します。
「ハーネス」がAI分野で指す3つの対象
ハーネス(harness)は本来、馬具や安全帯のように強い力を制御して方向づける装具を指します。ソフトウェアでは以前から、テスト対象を外側から駆動する仕組みを「テストハーネス」と呼んできました。AI分野では、同じ語が次の3つの対象に使われており、検索結果でも混在しています。
| 呼び方 | 指す対象 | 代表例 |
|---|---|---|
| エージェントハーネス | エージェントを動かす実行時の制御部品 | Claude Agent SDK、Deep Agents |
| 評価ハーネス | モデルにベンチマークを解かせて採点する枠組み | lm-evaluation-harness |
| ハーネスエンジニアリング | ハーネスを設計・改善する実践(職能) | AGENTS.md、Linter、CIでの検証 |
本記事が扱うのは1行目のエージェントハーネスです。2行目の評価ハーネスは、EleutherAIのlm-evaluation-harnessが代表で、PyPIでは lm-eval として配布されています(2026年8月31日公開の0.4.13が最新)。「LLM ハーネス」で探しているのがモデルの性能比較なら、こちらの文脈です。評価の指標やデータセットの組み方はLLM評価の指標とデータセット設計の解説で扱っています。
3行目のハーネスエンジニアリングは、モデルの周囲にある実行基盤を設計・改善する実践です。コーディングエージェント向けにリポジトリ構成やルールファイルを整えることも、その一部に含まれます。こちらはハーネスエンジニアリングの入門記事と、Spec・Context・Harnessの三層で組む三層設計の解説に分けています。
ハーネスとモデル・フレームワーク・ランタイムの境界
ハーネスとフレームワークの違いは、LangChain自身の整理が分かりやすいです。Deep Agentsの公式説明は「LangGraphはグラフのランタイム、LangChainの create_agent はその上の最小限のハーネス、Deep Agentsはさらにファイルシステム・サブエージェント・コンテキスト管理・スキルを同梱した、方針の強いハーネス」と3層で書き分けています。
つまりランタイムは「処理を順に実行する土台」、フレームワークは「部品を組むための道具箱」、ハーネスは「部品が組み上がり、既定値まで決まった実行体」です。境界ははっきりしておらず、Anthropicは公式Cookbookで、Claude Agent SDKが「Claude Codeを動かしているのと同じツール、エージェントループ、コンテキスト管理」へのアクセスを提供すると説明しています。Claude Codeという製品のハーネスを、SDKとして切り出して配っている形です。
AWSのAmazon Bedrock AgentCoreは、この部品一式をマネージドサービスにしました。2026年6月17日に一般提供となった「managed agent harness」は、公式発表で「オーケストレーションループの実行、ツール実行、コンテキストウィンドウ管理、ターン間の状態保持、障害からの回復、セッション分離」を引き受けると説明されています。機能と料金はAgentCoreハーネスGAの解説にまとめています。
エージェントハーネスを構成する6部品と設計で決めること
本記事ではSDKやマネージドサービスの機能を比較するため、制御基盤を6つの観点に整理します。この6分類は本記事の整理であり、各ベンダー共通の規格ではありません。部品ごとに「何を決めないと事故になるか」が異なります。
ループと停止条件:ターン数・予算の上限
ハーネスの中心は「モデルを呼ぶ→ツール呼び出しの要求があれば実行する→結果をモデルに戻す」を最終応答まで繰り返すループです。Strands Agentsの公式ドキュメントも、agent loopをこの反復として説明しています。設計で決めるのは止める条件で、SDKごとに既定値が大きく違います。
OpenAI Agents SDKは max_turns の既定が10で、超えると MaxTurnsExceeded を送出します。Claude Agent SDKの max_turns と max_budget_usd は既定が未設定(None)で、予算を超えると error_max_budget_usd の結果で止まります。Strands Agentsは呼び出しごとの limits でターン数・出力トークン・合計トークンの上限を指定でき、指定しなければ上限はありません。Deep Agentsはグラフの再帰上限を9,999に設定しています。業務で動かすなら、ターン数だけでなく金額かトークンの上限を必ず置いてください。ツールを呼び続けるモデルの挙動はプロンプトでは防ぎきれず、止めるのはハーネスの役目です。
ツール実行と権限:自動承認・人の承認・拒否
ツールを「使えるか」と「確認なしで実行してよいか」は別の設定です。Claude Agent SDKの allowed_tools は利用できるツールを絞る設定ではなく、列挙したツールを自動承認するリストで、列挙していないツールは permission_mode と can_use_tool の判定に回ります。使わせたくないツールは disallowed_tools で塞ぎます。permission_mode は default・acceptEdits・plan・bypassPermissions・dontAsk・autoの6種類です。
人の承認を挟む仕組みは、Deep Agentsでは interrupt_on を渡したときに入る HumanInTheLoopMiddlewareです。Strandsではツール呼び出し前のフックイベント BeforeToolCallEvent で cancel_tool に文面を入れると、その呼び出しを取り消せます。返金・削除・外部送信のように取り消せない操作だけを承認対象にし、読み取り系は自動承認に寄せると運用負荷が抑えられます。
実行環境:ファイルとシェルを隔離するサンドボックス
コードを書いて実行するエージェントには、隔離されたファイルシステムとシェルが要ります。OpenAI Agents SDKは2026年4月15日公開の0.14.0で、beta機能のSandbox Agentsを追加しました。公式ドキュメントは、ファイル配置・ファイル操作ツール・シェル・サンドボックスのライフサイクル・スナップショットをまとめた「execution harness」をSDKが提供すると説明しています。Claude Agent SDKにも sandbox オプションがあり、AgentCoreハーネスはセッションごとに分離した実行環境を持ちます。
社内データベースへの書き込みや本番サーバーへのシェル接続を、隔離環境の外で直接ツールにしてはいけません。サンドボックスで作業させ、外部への反映は権限付きの別ツールに分けます。
コンテキストと状態:履歴の圧縮と会話の保存
ループが長くなると、履歴がコンテキストウィンドウを埋めます。Strands Agentsは既定で直近のメッセージだけを残す SlidingWindowConversationManager(window_size の既定は40)を使い、要約して残す SummarizingConversationManager にも切り替えられます。Deep Agentsは要約用のミドルウェアとファイルシステムへの退避を標準構成に含みます。Claude Agent SDKには会話の圧縮直前に割り込める PreCompact フックがあります。
ターンをまたぐ状態は別の部品です。OpenAI Agents SDKのSessionsは、実行前に会話履歴を読み込み、実行後に新しいメッセージを保存し、セッションIDごとに会話を分けて管理します。圧縮の方針と長期記憶の分け方はエージェントメモリの設計解説とコンテキストエンジニアリングの解説で詳しく扱っています。
ガードレールとフック:入力・出力・ツール呼び出しの検査
検査対象は、最初の入力、最終出力、ツール呼び出しの前後に分けられます。ただしOpenAI Agents SDKの入力ガードレールは既定でエージェントと並行実行され、拒否判定までにツールが動く場合があります。入力検査を終えてから実行を開始するには、入力ガードレールに run_in_parallel=False を指定します。OpenAI Agents SDKは3か所それぞれにガードレールを持ち、入力と出力のガードレールは条件に当たると InputGuardrailTripwireTriggered などの例外で実行を止めます。ツールのガードレールは実行そのものを止めるほか、ツールを動かさずに拒否の文面をモデルへ返して処理を続けさせることもできます。
Claude Agent SDKのPython版0.2.162で定義されるフックは PreToolUse・PostToolUse・PostToolUseFailure・UserPromptSubmit・Stop・SubagentStop・SubagentStart・PreCompact・Notification・PermissionRequest の10種類です。PreToolUse では許可・拒否・確認・保留(allow・deny・ask・defer)を返せます。入力だけを検査して終わる設計は、ツール呼び出しの段で入ってくるプロンプトインジェクションを素通りさせます。検査層の選び方はAIガードレールの実装層の解説を参照してください。
トレースと記録:送信先とOpenTelemetryの規約
エージェントの失敗は、どのツールをどの引数で呼んだかを追えないと直せません。OpenAI Agents SDKのトレースは既定で有効で、既定の送信先はOpenAIのトレース収集エンドポイントです。社外にプロンプトや顧客データを出せない案件では、RunConfig(tracing_disabled=True) か環境変数 OPENAI_AGENTS_DISABLE_TRACING で止めるか、送信先を自社の基盤に差し替えます。
Strands AgentsはOpenTelemetryで計装されており、OTEL_EXPORTER_OTLP_ENDPOINT で送信先を指定し、StrandsTelemetry().setup_otlp_exporter() などでエクスポーターを設定すると、トレースをOTLPで送れます。OpenTelemetryのGenAIセマンティック規約はエージェント用のスパン名として invoke_agent {gen_ai.agent.name}、ツール実行に execute_tool {gen_ai.tool.name} を定めていますが、エージェント関連の規約はまだDevelopment(開発中)の段階です。属性名が変わる前提で、集計側を組んでおく必要があります。スパン木の組み方はエージェントトレーシングの解説で扱っています。
主要Python SDKに組み込み済みのハーネス部品の対応表
6部品が各SDKでどの設定名に当たるかを並べます。版は2026年9月30日時点のPyPI最新(claude-agent-sdk 0.2.162、openai-agents 0.22.3、deepagents 0.7.20、strands-agents 1.57.1)で、設定名はインストールしたパッケージのソースで確認しました。
| 部品 | Claude Agent SDK | OpenAI Agents SDK | Deep Agents | Strands Agents |
|---|---|---|---|---|
| 停止条件 | max_turns/max_budget_usd(既定なし) | max_turns(既定10) | recursion_limit 9,999 | limits(既定なし) |
| 権限 | permission_mode 6種/can_use_tool | needs_approval/ツールガードレール | interrupt_on | BeforeToolCallEventのcancel_tool |
| 実行環境 | sandbox | Sandbox Agents(beta) | backend(サンドボックス可) | sandbox(既定は隔離なし) |
| コンテキスト | PreCompactフック/resume | Sessions | 要約+ファイル退避 | SlidingWindow(40) |
| 検査 | フック10種 | 入力・出力・ツールの3か所 | ミドルウェア | フックイベント |
| トレース | OTelのトレース文脈を引き継ぐ | 既定で有効(OpenAIへ送信) | LangSmith連携 | OpenTelemetry |
表で「既定なし」「隔離なし」となっている欄が、そのSDKで自分が埋める部分です。たとえばStrandsの sandbox は未指定だと NotASandboxLocalEnvironment になり、ソースの説明どおり隔離なしでホスト上でコマンドを実行します。コードを実行させるなら DockerSandbox などを明示的に渡します。Claude Agent SDKは、権限モード、ツールの自動承認・拒否リスト、承認コールバックを組み合わせて実行権限を設定できます。フレームワーク自体の選び方は主要8種のAIエージェントフレームワーク比較、Strandsの基本はStrands Agentsの解説で確認できます。
Deep Agentsは0.7.0から、計画用ツール write_todos を提供する TodoListMiddleware を既定の構成から外しました。以前の記事やサンプルどおりに計画ツールがある前提で組むと動作が変わるので、必要なら middleware=[TodoListMiddleware()] で明示的に戻します。
表の設定名と既定値は、次の一次資料と各パッケージのソースで確認しています。
- Claude Agent SDK(Python)の型定義 types.py
- OpenAI Agents SDKのガードレール仕様
- Deep Agentsの公式ドキュメント
- Strands Agentsのフック仕様
- AgentCoreハーネスのGA発表(AWS、2026年6月17日)
いずれも版が上がると既定値が変わることがあるため、導入時は使う版のリリースノートと合わせて確認してください。
OpenAI Agents SDKでハーネスの権限と停止条件をテストするコード
ハーネスの部品は、モデルを呼ばずに検証できます。OpenAI Agents SDKの agents.testing にある ScriptedModel は、あらかじめ決めた応答を順に返すテスト用のモデルです。次のコードは、5万円を超える返金をツールガードレールで拒否する挙動と、ツールを呼び続けるモデルが max_turns で止まる挙動を、APIキー無しでアサーションにより確かめます。
import asyncio, json
from agents import (Agent, Runner, RunConfig, function_tool, MaxTurnsExceeded,
ToolGuardrailFunctionOutput, tool_input_guardrail)
from agents.testing import ScriptedModel, assistant_message, function_call
LIMIT = 50_000 # 自動で通す返金額の上限(円)
executed = [] # 返金ツール本体が実際に動いた記録
@tool_input_guardrail
def refund_limit(data):
args = json.loads(data.context.tool_arguments or "{}")
if args.get("amount", 0) > LIMIT:
return ToolGuardrailFunctionOutput.reject_content(
f"{LIMIT}円を超える返金は担当者の承認が必要です")
return ToolGuardrailFunctionOutput.allow()
@function_tool(tool_input_guardrails=[refund_limit])
def refund(order_id: str, amount: int) -> str:
"""注文に返金する"""
executed.append((order_id, amount))
return f"{order_id} に {amount} 円を返金しました"
NO_TRACE = RunConfig(tracing_disabled=True)
async def test_over_limit_is_rejected():
model = ScriptedModel([
[function_call("refund", {"order_id": "A-1", "amount": 80000}, call_id="c1")],
[assistant_message("上限を超えるため担当者に回します")],
])
r = await Runner.run(Agent(name="support", model=model, tools=[refund]),
"A-1を返金して", run_config=NO_TRACE)
out = [i for i in r.new_items if i.type == "tool_call_output_item"][0]
assert executed == [], "上限超えなのに返金ツールが実行された"
assert out.output == "50000円を超える返金は担当者の承認が必要です"
async def test_loop_stops_at_max_turns():
model = ScriptedModel([
[function_call("refund", {"order_id": "B-2", "amount": 100}, call_id=f"c{i}")]
for i in range(5)
])
try:
await Runner.run(Agent(name="loop", model=model, tools=[refund]), "B-2",
max_turns=3, run_config=NO_TRACE)
except MaxTurnsExceeded:
assert len(model.calls) == 3
else:
raise AssertionError("max_turns で止まらなかった")
asyncio.run(test_over_limit_is_rejected())
asyncio.run(test_loop_stops_at_max_turns())
print("ok")
実行環境はPython 3.12とopenai-agents 0.22.3です。仮想環境で python -m pip install openai-agents==0.22.3 を実行してから保存したファイルを実行すると、2つのテストが通って次の1行が出力されます。
ok
1つ目のテストは、返金ツール本体が一度も実行されず、拒否文がツール結果としてモデルに渡ったことを確かめています。reject_content は処理を続けさせる拒否で、実行全体を止めたいときは raise_exception を返します。2つ目は、モデルが3回呼ばれた時点で MaxTurnsExceeded になることを確かめ、止まらなければ失敗します。デコレーターの tool_input_guardrails を外して実行すると、1つ目が「上限超えなのに返金ツールが実行された」で失敗することも確認しました。
このサンプルをCIで実行すると、サンプル内のガードレールや停止条件の変更を検知できます。本番コードの設定漏れを検知するには、本番と共通のエージェント生成処理・ツール定義・実行設定をテストから呼び出す必要があります。ただし ScriptedModel は固定応答を返すので、実モデルやプロンプトを差し替えたあとの判断の質は、別途評価で確かめる必要があります。ループをSDKなしで一から書く手順はAIエージェントの作り方の解説にあります。
ハーネスを自作する場面と既製SDKに任せる場面
業務システムにエージェントを組み込むなら、ループと部品の既定構成は既製SDKのハーネスに任せるべきです。停止条件・権限・履歴圧縮・トレースを一から書く場合は、各機能の実装に加え、異常終了や承認拒否、履歴保存失敗などの回帰テストも自分で用意する必要があります。自作の範囲は、業務固有のツール、6部品の設定、承認や検査のコールバック、その回帰テストに絞るのが妥当です。
自作が見合うのは、処理順を監査のために決定論的に固定する必要がある場合と、特定ベンダーのSDKに依存できない契約上の制約がある場合です。前者は、エージェントに順序を委ねずワークフローとして組むほうが適しています。
既製SDKでも失敗しやすいパターンは決まっています。
- 停止条件を既定値のまま運用し、Claude Agent SDKで上限なしのループが課金を積み上げる
allowed_toolsを「使えるツールの制限」だと思い込み、未列挙のツールがpermission_mode次第で実行される- 入力のガードレールだけを置き、ツールの戻り値に紛れた指示を検査しない
- OpenAI Agents SDKのトレースを止めずに、顧客データを含む会話を社外へ送る
停止条件やトレース送信は設定で制御できますが、ツール権限の制限や戻り値の検査には、許可ルールと検査処理の設計も必要です。SDK導入時は、この4点の設定と拒否・停止時の挙動を確認してください。
よくある質問
AIのハーネスとは何ですか?
LLMをエージェントとして動かすために、モデルの外側でループ・ツール実行・権限・履歴管理・検査・記録を受け持つ部品一式です。LangChainは「モデル以外のすべてのコード、設定、実行ロジック」と定義しています。
LLMハーネスと評価ハーネスは同じものですか?
「LLMハーネス」は文脈によって評価ハーネスを指すため、常に別物とは限りません。エージェントハーネスはエージェントを動かす実行基盤で、評価ハーネスはlm-evaluation-harnessのようにモデルへベンチマークを解かせて採点する枠組みです。
ハーネスとエージェントフレームワークの違いは何ですか?
フレームワークは部品を組む道具で、ハーネスは部品が組み上がり既定値まで決まった実行体です。LangChainはLangGraphをランタイム、create_agent を最小のハーネス、Deep Agentsを方針の強いハーネスと位置づけています。
AIエージェントの構成要素は何ですか?
LangChainの「Agent = Model + Harness」という整理では、モデルとハーネスです。本記事ではSDKの機能を比べるため、ハーネスをさらにループと停止条件、ツール実行と権限、実行環境、コンテキストと状態、ガードレールとフック、トレースの6部品に分けています。
Strands Agentsはハーネスですか?
エージェントループ・会話管理・フック・OpenTelemetry計装を備えたSDKで、ハーネスの部品を持っています。AgentCoreのマネージドハーネスは、独自の制御が必要になったときにStrandsベースのコードへ書き出せます。Strandsの上に既定値を組み込んだ完成品のハーネスとしては、2026年9月に公開されたStrands Harnessがあります。