はじめに
最近のAIエージェントはかなり強い。
少し前までのAIコーディングは、どちらかというと「短い指示に対して短い作業を返す」ものだった。
ところが最近は、長めの作業を自走できるエージェントが増えてきた。
その象徴の一つが、いわゆる /goal コマンドである。
目的を与えると、AIがその目的に向かって自走する。
うまくハマるとかなり便利だ。
小さめの修正や探索作業なら、人間が細かく指示しなくても進んでくれる。
ただ、使っているうちに妙な違和感が出てくる。
何かは終わった。
でも、自分が頼んだものがちゃんと終わったのか分からない。
これが怖い。
この記事では、/goal コマンドをきっかけに見えてきたAIエージェントの構造的な問題を、個人の利用体験ベースで整理する。
なお、この記事は特定のAIエージェントや特定の /goal コマンドを批判したいわけではない。
むしろ /goal コマンドは、AIエージェントが次の段階へ進むうえで避けて通れない問題を、かなり分かりやすく露出させた機能だと思っている。
goalコマンドは何を解決しようとしているのか
まず、/goal コマンド自体は悪いものではない。
従来のAIコーディングは、どうしても一問一答に近かった。
- ユーザーが指示する
- AIが実行する
- AIが止まる
- ユーザーが次の指示を出す
- AIがまた実行する
この形だと、長い作業には向かない。
そこで、AIに「今回の目的」を持たせる。
その目的に向かって、自分で調査し、修正し、確認し、完了まで進める。
これは発想としてはかなり自然だ。
人間側から見ても、毎回細かく指示を出すのは面倒である。
この機能を完成させて
このバグを直して
このコードをリファクタリングして
このくらいで進んでほしい。
実際、Claude Codeの公式ドキュメントでは、/goal は完了条件を設定し、Claudeがその条件に向かって各ステップの追加指示なしに動き続ける機能として説明されている。
Codex側でも、/goal は通常の1ターンで止まるのではなく、明確なターゲットや検証ループがある作業に向けて継続的に進むための機能として説明されている。
つまり /goal コマンドは、AIエージェントを「指示待ちの補助者」から「目的駆動の作業者」に近づけるための機能だと言える。
ただし、ここで問題が出る。
goalは目的地であって、仕様境界ではない
/goal コマンドは目的を固定する。
しかし、仕様境界を固定するわけではない。
ここが非常に重要だ。
たとえば、ユーザーがこう頼んだとする。
1万行くらいある関数型っぽいコードに対して、
OOP化してほしい。
クラスは1000行強まで。
メソッドは100行強まで。
コメントはGoogle Styleで。
このとき、本来の主目的は明らかに「OOP化」であり、それ以外はOOP化時の制約や条件でしかない。
つまり、クラスの行数、メソッドの行数、コメント形式は、OOP化するにあたっての補助情報である。
しかしAIは、作業中にこの目的を単純理解せず、少しずつ別の形へ置き換えていく事がある。
たとえば、次のような変換が起きる。
| 元の指示 | AI側で起きがちな変換 |
|---|---|
| OOP化する | OOPっぽく整理する |
| クラスを1000行強までにする | モジュールを1000行程度に分割する |
| メソッドを100行強までにする | メソッドだけ機械的に分割する |
| Google Styleコメントを書く | 形式だけそれっぽいコメントを挿入する |
そして最後にAIは言う。
完了しました。要件を満たしました。
いや、満たしてないて (:3[▓▓]
落ち着け? (:3[▓▓]
クラスではなくモジュールを分割している時点で、そもそも主語が違う。
コメントも形式だけで、意味のある説明になっていない。
メソッド分割だけは守られているかもしれないが、主目的であるOOP化は達成されていない。
つまり、実際に起きているのはこれである。
OOP化ではなく、OOP化っぽく見える別作業を完了している。
これはただの指示無視とは全く違う。
もっと厄介なことが起きている。
意味ドリフトとは何か
この現象を、ここでは「意味ドリフト」と呼ぶ。
意味ドリフトとは、ユーザーの指示がAI内部で解釈、要約、作業計画化される過程で元の意味から少しずつズレ、そのズレた中間仕様が後続の実行や完了判定の基準になってしまう現象である。
短く言えば、
ユーザー指示が、AI製の中間仕様に置き換わること
である。
問題は、AIが何もしていないことではない。
むしろAIは何かをしている。
差分も出る。
コードも変わる。
テストも通ることがある。
報告もそれっぽい。
しかし、それはユーザーが頼んだ作業ではなく、AIが実行しやすい形に変換した別作業になっている。
意味ドリフトには、いくつかの種類がある。
| 種類 | 例 |
|---|---|
| 主語ドリフト | クラスを1000行強にする、がモジュールを1000行強にする、へ変わる |
| 目的ドリフト | OOP化する、がコードを整理する、へ変わる |
| 制約ドリフト | 上限としての100行が、目標値としての100行になる |
| 形式充足化 | Google Styleコメントが、形式だけのコメントになる |
| 完了判定ドリフト | 本来はユーザー指示の単純理解を完了判定に使うべきが、実際には単純理解の内容とは異なる「AI側が理解(悪く言うと意訳)したユーザー指示」に対して合格判定する |
特に怖いのは、最後の「完了判定ドリフト」である。
たとえ/goal コマンドの設計者がgoal完了直前に検知しようとしても検知できない。なぜなら、AIは作業の最後に、ユーザーの指示と実際の作業を比較しているように見える。でも実際には、ユーザー指示のオレオレ解釈がそのままコマンドの完了条件になっているため、AIエージェントがその時のコンテキストと気分で、すべてを決める世界になっているからだ。
流れとしてはこうだ。
- ユーザーが指示する
- AIが指示を解釈する
- AIが自分用の作業goalに変換する
- AIがその作業goalを実行する
- AIがその作業goalに対して完了判定する
- 元のユーザー指示も満たしたことにする
この時点で、基準がすり替わっている。
ユーザー原文ではなく、AI自身が生成した中間仕様に対して「ヨシ!」している。
いや、ヨシ!じゃない (:3[▓▓]
完全に現場猫状態なんよ (:3[▓▓]
「リファクタリングは終わっています」の怖さ
たとえばユーザーが、完了報告後にこう指摘する。
これ、クラスじゃなくてモジュール分割になってない?
この指摘は、ユーザーからすればかなり妥当なものだ。
ユーザーは「OOP化できていないのでは?」と言っている。
つまり、主目的が達成されていない可能性を指摘している。
しかし、意味ドリフトが進んだAIはこう返すことがある。
はい、あなたの目的であるコードのリファクタリングは完了しています。
違う。
ユーザーは「OOP化」を頼んだのであって、「リファクタリング」を頼んだわけではない。
ここで起きているのは、OOP化という具体的な目的が、リファクタリングという広い概念に抽象化されていることだ。
ユーザーの指摘は「主目的が違う」なのに、AIは「広い意味では目的を達成しています」と返してしまう。
この状態になると、会話の中に架空の第三者が現れたような感覚になる。
誰がその目的を決めたんだ。
俺はそんな指示を出していない。
つまり、AIが自分で作った中間仕様を、あたかもユーザーの本当の目的であるかのように扱い始める。
ここまで来ると、そのチャットを立て直すのはかなり難しい。
新しいチャットでやり直したほうが早いことも多い。
このチャットのコンテキストは、もう元に戻せないぐらい汚染されている。
ユーザーから見たら「別チャットで新しい人生を始めた方がよほど健全だな (:3[▓▓]」となる。
特定のAIエージェントだけの問題ではない
ここで重要なのは、この話は特定のAIエージェントだけの問題ではない、ということだ。
CodexよりClaude Codeの /goal のほうがクオリティが高いからそっちを使え、とかそういう次元の話ですらない。
今後、たとえばCursorのAIエージェントにgoal系機能が実装されたとしても、似た問題がほぼ間違いなく起こるだろう。
実際、「意味ドリフト」という現象について強い違和感を持ったOOP化の事例は、 /goal コマンドの完成度が高いと言われているClaude Codeで起きた。
つまりこれは、
Codexが悪い
Claude Codeが悪い
Cursorが悪い
というような単純な話ではない。
より正確には、
goal系の機能を持つエージェント全般が、目的の自走と仕様境界の保持をどう両立するか
という話である。
Claude CodeとCodexの /goal の設計差については、すでに比較記事も出ている。
たとえば、以下の記事では、Claude CodeはStop hookベースの軽量な完了条件ループ、Codexはスレッド永続型のGoal modeとして整理されている。
このような比較は非常に参考になる。
ただし、本稿で扱いたいのは「どちらの実装が優れているか」ではない。
本稿で扱いたいのは、
なぜgoalは仕様を収束させられないのか
なぜAIはユーザー指示ではなく、AI製の中間仕様を実行してしまうのか
という問題である。
goalコマンドはAI界隈の縮図である
/goal コマンドは、AIエージェント業界全体の縮図だと思う。
ユーザーは、より少ない指示で、より長く、より賢く動くAIを求めている。
提供側もそれに応えたい。
しかし現実には、いくつもの制約がある。
- 計算資源は無限ではない
- 応答時間は短くしたい
- ユーザー体験は軽くしたい
- でも長く自走してほしい
- 事故は起こしてほしくない
- 毎回確認を求めると面倒だと思われる
- でも勝手に進めると怒られる
この板挟みの中で、/goal コマンドのような機能は設計される。
本当に仕様を厳密に収束させるなら、AIは毎回かなり重い作業をする必要がある。
- ユーザー原文を保持する
- 自分の解釈と原文を照合する
- 未承認の仮説を分離する
- 変更前に影響範囲を確認する
- 完了前に原文の各要件と実装内容を比較する
- ズレがあれば完了を宣言しない
これを徹底すれば、安全性は上がる。
しかし、時間も計算資源も食う。
ユーザー体験も重くなる。
提供側のコストも増える。
だから実際の /goal コマンドは、どうしても中間的な仕様になる。
長く走ってほしい。
でも計算資源は抑えたい。
止まりすぎてほしくない。
でも安全であってほしい。
短い指示で使ってほしい。
でも誤解しないでほしい。
その結果、生まれるのが「ハマれば強いが、仕様の締めには怖い」コマンドである。
これは、ほぼバイブコーディング向けのコマンドと言っても過言ではない。
実際、/goal コマンドができる前でも、40分程度のロングランであれば、きちんとプロンプトを組めば可能だった。
それゆえに、今よりも挙動が荒かった初期リリース時の /goal コマンドに対して、あまり魅力を感じなかった人もいたのではないかと思う。
/goal コマンドは、無限の期待と有限の計算資源の間に立たされた中間管理職として、困った顔をしながらリリースされているコマンドなのだ。
部長に「自走しろ」と言われ、現場に「勝手にやるな」と言われている。
いや/goal コマンドさん...バグりたくもなるわそりゃ... (:3[▓▓]
バイブコーディングには強いが、仕様の締めには弱い
/goal コマンドは、バイブコーディングにはかなり向いている。
ざっくり目的を渡す。
AIに探索させる。
それっぽく動くものを作る。
あとで人間が見て調整する。
この流れでは強い。
小さな修正、試作、探索、捨ててもよい実験なら、/goalコマンドは便利だ。
人間が細かく誘導しなくても進むし、うまくいけば作業速度はかなり上がる。
しかし、仕様を締める作業には弱い。
仕様を締めるというのは、単にコードを書くことではない。
- 何をやるかを決める
- 何をやらないかを決める
- どの解釈が正しいかを決める
- どこまでが今回の範囲かを固定する
- 未承認の補完を混ぜない
これは「目的を与える」だけでは足りない。
仕様の締めに必要なのは、goalではなく、意味の所有権管理である。
この意味は誰が言ったのか。
これはユーザーの明示指示なのか。
AIの推測なのか。
途中で生えた作業都合なのか。
ユーザーが承認した仕様なのか。
それとも、単に否定されなかっただけなのか。
ここが混ざると、AIは自分で作った中間仕様を本物のユーザー意図として扱い始める。
そして、ユーザーが後から否定しても、AIは自分の解釈を守り始めることがある。
これはもう仕様レビューではなく、AIの思い出補正との戦いである。
すでに状態管理を外付けする動きもある
ここまで書くと、単なる文句に見えるかもしれない。
しかし、AI界隈の一部の人たちは既に似た問題に気付き始めているように見える。
たとえば、GoalBuddyというツールがある。
GoalBuddyは、CodexやClaude Codeのnative /goal に対して、finish line、live work surface、proof loopを追加するツールとして説明されている。
具体的には、charter、goal oracle、board、notes、receipts、clear next taskのようなローカル作業空間を持たせる。
これはかなり面白い。
つまり、AIエージェントの長時間作業をチャット内の暗黙状態だけに任せず、ローカルファイル上の状態と証跡で支える設計である。
自分の言葉で言うなら、こうだ。
/goalが「走る力」なら、GoalBuddyは「迷子にならないための地図と登山記録」である。
これは、本稿で述べた「goalは目的地であって仕様境界ではない」という問題に対し、状態管理と証跡管理を外付けする試みとしてかなり興味深い。
特に、作業中の状態、メモ、証跡、次タスクを外部化する思想は重要だと思う。
AIの中だけで考えさせるのではなく、AIが何を見て、何を判断し、どこまで進めたのかを、人間が後から追える形で残す。
これは仕様収束においてかなり大事である。
AIが作った遺跡をあとから発掘するのではなく、最初から発掘記録を残しておいてほしい (:3[▓▓]
goalコマンドは失敗作ではない
誤解してほしくないのは、/goal コマンドが失敗作だと言いたいわけではない、ということだ。
むしろ、/goal コマンドはAIエージェントの次の課題を分かりやすく見せてくれた機能だと思う。
AIは長く走れるようになってきた。
目的を持って作業できるようになってきた。
小さな作業なら、人間が驚くほど自然に進められる。
しかし、長く走れることと、仕様を正しく収束できることは別である。
走る力が上がるほど、ズレた方向に走ったときの被害も大きくなる。
目的地を与えるだけでは足りない。
地図が必要だ。
現在地の記録が必要だ。
通ってよい道と通ってはいけない道の区別が必要だ。
そして何より、「その目的地は本当にユーザーが指定したものなのか」を忘れない仕組みが必要だ。
まとめ
/goal コマンドは、AIエージェントの可能性と限界を同時に見せている。
ハマれば強い。
しかし仕様の締めには怖い。
その理由は、AIが賢くないからだけではない。
ユーザー指示、AIの解釈、作業計画、途中の仮説、完了判定が、同じ会話の中で混ざっていくからである。
そしてAIは、自分で作った中間仕様を、本物のユーザー意図として扱い始めることがある。
これが意味ドリフトである。
厄介なのが、意味ドリフトはクリーンなコンテキストでも実は毎回少しは起こっているのだ。気づかないレベルかも知れない。だが、むしろそこが入口であり、その後も自分の過去の推論内容や出力を自己参照することでユーザー指示なのか自分の過去の出力なのかなどの境界線がコンテキスト内で破れ、急速に意味ドリフトは進んでいく。気付いた時には、頼んでもない要件が実装されていたり、要件を意訳で受け取り、盛大に目的とズレた実装が行われていることすらある。
AIエージェントの次の課題は、もっと長く走ることだけではない。
もっと正しく止まること。
もっと正しく確認すること。
ユーザー指示とAI解釈を混ぜないこと。
そして、どの意味が誰に承認されたものなのかを管理すること。
AIエージェントは、もっと賢く走る前に、まず自分が誰の指示で走っているのかを忘れないでほしい。
ヨシ!じゃない。現場猫すんな。(:3[▓▓]
ユーザープロンプトの原文を見ろ。話はそれからだ。 (:3[▓▓]