Claude Codeは実際どう動いているのか?自作して仕組みを理解する
概要
Claude Codeに代表されるコーディングエージェントの内部構造を、モデル・ツール・メモリ・コンテキスト・ガードレールという5つの構成要素に分解して解説する回。LLM自体は「次のトークンを予測するだけ」であり、実際にツールを実行しループを制御しているのは周囲を包む「エージェントハーネス(ソフトウェア)」であることが繰り返し強調される。最後にPythonで約300行のミニ版Claude Codeを実装し、ファイル読み書き・bash実行・承認プロンプト・モデル切替まで動く様子とコードを実演する。
主なポイント
- エージェント=「ループするLLM」+「ハーネス」。ハーネスがループ・ツール実装・権限システムを担い、モデルは次の行動を提案するだけ。
- LLMはステートレスで、記憶も目的も持たない。過去のやり取りを覚えているように見えるのは、会話履歴をコンテキストに毎回詰め直しているから。
- ツール呼び出しの実体は、モデルが
{"type":"tool_call","name":"read_file","args":{...}}のような構造化テキストを出力し、ハーネスがそれをパースして実際の関数を実行し、結果をコンテキストへ戻すこと。 - 「ツール定義」と「ツール実装」は別物。モデルが見るのは名前・説明・入力スキーマだけの“メニュー”であり、調理(実行)はハーネス側が行う。
- メモリは魔法ではなくただのファイル。CLAUDE.mdは常時プロンプトに注入され、memoryフォルダやスキル(Markdown)は必要時にツール経由で読み込まれる。
- コンテキストウィンドウの内訳はシステムプロンプト/ツール定義/スキル定義/メモリ/会話履歴/ツール結果。ツール定義と会話履歴・ツール結果が特に大きく膨らむ。
- 使用率が80〜90%を超えるとモデルの性能は落ちる。何を入れるかを設計する「コンテキストエンジニアリング」が実質的な性能要因。
- ツールを大量に載せると誤ったツールを選びやすくなる。数千のツールより、狙いを絞った5〜6個の方が精度が高い。
- ガードレールはモデルではなくソフトウェア側のif文。だからモデルはこれを上書きできない。読み取り専用ツールは自動許可、破壊的コマンドは人間の承認待ちにする設計が一般的。
- 1回のユーザー指示に対しモデルは20〜40回走ることもある。「ツール呼び出しをやめてテキストだけ返した」=終了シグナルとしてループを抜ける。
- 暴走防止として1ターンあたりのツール呼び出し回数に上限(デモでは25回)を設ける。
- 最小構成のエージェントは15行程度で書ける。デモ版でもモデル切替(/model)、履歴クリア(/clear)、/helpまで約300行で実装可能。
実践に使えること
- コンテキストは有限資源として扱う。長い作業では区切りで履歴をクリアし、必要な情報だけを再投入する。使用率が高いまま作業を続けない。
- MCPサーバーやプラグインを「とりあえず全部入れる」のをやめる。ツール定義はコンテキストを食い、選択精度も落とすので、タスクに必要なものだけ有効化する。
- 常に守らせたい規約はCLAUDE.mdに書く(常時注入される)。逆に、たまにしか要らない詳細は別ファイルに切り出し、必要な時だけ読ませてコンテキストを節約する。
- エージェントが「覚えていない」時は記憶力の問題ではなくコンテキスト設計の問題と考え、ファイル化+読み込み経路を用意する。
- 自作エージェントを組むなら、model / context / memory / tools / guardrails / agent(loop) とファイルを分ける構成が理解しやすく拡張しやすい。
- 安全側の設計として、読み取り系は自動実行・書き込みと破壊的コマンドは承認必須・ツール呼び出し回数に上限、という3点をハーネス側に実装する。