Explore taskl-ai, an AI-agent-powered task manager that addresses search, duplicates, ordering, recovery, and safety through a JSON CLI, event sourcing, SKILL.md, and static S3 pages.
相模原市で IoT 設計を受託しているファームロジックスです。今回はタスク管理(To Do)アプリのお話です。
- Google Task を一切使用しない
- AI エージェントのための CLI ツール、SQLite データベース
- 検索、アイテム重複防止、高度な AI 推論によるソーティング
- AI フェイルセーフなデータ構造
- ウェブページ同期
AI エージェントが話題です
久しぶりのブログになってしまいました。これはまた別に書こうと思っているのですが、最近は AI が書いたようなブログが多くなってきたと同時に、ちょっとしたアイデアは AI が長文にまとめてくれるので、ブログを書くモチベーションが下がってしまいますね。そういえば最近、食べ歩き系のブログが下火のような気がします。私の気のせいでしょうか。
愚痴はこの辺にしておきましょう。最近ちょっと頭がボケがちなので、アイデアを忘れてしまわないうちに書いておきます。今日は、最近流行りの AI エージェントを使って、タスク管理、To Do リスト管理をするアプリを構築した話です。
コード自体はほとんど AI に書いてもらったもので、公開するのは忍びない(?)ので、以下に、モチベーション、技術背景、アイデアなどだけまとめておきます。みなさんも、以下の記事を AI に渡せば、同様なツールを設計してもらえるはずですよ。(すごい時代になりましたね。)
既存の To Do アプリの何が不満なのか
Google Tasks のような To Do 管理アプリを、スマートフォンで使っている方は多いと思います。私も、買い物メモ、仕事メモ、後で調べたいこと、ブログのネタなどを、とりあえずタスクとして放り込む使い方をしていました。
しかし、この使い方をしていると、だんだん困ったことになります。
まず、似たような項目を何度も登録してしまいます。 「牛乳を買う」「牛乳」「牛乳(安いとき)」。この程度なら人間が見れば同じだと分かりますが、To Do アプリ側は基本的に何もしてくれません。気づいたときにはリストが膨らみ、同じような項目があちこちに散らばっています。
次に、探せません。これは Google Tasksで私が最も不便に感じる点だと思うのですが、タスク項目の検索がまともにできません。 コンピュータが登場して以来、コンピュータが一番得意なのは検索です。検索できない情報管理ツールというのは役立たずです。
さらに、買い物中に「今日買わないといけないものだけ出して」「このスーパーで買えるものだけ出して」「野菜、肉、冷蔵品、惣菜、日用品の順に並べて(店内の動線)」と言いたくても、普通の To Do アプリではそういうことが一切コントロールできません。単に「買い物」というフラットなリストを表示するだけでは不十分なのです。
これだけ AI や LLM(大規模言語モデル)が普及してきたのだから、タスク管理そのものを AI エージェントに任せて、好みの形で提示してもらえば良いのではないか、と思ったのが出発点です。
スマホ AI が Internet Explorer になってしまう危機感
もう一つ、大きな動機があります。
今後、Android などのスマートフォン OS はますます AI 化していくはずです。しかし、どうせ Google などの巨大テック企業が用意した、特定の AI サービス(Gemini など)を使うことが前提の機能としてお仕着せで提供されるだけでしょう。私には、Windows 95 が登場してきた頃、Microsoft が Internet Explorer を既定ブラウザとして OS に組み込もうとしていた時代が思い出されます。幸いに PC では、自由なアプリのインストールが許されていましたが、スマホでは原則として Google や Apple が許したアプリしかインストールできず、OS の細かい制御に割り込む隙間はありません。
便利になる面はもちろんありますが、ちょっとプログラミングができる技術者や、自分の作業環境を自分の手で調整したい人のニーズを、そこまで細かく満たしてくれるとは思えません。
しかしながら、タスク管理に限って言えば、OS ベンダが提供するアプリに依存する必要はなく、いま流行りの AI エージェント(nanobot や Hermes Agent など)をバックエンドに、また Matrix や Telegram などのチャットボットアプリをフロントエンドにすれば、スマホからのタスク管理が今よりもっと便利になるのではないでしょうか。
そこで今回、私はまず手始めに、完成品の To Do アプリではなく、AI エージェントが操作しやすく実情に合わせて拡張しやすい小さな To Do CLI の作成から始めることにしました。その基本的なアイデアは、AI エージェントが操作できる To Do アプリというものです。名前は taskl-ai(タスクル・AI)としました。(あまり良い名前ではないですね。)
アイデア1:AI が操作するための CLI と、データベースを「ログ」にする設計
taskl-ai は、人間がマウスやスマホ画面で操作する GUI アプリではありません。コマンドライン(CLI)アプリとして設計し、操作するのは AI エージェントです。
もちろん人間がターミナルから使うこともできますが、設計の中心は「AI がコマンドを実行し、JSON を読み、次の判断をする」ことに置いています。そのため、コマンド出力は基本的に JSON です。成功時は ok: true が返り、失敗時は ok: false と error が返ります。
以下に、実行ヘルプ画面を示します。イメージをお摑みいただけるでしょうか。
usage: taskl [-h] [--data-dir DATA_DIR] [--version]
{init,migrate,lists,add,ls,show,done,delete,candidates,merge,prop,ext} ...
Small SQLite-backed todo CLI for AI agents.
positional arguments:
{init,migrate,lists,add,ls,show,done,delete,candidates,merge,prop,ext}
init Create the data directory and DB.
migrate Apply data-dir migrations.
lists Manage todo lists.
add Add a todo item.
ls List todo items.
show Show one todo item.
done Mark a task done.
delete Hide a task by appending a delete event.
candidates Find existing tasks similar to a proposed title.
merge Merge source task into target task.
prop List, get, set, or delete task properties.
ext List or run trusted local extensions.
options:
-h, --help show this help message and exit
--data-dir DATA_DIR Directory containing taskl.sqlite, migrations, and
extensions. Defaults to TASKL_HOME or XDG data.
--version show program's version number and exit
コアコマンドは、意図的に少なくしています。 一般的な To Do アプリにありがちな、優先度、期限、通知、繰り返し、詳細説明欄などは最初から入れていません。これは手抜きではなく、設計方針です。AI がインターフェイスになるのであれば、固定欄をたくさん持つ必要はありません。prop(属性)というサブコマンドを用意し、必要な情報だけ、後から「属性」として key/value で足せば良いという考え方です。
また、さらに重要なアイデアは、AI エージェントにはプログラムのコーディング能力があるので、必要に応じて taskl-ai を改良、あるいは拡張の提案をしてもらおうというものがあります。そのため、AI エージェントにはあえて taskl-ai のソースコードにアクセスできるようにしています。
状態(Status)を直接上書きしない:Log Structured の採用
今回の設計で重要なアイデアの一つに、データベース(SQLite)を log structured (イベントログ構造あるいはイベントソーシング event sourcing)にしていることがあります。
普通に To Do アプリを書くと、まず tasks テーブルを作りたくなります。そして、タスクを完了したら status を doneに更新し、削除したら行を消す、という書き方が普通だと思います。
しかし taskl-ai では、現在のタスク状態を直接の正本にはしていません。データベースの正本は events テーブルです。
- タスクを追加すると
task.addedイベントが追加される - 完了すると
task.completedイベントが追加される - 削除は物理削除ではなく
task.deletedイベント
つまり、DB の中身は「操作のイベントログ」そのものです。この方式の欠点は、データベースのサイズがどんどん増えてしまうことですが、人が扱う程度の To Do アイテムの量であれば、まず問題になりません。
現在のタスク一覧を得るときは、このイベントログを頭から再生(replay)します。task.added が来たら未完了タスクを作り、task.completed が来たら status を done にする、という具合です。個人用の小規模 To Do であれば、毎回ログを replay しても一瞬で終わるので何も問題はありません。
この設計にしておく大きな利点ですが、「AI エージェントが間違えたとき」にも簡単に行動を戻しやすくなります。AI は便利ですが、平気で大胆なミスをします。有名な OpenClaw が、ユーザーのメールを全て削除してしまった逸話は有名です。ミスを前提にするなら、状態を直接上書きするより、イベントを積み重ねておく方が圧倒的に安全です。
タスクアイテムの重複チェック
Google Tasks などで To Do リストが膨らむ最大の原因の一つは、同じような項目を何度も追加してしまうことです。
taskl-ai では、add の実行時に既存タスクとの類似候補を返します。明確に重複している場合は、--dedupe を指定することで追加を抑止できます。たとえば、すでに「Buy milk」がある状態で、次のように入力したとします。
taskl add "buy milk!" --list --dedupe
テストでは、このケースで新規タスクは作られず、既存タスクが返ることを確認しています。
なお、この重複判定には LLM API を使っていません。LLM を呼べば、もちろん「牛乳を買う」と「牛乳の購入」は似ている、といった判断ができます。しかし、全タスクアイテムを対象に LLM を呼ぶのは重いので、difflib.SequenceMatcher などを使った処理にとどめています。
アイデア2:隔離(sandbox)AI エージェントから「一方通行」の S3 静的ページ生成
CLI はできました。しばらく操作を楽しんでいましたが、買い物中にスマートフォンで毎回 AI とチャットしてタスク一覧を見るのは現実的ではないことに気づきました。スマホの画面でリストを見て、買ったものをカゴに入れたら、その場でタップしてチェックを入れて消していきたいわけです。
本来なら Web サーバーを立てて、そこから SQLite の DB を読ませるのが自然です。しかし、私の AI 範囲は二重隔離(Double-quarantine)な環境にあり、外部から普通にアクセスできる Web サーバーを置こうとすると、認証セキュリティや Web サーバーの設定、リバースプロキシなどが大変です。(運用経験を経た現在ではあまり気にしていませんが、当初、nanobot などの AI エージェントハーネスが、プロンプトインジェクションなどで危険な動作をすることを恐れ、ESXi + QEMU/KVM による二重隔離にしていました。)
そこで今回は、思い切って「一方通行」S3 静的ページ生成という実装を採用しました。
具体的には、AI エージェントがタスク一覧を読み、必要なタスクだけを選び、1枚の自己完結型 HTML ファイル(CSS も JavaScript も全部埋め込み、外部ライブラリなし)を生成します。そして、その HTML を AWS の S3 静的ウェブサイトホスティングに置きます。スマホからは、その静的ページを見るだけです。
「どのタスクを表示するか」「どういう順番で並べるか」のロジックは、HTML レンダラー側には一切持たせません。AI エージェントが taskl コマンドで取り出してきた結果から、店内の動線に合わせて並べ替えた JSON を作り、レンダラーはそれを JavaScript の TASK_PAGE_DATA という定数部分に差し替えるだけです。
チェックボックスは DB を直接更新しない(ローカルでスクリプト生成)
S3 に置いた静的 HTML なので、スマホのブラウザから直接 SQLite を更新する API は存在しません。
ではどうするか?
スマホ側でチェックを入れる(カゴに入れた)状態は、単にブラウザの localStorage に保存して画面上グレーアウトします。 そして、チェックを入れるたびに、画面下部のテキストエリアに、次のような「AI エージェントに後で渡すための更新コマンド(スクリプト)」を自動生成します。
# Infer omitted options before execution: # - Assume $BIN_DIR points to the deployed CLI directory # - Assume taskl data dir: ./taskl-data # - Equivalent full form: $BIN_DIR/taskl --data-dir ./taskl-data done <TASK_ID> $BIN_DIR/taskl done 10 $BIN_DIR/taskl done 32
スマホ画面のイメージは次のようなものです。AI エージェントに「スーパー三和に寄ろうと思います。売り場の動線順にリストを表示して」と頼んでみましょう。次のようなウェブページが生成されました。
買い物が終わったら、このテキストエリアに溜まったスクリプトをコピーして、自宅や職場の AI エージェントのチャット欄に「これ実行しといて」と貼り付けるだけです。AI は必要な環境変数を補って、裏で一括して taskl done 10 などを実行し、SQLite のイベントログに完了を記録します。
AI を助けるための「SKILL.md」
今回、コーディングの大部分は AI エージェントに手伝ってもらったわけですが、README 以外に最も重要だったファイルが SKILL.md(AIへの指示書)でした。
AI にツールを使わせたり、コードを改変させたりする場合、人間向けの README だけでは不十分です。AI エージェントに対する指示が重要です。今回の場合は、
- schema が必要な場合は勝手にテーブルを増やさず、migrations/ の SQL を経由する
- 静的ページ生成の際は、HTML の全体を書き換えてはならない。TASK_PAGE_DATA 部分だけを差し替える
のような詳細を SKILL.md で指示するようにしました。
まとめ
実は、今回ブログにまとめた結果は一度にまとめて作成した成果ではなく、何回の追加設計をしています。当初は全て AI エージェントにチャットで尋ねたり指示したりという形式でしたが、買い物中にアイテムにチェックを入れたりなどの操作ができず不便でした。ウェブページの作成機能は、後から追加したものです。
また、ツールの設計や修正では、AI エージェントに多くを手伝ってもらいました。運用を一度開始してから、データベースの破壊未遂、AI の勘違いなどが発生したときなど、AI チャットボットに「なぜ事故を起こしかけたのか」、「なぜ勘違いをしたのか」などを尋ね、ツールの設計や SKILL.md の修正提案をしてもらいました。それを反復して適用したのが、今回の結果です。
今後も、少しずつ運用を重ねて修正していきたいと考えています。
今回の経験から得られた知見は以下のようなものです。
- 既成品の「なんでもいろんなことができるアプリケーション」は時代遅れになるかもしれない。ごく基本となる骨格だけを用意し、必要な改良については、ユーザーと AI が対話をしながら改良していくことができる。
- 最近言われているように、スマートフォンのアプリは消滅するか、そこまでいかなくても、本質的なアプリに集約していくだろう。AI エージェントがスマートフォンの基本機能にアクセスできるようになれば、多くのアプリケーションは不要になる。
例えば、AI エージェントがアラームを設定できるようになれば、今回の To Do 管理アプリが、スーパーマーケットへの近接を検出してアラームを鳴らすことができるので、従来使われていたような「目的地への接近お知らせアラート」アプリは要らなくなる。 - 現在、Google や Apple などのスマートフォンベンダは、いわゆる AI エージェント(OpenClaw、Hermes Agent など)への強い危機感を持っているはずである。表向きは、Gemini や Siri などのアプリを改良することでユーザーの目をそらしているが、いずれ、押し付けの AI でユーザーを納得させ続けることはできなくなるだろう。
おしまい。


