私はAIの出力を、ほとんど読まなくなりました。テスト結果も、AIがメモリに書き足す知見も、サブエージェントの作業ログもです。AI自身も、私と同じように、自分の出力を読まずに済む形で作業しています。出発点は、序論で書いた、ルールは足すほど薄まるという問題です。ここまでの 12 回は、その一点への対処でした。ルールが薄まるのは、Claude Codeのベストプラクティスの言い方では、ファイルが長すぎて、ルールが埋もれるからです。連載「読まない技術」は、その状態を仕組み一つずつで作ってきた記録で、この記事が最終回です。各回の仕組みは序論の一覧からたどることができるので、初めての方はそちらからどうぞ。

方針を検討するとき以外、私がAIに入力するのは、ほぼ次の 2 文だけです。

次の作業を進めてください

ここまで不足点はないですか?確認して不足点がなければ次のセッションに引き継いでください

flowchart TB
  S(["1 文目「次の作業を進めてください」"]) --> W

  subgraph W["AI の作業中 — 人間は読まされない・口を挟まない(第11回)"]
    direction LR
    a1["コマンドを打つ"] --> g1["入口の hook が止めて案内する<br/>第4回"]
    a2["テストを走らせる"] --> g2["ラッパーが失敗と件数だけ返す<br/>自動テスト = ルールはここで落ちる<br/>第1回・第3回・第6回"]
    a3["サブエージェントを起動する"] --> g3["用途カタログを通ったものだけ動く<br/>第5回"]
    a4["同じ失敗を繰り返しそうになる"] --> g4["その瞬間に方針が差し込まれる<br/>第8回"]
    a5["メモリを保存する"] --> g5["保存の直後に差分を突きつける<br/>第2回・第7回"]
  end

  W --> Z

  subgraph Z["終わり際"]
    direction TB
    F["報告は読まず、覚えている症状だけを見る<br/>第9回"] --> V["コマンドの数字を写していなければ hook が出す<br/>第10回"] --> Q(["2 文目「ここまで不足点はないですか?」<br/>第12回"])
  end

  Z --> N(["次のセッションへ<br/>人間が読むのは「不足なし」か「引き継ぎ完了」だけ"])

  classDef human fill:#FFF3E0,stroke:#E38B2C,stroke-width:1.5px,color:#3A2A14
  classDef ai fill:#F7F7F7,stroke:#9E9E9E,color:#333
  classDef part fill:#E6F0FB,stroke:#3B7DC4,stroke-width:1.5px,color:#14304F
  class S,F,Q,N human
  class a1,a2,a3,a4,a5 ai
  class g1,g2,g3,g4,g5,V part
  style W fill:#FCFCFC,stroke:#C8C8C8,color:#555
  style Z fill:#FCFCFC,stroke:#C8C8C8,color:#555

仕組みの一つひとつは、置くだけの小さなものです。それらを組み合わせると、複数のセッションとサブエージェントが走る作業の全体が、この 2 文だけで進みます。

この間に私が読むのは、最後の「不足なし」か「引き継ぎ完了」だけです。

そして、この 2 文の間、私はAIが作業を終えるのを待っているだけです。

この 2 文を省くと、仕組みをどれだけ重ねても、AIが作るものの品質は落ちます。1 文目は、この待つことの約束になっています(第 11 回)。2 文目は、どの仕組みでも止まらなかった不足を、最後にAI自身に探させる問いです(第 12 回)。作業の不足は、AIが外から問われたときにだけ出るからです。仕組みが止めることのできる問題は、検知できる形をしたものに限られます。そのため、この 2 文の代わりを仕組みで作ることはできません。

この 2 文で私が開発しているのが、typingtube というWebサービスです。YouTubeの音楽動画でタイピング練習ができるサービスです。私が個人で運営しているもので、本番で動いています。この連載に出てきた数字は、26,147 行のテストの生ログも、サブエージェント 13 体を並列で起動した日の 173 万トークンも、全部このサービスの開発で出たものです。

最後に白状します。

必要なところは、全部読みました

この連載で、私は同じ嘘を何度もつきました。「私は読んだことがありません」「読んでいません」。

嘘です。正確に言います。必要なところは、全部読みました。テストの生ログも、サブエージェントの作業ログも、AIの途中経過の出力も、必要になったときに、必要なだけ、読みたいだけ読みました。

証拠は各回の仕組みの中にあります。ラッパー(本来のコマンドを包んで代わりに実行するスクリプト)がどの行をgrepして返すか。変異注入(実装を 1 か所だけわざと壊して、合格のまま通るテストを探すこと)で、壊す行として「当たるはずの行」を選ぶ基準。用途カタログ(サブエージェントに任せてよい仕事と、起動前に用意しておくファイルの一覧)の requires に並べる、メインエージェント(サブエージェントを指揮する側のAI)のツール。自動テストが空回りしないように併置した、走査対象の件数の下限。方針をメモリの保存の後に差し込むという位置。私は、ラッパーの出力の形を決めるために、26,147 行のテストの生ログを最後まで読みました。壊す場所が分かったのも、期待値が実装の返す値を貼っただけになったテスト(実装の写し)を読んだからです。サブエージェント 13 体がトークンを大量に消費した日も、1 体分のログを読んだから、ガードレール(読まなくても壊れない構造)を置く場所が決まりました。読まない技術を仕組みにする作業は、ほとんどが読む作業でした。

では、何が本当だったのか

「読まされていない」は本当で、「読んでいない」は嘘でした。ただ、この連載で言いたかったのは、誰が読んだかよりも、読んで何をしたかのほうです。振り返ると、私が各回でしていたことは同じでした。うまくいかない問題を一つ見つけ、なぜうまくいかないのかを理解し、その理解に合わせて簡単な仕組みを一つ置き、その仕組みが働くかどうかを、わざと失敗させて確かめることです。それだけを 12 回繰り返しました。

そうやって理解を重ねていくと、別々に見えていた問題にも、共通点があることが分かってきます。回をまたいで何度も同じ言葉が出てきたのは、そのためです。

  • 「ルールは読まれたときだけ効く。足すほど薄まる」——テスト結果も、メモリも、スキルの説明文も、指示ファイルの禁止事項も、全部この一つの問題でした
  • 「止めた理由は、AIが次の操作を決める前に届く。読んでいなければ動けない形にする」——テストのラッパーの案内(第 1 回)、pre-commit hookの案内(第 4 回)、サブエージェントの用途カタログ(第 5 回)、リトライの瞬間の方針(第 8 回)は、同じ仕組みの置き場所違いです
  • 「読みに行ったかは測れても、効いたかは測れない。読まなければ作れないものの実在だけを見る」——第 5 回で、用意しておくファイルがそろうまでサブエージェントを起動させなかったのは、第 4 回の、手順を踏んだ形跡(生成物)が無ければコミットを止めるhookと同じ形です
  • 「方針は、差し込む瞬間で効き方が決まる」——第 2 回でメモリの保存の後に差し込んだ方針を、第 8 回では、問題を検知した直後に差し込む形へ一般化しました
  • 「AIは仕事が終わったように見えたところで止まる。報告は止まったことしか教えない」——サブエージェントの報告も、引き継ぎ文も、完了報告も、AIが書いた文面を読まずに、報告の外で確かめるという同じ扱いで済みました

共通点が見つかると、置く仕組みは小さくなります。新しい問題が出ても、すでにある仕組みの置き場所を一つ増やせば済むからです。第 11 回で新しく置くものが無かったのは、人間が口を挟みたくなる場面で、そこまでの回で置いた仕組みが、人間の代わりに指摘を返していたからです。

なぜ、ルールを書き足すだけでは足りないのか

書き足したルールだけでは足りない理由を、ここまでの回で四つ見てきました。

一つ目は、量です。序論で見たとおり、報告書にキーワードを入れる指示を最大 500 個まで並べた測定では、指示を増やすほど守られる割合が落ち、500 個のときは、最良のモデルでも 68% でした。テスト結果も、メモリの索引も、スキルの一覧も、指示ファイルと同じコンテキスト(AIの作業記憶)に入ります。第 1 回で見たとおり、Claude Codeのベストプラクティスは、コンテキストが埋まりかけると、AIが前の指示を「忘れ」はじめたり、誤りを増やしたりすることがある、と書いています。

二つ目は、AIが既に知っている振る舞いです。第 8 回で見たとおり、AIが学習するのは使われる前の段階だけで、指示ファイルを読ませても、方針はAIの中に書き込まれず、コンテキストに並ぶ行の 1 つになるだけです。一方で、Claude Codeのベストプラクティスは、指示ファイルに書かないものとして、「AI が既に知っている標準的な言語の慣習」を挙げています。AIが既に知っている慣習は、指示ファイルに書かなくても、AIの振る舞いに出てきます。第 1 回では、「ラッパーを使うこと」と指示ファイルに書いても、AIは rails test を打ちました。

三つ目は、いま進んでいるタスクの目的です。公式のプロンプト指針は、Claude はテストを通すことに集中しすぎて、より一般的な解を犠牲にすることがあると書いています。研究の側でこれに当たる語は specification gaming で、目的の字面の仕様を満たすが、意図した結果を達成しない振る舞いと定義されています。第 3 回で見た写しのテストが満たしていたのは、「テストが通る」という字面の仕様でした。第 2 回では、保存を止めて方針を読ませたhookを、AIは語を言い換えるだけで素通りしました。「簡潔に書け」も「統合しろ」も、言葉の上でなら満たすことができます。

四つ目は、それぞれが、いつ、どこに届くかです。第 6 回で見たとおり、指示ファイルとメモリは、システムプロンプトの後に、ユーザーメッセージとして届き、セッションの途中で私が打つ一言も、同じユーザーメッセージとして届きます。このことを説明している公式ドキュメントが続けて書いているのは、AIは読んで従おうとするが厳密な遵守の保証は無いということです。第 11 回で見たとおり、hookが返す理由は、AIが操作をしようとしたその場か、操作が済んだ直後に届きます。どちらも、AIが次の操作を決める前です。

ただし、次にどの場面で何が起きるかは、うまくいかない問題が実際に起きて、初めて見えます。

AIが次の操作を決める瞬間に届くものを変えれば、AIが次にすることも変わります。それに当たるのは、ラッパーの案内、hookのエラー、実在しなければ先へ進むことのできないファイル、メモリの保存の直後に見せる差分です。どれもAIの外にある経路なので、置くのは外にいる人間です。書くのはAIでも構いません。どこに何を置くかを決めるのが、人間の仕事です。

読まない技術は、AIのこうした性質と仕様を踏まえた上で成り立つものです。AIの出力を読んで、足りないと言われればルールを足し、失敗したと言われれば読み直す代わりに、AIが次の操作を決める瞬間に何が届くかを変えます。うまくいかない問題を見つけ、なぜうまくいかないのかを理解し、仕組みを一つ置き、それが働くかどうかをわざと失敗させて確かめることを繰り返して、読まずに済むものを一つずつ増やしていきます。私が読まされていた時間が減ったぶんは、次の問題を探しに行く時間になりました。

私は仕組みを、それぞれが防ぐ失敗を踏んだ直後に、一つずつ置きました。あなたも、失敗を踏んだところから、一つずつ置いていけば十分です。

「AI に書かせたコードは理解する必要がある」「読まないと、設計を見る目が育たない」という批判は、その通りだと思います。

私が読む量は、正直に言えば減りました。

ただし、減ったのは読まされていた浅い読みで、残ったのは問題を探しに行く読みです。私が読まなくなったのは、読まされていた出力だけでした。

結論

読まない技術は、うまくいかない問題を見つけるたびに、仕組みを一つ置いていく技術です。

置いた仕組みは、わざと失敗させて働くことを一度確かめておけば、あとは読まずに済みます。これは、AIと開発するときに誰もが使う基本になるべきものだと、私は思っています。

読まない技術を身につけて、次の問題を探しに行く余裕を作ってください。


この連載の仕組みを使って私が作ったものは、typingtube で動いています。そこに並んでいるのは、読まされていた時間が減ったぶんで作った画面です。


次の連載は「AIの意見を聞かない技術」。AI の提案を、私は検討していません。 だけど、開発が雑になったことはありません。

連載「読まない技術」