はじめに -- 2026年3月31日に起きたこと
2026年3月31日の早朝、AnthropicのAIコーディングアシスタント「Claude Code」のソースコードのスナップショットが、オンライン上で閲覧可能になった。
Claude Codeは2025年のリリース以来、エンジニアを中心に広く利用されてきたツールである。Wall Street Journalが「The Trillion Dollar Race to Automate Our Entire Lives」と題した記事で取り上げるなど、社会的な注目度も高い。コード断片の流通を受けて、内部構造の分析がコミュニティに広がった。
韓国の開発者Sigrid Jin氏(@instructkr)は、この一件をきっかけにClaude Codeのアーキテクチャを分析し、Pythonで再実装するプロジェクト「claw-code」を立ち上げた。法的・倫理的なリスクを考慮して元のスナップショットをリポジトリから除去しつつ、アーキテクチャのエッセンスだけをクリーンルーム方式で再構築したものだ。
コミュニティの反応は大きく、リポジトリ公開後まもなくGitHub上の星数が急増したことが報告されている。
本記事では、claw-codeが保存・再構成したClaude Codeの内部構造を紐解きながら、現代のAIエージェント設計における原則とトレードオフを考察する。
claw-codeとは何か
claw-codeは、公開状態になったコード断片を分析し、そのアーキテクチャパターンをPythonで再実装したプロジェクトである。「コピー」ではなく「再構築」である点が重要だ。
プロジェクトの設計判断は3つに集約される。
- 元のプロプライエタリコードを保持しない: 法的リスクを避けるため、TypeScriptのスナップショットはリポジトリのトラッキング対象から除外
- アーキテクチャパターンの抽出: ツール配線、エージェントワークフロー、ランタイムコンテキスト管理といった「ハーネスエンジニアリング」の知見を構造として保存
- 動作するPython実装の提供: CLIエントリポイント、ランタイム、クエリエンジンなどの中核コンポーネントを再実装
開発にはOpenAIのCodex上に構築されたワークフローツール「oh-my-codex (OmX)」が使用されたとされる。$teamモードによる並列コードレビューと$ralphモードによる永続実行ループを組み合わせ、短期間でポーティングが完了したという。
Claude Codeの内部アーキテクチャ -- 設計原則を読む
claw-codeが保存したスナップショットデータによると、Claude Codeのsrc/ディレクトリは1,902個のTypeScriptファイルと35個のサブディレクトリで構成されていた。coordinator(タスク調整)、skills(スキル管理)、voice(音声入力)、vim(Vimキーバインド)といった構成から、Claude Codeが単なるチャットボットではなく、IDEに深く統合されたエージェントとして設計されていることが分かる。
ここから見えてくる原則は3つある。
原則1: 単一の検証に依存しない安全設計 -- BashToolの深層防御
Claude Codeの中で最も複雑なツールがBashToolである。ユーザーのターミナルでシェルコマンドを実行するという高リスクな操作を担うため、tools_snapshot.json上では18個のモジュールで構成される多層アーキテクチャが採られている。
機能ごとに整理すると、以下の構成になる。
| 層 | 主なモジュール | 役割 |
|---|---|---|
| セキュリティ判定 | bashSecurity.ts |
実行可否の中核判定 |
| 権限管理 | bashPermissions.ts |
許可/拒否ルールの管理 |
| 破壊的操作の検知 | destructiveCommandWarning.ts |
rm -rf等の警告 |
| コマンド意味解析 | commandSemantics.ts |
コマンドの意図を分類 |
| パス安全性 | pathValidation.ts |
ファイルパスの検証 |
| sed専用検証 |
sedValidation.ts, sedEditParser.ts
|
sedコマンドの安全性解析 |
| サンドボックス判定 | shouldUseSandbox.ts |
隔離実行の要否判定 |
| インターフェース分離 |
prompt.ts, UI.tsx
|
AI向け/人間向け表示の分離 |
要するに「深層防御(Defense in Depth)」だ。セキュリティ判定、権限管理、意味解析、パス検証 -- どれか一つが破られても、別の層が食い止める構造になっている。
この多層構造は安全性を高める一方、18モジュール間の整合性維持が開発コストとなる。各層のバリデーションはレイテンシの積み上げ要因でもある。しかし、ユーザーのマシン上で任意のシェルコマンドを実行するという操作のリスクを考えれば、この設計コストは正当化される。AIエージェントにおけるセキュリティ設計は「過剰に見えるくらいがちょうどよい」という判断が読み取れる。
原則2: LLMと人間のインターフェースは分離すべき -- prompt.ts / UI.tsx パターン
tools_snapshot.jsonに記録された184個のツールモジュールを観測すると、ほぼすべてのツールで共通のファイル構成パターンが浮かび上がる。
tools/SomeTool/
SomeTool.tsx # ツールのコアロジック
prompt.ts # LLMに渡すプロンプトテンプレート
UI.tsx # ユーザーに見せるUIコンポーネント
- prompt.ts: AIモデルに「このツールは何ができるか」「どう使うべきか」を伝えるプロンプトテキスト。モデルが解釈しやすい自然言語で記述される
- UI.tsx: ユーザーに実行結果を表示するReactコンポーネント。人間が理解しやすいフォーマットで出力する
ここで重要なのは、同一のツールでもAIと人間では必要なインターフェースが違う、という点だ。両者を分離することで、AI向け説明と人間向け表示を別々に育てられる。プロンプトの改善(モデルの精度向上)とUIの改善(ユーザー体験向上)が互いにブロックしない。
多くのエージェントフレームワーク(LangChain、CrewAI等)では、ツールの説明文がそのまま人間向けのドキュメントを兼ねる設計が一般的だ。Claude Codeはこれを明示的に分離した。184個のツールを抱えるシステムでは、この分離なしに両方を最適化し続けることは困難だろう。
原則3: 専門化されたサブエージェントによるタスク分割 -- AgentTool
なぜ一つの賢いエージェントにすべてを任せないのか。tools_snapshot.json上でAgentTool配下に記録された20個のモジュールが、その答えを示している。
Claude Code内部では、タスクの性質に応じてサブエージェントに委任する仕組みが採られている。built-in/配下に定義された5種類のビルトインエージェントは以下の通り。
- claudeCodeGuideAgent -- Claude Code自体の使い方をガイド
- exploreAgent -- コードベースの探索・調査
- generalPurposeAgent -- 汎用タスクの処理
- planAgent -- タスクの計画策定
- verificationAgent -- 実行結果の検証
サブエージェントのライフサイクル管理として、forkSubagent.ts(生成)、agentMemory.ts/agentMemorySnapshot.ts(メモリ共有・スナップショット)が用意されている。またtools/shared/spawnMultiAgent.tsによる複数エージェントの同時起動も可能な設計である。
特に注目すべきは、planAgent(計画)とverificationAgent(検証)が分離されている点だ。計画と検証を同じエージェントに担わせると、自分の判断を甘く評価するバイアスが入りやすい。これを構造的に分離した設計判断は、エージェントシステムの信頼性を高める実践的な手法である。
ただし、この構造には副作用もある。サブエージェント間のメモリ共有とコンテキスト同期は、システムの複雑性を大幅に増す。agentMemory.tsとagentMemorySnapshot.tsが独立モジュールとして存在すること自体が、この問題の難しさを物語っている。サブエージェントの起動にはLLM APIの追加呼び出しが伴い、コストとレイテンシも増大する。シングルエージェント設計のシンプルさを捨てる以上、少なくとも、そうしたコストに見合う精度向上が期待できる場面で採るべき設計だろう。
実態 -- 動くが、模擬実行のみ
ここで正直に記しておくべきことがある。claw-codeのPython実装は動作するが、実際のツール実行は行わない。
src/tools.pyのexecute_tool関数を見ると明らかだ。
def execute_tool(name: str, payload: str = '') -> ToolExecution:
module = get_tool(name)
if module is None:
return ToolExecution(name=name, source_hint='', payload=payload,
handled=False, message=f'Unknown mirrored tool: {name}')
action = f"Mirrored tool '{module.name}' from {module.source_hint} would handle payload {payload!r}."
return ToolExecution(name=module.name, source_hint=module.source_hint,
payload=payload, handled=True, message=action)
ツール名とペイロードを受け取り、「このツールがこのペイロードを処理するだろう」という文字列を返すのみ。実際のBashコマンド実行やファイル読み書きは行わない。query_engine.pyのsubmit_messageも同様に、プロンプトとマッチしたコマンド/ツールの情報を整形して返すだけで、LLM APIの呼び出しは発生しない。
ただし、ランタイムの骨格 -- ターン数管理、トークンバジェット制御、トランスクリプトのコンパクション、セッション永続化 -- は忠実に再現されている。これは欠陥ではなく意図的な設計だ。claw-codeの目的は「Claude Codeのクローン」ではなく「アーキテクチャパターンの学習可能な保存」にある。
claw-codeならではの知見 -- 既存記事との差別化
ツール登録やルーティングといったパターンは、エージェント設計の解説記事で広く扱われている。ここでは、claw-codeのソースコードから読み取れる、より具体的かつ独自性の高い知見に焦点を当てる。
ルーティングの割り切り: ルールベースで十分な領域
src/runtime.pyのPortRuntime.route_promptは、プロンプトをスラッシュ・ハイフン・スペースで分割してキーワードを抽出し、各ツール/コマンドの名前・説明文とのスコアリングでマッチングを行う。
ここで効いているのは、あえて学習ベースに寄せず、単純なルールベースで割り切っていることだ。LLMによる意図分類やembeddingベースの類似度検索ではなく、単純なキーワードマッチが採用されている。ただし「コマンドとツールの両方から最低1つずつ候補を返す」というヒューリスティックが組み込まれており、片方の候補が零になる偏りを防いでいる。
学習ベースのルーティングは曖昧な入力への対応力が高いが、LLM呼び出しのレイテンシとコストが加わる。ここでは、柔軟性より応答速度を取ったのだろう。ユーザーが明示的にツール名やコマンド名を入力する対話型CLI環境では、この割り切りは合理的だ。
ガードレールの具体的な数値設計
QueryEnginePort(src/query_engine.py)に設定されたデフォルト値は、実運用エージェントの設計判断として参考になる。
| パラメータ | デフォルト値 | 設計意図 |
|---|---|---|
max_turns |
8 | エージェントの暴走防止 |
max_budget_tokens |
2,000 | コスト上限の制御 |
compact_after_turns |
12 | メモリ使用量の抑制(直近12メッセージのみ保持) |
structured_retry_limit |
2 | 構造化出力失敗時のリトライ上限 |
特にcompact_after_turnsの実装は具体的だ。12ターンを超えると古いメッセージを切り捨て、直近12メッセージのみを保持する。これはLLMのコンテキストウィンドウの効率的な利用とメモリコストの制御を両立するための設計であり、「どこまでの履歴をLLMに渡すか」という実装判断の一つの回答になっている。
deny-list方式のパーミッションモデル
ToolPermissionContextによるパーミッション管理は、allow-list(許可リスト)ではなくdeny-list(拒否リスト)方式を採用している。これは「デフォルトで全ツールを利用可能とし、危険なものだけをブロックする」という設計思想だ。
runtime.pyの_infer_permission_denialsを見ると、ツール名にbashを含むものに対して自動的にパーミッション拒否が推論される。新しいツールの追加時にallow-listを更新し忘れるリスクを排除する一方、未知のツールがデフォルトで許可されるリスクを受け入れる判断であり、開発速度と安全性のバランスを取った設計といえる。
まとめ -- ハーネスエンジニアリングという視座
claw-codeが示したのは、現代のAIエージェントが「LLMのAPIを呼ぶだけ」の存在からいかに遠いか、ということだ。
Claude Codeの1,902ファイル、35ディレクトリ、184個のツール、207個のコマンドという規模(いずれもスナップショットデータに基づく観測値)は、エージェントシステムの複雑さを示している。そしてその複雑さの大部分は、LLMそのものではなく、LLMを安全に、効率的に、ユーザーフレンドリーに動作させるための「ハーネス」(制御装置)に費やされている。
本記事で抽出した3つの設計原則を改めて整理する。
- 単一検証に依存しない安全設計: BashToolの18モジュール多層防御。セキュリティコストは高いが、高リスク操作では正当化される
- LLMインターフェースと人間インターフェースの分離: prompt.ts/UI.tsxパターン。大規模ツール群では両者の独立した最適化が不可欠
- 専門化されたサブエージェントへの委任: AgentToolの5種ビルトインエージェント。特に計画と検証の構造的分離が信頼性を高める
重要なのは、優れたエージェントが優れたモデルだけから生まれるわけではない、という点である。実運用で差を生むのは、モデルの知能そのものよりも、その知能をどのような制約・分業・検証の上に載せるかという設計判断だ。
Jin氏はこの分野を「ハーネスエンジニアリング」と呼んでいる。馬具になぞらえた命名だが、この分野の本質をよく表している。どれほど優秀なLLMであっても、適切なハーネスがなければ暴走しうる。逆に、優れたハーネスがあればLLMの能力を最大限に引き出せる。
claw-codeは実行こそ模擬に留まるが、設計判断とそのトレードオフを具体的なコードで示した点に価値がある。エージェント設計において何が難しく、どこに工夫が必要なのかを具体的に示すリファレンスとして、きわめて示唆的なリファレンスである。
本記事で参照したリポジトリ: instructkr/claw-code
なお、観測された範囲では、Rust版の開発がdev/rustブランチで進行中とのことである。より高速でメモリ安全なハーネスランタイムの実現を目指しているとされる。