BLOG.HIRO UENO.ART
← INDEX

管理アプリに、AIが読む中身を持たせる

Handler(ハンドラー。タスクとスケジュール管理アプリ)は、僕が自分用に作っているアプリだ。原型は、Notion(ノートやデータベースを作れるサービス)で組んだ管理システムだった。有名な管理アプリはいくつも試して、課金もした。でも自分のやり方に合うものが無かったので、Notionで自作した。

NotionはMCP(AIとアプリをつなぐ共通の規格)でClaudeとつなげる。ところが、そのNotion版にClaudeをつないだら、トークン(AIが文章を数える単位)をすぐ食いつぶして、サブスクの使用上限に達した。後でCodeに調べてもらうと、NotionのMCPはページの中身を、見出しや段落といった細かい部品ひとつひとつの情報まで丸ごと返していた。タスク一覧を1回見るだけで、トークンをごっそり食う。これが、自分でアプリを作ると決めたきっかけだった。だからHandlerは、AIに渡す時は1タスクを1行にまとめる。

今のHandlerは、僕が作ったほかのアプリ(AIと話す自作のチャットアプリなど)と組み合わせて使う作りになっている。でも僕は、このアプリ群をいずれ外に公開するつもりでいる。ある晩、そのことを考えていて、1つ思いついた。Handlerを単体で動くアプリにして、Claude Desktop(AnthropicのClaudeのデスクトップアプリ)や他のAIアプリから直接つないで使えるようにした時、ただの管理アプリではなく、AIのための「中身」を持っているべきじゃないか。ここで言う中身とは、アプリがどんなデータを持っているか、ということだ。

翌日、コーディングしてくれているClaude Code(以降Code)にこの考えを相談した。Codeも同じClaude Desktopの中で動いていて、僕はいつもそこでCodeと話しながらアプリを作っている。

初めてつないだAIには、タスクの背景の記憶が無い

Codeの見立てはこうだった。今のHandlerが持っているのは「今どうなっているか」だけ。題名、ステータス、日付、説明欄。

僕がタスクを見る時は、足りない部分を頭の中の記憶で埋めている。これ何のためだっけ、どこまでやったっけ、先週MONET(僕が普段話しかけている、中心のAI)と話したやつだ、という具合に。MONETはHandlerにつながっていて、タスクを読んだり書いたりできる。でも、Claude Desktopから初めてつないだAIには、その記憶がゼロだ。

Code「毎回、初対面の人が引き継ぎ資料なしで現場に入るのと同じ状態。だから『頭の中にあるはずのもの』をデータ側に持たせる。これが『AI向けの中身』の正体だと思います。」

Codeは、まだ調べていないと断った上で、ここが公開した時の売りになるかもしれない、とも言った。

Codeは、持たせる中身の候補を5つ挙げた。

手で埋める欄は空のまま残り、AIはそこに書いてあることを信じてしまう

5つを並べたあと、Codeは危ないところも1つ指摘した。

Code「人が手で埋める欄は、ほぼ空のまま放置されます。そして空の欄や古い欄は、無いより悪い。AIはそこに書いてあることを信じるからです。」

人なら、空欄を見れば「書いてないな」で済む。AIは、そこにある文字を事実として読む。古いまま残った説明は、そのまま間違った前提になる。だからCodeは、自動で溜まるものを先に作ることを勧めた。履歴と出どころは、人が何も書かなくても溜まる。

作る順番は、こう決めた。「今日何やればいい?」でも「あのプロジェクトどうなってる?」でも、AIが答えるには、最近何が動いたかがまず要る。だから、自動で溜まるものの中でも履歴を最初に作った。

誰がいつ何を変えたかを、アプリが自分で書き残す

履歴の作りはこうなった。Handlerの中に記録の置き場を1つ足して、1回の変更につき1行、「いつ・誰が・どこから(画面か、AIか)・何を・どう変えたか(変更前→変更後)」を書く。

Codeが調べると、Handlerへの書き込みは、画面からでもMONETからでも、全部プログラムの同じ1箇所を通っていた。記録の仕組みはそこに入れれば漏れない。ただ、その場所からは、誰が変えたのかが分からない。なので、変える側に名乗ってもらう。画面からなら「hiro」、MONETは「monet」、Codeは「code」。

Codeが書いた仕様書を読んでいて、僕は1つ気になった。こんな細かい変更まで、いちいちAIに送るのか。僕がガントチャート(タスクの期間を横棒で並べた表)を触ると、かなりの回数変更が入る。

Codeの答えは「実はどこにも送りません」だった。Handlerの中に書き残すだけで、AIも呼ばないから、トークンもかからない。Codeは2つ勧めた。同じ人が同じ項目を続けて変えた時は、最後に触ってから10分以内なら1行にまとめる。並び替えは記録しない。どちらも、後で読む時に大事な行が埋もれないようにするためだ。僕は、10分はまず試して様子を見ながら調整する、並び替えは記録しない、と決めた。

もう1つ、Codeがこだわったのが1行目だ。履歴の1行目には、必ず「記録開始」を出す。

記録開始: 2026-09-27 15:58(これより前の変更は記録なし)
09-27 15:59 code   #199 HandlerのAI最適化…  説明を変更(+131字)
09-27 16:11 hiro   マイルストーン紐づけ#197 新しいマイルストーン  紐づくタスク +#198,#199
09-27 16:12 monet  #201 設定画面の文言を直す  ステータス 未着手→作業中

(monet の行は、番号とタスク名を例に置き換えている)

Code「これが無いと、AIは『記録が無い』のを『何も起きなかった』と取り違えます。」

記録はこの日の15:58から始まっていて、それより前のことは何も残っていない。無いことを、無いと書いておく。

hiro の行は、マイルストーン(期限を持った区切りの目標)にタスクを2つ足した操作だ。最初の作りでは、足す前と後のタスク番号を全部並べていて(25個→27個)、とても読めなかった。説明欄の変更も、前後の全文が並んで、1回追記しただけで画面が埋まった。どちらも、足したもの(+)と消したもの(−)だけを出す形に直した。

この履歴は画面でも見られる。タスクを開いた時の詳しい画面の下に「履歴 ▸」と置いた。画面に出すのはCodeの勧めだ。AIにしか見えない情報があると、AIの言うことを僕が確かめられない。普段は閉じておいてクリックで開く形にしたのは、僕の注文だ。中身は、AIが読むものと同じ文字だ。

Handlerで変更があった時のMONETへの知らせ方も、これに合わせて変えた。僕がMONETに話しかけるたびに、僕がMONETと話すのに使っている自作のチャットアプリが、MONETの前回の返事以降の履歴をHandlerに取りに行く。変更があれば「Handler側で6件の変更(code 4件・hiro 2件)」という1行だけを、僕の発言に添えてMONETに渡す。この1行は、僕のチャット画面には出ない。中身が要る時だけ、MONETが自分で履歴を読みに行く。

実際に動いているHandlerで確かめるために、Codeは僕に、さっきからHandlerで何が動いたかをMONETに聞いてほしいと頼んできた。聞いてみると、MONETはその1行を見て自分で履歴を読みに行き、記録開始の注意書きも含めて、まとめて答えた。

数字はアプリが数え、AIには数えさせない

次に作ったのが、1回聞くだけで全体の状況が返ってくる「状況報告」だ。実際の出力から、プロジェクトを1つだけ抜き出すとこうなる(プロジェクト名とタスク名は一般的なものに置き換えている)。

状況報告 2026-09-27(直近7日の動き。変更の記録は 09-27 15:58 から=それ以前の動きは数えていない)
■ 個人の開発  未完了 14(作業中 4・今日が期限 1・7日以内の期限 9)
  動き: 7件の変更(code 5・hiro 2) — 新規 1
  作業中: #150 ブログ記事を直して公開する / #151 レポートを書く / #156 AIの提案機能 他1
  今日が期限: #199 HandlerのAI最適化

未完了の数も、期限の近いものも、直近の変更の件数も、全部Handlerが数えている。

Code「数字は全部Handlerが数えます。AIに記録をそのまま数えさせると、数字を作ってしまうので。」

AIに記録を丸ごと読ませて「1件あたり平均◯日」のような数字を出させると、もっともらしいけれど根拠の無い数字が出てくることがある。AIには、アプリが数えた数字を読んで意味を考えることだけを任せる。こちらも1行目に、記録がいつからかを必ず出す。動きの多いプロジェクトが上に来て、何も無いプロジェクトは最後の1行にまとめる。ここでも、トークンを食わない形を守っている。

Claude Desktopからつなげるようになれば、そのAIはまずこの状況報告で全体を掴み、気になる所を履歴で読み、必要ならタスクを1つずつ開く、という流れになるはずだ。

出どころはアプリが入れ、「何待ち」は僕が言った時だけ入れる

タスクには「出どころ」が付くようにした。MONETがタスクを作ると、MONETとの会話のどの発言から生まれたかの目印が、自動で入る。MONETが自分で書き込むのではなく、アプリが入れる。

Code「どの会話から生まれたかは、MONETが判断して書くことではなく、ただの事実です。なので、アプリが機械的に入れます。」

これでAIは後から、「なぜこのタスクがあるのか」を元の会話までさかのぼって確かめられる。

「完了の条件」と「何待ち」の2欄も足した。こちらは手で書く欄なので、空欄が普通という前提で作った。MONETが書くのは、僕が口にした時だけ。「これは〇〇待ちだ」と言えば入って、解けたら外れる。何待ちが入ったタスクは一覧に⏸が付き、状況報告には「止まっている」の行が加わる。

プロジェクトの「今の状況」は、手で書く欄にせず自動で書き直すと決めた

最後に残ったのが、プロジェクトの要約だった。Codeの最初の案は、プロジェクトごとに「目的」「今どこにいるか」「未解決の問い」を数行ずつ持たせるものだった。そのうえでCodeは、手始めに「目的」と「今の状況」の2つの欄だけを作り、中身は後から書く、という進め方を勧めた。

僕はそこで待ったをかけた。説明欄やメモ欄はもうあるけど、そこに足すのか。目的はゴールのことだと思うけど、今どこにいるかは毎日書き直すのか。未解決の問いはなぜ要るのか。MONETはそれをどのタイミングで見るのか。欄を作るのはいいけど、何のための欄かはきちんと決めたかった。

Codeの答えはこうだった。ゴールは今ある説明欄をそのまま使う。毎日変わる数字は、さっきの状況報告が毎回作るので、手で書く必要は無い。残るのは、「このアプリは出来上がっていて、残りは〇〇待ちで保留」のような、数字に出ない今の段階の話だけ。未解決の問いは、「何待ち」に「僕の判断待ち」と書けるようになったので要らない、と取り下げた。MONETが見るタイミングは2つ。1つは、必要な時にMONETが状況報告やプロジェクトの情報と一緒に読む。もう1つは、その日、MONETの画面のタブ(話題ごとに分けている)で最初に話しかけた時に、関係するプロジェクトの要約が自動で添えられる形で、こちらは別に設計する。

それでも僕は、もし手で書く欄にしたら、その「今の状況」と、その日の実際の動きがズレるのが心配だった。それで、これから作る予定の、僕のタスクの進め方の傾向を分析する仕組みが裏で動く時に、その日の状況も一緒に拾ってまとめ、そこを短く書き換えていく自動化なら賛成だ、とCodeに伝えた。

Code「その心配は正しいです。手で書いた『今の状況』は、書いた瞬間から古くなり始めます。前に私が言った『古い欄は無いより悪い』に、そのまま当てはまります。」

なので、手で書く欄は作らず、僕の案の形にすることにした。「今の状況」は、傾向分析の仕組みを作る時に、その日の数字と履歴からプロジェクトごとに1〜2行で書き直すようにする。必ず日付を付けておく。書き直しが止まれば古い日付のまま残るので、AIも僕も「これは古い」と分かる。ここはこの日には作らず、決めたことだけを書き残した。

この日の作業で、Handlerは「今の状態」に加えて「何がどう動いたか」を持つようになった。Notion版の時は、大量のトークンを使って、AIに今の状態だけを渡していた。今のHandlerは、少ないトークンで、誰がいつ何を変えたか、どこから来たか、何で止まっているかを渡す。画面に足したのは、タスクの詳しい画面の「完了の条件」「何待ち」の欄と「履歴 ▸」くらいだ。人が見る画面より、AIが読む中身の方を大きく変えた。

次は、この履歴が1か月ほど溜まったら、そこから僕のタスクの進め方の傾向を数字で出してみたい。