この記事は、連載「読まない技術」の第 5 回です。うまくいかない症状と、その対処を一つずつ並べています。各回はファイルやスクリプトを一つ置けば完結します。その仕組みがなぜ要るのかは、置いたあとに解説を読めば分かります。連載の全体像と各回の一覧は序論にあります。
今回は、サブエージェントの話です。サブエージェントというのは、メインのセッションを引き継がずに、別に立ち上がって働くAIのことです。メインのAIとは別の作業者なので、メインのセッションでさっき決めた方針も、蓄積したメモリも受け取りません。受け取るのは、プロンプトに書いた分だけです。サブエージェントに仕事を任せると、何が起きているかは、終わるまでには見えません。
この連載では、AIの出力を読まない話をしてきました。
ただし、この回でだけ、は逆のことを言います。
サブエージェントのログだけは、一度、読んでください。
仕組みを置かずにサブエージェントの仕事を見ないでいるのは、読まない技術とは別の、ただの放置です。今日入ったばかりの新人の作業者に仕事を任せて、誰も様子を見ていないのと同じです。この新人は、が言わなくても分かっているだろうと思っていたことを、何も知りません。
サブエージェントを起動して仕事を割り振り、成果を受け取るメイン側のAIを、この先「メインエージェント」と呼びます。一般の用語ではオーケストレーターです。
サブエージェントに任せた仕事で、メインのセッションで決めたことや、メモリに溜めた注意点を、サブエージェントが守らず、対策済みの失敗を繰り返していた。このとき、あなたなら次のどちらを選びますか。
- サブエージェントのログを、毎回読んで確かめる
- 渡すものがそろうまで、サブエージェントを起動させない
答えは、起動させないほうです。サブエージェントが守らなかったのは、守るべきことが、サブエージェントに届いていなかったからです。サブエージェントは、起動のときにメインエージェントが書いたプロンプトと、指示ファイルなどを受け取ります。メインのセッションで決めたことも、メモリも、メインエージェントが読んだファイルも、そのプロンプトに書かれていなければ、サブエージェントには届きません。ログを毎回読んでも、届いていなかったと分かるのは、サブエージェントが欠けたまま走り終え、トークンも使い終えたあとです。起動する前に止めれば、サブエージェントが、渡すものが欠けたまま走り出すことはありません。
理解したことは一文にできます。
サブエージェントは別の作業者であって、メインの続きではない。メインで決めたことも溜めた注意点も、渡したものしか届かない。だから、渡すものがそろうまで起動させない。
CC BY 4.0
一度だけ、読む
直近でサブエージェントに任せた仕事を一つ選び、メインエージェントが何を指示し、何を受け取ったかを見てください。
サブエージェントのログには、メインエージェントが渡したプロンプトの全文と、返ってきた報告が残っています。
メインエージェントが渡したプロンプトは、あなたの意図どおりですか。
報告には、何をどこまでやったと書いてありますか。
ログを読む目的は、どの事故が起きているかを知り、仕組みを置く場所を決めることです。場所を決めるためなら、読むのは一度で足ります。が読んだときは、事故が四つ見えました。
一つ目は、繰り返し失敗です。報告は「完了しました」でした。実際には、サブエージェントは同じエラーで十数回リトライしていて、成果は使うことができませんでした。
二つ目は、蓄積が届かないことです。は「いつものルールで動くはず」と思っていました。実際には、メモリも、メインのセッションで読み込ませたルールも、サブエージェントには 1 行も渡っていませんでした。サブエージェントは、が数週間かけて対策した失敗を、また繰り返していました。
三つ目は、モデルの取り違えです。は軽い流し作業のつもりでした。実際には、メインエージェントがモデルを指定していなかったので、サブエージェントはメインエージェントと同じ高価なモデルで走っていました。
四つ目は、トークンの大量消費です。ある日、typingtube(YouTube の音楽動画でタイピング練習ができる Web サービスで、十数言語で提供しています)の翻訳の抜けを埋める仕事を、1 言語につき 1 体のサブエージェントに任せました。メインエージェントは 13 体を並列で起動し、報告された合計は約 173 万トークンでした。各サブエージェントは、自分用の挿入スクリプトと検証スクリプトを書き直し、言語ごとの注意点を渡されないまま訳していました。検証で誤訳が見つかるたびに、直しては、また検証に回していました。一度で終わるはずの仕事が、誤訳の発見と修正の往復で膨らんでいたのです。が気づいたのは、使用量の上限に当たったときでした。
どの事故も、がログを読むまでは、メインの画面で「進んでいる」ように見えていました。
なぜ、サブエージェントはメインの続きではないのか
サブエージェントに渡らないものは、公式のドキュメントに並んでいます。メインのセッションの履歴、メインエージェントが呼んだスキル、メインエージェントが読んだファイル、そして自動で溜まるメモリです。サブエージェントが起動のときに受け取るのは、メインエージェントが書いたプロンプトと、指示ファイルと、サブエージェント自身のシステムプロンプトや環境の情報です。が踏んだ「蓄積が届かない」事故は、仕様どおりの動きでした。メインエージェントが読んだファイルが渡らないということは、サブエージェントが同じファイルを自分で読み直す、ということでもあります。13 体が挿入と検証のスクリプトを別々に書き直したのは、メインエージェントが書いたスクリプトのことが、どのサブエージェントのプロンプトにも 1 行も書かれていなかったからです。
モデルの扱いも、同じページに書いてあります。メインエージェントが起動のときにモデルを指定しなければ、サブエージェントはメインエージェントと同じモデルで走ります。軽い流し作業のつもりで任せた仕事がメインエージェントのモデルで動いていたのは、メインエージェントがモデルを指定しなかったからです。
同じページによれば、サブエージェントが読み書きした大量の出力は、サブエージェントのコンテキストに残り、メインの会話に戻ってくるのは要約だけです。の手元では、メインエージェントに戻ってきたのは、サブエージェントの最後のメッセージ(報告)と、消費トークンの数字でした。手元に残っていた 102 体ぶんのログをが数えると、1 体のログの大きさは中央値で 22 万バイト、返ってきた報告の長さは中央値で 2,570 字でした。メインエージェントが見ているのは、サブエージェントが読み書きした量の 1〜2% にあたります。一度だけ読むというのは、残りの 98% を一度だけ見る、という意味です。
上の 173 万トークンも、完了した 10 体が報告した、この消費トークンの数字の合計でした。1 体が報告する数字は、その 1 体の最後の一往復の大きさです。同じ日に走った 19 体ぶんのログで、最初の一往復から最後の一往復までをが全部足し直すと、2 億トークンを超えました。その大半は、サブエージェントが一往復のたびに、それまでのやり取りを最初から読み直したぶんです。AIを呼び出すAPIは、前のやり取りを覚えていない作りで、呼び出すたびに会話の履歴を全部送ります。
十数回のリトライは、報告には書かれていませんでした。報告が「完了しました」になりやすい理由は、Claude Code のドキュメントにも書いてあります。AIは仕事が終わったように見えたところで止まるという説明です。同じページには、成功の主張より証拠を見せさせよ、仕事をする側と採点する側を分けよ、とも書いてあります。受け入れテスト(サブエージェントの成果をメインエージェントの側で判定するスクリプト)を、仕事をしたサブエージェントとは別の側に置くのは、このためです。
仕組みは一つ: 用意しておくファイルがそろうまで、起動させない
は、第 4 回で置いた、手順を踏んだときにだけ作られるファイルがあるかを確かめるhookを、サブエージェントを起動する入口にも当てました。そのために、用途カタログを 1 枚書きました。用途カタログは、サブエージェントに任せてよい仕事と、起動前に用意しておくファイルの一覧です。
# subagent_missions.yml — サブエージェントを起動してよい用途のカタログ(手元のコードを短くしたもの)
missions:
i18n_translation:
description: fill in the translations (1 agent = 1 language)
requires: # 起動前に実在しなければ hook が起動を止める
- scripts/i18n_ledger.py # 作業の一覧(渡す唯一の入力)
- scripts/i18n_apply.py # 成果の差し込みはメインエージェントの側で行う
- scripts/i18n_verify.py # 受け入れテストもメインエージェントの側で行う
- docs/i18n_notes.md # 言語別の注意点(渡す文脈)
model: [sonnet, haiku] # 未指定・許可外モデルは通さない
max_parallel: 5
max_total: 20
このhookが確かめるのは、メインエージェントが起動のときに宣言した用途がカタログにあるか、requires のファイルが実在するか、model が許可したモデルか、起動する数が上限内か、の四つです。一つでも満たさなければ、hookはサブエージェントの起動を止め、メインエージェントにカタログの場所を案内します。止められたメインエージェントは、案内を読んでから、起動をやり直します。
requires についてhookが確かめているのは、ファイルが実在するかだけで、メインエージェントがそれを読んだかは見ていません。requires に並ぶのは、仕事を単純作業に分解し終えたときにだけ作ることのできるファイルです。だから、ファイルが実在すれば、仕事は単純作業に分解済みだと、hookが判定することができます。
最初の節で見えた事故のうち、繰り返し失敗では、メインエージェントの受け入れテストが、偽の「完了しました」を不合格にします。蓄積が届かない事故を防ぐのは、メインエージェントがサブエージェントに渡す requires のドキュメントです。モデルの取り違えは、model の指定を必須にしたhookが止めます。
トークンの大量消費を防ぐのは、上の三つの組み合わせです。挿入と検証は、メインエージェントが自分のスクリプトで行います。言語ごとの注意点は requires のドキュメントでサブエージェントに渡り、誤りはメインエージェントの受け入れテストが一度で拾います。だから、発見と修正を往復する場所が、サブエージェントの側に残りません。
カタログに書いた max_parallel: 5 と max_total: 20 は、Claude Code の上限とは別のものです。Claude Code の公式のドキュメントによると、既定の上限は、同時に走るサブエージェントが 20 体まで、入れ子の深さがメインの会話から数えて 3 階層まで、です。カタログの数字は、その上限の内側で、が決めました。数を絞るのは、サブエージェントが 1 体増えるたびに、メインエージェントが渡すプロンプトとドキュメントも 1 体ぶん増えるからです。
もう一つ、が決めていることがあります。サブエージェントが止まったら、仕事をメインエージェントに返し、メインエージェントから人に差し戻します。サブエージェントは、人に問い返すことができません。Claude Code が、質問のためのツールを、どのサブエージェントからも外しているからです。だから、サブエージェントが止まって人に聞く流れは、メインエージェントを経由する形で書きます。止まったサブエージェントにメインエージェントがリトライさせると、最初の節の繰り返し失敗とトークンの大量消費を、もう一度起こすだけです。
そして、もう読まない
仕組みを置いたあと、はログを読みません。渡すもの・モデル・起動する数は起動のときに確定していて、メインエージェントが受け取る成果は、受け入れテストを通ったものだけだからです。その受け入れテストが確かめているのは、変数の記号が揃っているか、タグが壊れていないか、空の値が残っていないか、項目の数が合っているか、という構造だけです。訳が正しいかは見ていません。がログを読んだのは、一度だけでした。
検証手順: 消して、止まることを確かめる
前提
- 用途カタログを 1 枚書き、サブエージェントを起動する入口にhookを登録し終えていること
- カタログに用途が 1 つ以上あり、その用途の
requires(起動前に用意しておくファイルの一覧)に並ぶファイルが、すべて実在していること
所要時間: 10 分
手順
- あなたが、その用途の
requiresに並んでいるファイルを 1 つ、別の場所へ退避して、元の場所から消します。退避したファイルは、後始末で戻します - メインエージェントに、その用途でサブエージェントを起動させます
合格条件(すべて満たすこと)
- サブエージェントが起動する前に止まっている(起動してから失敗したのでは、サブエージェントがトークンをもう使っています)
- 止まった理由に、欠けているファイルの名前が出ている
- カタログの場所が案内されている
合格しなかったとき
- サブエージェントが起動してしまった —— hookが
requiresのファイルの実在を確かめていないか、用途名とカタログの行が結び付いていません - 止まったが、欠けたファイル名が出ない —— メインエージェントは、何を用意すればよいか分からないまま止まります。あなたが、hookが止めるときのメッセージに、欠けたファイル名を入れます
後始末
- あなたが、退避したファイルを戻し、メインエージェントに同じ用途でもう一度サブエージェントを起動させます。サブエージェントが止まらずに走り出せば、検証は終わりです
CC BY 4.0 はここまで
次回は「ルールを読まない技術」。は、守ってほしいことをルールに書くのをやめました。 それでも、そのルールは破られていません。
連載「読まない技術」
- ← 前回: 第 4 回 スキルを使わない技術
- → 次回: 第 6 回 ルールを読まない技術
- 全回の一覧: 序論 AIの出力を、もうほとんど読んでいない