ブログ • AI / Agent
AI Coding Agent 大戦 2026:Claude Code、Codex、OpenCode、DeepSeek Agent は何を争っているのか?JSON Tool Calling から見る Agent Harness アーキテクチャ
ランキングはまだ、誰の点数が高いかを聞いている。ターミナルを開くと、本当にファイルを変え、テストを走らせ、MCP につながるのは、あの自然言語の返答ではない。
Claude Code、Codex、OpenCode、DeepSeek Agent は、表向きみな「仕事ができる Coding Agent」を売っている。本当に差が開くのは Agent Harness だ。一度の JSON Tool Calling を、arguments から副作用まで、誰が握るか。
この記事では:
- Coding Agent が補完に対して足している層は何か
- Agent Harness が担うもの、モデルが担わないもの
- JSON Tool Calling が四社の共有電線である理由
- 一度の tool call の七跳:各社が門をどこに置くか
- JSONNote で arguments と schema をローカルに分解する方法
まずこれだけ:2026 年の競争は「誰が次の一行をより正確に補完するか」ではない。モデルが出すのは tool call、引数は JSON。parse できるか、承認するか、どのサンドボックスで走らせるか、結果をどう書き戻すかは harness が決める。Claude Code は毎回の呼び出し前後にフックを打つ。Codex はサンドボックスと承認を既定の境界にする。OpenCode はモデルと権限を差し替え可能な設定にする。DeepSeek Agent はパイプライン全体をプラグインに分解する。
本当に争っているのは補完ではない
補完が解くのは「次の一行は何か」。Coding Agent が解くのは「この目標を実リポジトリでどうやり切るか」——文脈を読み、ツールを選び、コードを変え、コマンドを実行し、結果を見て、また判断する。
四社の UI はどれもチャットに見える。下のループはほぼ同じだ:
User goal
→ Agent loop
→ LLM emits tool_call (JSON arguments)
→ Harness parses / validates / gates / executes
→ Tool result returns to context
→ Agent decides again
モデルは推論と「次に誰を呼ぶか」を担う。harness は、モデルが見えるツール、引数が合法か、高リスク動作を人に聞くか、ツールが本当に何をするか、セッションの記録、「完了」の定義を担う。
機能一覧はますます似てくる。Skills、MCP、子 Agent、権限スイッチは誰もが持つ。差は制御権がどの層に落ちるかだ。製品の位置づけは次を参照:AI Coding Agent はもうコード補完だけではない:Codex、Claude Code、OpenCode、DeepSeek Harness は何を争っているのか?。ループの回り方は次を参照:AI Coding Agent はどう動くか?。本稿が分解するのは一件だけだ。JSON Tool Calling がモデルを出たあと、harness がどう引き継ぐか。
Agent Harness とは何か
2026 年、この層にはすでに名前がある。十一の本番 Coding Agent をソースから解剖した論文は、それを Harness Engineering と呼ぶ。Agent はモデル+harness だ——LLM を実世界へつなぐランタイムであり、ループ、ツール、文脈、安全制御、オーケストレーション、拡張面を含む。
別の対照実験はもっと直球だ。harness を替えると、同じモデルはより多く解けるのか。平均点はしばしば近い。リポジトリ課題と競技課題は逆方向へ動くことがある。コストと取消率も変わる。結論は「公式 harness が必ず勝つ」ではない。「買うのは完了経路であり、ランキング上の一点ではない」だ。
だから四社はボタンを一つ多く出したかを競っていない。ツール契約、実行境界、人の拒否権を、誰がよりはっきり組織するかを競っている。
| 層 | 担うもの | 担わないもの |
|---|---|---|
| モデル | ツールを選び、JSON 引数を埋め、結果を読んでまた判断する | ディスクへ書く、shell を走らせる、ネットへ出る、認可する |
| JSON 契約 | 引数と結果の形 | この呼び出しが起こるべきか |
| Agent Harness | 見えるツール、検証、承認、サンドボックス、書き戻し、セッション | 業務目標を代わりに考えること |
技術スタックの層は次を参照:2026 AI Agent 技術スタック:LLM、MCP、Function Calling、JSON Schema。
共有の電線:JSON Tool Calling
Tool Calling(Function Calling とも呼ばれる)は「モデルがコードを書ける」の別名ではない。構造化された呼び出しだ。モデルは宣言したツール一覧から名前を選び、引数契約に合う JSON を生成する。
OpenAI 互換 API では、ツール定義の parameters 自体が JSON Schema だ:
{
"type": "function",
"function": {
"name": "run_tests",
"description": "Run the project test suite and return a structured summary.",
"parameters": {
"type": "object",
"additionalProperties": false,
"properties": {
"suite": { "type": "string", "enum": ["unit", "integration", "e2e"] },
"path": { "type": "string", "minLength": 1 }
},
"required": ["suite"]
}
}
}
モデルが返すとき、arguments はしばしば文字列であり、すでに parse 済みのオブジェクトではない:
{
"id": "call_7f21",
"type": "function",
"function": {
"name": "run_tests",
"arguments": "{\"suite\":\"e2e\",\"path\":\"tests/checkout.spec.ts\"}"
}
}
だから harness は少なくとも二つのことをする。まず文字列を合法な JSON に解析し、宣言した schema でフィールド、型、列挙を検証する。欠けた引用符、余分なカンマ、未宣言キーは、この一跳で起きる。
MCP は同じ電線を外部 Server につなぐ:inputSchema / outputSchema はなお JSON Schema であり、tools/call はなお一度の構造化呼び出しだ。Server が増えれば、モデルが見る description と schema も増え、harness が守る門も増える。安全責任の分け方は次を参照:MCP セキュリティ脆弱性の全面解説。
戦場:一度の tool call の七跳
四社を広げると、機能名は違う。パイプの形は同じだ。争うのは、各一跳を誰が決めるかだ:
-
1
提示
どのツール、どの一段の schema が、このリクエストに書かれるか。見えないツールは、モデルは呼べない。
-
2
発信
モデルが名前を選び、arguments 文字列を生成する。この一跳は「呼びたい」と示すだけだ。
-
3
解析
文字列がオブジェクトになる。不正な JSON は、実行層へ入る前に失敗しなければならない。
-
4
検証
JSON Schema で必須、型、列挙、additionalProperties を見る。
-
5
門
allow / deny / ask。形が合法でも、認可されたことにはならない。
-
6
実行
サンドボックス、ワークスペース、またはホストの全権限で本当に走らせる。副作用はここから始まる。
-
7
書き戻し
結果はテキストまたは JSON になり、セッションに記され、次の一周へ戻る。失敗にも構造が要る。「エラーが起きた」の一文だけでは足りない。
四社ともこの七跳を歩く。差は、フックをどこに挿すか、既定サンドボックスの締まり、モデルを替えられるか、パイプ自体を差し替えられるかだ。
Claude Code:呼び出しの前後にフック
Claude Code は主 Agent を強くする。Skills、MCP、子 Agent、CLAUDE.md は同じ Claude Agent を囲む。JSON Tool Calling に本当に噛み合うのは、毎回の呼び出し前後の確定的なフックだ。
公式のライフサイクルでは、ループ中の毎回のツール呼び出しが PreToolUse と PostToolUse を通る。権限プロンプトが出るときにも止められる(PermissionRequest)。失敗のあと、再試行を許すかも決められる(PermissionDenied / PostToolUseFailure)。
フックが読むのはイベント JSON であり、散文ではない。入力を書き換え、呼び出しを拒み、確認を求め、成功後にログを足し、フォーマッタを走らせ、新しい文脈を戻せる。すでに起きた副作用は取り消せない——PostToolUse では遅い。
権限ルールは deny → ask → allow で照合し、deny が勝つ。フックが返す allow は対話プロンプトを飛ばすだけであり、企業管理の deny 一覧は越えられない。たとえ bypassPermissions を開いても、deny を返す PreToolUse はなお呼び出しを止める。
エンジニアリングの意味ははっきりしている。確率的な Agent に、確定的な門を足す。直したあとテストを走らせ、危険コマンドを止め、保護パスには承認を求める——モデルが「毎回思い出す」ことに頼ってはいけない。
向くのは、ワークフローが安定し、主ループに Skills / 子 Agent / フックを打ち、経験を再利用できる単位にまとめたいときだ。
Codex:実行の前にサンドボックスと承認
Codex(Codex CLI を含む)は問いを実行層へ押し出す。Agent がファイルを変え、shell を走らせ、依存を入れ、ネットと資格情報に触るなら、同時に二つの違う問いに答えねばならない。能力の境界と、いまこの動作が許されるかどうか。
| 仕組み | 答える問い | よくあるつまみ |
|---|---|---|
| Sandbox | 技術上、何に触れ、何を変えられるか? | read-only / workspace-write / danger-full-access |
| Approval | この動作はいま許されるか? | untrusted / on-request / never |
既定は最小権限だ。先に環境を締め、必要になってから開く。信頼していないディレクトリは read-only から始まる。ワークスペースを信頼したあと、よくある既定は workspace-write に on-request を足す——ワークスペース内の読み書きと通常コマンドは自動で走り、ワークスペースを出るかネットに触るときは承認が要る。ネットは既定で閉じ、明示的に開ける。
新しい版はファイルシステムとネットを permission profile で述べる。古い sandbox_mode と混ぜてはいけない。名前は変わる。分け方は変わらない。一方は「何に触れるか」、他方は「いまやってよいか」だ。
向くのは、副作用が大きく、実行軌跡を監査でき、隔離と承認を第一級にしたいときだ。オープンソース倉庫:openai/codex。
OpenCode:モデルは差し替え、権限は設定
OpenCode の差は「もう一系統の Skills 文法を発明すること」ではない。既定の立場は「モデルは差し替えられる」だ。MIT オープンソース、ターミナル優先、複数ベンダーとローカルモデルにつながる。柔軟性は主に設定——provider、model、permission、agent——にあり、harness 核をプラグインバスへ分解することにはない。
権限は初期のブール tools から permission へ収まった。各動作は allow、ask、deny。ツール名、コマンドのパターン、ワークスペースを出るか(external_directory)でルールを書ける。最後にマッチしたルールが効く。子 Agent は主 Agent より厳しくできる。たとえば review 役は edit をそのまま deny する。
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git push *": "deny"
},
"edit": "allow",
"external_directory": "deny"
}
}
勝ちやすい点はこうだ。マルチモデルは既定の能力であり、ベンダーのおまけではない。オープンソースのライセンスとコミュニティ。「モデルを替える」は第一級の操作だ。代償もはっきりしている。実行境界とプラグインの深さは、売りの第一位とは限らない。買うのはモデル差し替えの harness であり、いちばん重いサンドボックス製品でも、「Everything is a plugin」のプラットフォーム核でもない。
向くのは、単一ベンダーを信じないとき、または同じループの中でモデルを替え、ローカルの重みも使いたいときだ。
DeepSeek Agent:パイプライン自体がプラグイン
DeepSeek はこの問題をもう一段下へ押す。公開プレビューの製品は DeepSeek Harness(dsh)。外向けの契約は Agent インターフェースであり、既定実装は差し替え可能な agent-loop だ。スローガンは Everything is a plugin——モデル、ツール、Skills、セッション、サンドボックス、ストレージ、loop、スケジューリング、UI まで差し替えられる。
Tool Calling に揃うのはツールパイプラインであり、もう一つのチャット枠ではない。レジストリの ToolDefinition は型付きの引数と出力を持つ。モデルに投影されるのは name、description、parameters だけだ。execute、タイムアウト、並行フラグ、UI 表示はリクエストへ漏らしてはいけない。
毎回の呼び出しは、決まったウォーターフォールを歩く:
tools/pre-execute → allow / deny / ask
monotonic guards → 只收紧,不能再放行
tools/execute → 真正派发(可包超时 / 重试)
tools/post-execute → 检查或替换结果
finalizeContent → 定义自己的收尾
tools/result → 冻结后的权威结果
ネイティブの Function Calling も、PTC も使える(予約された run_code を転送に使い、子呼び出しはなお同じパイプラインへ入る)。並行は呼び出しごとに分ける。独占は障壁になり、並行可能なものは有界プールへ入る。イベントはなおモデル順でセッションへ書く。
向くのは、より強い助手ではなく、ランタイム自体をプラットフォームにしたいときだ。モデル層は次を参照:DeepSeek V4-Pro 完全解説。
同じ JSON、四つの門
同じ tool call JSON でも、四社は門を違う位置に置く:
| この一跳 | Claude Code | Codex | OpenCode | DeepSeek Agent |
|---|---|---|---|---|
| モデルに見せるツール面 | 内蔵ツール + Skills + MCP。schema は遅延読み込みできる | セッションのツール箱 + プロジェクト説明(AGENTS.md) | 内蔵 + MCP + agent ごとの切り詰め | スコープ付きレジストリが allowlist で ToolSchema を投影する |
| 引数が実行層へ入る前 | フックは完全な tool イベント JSON を読める | 先にサンドボックス能力、それから承認ポリシー | permission ルールがツール名と入力にマッチする | parse のあと、pre-execute のウォーターフォールと単調ガード |
| 人がどう拒否するか | PermissionRequest。deny はフックの allow に勝つ | on-request / untrusted。reviewer に渡せる | ask。子 Agent はより厳しくできる | ask の判断はパイプラインの第一級の結果だ |
| 副作用はどこで起きるか | 本機ツール + フックの後処理 | OS 級サンドボックス。既定は無ネット、ワークスペースは書き込み可 | 本機実行、git スナップショットで undo | 差し替え可能な sandbox プラグイン |
| 結果をどう書き戻すか | PostToolUse / 失敗フックが文脈を足す | JSONL イベント。CI 監査がしやすい | LSP 診断をループへ戻せる | tools/result を凍結したあと、セッションログへ書く |
最後の行は順位ではない。買うのは「より使いやすい主 Agent」か、「より制御できる実行環境」か、「モデル差し替えの設定層」か、「組み立てられるランタイム」かだ。
制御権マップの製品視点は次を参照:四つのアーキテクチャ中心。MCP がツール面を広げたあと、安全を誰が負うかは次を参照:AI Agent が「自分でインターネットを攻撃し始めた」:JSON はどう安全境界になるか。
なぜ自分で JSON Schema を見るのか
四社の harness がどれだけ強くても、汚れた引数が実行層に入れば事故になる。モデルが埋める引数は緩い制約だ。arguments は壊れた JSON になり、フィールドが欠け、未宣言キーが足されることがある。
Schema として合法でも、認可されたことにはならない。下の二段は、どちらも「sql フィールドがある」緩い schema を通る。締めた側だけが操作を列挙に収め、識別子を pattern で書く:
{
"loose": {
"type": "object",
"properties": { "sql": { "type": "string" } },
"required": ["sql"]
},
"tight": {
"type": "object",
"additionalProperties": false,
"properties": {
"op": { "type": "string", "enum": ["get_user_by_id"] },
"user_id": { "type": "string", "pattern": "^[a-z0-9-]{8,36}$" }
},
"required": ["op", "user_id"]
}
}
契約の書き方、JSON Mode と Strict Schema の差は次を参照:AI に JSON Schema が必要な理由、および AI Agent に JSON Schema はなぜ必要?Tool Calling から Structured Output まで完全解説。
JSONNote で tool call を分解する
harness をデバッグするとき、いちばん役に立つ材料は、たいてい一段の JSON だ。ツール定義、モデルの arguments、フックイベント、拒否理由。ブラウザローカルで分解できる。リポジトリを上げる必要はない。
-
1
先に arguments が合法な JSON かを見る
文字列のエスケープをほどき、JSON フォーマット に貼る。欠けたカンマ、末尾カンマ、単引用符は、ここで落ちる。
-
2
宣言した schema で検証する
ツールの parameters / inputSchema と、解析したオブジェクトを JSON Schema に入れる。欠けたフィールドか、型の誤りか、あってはならないキーの追加かが分かる。
-
3
「承認したとき」と「いま」を比べる
先週保存したツール一覧と今日の一覧を JSON Diff に入れ、description と schema の静かな変更だけを探す。
-
4
同僚に見せるときは Hash 共有
データは URL fragment に残り、サーバを通らない。次を参照:URL Hash で JSON を共有する。
よくある質問
Claude Code、Codex、OpenCode、DeepSeek Agent は何を争っているのか?
機能一覧でも、次の一行の補完精度でもない。争っているのは Agent Harness だ。一度の JSON Tool Calling を、引数の解析、契約検証、承認、サンドボックス実行、結果の書き戻しまで、誰が握るか。
Agent Harness とモデル、どちらが大事か?
モデルは推論と次の一手を担う。harness は、見えるツール、引数が合法か、高リスク動作を人に聞くか、副作用がどこで起きるかを担う。harness を替えても平均点が上がる保証はない。だが完了経路、コスト、取消率は変わる。製品を選ぶのは制御権を選ぶことであり、点数だけを選ぶことではない。
四社のどれを選ぶべきか?
統一の勝者はない。主 Agent に確定的なフックと権限を打ちたいなら Claude Code。サンドボックスと承認を既定の実行境界にしたいなら Codex。モデルを替え、ロックインを避けたいなら OpenCode。loop、ツールパイプライン、サンドボックスを差し替え可能なプラグインにしたいなら DeepSeek Agent(DeepSeek Harness)。
JSON Tool Calling 自体に権限制御はあるか?
ない。モデルがツール名を選び、arguments を埋める。その一跳は「呼びたい」と示すだけだ。止めるか、どのサンドボックスで走らせるか、結果をモデルに戻すかは harness の仕事だ。ツールが無い、権限が拒まれる、JSON 検証が失敗する——ディスク上では何も起きない。
なぜ自分で JSON Schema を検証するのか?
モデルが埋める引数は緩い制約だ。arguments はしばしば文字列で、フィールドの欠落、型の誤り、未宣言キーの追加が起きる。Schema として合法でも、認可されたことにはならない。本番経路はなお parse と検証のあと、権限とサンドボックスへ渡す。四社の harness がどれだけ強くても、汚れた引数が実行層に入れば事故になる。
まとめ
2026 年の Coding Agent 大戦は、モデル戦争に見える。リポジトリの中では、harness 戦争だ。
モデルが出すのは JSON。Harness は、その JSON が副作用になれるかを決める。四社が争うのは同じパイプ上の制御権だ。Claude Code はフックを打ち、Codex は実行境界を締め、OpenCode はモデルのロックを外し、DeepSeek Agent はランタイム自体をプラグインにする。
機能はこれからも似てくる。本当に見るべきは、tool call がモデルを出たあと、誰が決めるかだ。
次へ:一度の tool call の arguments を JSONNote に貼る