この記事は、連載「読まない技術」の第 5 回です。各回はファイルやスクリプトを一つ置けば完結します。連載の全体像と各回の一覧は序論にあります。
今回は、サブエージェントの話です。サブエージェントというのは、メインの会話を引き継がずに、別に立ち上がって働く AI のことです。そこへ仕事を投げると、何が起きているかは、終わるまで見えません。
ここからは応用編で、仕組みを作って渡す側の話になります。この連載は、AI の出力を読まないという話をしてきました。ただし、この回だけは逆のことを言います。サブエージェントのログだけは、一度、読んでください。
サブエージェントを起動して仕事を割り振り、成果を受け取るメイン側の AI を、この先「中央」と呼びます。指揮を執る側です。一般の用語ではオーケストレーターです。主流の設計では、サブエージェントは中央が管理するもので、人はログを見ません。それで正しくなるのは、読まなくても壊れないガードレールを置いてからです。ガードレールを置かずに見ていないのは、読まない技術ではなく、ただの放置です。
しかもサブエージェントは別のコンテキストで動く別の作業者です。メインの会話も、さっき決めた方針も、蓄積したメモリも、渡したプロンプト以外は届いていません。「言わなくても分かっているだろう」が全部消えた、今日入った作業者を、誰も見ていない。
理解したことは一文にできます。
サブエージェントは別の作業者であって、メインの続きではない。だから使い方を読ませてから働かせる。
CC BY 4.0
一度だけ、読む
直近でサブエージェントに任せたタスクを一つ選び、中央が何を指示し、何を受け取ったかから見てください。メインの画面で呼び出しを開くと、渡したプロンプトの全文と、返ってきた報告が読めます(Claude Code なら会話の詳細表示か、セッションログのファイルで)。渡した文章は、あなたの意図どおりですか。報告は、何をどこまでやったと言っていますか。あわせて、呼び出しの回数・使ったモデル・消費トークンの数字も見ておきます。こちらは使用量の画面で分かります。
目的は監視ではなく、どの事故が起きているかを知ってガードレールの場所を決めること。だから一度でいい。私が読んだときに見えたものを、メイン側の見え方/実際の対比で並べます。
- 繰り返し失敗。表示は「完了しました」。実際は同じエラーで十数回リトライした末の報告で、成果物は使えませんでした
- 蓄積の無視。私は「いつものルールで動くはず」と思っていました。実際はメモリも起動ルールも 1 行も渡っておらず、サブエージェントは数週間かけて塞いだ抜け穴をまた踏んでいました
- モデルの取り違え。私は軽い流し作業のつもりでしたが、モデル未指定は親の高価なモデルを継承していました
- トークンの大量消費。ある日、typingtube(YouTube の音楽動画でタイピング練習ができる Web サービスで、十数言語で提供しています)の翻訳の抜けを埋める作業を 1 言語 1 体で任せ、13 体を並列起動して約 173 万トークン。各エージェントが自分用の挿入スクリプトと検証スクリプトを書き直し、言語ごとの注意点を渡されないまま訳し、検証で見つかった誤訳を直しては投げ直す——本来一度で終わるはずの作業が、発見と修正の往復で膨らんでいました。私が気づいたのは、使用量の上限に当たったときでした
どの行も、読むまではメイン側の画面で「進んでいる」ように見えていました。
仕組みは一つ: 第 4 回と同じものを当てるだけ
新しい発明はありません。第 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 が許可内か、数が上限内か——それだけです。1 つ欠ければ起動自体が止まり、カタログが案内されます。
第 4 回と同じ一文がここでも言えます。hook は「読んだか」を判定していません。requires にあるのは仕事を単純作業に落とし込んだ人にしか作れないファイルで、その実在が「落とし込み済みか」の機械的な判定になっています。さっきの事故の一覧に、対応がひとつずつ付きます。
- 繰り返し失敗は、中央の受け入れテストが偽の「完了」を落とします
- 蓄積の無視は、
requiresのドキュメントが渡す文脈で消えます - モデルの取り違えは、必須指定が止めます
- トークンの大量消費は、上の三つがまとめて消します。ツールは中央のものを使い、知見は
requiresのドキュメントで渡り、誤りは中央の受け入れテストが一度で拾う——往復が起きる場所が残らないからです
もう一つ。止まったら中央に返して、人間に差し戻します。再試行させると、リトライの山というトークン消費問題を作り直すだけです。
そして、もう読まない
ガードレールが立ったら、私はログを読みません。渡すもの・モデル・数は起動時に確定していて、成果は中央の受け入れテストを通ったものしか受け取らないからです。読んだのは一度だけ。その一度がガードレールの場所を教えてくれて、ここから先はまた読まない側に戻れます。
注意: このガードレールで止まらないもの
機械的に確かめられるのは requires の実在・モデル・数だけで、用途名を名乗ることは止められません(中身の正しさは測れない)。それでもブロックは必ず中央の会話に表示され、すり抜けの形跡は人間が読める場所に残ります。ガードレールは完璧でなくていい。静かに通り抜けられなければ足ります。
検証手順: 消して、止まることを確かめる
前提
- 用途カタログを 1 枚書き、起動に割り込む hook を登録し終えていること
- カタログに用途が 1 つ以上あり、その用途の
requires(起動前に用意しておくファイルの一覧)が実在していること
所要時間: 10 分
手順
- あなたが、その用途の
requiresに並んでいるファイルを 1 つ退避します。⚠️ 消すのではなく退避です。後始末で戻します - 中央(メイン側の AI)に、その用途でサブエージェントを起動させます
合格条件(すべて満たすこと)
- サブエージェントが起動する前に止まる。⚠️ 起動してから失敗するのでは遅すぎます。トークンはもう使われています
- 止まった理由に、欠けているファイルの名前が出ている
- カタログの場所が案内されている
合格しなかったとき
- 起動してしまった —— hook が
requiresの実在を見ていないか、用途名とカタログの行が結び付いていません - 止まったが、欠けたファイル名が出ない —— 中央の AI は、何を用意すればよいか分からないまま止まります。判定のメッセージにファイル名を入れます
後始末
- 退避したファイルを戻し、同じ用途でもう一度起動させます。止まらずに走り出せば終わりです
CC BY 4.0 はここまで
次回は「ルールを読まない技術」。私は、守ってほしいことをルールに書くのをやめました。それでも、そのルールは破られていません。
連載「読まない技術」
- ← 前回: 第 4 回 スキルを使わない技術
- → 次回: 第 6 回 ルールを読まない技術
- 全回の一覧: 序論 AIの出力を、もうほとんど読んでいない