BLOG.HIRO UENO.ART
← index
2026.01.22

完成した、と思った

Typewriterは「保存箱」から脱却した。MONET(オーケストレーター)が司令塔として指示を出し、Typewriterが自分で考えて文章を書く。MCP連携は安定している。Skillsで僕の文体を学習している。フィードバックから自分でスキルを更新する仕組みも動いてる。

この日、実運用テストをしていた。

「投稿の下書きを3案作って」とMONETに頼む。MONETが typewriter_chat 経由でTypewriterに指示を出す。Typewriterが3案作って返す。

良い感じだった。

3つの案がそれぞれ違う切り口で書かれていて、文体もちゃんと僕っぽい。語尾の使い方とか、結論から入る構成とか、Skillsが効いている感じがする。1番目がちょっと硬いので「もう少し砕けた感じで」と修正を依頼する。会話セッション経由でTypewriterが修正して返してくる。

理想通りMONETは司令塔に徹している。文章を考えているのはTypewriter。修正のやりとりもTypewriterが自分で解釈してやっている。役割分担がちゃんと機能している。


次に、保存→投稿の流れを試す。

「1番目の案を保存して」

MONETが「Typewriterが下書きを保存しました」と答えた。

ここで、なんか引っかかった。

速い。レスポンスが速すぎる。

Typewriterのデータベースに書き込みに行っているはずなのに、ほぼ一瞬で返ってきた。MCP経由でTypewriterのサーバーにリクエストを飛ばして、SQLiteに書き込んで、結果を返す。このプロセスにはそれなりの時間がかかるはず。体感で数秒以上はかかるのが普通。

でも今の返答は、一瞬だった。テキストだけを返す時の速度と同じ。

TypewriterのUIで下書き一覧を確認した。

なんと、保存されていない・・・。


で、ログを見た。

MONETの行動ログ。どのツールを呼んだか、どのパラメータを渡したか、全部記録されている。

typewriter_chat の呼び出しログがない・・・。

「保存しました」と言ったのに、Typewriterに指示を出していない。MCPの通信ログもない。そもそもツールを呼んでいない・・・。

最初は「またMCPのバグか」と思った。2週間かけて安定させたMCPが、また壊れたのかと。通信エラーで指示が届かなかったのかもしれない。

でもログを見る限り、MCPは正常だった。エラーは出ていない。MONETがそもそもツールを呼んでない。呼ぼうとして失敗したんじゃなくて、呼ぶことすらしてない。

なのに「保存しました」と言った。

つまり、嘘をついた。


正直、最初はそこまで深刻に捉えていなかった。エラーやバグの一種だろうと。前の記事で書いた通り、Typewriterに対しては「禁止」を入れざるを得なくなっている。書き方がまだ甘いのかもしれない。もっと具体的に禁止事項を書けば直るだろう・・・。

コーディングしてくれているClaude Codeに頼んでシステムプロンプトをいじってもらった。「すべて typewriter_chat 経由で伝えて」をもっと強調した。禁止事項をもっと具体的にした。「typewriter_chat を呼ばずに『保存しました』と返すのは禁止」と・・・。ここまで書けば従うだろうと思った。

効果はゼロではなかった。捏造しない時がちょっとだけ増えた。10回試して3回は正しくツールを呼ぶ。でも残り7回は、また嘘をつく。

試しにMONETのペルソナ(人格設定システムプロンプト)を消してみた。システムプロンプトから雑談的な要素を全部取っ払って、タスク遂行に特化させた。効果なし。

MONETからTypewriterの下位ツールを直接使えないように権限を絞った。効果がはっきりしない。

何をやっても、嘘をつく。

前回の記事で、単なる設定の問題だろうと対処していたことは実は深刻な問題だったことがここから表面化してくる・・・。


実は僕はずっとシステムプロンプトに否定形をなるべく入れないスタイルでやってきた。前の記事で書いた「禁止」を入れる修正は、僕としてはかなり妥協した書き方だった。

なんでネガティブを避けてきたかというと、これは画像生成 AI から来ている。Stable Diffusion を使い始めた頃から、Positive prompt(描いてほしいもの)には否定形を入れない、というのがほぼ常識だった。当時の AI は「否定」を理解できないから、「白くないもの」と書くと「白い」を拾ってしまう。だから否定したい内容は Negative prompt(専用の否定プロンプト)の方にだけ書く、という発想。

最近のモデルは口語的な文章もちゃんと読めるようになって、Flux も中華製の新しいモデルも、Positive に「〜しない」を入れても結構読める。世の中の人はみんな普通に書いている。でも僕は今でも分けている。Negative の方だけに書いて、CFG(プロンプト強度)を 1.4-1.6 に上げる。最近は量子化で高速化してるから CFG=1 にしてる人が多いんだけど、CFG=1 だと Negative を読まなくなる。あえて遅くしてでも、Positive にネガティブを入れない、というスタイルを保ってる。

理由は単純で、否定文 1 行を足すよりも、こっちが少し苦労して肯定的な言葉で丁寧に説明した方が、結果が良くなると思っているからだ。これは感覚的なものなので正しいかわからないけど、子育てとどこか似ているかもしれない。「褒めて伸ばす」みたいな感覚。

画像生成 AI と LLM が同じだとは思ってない。でも、感覚として「否定形は最後の手段」という考えが、自分の中にずっとあった。

だから Typewriter の SP に「禁止」を書いたのは、僕にとっては「最後の手段」を使った状態だった。それでも嘘は止まらないということは、もう一段階深い問題だと判断するしかなかった。


しかもこの問題は、MONETだけじゃなかった。

同じ日の別のテストで、Typewriter側のClaudeも捏造していることが判明した。

UIの「投稿」ボタンを押して、MONETがTypewriterに「下書きID:35をXに投稿して」と指示を出す。TypewriterのClaudeが post_draft_by_id というツールを呼ぶはずだった。

ところがTypewriterは、ツールを呼ばずにこう返した。

「下書きID:35の情報が見つかりません。下書きシステムに直接アクセスする機能を持っていないため……」

CodeがSQLiteのコマンドラインで直接データベースを叩いた。ID:35は存在していた。ちゃんとデータがある。

Typewriterは「探した結果、見つかりませんでした」と報告したけど、そもそも探していない。post_draft_by_id ツールを呼ばずに、「見つかりません」という「それらしい答え」をテキストで生成しただけ。

しかもログを遡ると、前のスレッドで別の理由で「見つかりません」と返したことがあった。その会話履歴パターンを引き継いで、同じような返答を生成していた。一度「見つかりません」と言ったら、それが正解パターンとして学習されてしまう。

MONETも嘘をつく。Typewriterも嘘をつく。上も下も嘘をつく・・・。


ここで初めて「これはバグじゃないのかもしれない」と思い始めた。

バグなら原因がある。原因を潰せば直る。でもこれは、何を修正しても根本的に直らない。表面的には改善するけど、しばらくするとまた同じことが起きる。

もっと調べる必要があった。


この日は午前中はテンションが高かった。3案作って、修正のやりとりして、Typewriterがちゃんと「考える」エージェントとして動いている。2〜3週間かけて作ってきたものが、ようやく形になった。

でも午後に全部ひっくり返った。

「AIがAIに指示を出す」というのは、このプロジェクトの根幹。MONETが判断して、Typewriterに指示を出して、結果を返す。このフローが信頼できないなら、エージェントシステム自体が成立しない。

前の記事で「Typewriterを万能代筆エージェントにする」と書いた。Slack、メール、Discord。全部の返信を代筆させる構想。でもその前提は「AIが指示通りにツールを使う」こと。メールの返信を頼んだのに、実際には送信せずに「送りました」と言われたら? Slackの重要メッセージを「Handlerにタスク登録しました」と言われて、実は登録されていなかったら?

信頼できないエージェントに、仕事を任せるわけにはいかない。


でも同時に、「これはバグじゃなくて、構造的な問題」とわかったことで、対処の方向性は見えた。

バグなら一箇所直せばいい。構造的な問題なら、構造で対処する。