エージェントハーネスとは
エージェントハーネスとは、AIエージェントのモデル呼び出し・ツール登録・ログ記録・エラーハンドリングを単一のフレームワーク層で統一管理する仕組みを指す。「ハーネス」という言葉はソフトウェアテストの「テストハーネス」に由来し、テスト対象(ここではAIエージェント)を外部から制御・観察するための足場を意味する。
OpenAIが公開しているEvalsフレームワーク(openai/evals)はその代表例で、さまざまなモデルやプロンプトをハーネス経由で統一的に評価できる。Anthropicも「Building effective agents」の中でハーネス的な実装パターンを多数紹介しており、エージェントロジックをハーネス内にカプセル化することでテスト・監視・差し替えを容易にすることを推奨している。各社のAgents SDKもハーネスの役割を担うコンポーネントを内包しており、標準化が進んでいる。
なぜ注目されているのか
エージェントシステムの最大の課題の一つが「品質保証の困難さ」だ。従来のソフトウェアは入力と出力が決定論的だが、LLMを使ったエージェントはプロンプトのわずかな変更やAPIのバージョン更新で挙動が変わりうる。ハーネスはこの問題に対して、実行ごとの入出力をキャプチャし、期待値との差異を自動検出する仕組みを提供する。
また、ハーネスを使うことで本番APIを呼び出さずにモックを差し込んだ単体テストが可能になる。これはCIパイプラインにエージェントテストを組み込む際に特に重要で、AnthropicとOpenAIの両社がSDKレベルでモック機能を提供し始めている。テスト速度とコストを大幅に削減しつつ、エージェントの回帰テストを自動化できる。
メタハーネスとの関係
エージェントハーネスが単一エージェントの実行を管理するフレームワークであるのに対し、「メタハーネス」は複数のハーネスを統合・オーケストレートする上位概念だ。複数のサブエージェントが協調して動作するシステムでは、各エージェントがそれぞれのハーネスを持ち、メタハーネスがそれらの連携を制御する階層構造が一般的になりつつある。ループエンジニアリングのパターンと組み合わせることで、堅牢なマルチエージェントシステムを構築できる。
ドラゴンボールで例えると
エージェントハーネスはスカウター(戦闘力計測装置)と戦闘の記録係を合わせた役割だ。
- エージェント(悟空) = 実際に戦うAI本体。ハーネスがなければ何をしているか外から把握できない
- ハーネス = 悟空の全戦闘をリアルタイムで記録するスカウター兼ログシステム。「どのツールを呼んで・何トークン使って・何を返したか」をすべてキャプチャする
- モックへの差し替え = 本物のフリーザの代わりに「訓練用ロボット(モック)」を使って技の精度を試す——本番APIを呼ばずにエージェントのロジックだけをテストできる
- ハーネスなしでのデバッグ = スカウターなしで戦って「なぜ負けたかわからない」状態。ログがないと問題の原因を追えない
- メタハーネスとの違い = スカウターは1人の戦士(エージェント)を観測する道具。複数の戦士を束ねる指揮は界王神(メタハーネス)の仕事
ハーネスは「強くする道具」ではなく「何をしたか見える化する道具」——悟空がどれだけ強くなっても、記録がなければ次の改善につながらない。
実装してみる
- 01 ハーネスクラスを定義し、モデル呼び出し・ツール登録・ログ記録を一元管理する
- 02 各エージェント実行をハーネス経由に統一することで、テスト・モニタリングを容易にする
- 03 ハーネスのモックを差し替えることで、本番APIを呼ばずにロジックをテストできる
import anthropic
class AgentHarness:
def __init__(self, client, model, tools, system):
self.client = client
self.model = model
self.tools = tools
self.system = system
self.trace = []
def run(self, user_message: str) -> str:
messages = [{"role": "user", "content": user_message}]
response = self.client.messages.create(
model=self.model,
max_tokens=4096,
system=self.system,
tools=self.tools,
messages=messages,
)
self.trace.append({
"input": user_message,
"output": response.content,
"usage": response.usage,
})
return response.content[0].text
あなたはエージェントです。以下のツールを使ってユーザーのタスクを実行してください。各ステップで何を行うか説明してから実行してください。 タスク: [タスクをここに記述]