「呼べる場所」と「働ける場所」は違った ── SkillをPlugin化して、Workへ戻ってくるまで
Personal SkillをPlugin化すれば通常Chatから呼べる。実際に呼べた。でも同じ処理をWorkと比べたら成果物が3分の1だった話。
トークンをケチろうとして、成果物が3分の1になった
前回、AIに先回りされずに本を読むための仕組み「Reading Project Starter」をPersonal Skillとして作った話を書いた。
その続き。今回は完全に遠回りの記録である。
Workを使うとトークンを消費するので、通常のChatから呼べないかと試行錯誤した。Plugin化して、呼べるようになった。呼べるようになった結果、中身が3分の1の成果物と、リクエスト制限が手に入った。
Codexからしか呼べない
Skillが完成して、%USERPROFILE%\.codex\skills\reading-project-starter にインストールした。全12ファイル、SHA-256一致確認済み、バリデーション合格。
作ったのはCodexのSkill Creatorである。そして気づいた。Codexからしか起動できない。
私がこのSkillを使いたいのは、本を読み始めるときである。Codexを開くのは、コードやファイルをいじるとき。そもそもスマホにCodexはない。用途が合っていない。
2026年8月11日に私が試した環境では、Personal SkillはデスクトップとWeb・モバイルで別々に追加する必要があり、自動同期されなかった。そこでSkillフォルダをzipにして、ChatGPTのSkills画面からアップロードした。インストール自体は問題なく通った。
「チャットで試す」を押したらWorkが起動した
インストールできたので、Skillの管理画面にある「チャットで試す」を押してみた。
Workが起動した。
動きはする。動きはするのだが、ここで引っかかった。
Workはトークンを使う。
Reading Project Starterは本を読み始めるたびに呼ぶものである。1冊ごとに毎回Workを回すのは、正直もったいない気がした。
通常Chatから @Reading Project Starter と呼べれば、それで済むのではないか。
……これが今回の遠回りの出発点になる。
Personal SkillをPluginに包む
通常Chatから呼ぶ方法を調べると、Pluginという別ルートがあった。PluginはSkillを含むことができる。
ならば、Personal SkillをSkills-only Pluginに包めば、通常ChatからPluginとして呼び出せるのではないか。
動機は2つあった。
1つは上に書いたとおり、Workのトークン消費を避けたかったこと。読書のたびに毎回Workを回すより、通常Chatで済むならその方が軽い。
もう1つは、ChatとWorkの境界がどこにあるのかを知りたくなったこと。すでにWorkなら動くことは分かっていたので、実用上はそのままでもよかった。それでも、実際に試せるなら試したい。
結果から言うと、1つ目の見込みは完全に外れる。
元Skillには絶対に触らせない
Plugin化のために上位モデルのトークンを大量に使うのはもったいないので、作業はCodexのLunaに任せることにした。その代わり、迷わないように指示書をかなり具体的に書いた。
一番重要な条件はこれ。
元Skillを変更・削除・移動・改名・上書きしないこと。
Plugin版は完全に別フォルダへ作る。MCP Serverは追加しない。AppもConnectorもHookも使わない。目的はあくまでSkills-only Pluginを作ること。
そして、元Skillの内容を改善したりリファクタリングすることも禁止した。
今回知りたいのはPlugin化による挙動の違いなので、Skillの中身まで変わってしまうと実験条件が崩れるからである。
できあがったPluginの構造はこうなった。
reading-project-starter/
├─ .codex-plugin/
│ └─ plugin.json
└─ skills/
└─ reading-project-starter/
├─ SKILL.md
├─ agents/openai.yaml
├─ assets/templates/
├─ references/
└─ scripts/
Plugin直下は .codex-plugin と skills だけ。Personal Marketplaceの登録は %USERPROFILE%\.agents\plugins\marketplace.json に作られ、reading-project-starter が AVAILABLE として認識された。
公式のPlugin validatorは、最初PyYAMLの依存で止まった。Skill検証のときと同じように一時フォルダにだけPyYAMLを用意して再実行したら合格した。検証後、その一時フォルダだけ削除した。
元SkillとPlugin内コピーの比較結果は、ファイル数12対12、相対パス一致、SHA-256差分0。Plugin化の過程でSkill本体は一切変わっていない。
これが後の比較で効いてくる。
通常Chatから呼べた
PCの通常Chatで、Plugin参照を使って呼び出した。
[@reading-project-starter](plugin://reading-project-starter@personal)
DXの思考法 西山圭太、冨山和彦
反応した。
一瞬、実験成功だと思った。
でも、質問が3つ返ってきた
そのとき返ってきたのは、こういう質問だった。
- なぜ今この本を読もうと思ったか
- 読む前のDXのイメージ
- 読み終わったときに何を持ち帰りたいか
背景情報があった方が、後の読書支援の質は上がるとは思う。
ただ、**「そんなことまで言わないといけないSkillだったっけ?」**という違和感があった。
Reading Project Starterは、本と関係者を指定すれば開始できる設計にしてある。最初から質問攻めにするものではない。
あとで SKILL.md を確認したら、こう書いてあった。
任意の設定質問をするな。通常の曖昧さはWeb調査で解決しろ。
気のせいではなかった。仕様に真正面から反していた。
ここで思った。「Pluginが指定できたこと」と「Skillの指示が意図どおり反映されたこと」は、どうも別の話らしい。
Skillを消したら、Pluginも動かなくなった
Plugin版が使えるようになったので、「もう元のPersonal Skillはいらないのでは」と考えて、一度Skillをアンインストールした。
すると、Pluginはアンインストールしていないのに、Reading Project Starterが起動しなくなった。 PCでもスマホでも同じだった。
Pluginの中にはSkillファイルが完全コピーされているのに、である。
ここから考えたのは、Pluginの呼び出し自体には成功しても、その先で参照されるSkillがインストールされていなければ実行できないのではないか、ということ。
ただしこれは内部実装を確認した事実ではない。観測した挙動から立てた仮説である。
少なくとも今回のPersonal Skills-only Pluginにおいては、PluginはSkillの完全な代替物ではなく、Skillを使うための入口に近い、という理解に変わった。
切り分けのため全部消して入れ直したところ、PCでは再び通常Chatから呼べるようになった。ただしスマホでは同じ状態を安定して再現できなかった。スマホには個人用Marketplaceを管理する入口が見当たらない。ここを追いかけるのは、たぶんそもそも想定された使い方ではない。
諦めてWorkでやり直した
ここまでは起動テストである。本題はここから。
通常Chat+Pluginで、実際に『DXの思考法』の読書プロジェクトを生成させた。
まず、出来上がった内容がかなりスカスカだった。
さらに処理中、内部で大量のリクエストが発生したらしく、「リクエストが多すぎる」状態になって一時的にChatが制限された。 内容は薄いのにリクエストだけ増える。トークンを節約するつもりだったのに、逆である。
ここで諦めた。
「チャットで試す」が最初から示していたとおり、Workでやることにした。同じSkillを @ で呼び出し、同じ本を渡す。
出てきたものが、明確に違った。
Skill本体は上で確認したとおりSHA-256一致、つまり完全に同一である。違うのは実行環境だけ。あとから2つの出力を突き合わせてみた。
出力サイズ
| ファイル | Chat+Plugin | Work |
|---|---|---|
01_book-context.md | 2,048 | 8,316 |
02_author-context.md | 1,800 | 9,725 |
03_reviews.md | 1,909 | 11,853 |
project-instructions.md | 4,270 | 5,160 |
| 合計 | 11,269 | 35,642 |
| 記録された出典URL数 | 5 | 22 |
(バイト数)
3倍以上の差がついていた。
サイズより、中身の方が決定的だった
ただ、この記事で本当に書きたいのはサイズの話ではない。あとから中身を突き合わせて、もっとはっきりしたことが分かった。
その1。フォルダ名が英語になっていた。
Chat版の出力先は dx-thinking-reading-project。Work版は DXの思考法 日本経済復活への最強戦略-reading-project。
SKILL.md には「意味のあるUnicodeを保持し、ファイルシステム上不正な文字だけを除去せよ」と書いてある。Work版は仕様どおり。Chat版は勝手にローマ字化している。
その2。テンプレートを使っていない。
Skillには assets/templates/ に5つの雛形がある。04_my-reading.md の見出しは「読む前の自分の考え」「読書中に生まれた重要な問い」……と決めてある。
Work版はこのとおりに出力された。
Chat版は違った。「読み始める前」「読書ログ」「仮説の変化」「読了後」という、まったく別の見出し構成を自分で考えて出力していた。
内容は悪くない。悪くないのだが、Skillが持っているテンプレートファイルを読んでいない。
その3。レビュー調査が丸ごと実行されていなかった。
これが一番大きい。Chat版の 03_reviews.md にはこう書かれていた。
外部レビューの取得環境を確認できなかったため、推測や検索スニペットからレビュー内容を埋めていない。
つまり Stage B が実行できていない。出典URLは0本。
一方Work版の 03_reviews.md は11,853バイトあり、「抽象性は強みか、障壁か」「入門書か、再読を要する思考書か」といった、評価が割れている論点が7本の出典つきで整理されていた。
ついでに 02_author-context.md も、Chat版は冨山和彦について「出版社の書誌上で解説と明記されていることだけを固定する」で終わっている。なぜこの人が解説を書いているのかは何も分からない。
ただし、嘘はついていなかった
公平のために書いておく。
Chat版の 03_reviews.md には、Stage Aで固定した4ファイルのSHA-256が4本書き込まれていた。本来この基準値は一時JSONファイルに保存する仕様なので、ここも我流である。
疑って、後から自分で照合してみた。
4本とも一致した。
ハッシュは実際に計算されていた。捏造ではない。レビューが取れなかったことも、ごまかさずに「確認できなかった」と書いている。これは設計の記事で書いた「情報が足りなければレビューで埋めずに確認できなかったと書け」というルールを、ちゃんと守った結果でもある。
だからこれは「Chat版がサボった」話ではない。
SKILL.md に書かれた思想は伝わっていて、それを実行するための環境がなかった。 そう理解するのが一番近いと思う。
段階は5つあった
最初は「Skillが動く・動かない」の二択だと思っていた。実際には、こう分かれていた。
- Skillが存在すること
- Pluginとして呼び出せること
- Pluginが参照されること
- Skillの処理が実際に走ること
- 十分な品質で最後まで処理できること
Chat+Pluginは3までは行った。4も部分的には行った。5には届かなかった。
そして、「呼べる場所」と「ちゃんと働ける場所」は同じではない。
これはUIを眺めていても絶対に分からなかった。同じ処理を両方へ投げて、出力を突き合わせて、初めて分かったことである。
結局、Workが正解だった
最終的にReading Project StarterはWorkで使うことにした。
理由は「Workでしか起動できないから」ではない。Plugin化によって通常Chatから起動するところまでは実際に成功している。 その上でWorkを選んだ。
このSkillは、複数ファイルを扱い、テンプレートを使い、背景を調査し、ルールを読み分け、情報源を隔離し、複数段階で処理して、成果物を作る。かなりエージェント的な仕事である。
通常のチャットで一回答えるだけの機能ではない。
しかも読書用途では、Starterを何度も起動するわけではない。一度走らせてProjectの材料を作ってしまえば、あとはProject内の普通のチャットで思考を重ねていく。1冊につき1回だけWorkを開くのは、大した負担ではない。
節約したかったトークンの話にしても、薄い成果物を作った上でリクエスト制限を食らうより、Workで一発で終わらせた方が結局安い。
スマホでもWorkからなら起動できる。Personal Pluginをスマホで安定して呼ぶより、こちらの方がずっと素直だった。
ボタンが最初から答えを出していた
冒頭に書いたとおり、Skillの管理画面で「チャットで試す」を押したら、勝手にWorkが起動した。
あれが答えだった。
私はそれを「Workはトークンを使うから」という理由で回避しようとして、Pluginを作り、Marketplaceを登録し、validatorのPyYAML依存と格闘し、ハッシュで同一性を確認し、アンインストールして壊し、入れ直して、リクエスト制限を食らって、最後にWorkへ戻ってきた。
結果だけ見れば、Plugin化する必要はなかった。
しかも節約のつもりが、薄い成果物と引き換えにリクエストを浪費している。得しなかった。
それでも無駄ではなかった
とはいえ、無駄だったとは思っていない。
Plugin化を実際にやったから、Personal Skill、Skills-only Plugin、Personal Marketplace、PC通常Chat、スマホ通常Chat、Work、Codex——これらの違いを、仕様説明としてではなく実際の挙動として理解できた。
そして今回のやり方自体が、そのまま次に使える。
- 最初から正解を予想して一気に構成を変えない
- 元の正常系を保存する
- コピーを作る
- 一つずつ条件を変える
- 実際に同じ処理をさせて比較する
- 結果が悪ければ元に戻る
Plugin化が不要だと即断できたのは、元Skillを一文字も変えなかったからである。戻るのが一瞬だった。
次にSkillを作るときは、先に場所を決める
「Skillを作れるか」だけでなく、**「そのSkillはどの実行環境で使うものなのか」**を最初に考えた方がよさそうだった。
短い処理を一度行うだけなら、通常ChatからPluginとして呼ぶことにも意味があるかもしれない。ただし、ファイルを複数読む・何段階も判断する・調査を行う・成果物を作る・ルールを厳密に守る、といった処理は、たぶんWork向きである。
技術的に可能な構成と、実際に使いやすい構成は別である。
……という当たり前のことを、Marketplaceを登録してvalidatorと格闘してリクエスト制限まで食らって確認した。
そして肝心の『DXの思考法』は、まだ読み始めたところである。仕組みばかり作っていた。