MONET(オーケストレーター)のシステムプロンプト(AIに最初に渡す指示文、以降SP)は、3つのファイルに分けて持っていた。書き手が違うから分ける。理屈としては綺麗に分かれてる・・・と思ってた。
分けたはずのものが、あちこちで混ざってきた。
3つのファイルはこう。
system_prompt_persona.txt ← MONETの人格・口調。僕が書く
system_prompt_core.txt ← 僕の恒久的な情報(プロジェクトとか価値観とか)。僕が手で足す
context_summary.txt ← 直近の状況。Librarianが毎朝4時に自動生成する
分けた理由は、書き手が違うから。人格と恒久情報は僕。直近の状況は Librarian(前の記事で書いたメモリ管理アプリ)。触る頻度も違う。人格はめったに変わらないし、Core も昇格した内容を足す時だけ。Context は毎日書き換わる。
書き手と頻度が違うなら、ファイルも分けておく。各ファイルが自分の役割を持ってる。当時はこれで整理できていると思っていた。
でも実際それで運用してみると扱いづらかった。
まず、3つが別々に育っていく。Persona に書いたことと Core に書いたことが似てきたり、Context の内容が Core と微妙に食い違ったり。ファイルを3つ開いて見比べないと、MONET が全体として何を読んでいるのかわからない。
次に、Librarian が取ってくるメモリの層。前の記事で書いた通り、Librarian は最新100件のうち25件を「人物像」、75件を「最近の会話」として取ってくる。この「人物像」の25件が、Core に書いてあることとほぼ同じだった。僕の価値観、判断基準、変わらない事実。Core に手で書いたものと、Librarian が毎朝メモリから拾ってくるものが、同じことを2回言ってる。
前の記事で、重複してもそんなに困らない、と書いたばかりだった。あれはサマリーの中で数行かぶる話。今回は取ってくる層そのものが、Core と同じことをもう一回言うための層になっていた。層ごと廃止した。
一番気持ち悪かったのは3つ目。
Librarian が生成した Context を読んだら、去年12月の週間サマリーが「直近の状況」として載っていた。1ヶ月前の話が、今の話として MONET に毎朝渡っていた。
コーディングしてくれている Claude Code(以降 Code)に見てもらったら、原因はインポートの日付。古いメモリを別のシステムから移した時に、作成日がインポートした日になっていた。Librarian は「直近30日・100件」の条件でメモリを取りに行くので、中身は12月でも作成日が今月なら「直近」に引っかかる。
対策は取得範囲を絞っただけ。30日100件を、7日10件に。目の前の混入は止まったけど、根本は何も直ってない。日付が化けたデータはそのまま残ってるし、取ってくるロジックも変えてない。
Librarian が書いたものを、毎朝そのまま MONET に渡していた。読み返しもせずに。司書に棚を任せて、棚に何が並んだか見てなかった。
3つとも同じ形をしてる。分けて置いたはずのものが、別の場所で混ざって出てくる。
ファイルを分けても、中身は分かれてくれない。 そういうことだと思う。
で、Code に頼んで1つにまとめてもらった。
system_prompt.txt
├── PERSONA MONETの人格・口調
├── CORE 僕の恒久的な情報
├── CONTEXT 直近の状況(Librarianが更新)
└── RULES ツール使用ルール
1ファイルの中をセクションで区切る。区切りは HTML コメントのマーカーで、Librarian は CONTEXT のセクションだけを見つけて書き換える。設定ページはタブ切り替えにして、CONTEXT には読み取り専用のバッジをつけた。僕が間違えて手で触らないように。
分けるのをやめた代わりに、中で決めたことがある。どのセクションを誰が書くか。
| セクション | 書く人 |
|---|---|
| PERSONA | 僕 |
| CORE | 僕 |
| CONTEXT | Librarian |
| RULES | 僕 |
MONET 本人は読むだけ。自分の SP を書き換える権限は、当面渡さない。
あと、保存のたびにバックアップを残すようにした。SP が壊れると、MONET は自分が誰かわからない状態で起動しかねない。Librarian が毎朝自動で書き込むファイルなので、いつでも前の版に戻せるようにしておきたかった。
変更としては小さい。3つのファイルを1つにして、タブをつけて、書く人を決めた。それだけ。
でも、ファイルを3つ開いて見比べる作業がなくなった。MONET が何を読んでいるかは、1つのファイルを上から読めばわかる。
Librarian 周りは、とりあえず動いてる状態のまま。CONTEXT には古い情報がまだ混ざってて、これは手で直す。取得ロジックの見直しも残ってる。分けるのをやめただけで、混ざったものの掃除はこれから。