目次

Claude CodeやCodexのようなAIと開発していると、セッションが変わった瞬間に話が振り出しへ戻ることがある。昨日のAIが何を試して、どの方向が行き止まりで、何が原因だったのか。今日のAIはそれを知らない。別のAIに切り替えると、同じ説明をもう一度することもある。もっと困るのは、前のAIが「直りました」と言ったので直ったことにしていたのに、あとから見ると検証が走っていなかったときだ(このAIの「できました」を信じない話は、前にも書いた)。

この「AIをまたぐと問題解決の状態が失われる」問題に対して、MCP(AIから外部のツールやデータへ接続するための仕組み)のサーバーを1つ作った。ai-problem-solving-memoryとして、MIT LicenseでGitHubに公開している。

先に書いておくと、これは完成報告ではない。技術的に動くところまでは確認できたが、日常の開発で本当に便利なのかは、まだ分かっていない。この記事はその現在地の記録だ。

最初は「AIのMemory」を考えていた

出発点は素朴で、「AIが過去を覚えていればいいのでは」だった。いわゆるAI Memory——会話や知識を保存しておいて、次のセッションで思い出させる方向だ。

ただ、既存のMemory系の仕組みを調べながら設計を進めるうちに、自分が失って困っているものは会話の全文ではない、と思うようになった。欲しいのは「あの問題はいまどういう状態で、何が試されて、何が行き止まりだったか」という、問題解決の状態と証拠のほうだ。それも、人間があとで読み返すためのメモとして残したいわけではない。次に作業するのが別のAIでも、いま何が分かっていて、何はもう試してダメで、どこから続きを始めればいいか——それを判断できる状態のまま残っていてほしい。会話を丸ごと覚えていても、そこから状態を再構成するのは結局AIの読解頼みになる。

それで途中から、責務をはっきり絞った。汎用のAI Memoryではなく、複数のAIが同じ「問題」を、状態と証拠ごと安全に引き継ぐための層。設計文書にもその趣旨で書き直した記録が残っている。

何を作ったのか

管理の単位は会話でも人間向けのメモでもなく、Problem——「いま解こうとしている問題」そのものだ。残したいのは記録そのものではなく、あとから来た別のAIが同じProblemの続きを安全に始められる状態のほうで、仕組みは全部そのために組んである。

Problemには型のついた記録を積んでいく。こういう仮説を立てた(HYPOTHESIS)、これを試した(ATTEMPT)、この方向は行き止まりだった(DEAD_END)、これが分かった(DISCOVERY)、こう直した(FIX)。それとは別に、「実際に何を実行して、成功したか失敗したか」をVerificationとして記録する。FIXとVerificationをわざと分けているのは、「直すコードを書いたこと」と「直ったことを確認したこと」が別物だからだ。

そのうえで、いくつかのことをAIの善意ではなくサーバー側の規則にした。

  • Problemの状態には遷移規則があり、成功したVerificationがないProblemはVERIFIEDにできない。AIが「直りました」と宣言しても、それはVerificationではない
  • どのProblemに取り組んでいるかはサーバーが権威を持つ。手元に残った古い紐づけはヒント扱いで、使う直前に毎回サーバーで再検証される。別の問題を「続き」だと思い込んで進める事故を防ぐためだ
  • 同じProblemへの並行更新は楽観ロックで守られ、静かな上書きは起きない。記録の追記は冪等で、再送しても二重には入らない

AI側からは9個のMCP toolでこの仕組みに触る。問題を始める・続きに入る・記録を積む・検証を記録する、という並びに加えて、過去の似た経験を引くtoolも用意している。ただし「似た経験がありそうだ」と自動で判断して呼び出す仕組みはまだなく、現時点では明示的に呼ぶ形だ。裏で勝手に何かを覚えたり共有したりする仕組みではなく、記録は明示的に行われる。

実際にどこまで動いたか

確認できたのは、次の2つの組み合わせで「同じProblemを別のAIが継続できる」ことだ。

1つ目はClaude Code ↔ Codex。Claude Codeが開始したProblemを、実際にインストールしたCodexが同じproblem_idで正規に継続できた。IDを手で注入したりせず、サーバーの再検証を通った継続で、別プロジェクトの過去経験を引いて記録を積み、Claude Code側へ戻っても続きが見える。

2つ目はClaude Code → Claude.ai。remote MCP(Streamable HTTP)としてClaude.aiのカスタムコネクタから接続し、9 toolの発見と実際のtool呼び出し、そしてClaude Codeが開始したProblemの同一IDでの継続が、実際のClaude.aiホストで成立した。会話の生ログやcredentialが保存されないことも確認している。

このClaude.aiの検証で、この仕組みの狙いがそのまま見えた場面がある。remoteのセッションは手元でテストを実行できない。だからサーバー側の入口が、テスト実行のような「実行に接地した」種別のVerificationの記録をそもそも拒否する。そして実際のClaude.ai側のモデルも、実行していないテストをVerificationとして記録することを自分から断った。やっていない検証が記録されなかった——仕組みとしても、挙動としても、そうなってほしかった通りだ。

正直に書いておくと、この2つは別々の確認であって、3つのホストを1本の連続チェーンで通したわけではない。またChatGPTについては、互換設計にはなっているが書き込みまでの受け入れ確認は未完了のままで、対応済みとは言えない。

有料のAI APIがなくても動く

途中の設計では、過去の経験を検索する部分をembeddingなどの外部providerに頼る方向も検討していた。最終的には、コアは有料のAI APIなしで成立する形にした。

保存された記録から検索用の成果物を決定的に生成し、全文検索で別プロジェクトの過去経験を候補に出す。語彙がぴったり一致しないときは、厳密な検索がゼロ件のときに限って一度だけ条件を緩める。embeddingを設定すれば意味ベースの検索が上に足されるが、providerがなくても、落ちていても、コアの検索は失われない。財布と切り離してもこの仕組みの芯が動く、というのは個人的に譲りたくなかった部分だ。

一番大事な現在地

ここまでは「技術的に動いた」という話で、そこは確認できている。継続のテストは通っているし、拒否すべきものを拒否する安全側の仕組みもテスト済みだ。

でも、「技術的に動くこと」と「自分の普段の開発で便利なこと」は別の話だ。ここまでの確認は、検証のために用意した問題での確認であって、本物の開発のなかで説明のやり直しが本当に減るのかは、まだ検証できていない。だからこの記事には「めちゃくちゃ便利になった」とは書かない。まだ分からないからだ。

次に実際の開発で問題を踏んだとき、これを本番投入してみる。見たいのはこういうことだ。前回の説明をやり直さずに続きから入れたか。記録してあったDEAD_ENDをもう一度掘らずに済んだか。別の問題を続きだと思い込まなかったか。未検証のものを直った扱いにしなかったか。そして——MCPに記録する手間のほうが、説明をやり直す手間より大きくなっていないか。

最後のひとつが、たぶん一番厳しい審査になると思っている。