第6章: 良い道具・悪い道具 ── description・権限・並列呼び出し
あなたが新しくエージェントを自作する立場になったとしよう。 LLM とハーネスのあいだの契約は、前章で見たとおり JSON Schema で固まっている。 だから「ツールを定義するコード」は、書けば動く。
書けば動く。問題はそのあと だ。
- 渡したのに、LLM がぜんぜん呼んでくれない
- 呼んでくれるが、引数がいつも変
- 呼びすぎる ── 1 ファイル読むのにループを 8 回も回す
- ファイルを破壊した ── 「いま勝手に書き換えるとは思わなかった」
同じ契約 (第5章) の上で、なぜここまで体感が割れるのか。 答えは ── 派手なアルゴリズムではない ── 道具の設計判断 にある。 description の書き方、粒度の切り方、権限と副作用の線引き、そして並列呼び出しの扱い。 本章はこの 4 つを、Claude Code・Cursor・Aider などを横断して解剖する。
6.1 そもそも、なぜ “道具設計” がエージェントの賢さなのか
第1章で見たとおり、LLM は変わっていない。変わるのは外側だ。 そして外側のうち、LLM が直接 目にする ものは限られている。
- カタログ (ツールの一覧 = name + description + JSON Schema)
- システムプロンプト相当の指示 (第7章で詳述)
- 会話履歴と tool_result
このうち カタログ は、LLM が 「いま自分は何ができる存在なのか」 を理解する一次資料だ。 ここに並んでいる道具の名前と説明が、LLM の行動範囲そのものを決める。
LLM が手にできる「動詞」の解像度が、エージェントの賢さの解像度になる。
道具を増やすか減らすか・粒度を粗くするか細かくするか・description をどう書くか ── これらは LLM が次の一手を選ぶときの判断ノイズを直接動かす。 派手な機能より、ここの設計が体感を支配する。
このことは Anthropic の Engineering Blog の “Writing tools for agents” でも繰り返し強調されている。同じ LLM・同じ契約面の上で、道具の書き方を直しただけ で性能が大きく動くケースが現場では普通に起きる。
6.2 description は LLM への「求人票」
前章でも触れたが、本章で改めて正面から扱う。
ツール定義の description は、ハーネス側のドキュメントではない。
LLM が「いま自分はこの道具を呼ぶべきか」を判断する材料 だ。
読者を想定して書くなら、読者は LLM である。
良い description には、次の 4 つが書かれている。
| 要素 | 中身 |
|---|---|
| いつ呼ぶか | 「ユーザーがファイルの内容を見たいと言ったとき」「テストを走らせたいとき」 |
| いつ呼ばないか | 「コード片だけ見せたいときは Read ではなく直接出力する」 |
| 引数の意味 | 「path は絶対パス。相対パスはエラーになる」 |
| 副作用の明示 | 「このツールはファイルを 書き換える。実行前にユーザー確認が走ることがある」 |
悪い例と良い例を並べてみる。
悪い description の例{ "name": "read_file", "description": "ファイルを読む" }
- いつ呼ぶかが書かれていない
- 引数の決まりがない(相対パス? 絶対パス?)
- 副作用が読み取り専用かどうかも書いていない
良い description の例{ "name": "Read", "description": "ローカルファイルの中身を読み取って行番号付きで返す。読み取り専用(副作用なし)。ユーザーがファイルの中身を確認したいとき、または編集の前に現状把握したいときに使う。path は必ず絶対パス。" }
- 呼ぶ場面が言語化されている
- 「読み取り専用」が明記され、LLM は安心して呼べる
- 引数の形式(絶対パス)が明記され、ミスが減る
description は、LLM への「求人票」と思うと書きやすい。 「この職にはどんなときに就いてほしいか、引き受けたら何をするか、何はしないか」を、応募者 (LLM) が読んで判断する。 求人票が雑だと応募が来ないか、来ても噛み合わない人が来る ── ツールの呼ばれ方もそれと同じだ。
実務メモdescription は 将来の自分への申し送り でもある。半年後にツールを増やしたい人 (or LLM 自身) が、既存ツールとどう棲み分けるかを判断する材料になる。「
Editは 1 箇所だけ置換」「Writeはファイル全体を書き換え」のように、互いの境界を description で示す と、似たツールの誤発火が劇的に減る。
6.3 道具の粒度問題 ── 大きすぎる道具・小さすぎる道具
道具の名前と引数の切り方は、粒度の選択 でもある。 両極端から見てみよう。
極端 1: 大きすぎる道具 (do_everything)
「ファイルを開いて、編集して、テストを流して、結果を要約する」という巨大ツール 1 個。 contract としては動くが、LLM 視点では地獄だ。
- description に書くべき内容が増えすぎて、いつ呼ぶかの判断ができない
- 失敗したとき、どの段階で失敗したか が tool_result から読み取れない
- 引数のスキーマが複雑になり、LLM が間違いやすくなる
極端 2: 小さすぎる道具 (read_one_line)
「ファイルから 1 行だけ読む」というミニツール 1 個。 これも contract としては動くが、
- 23 行のファイルを読むのに 23 回ループを回す羽目になる
- ハーネスの往復回数が爆増し、コンテキストと時間を食う
- LLM が「全体を把握したい」気持ちと噛み合わない
良い道具の粒度は、LLM が「1 回の決断」で完結したい単位 に合っている。 「1 ファイルを読む」「1 ファイルの 1 箇所を置換する」「1 つのテストを走らせる」── これくらいが現代のエージェントが落ち着いた粒度。
たとえば Claude Code は Read / Edit / Write / Grep / Glob / Bash の 6 つに代表的な動詞を切っている。Cursor の Agent モードもほぼ同じ粒度。Aider はやや独自で、ファイル単位の差分提案 (/add / /edit) を中心に据えている。粒度の選び方は各プロダクトの設計判断だが、LLM が 1 ステップで完結したい単位 に合わせる、という勘所はどこも共通だ。
6.4 権限と副作用 ── read-only / write / destructive の線引き
道具を切ったあと、次に決めるのは 副作用の度合い だ。 契約面 (第5章) だけ見ると、すべてのツールは平等な「JSON ブロック → 関数呼び出し」だが、何が起きるか はぜんぜん違う。
| 副作用クラス | 例 | リスク |
|---|---|---|
| read-only | Read, Grep, Glob, WebFetch | ほぼゼロ。ローカル状態を変えない |
| write | Edit, Write | ファイル内容が変わる。git で復元可能 |
| destructive | Bash(rm -rf ...), Bash(git push --force) | 不可逆。本当に壊れる |
ツールカタログにこの分類を メタデータとして 載せておくと、ハーネス側で
- read-only → 無条件で実行
- write → ユーザー確認を 1 回挟む
- destructive → そもそも実行を拒否、または明示的な許可リストにあるときだけ
という単純なルールが書ける。ツールごとの副作用クラスが decl で見える からこそ、人間が制御しやすい。
サンドボックス (sandbox)ツールの副作用が、ホスト環境に届かないように 隔離された実行環境 で道具を動かす仕組み。Docker コンテナ、リモート VM、git worktree、
chroot環境などが使われる。Devin や Codex 系の「ブラウザ内 IDE」型エージェントは強めのサンドボックスを前提に設計されている。
承認フロー / 権限モードハーネスが「このツール呼び出しを実行していいか?」をユーザーに尋ねる仕組み。Claude Code には
default/acceptEdits/bypassPermissionsのような モード があり、現場の信頼度に応じてユーザーが切り替える。Cursor も「Auto-run」を on/off できる。要は どこまで自動承認するかのつまみ だ。
権限の線引きは「LLM が悪さをしないように」だけのものではない。 LLM が安心して動くため のものでもある。 「destructive な道具は permitted list にあるときだけ」というガードレールがあれば、LLM は躊躇せず候補に挙げ、ハーネス側で止めればいい。 権限はブレーキだが、ブレーキのある車のほうが速く走れる ── という関係に近い。
6.5 並列ツール呼び出しは「誰の責任か」
第5章で見たとおり、LLM は 1 応答に複数のツール呼び出しブロックを並べて返せて、ハーネスはそれをまとめて同時実行する。 契約面・しくみそのものは第5章の本拠地に譲って、本章で考えるのは 道具設計の側でどう振る舞うか だ。
ここで言いたいのは三つだけ。
- 並列するかどうかの判断は LLM 側の責任。ハーネスは「並べて来たら並列で走らせる」だけで、自分から並列化はしない。だから description やシステムプロンプトに「独立な読み取りはなるべく並列で呼んでよい」と書いておくだけで、応答時間が目に見えて縮むことがある
- 描画速度に直接効く。3 ファイルの読み取りが直列なら 3 ターン、並列なら 1 ターン。ターン数はそのままユーザー体験の “もたつき” になる
- 順序依存があるものを並列にすると壊れる。判別の合言葉は「次の道具の引数が前の道具の結果に依存しているか?」── 依存していれば直列(
Read(config.json)の中身を見てから次のRead、Bash("pnpm test")の結果を見てからEditなど)。現代の主要モデルはこのへんを言わなくても守ってくれるが、ハーネスは “誤って並列にされた順序依存” を救済できないので、危ない道具(EditやBash)は 副作用クラスの設計 でも保険をかけておく
実務メモプロバイダによって並列ツール呼び出しのデフォルト挙動が違う。Anthropic は parallel tool use が標準的に効く一方、OpenAI には
parallel_tool_calls: true/falseのような切替フラグがある(時期によって挙動が動く)。「並列で呼ばれないな」と思ったら、API 設定や SDK のオプションを確認するとよい。
6.6 プロダクトごとの動詞の切り方
道具セットそのものは、プロダクトごとにかなり違う。
たとえば Claude Code は Read / Edit / Write / Grep / Glob / Bash のように動詞を細かく切り、Bash を逃げ道として残す。Cursor はエディタ統合の差分提案を主役に据える。Devin は強サンドボックス前提で「PC を丸ごと触れる」道具群を開放する。
並べると、契約面(function calling)は同じでも、動詞の切り方とサンドボックスの強さで体感は全く別物 になる。プロダクトごとの道具セットや権限モデルの詳しい横並び比較は 付録A に集約してあるので、評価軸として使ってほしい。
エージェントのレビュー記事を読むときの裏ワザ:
「機能が多い・速い・賢い」のような感想を読み飛ばして、そのプロダクトが LLM に渡している道具の名前と粒度 に注目すると、設計の癖が手に取るように分かる。
名前は同じでも、たとえば Edit が「ファイル全体置換」なのか「1 箇所置換」なのか、Bash がサンドボックス内かホスト直撃か、で体感は全く違う。
6.7 道具設計が決めるもの ── まとめ
道具設計は、次の 4 つを同時に決める。
- LLM の判断ノイズ ── 名詞を選ぶだけで済むか、文字列を組み立てるか
- 出力の安定性 ── 後続ツールが結果を再利用しやすいか
- 安全制御の解像度 ── ツール単位 or コマンド文字列で線が引けるか
- 並列性 ── 独立な動作をひとまとめに表現できるか
道具のレイヤでも、結局は 設計判断の総量がエージェントの体感を決める。 description の一文、粒度の一つの線、権限クラスの一段階、並列を勧めるかどうかの一行 ── どれも単独では地味だが、足し合わせた結果が「呼ばれ方」「速さ」「安全性」のすべてを動かす。
次章からは 第Ⅲ部 文脈とメモリ に入る。
LLM の机の広さ(コンテキストウィンドウ)と、CLAUDE.md / AGENTS.md / .cursorrules のような 外部記憶 をどう束ねるか ── 道具と並ぶもう一つの大きな設計レイヤだ。
この章の振り返り
- 契約面(第5章)が同じでも、道具設計 でエージェントの体感は別物になる
- description は LLM への 求人票。「いつ呼ぶか・呼ばないか・引数・副作用」を書く
- 粒度は LLM が 1 回の決断で完結したい単位 に合わせる。大きすぎても小さすぎても効率が落ちる
- 副作用は read-only / write / destructive で分類し、サンドボックスと承認フローでガードする
- 並列ツール呼び出し の判断は LLM 側の責任。順序依存があれば直列、独立なら並列 ── 描画速度に直接効く
- 動詞の切り方やサンドボックスの強さで、同じ契約の上でも体感は別物になる(プロダクト別の詳細は付録A 参照)
この章で読めるようになるツイート / ブログ
- 「Anthropic の Writing tools for agents、結局なんでそんなに description を磨けって言うんだ?」 → description は LLM への求人票だから。判断ノイズと呼び出し率を直接動かす、と読める
- 「Devin と Claude Code、Bash の扱いがぜんぜん違うのはなぜ?」 → Devin は強サンドボックス前提で destructive まで開放、Claude Code はホスト直撃を前提に Bash に厳しい承認フロー ── という設計差として読める
- 「parallel tool calls を有効にしたらエージェントが体感 2 倍速くなった」 → 独立な道具を 1 応答にまとめて並べているだけ。順序依存がない場面に効く設計判断だ、と読める
次章は文脈とメモリ。 LLM の机の広さ (コンテキストウィンドウ) と、何をどこまで覚えさせるかという、ハーネス設計のもう一つの主要レイヤに進もう。