動作動画
本記事は以下を目的としたものではありません。
- 医療行為・治療
- 他人に対する行動強制
本記事で紹介する仕組みは、
「自分で決めたルールを、自分で破ったときだけ発動する」
個人実験・OSSとしての実装記録です。
はじめに
私は、意思だけでは行動を制御できない人間です。
ストレスが溜まると、どうしても報酬を求めて悪習慣に流れてしまいます。
習慣管理系の有料サービスを使っても、
スマホにいくらリマインドしても、結局は無視してしまいます。
なぜなら、守らないといけない強制力が低いからだと私は結論しました。
そこで、
ストレスの少ない状態で自分自身が決めたルールを、
1日中、仕組みとして自分に強制させ、
破ったら痛い、無視したら痛いという形で執行することで、
行動が本当に変わり、QoLを上げられるのかを試す仕組みを作りました。
この仕組みと、その実装・運用結果をまとめたのが本記事です。
想定読者
- 自堕落な生活を是正したいけど治せない方
- 習慣化アプリ・リマインダー・ToDo管理に何度も挫折してきた方
- 「結局、人は痛い目を見ないと変わらないのでは?」と内心思っている方
- LLM / Agent / CLIツールの実験的活用に興味がある方
- 商用サービスでは絶対に実装できないアイデアをOSSで試したい方
目次
- 背景
- システム概要
- 実装解説
- 結び:現時点の効果と手応え
1. 背景
前回の記事
【狂気の実証実験1】AIエージェントに電気ショック権限を付与したら生活が更生した
では、懺悔すると電気ショックを受ける仕組みを作り、二度寝の改善を試みました。
その結果は以下の通りです。
- 二度寝率:
30%(17日中、5日二度寝)
※ 実証実験前は57%
数値としては改善したものの、正直なところ、全然ダメダメという印象でした。
しかし、懺悔を通して日々の行動を振り返る中で、
「なぜ二度寝してしまうのか」という因果関係が見えてきました。
二度寝を誘発するサイクル
- 適切に休憩せずに集中し続けるため、ストレスが溜まる
- 業務時間後にストレスを発散しようと、報酬系を求める行動を取ってしまう
(ギャンブル、ネットサーフィン、無駄な ChatGPT との対話など) - 就寝が遅くなる
- 6時半起床では睡眠時間が足りず、二度寝する
こうして見ると、
原因は 1 と 2 にあり、その結果として 3 と 4 が発生していることが分かります。
そこで本記事では、
ストレスが溜まる前に決めた行動ルールに、
1日中、仕組みとして従わざるを得ない状態を作ることで、
このサイクルを断ち切れるのではないかと考えました。
その仮説を検証するために実装したのが、
本記事で解説するシステムです。
2. システム概要
※Pavlokについて知らない方は開いて下さい※
Pavlokは、行動変容(Behavior Change)を目的としたウェアラブルデバイスです。
主な特徴:
-
手首に装着するリストバンド型デバイス
-
以下の刺激をユーザーに与えることが可能
- バイブレーション(vibe)
- ビープ音(beep)
- 電気刺激(zap)
-
スマートフォンアプリおよびAPI経由で外部から制御可能
本来は「禁煙 / 早起き / スマホ依存対策」などが想定用途ですが、
APIを公開しているという一点で、今回の構想と相性が良すぎるデバイスでした。
本記事では、
「AI Agentが人間を監視し、必要に応じて物理的な刺激を与える」
という用途でPavlokを使用します。
※電気刺激と書いていますが、強度は 1〜100で調整可能 です。
とはいえ、利用は自己責任でお願いします。
このシステムは、
「自分で決めた行動ルールを、1日中、AIに監視・執行させる」
ことを目的としています。
全体の流れは大きく以下の3工程に分かれています。
- 朝:その日の行動ルールに合意し、スケジュールを作成する
- 日中:行動を定期的に確認し、必要に応じて即時介入する
- 夜:1日の振り返りと、溜まった負債(罰)の精算を行う
上の図は、この3工程が
Slack・AIエージェント・Pavlok・ローカルスクリプト
によってどのように連携しているかを表しています。
以降では、それぞれの工程について詳しく解説します。
0) 前提: AIエージェントの判断基準
AIエージェントの判断基準は
ユーザーが自身で定義した情報がベースになります。
私の場合は、以下のように定義しています。
## コーチング対象者情報
### 目標
生産性の高い時間の使い方ができるように習慣化したい
### 良い習慣
- 毎日6:30(JST)に起きる
- 毎朝ジムに行く、ないし運動する
- 毎日1時間、エンジニアリングに関わるInputをする
- 毎日1時間、何かしらのoutputをする
- 就寝前に瞑想をする
- 毎日22時(JST)に寝る
- 週に1度、子供と散歩する
- 週に1度、子供と公園に行く
### 悪い習慣
- ギャンブルをする
- 繁華街に遊びに行く
- スマホゲームをする
- ポルノサイトを見る
- ラーメン食べる
- 自身にコントロールできない他者依存の問題解決を考える
1) 合意とスケジューリング(計画作成)
👆の形で、以下を実施する工程です☀️
- AIエージェント:決まった時間に当日の行動計画候補を立案しSlackへ送信
- ユーザー:リマインド、振り返り、計画策定のスケジュールを決めてSlackへ返信
- AIエージェント: ユーザーの指定通りにDBへスケジュールを登録しSlackへ返信
2) 監視と即時介入(リマインド)
👆の形で、以下を実施する工程です⚡️
- AIエージェント:決まった時間にリマインドをSlackへ送信
- ユーザー:今の状況を素直にSlackへ返信
- AIエージェント:
ユーザー返信をもとに、ユーザー自身が定義した「悪い習慣」に該当するかを判定- 該当した場合:電気ショックを実行
- 該当しない場合:何も起きない
- AIエージェント: 結果をSlackへ返信
なお、規定時間返信がない場合はPAVLOK POINTが1加算され次工程で精算されます。
また、無視した場合は15分後に再度同様のリマインドが来ます。
3) 振り返りと負債の精算
👆の形で、以下を実施する工程です⚡️⚡️
- AIエージェント:決まった時間に振り返りするようにSlackへ送信
- ユーザー:1日の振り返りをSlackへ返信
- AIエージェント: 溜まっている
PAVLOK POINT回分の電気ショックを実行し精算 - AIエージェント: ユーザーに日次レポートをSlackへ返信
3. 実装解説
3.1 レポジトリ
詳細な設計を知りたい方は、こちらを参照してください。
3.2 全体アーキテクチャ
このシステムは、codex CLI × Pythonスクリプト × SQLiteの構成です。
本システムでは以下のように責務を明確に分離しています。
- LLM:判断・文章化のみ(副作用なし)
- Orchestrator:スケジューリングと状態遷移
- Scripts:Slack/Pavlok/DBなどの実処理
- SQLite:強制力を継続させるための状態保持
概要図
3.3 正常起動に必要な前提条件
- AGENTS.md
-
motoya個人向けの定義になっているので自身用に修正してください
-
- codex CLI
- ローカルにインストールされていること
- LLMと疎通可能な状態になっていること
- Pavlok
- 端末を所有していること
- APIキーを取得していること(README.md参照)
- slack
- APIキーを取得していること(README.md参照)
- BOTUSERに適切な権限を付与していること(README.md参照)
3.4 コア設計のポイント
以降、技術的な工夫の要点になります。
1) CLI型Agentをオーケストレーター化
main.py の ScheduleExecutor が1分周期で schedules テーブルを監視し、
scheduled_date <= now のレコードを順に処理します。
-
schedulesレコードで指定されたprompts/{prompt_name}.mdを読み込み -
schedule_id / state / last_result / last_error / input_valueを埋め込み
そのプロンプトを codex exec に渡してLLMを起動します。
成功時は state=done、失敗時は state=failed にし、RETRY_DELAY_MIN 分後に再実行させることで無限ループを防ぎます。
また、当日分の morning が未登録なら自動で1件作成するため、起動するだけで朝の計画作成が必ず走る仕組みです。
2) Pythonスクリプト + Skills の組み合わせ
プロンプト内の「行動」は、すべて scripts/*.py に切り出し、
各scriptの実行方法を.codex/skills/*に定義しています。
つまり、LLMはskill実行の指示を出すだけで、実際の処理はスクリプトが実行します。
-
scripts/slack.py:質問投げる / 返信待ち / スレッド返信(JSONで返す) -
scripts/pavlok.py:Pavlok刺激(API)送信。日次上限や強度上限をDB,設定値で制御 -
scripts/add_schedules.py:その日の予定を一括登録 -
scripts/behavior_log.py:行動ログの書き込み・読み出し -
scripts/add_slack_ignore_events.py:返信なしイベント登録 & 罰ポイント加算 -
scripts/repentance.py:未消化の罰をまとめて実行
この「Pythonスクリプト群」が、Codexの Skill として機能しています。
3) SQLiteで状態を保持
app.db(SQLite)に状態を持たせることで、プロセス再起動や無視の累積にも耐えます。
-
schedules:実行待ち/実行中/失敗/完了の状態管理 -
behavior_logs:良い/悪い行動ログ -
slack_ignore_events+daily_punishments:返信なし → 罰ポイントの累積 -
pavlok_counts:Pavlok日次上限カウント
LLMが落ちても「どこまで進んだか」「罰がいくつ溜まってるか」はDBに残るため、強制力が途切れません。
具体的なDB定義はこちらを参照ください
schedules
| column | type | note |
|---|---|---|
| id | integer PK | |
| prompt_name | string | 実行プロンプト識別子(例: morning/remind_ask/reflection) |
| input_value | string | prompt用入力(JSON文字列可) |
| scheduled_date | datetime | 実行予定時刻(JST解釈) |
| state | enum | pending/running/done/failed |
| last_result | text | 前回実行結果(stdout) |
| last_error | text | エラー内容 |
| created_at | datetime | |
| updated_at | datetime |
slack_ignore_events
| column | type | note |
|---|---|---|
| id | integer PK | |
| slack_message_ts | string | Slackメッセージts(ユニーク) |
| detected_at | datetime | 無視確定時刻 |
| date | date | 集計日(JST) |
| created_at | datetime |
daily_punishments
| column | type | note |
|---|---|---|
| id | integer PK | |
| date | date unique | 対象日 |
| ignore_count | integer | 無視回数の事実集計 |
| punishment_count | integer | 実行すべきPavlok回数 |
| executed_count | integer | 実行済み回数 |
| state | enum | pending/running/done/failed |
| last_executed_at | datetime | |
| created_at | datetime | |
| updated_at | datetime |
pavlok_counts
| column | type | note |
|---|---|---|
| id | integer PK | |
| date | date unique | 集計日(JST) |
| zap_count | integer | 当日のzap累計回数 |
| created_at | datetime | |
| updated_at | datetime |
behavior_logs
| column | type | note |
|---|---|---|
| id | integer PK | |
| behavior | enum | good/bad |
| related_date | date | 任意(対象日) |
| pavlok_log | json | Pavlok実行結果要約 |
| coach_comment | text | 叱責・助言・要約 |
| created_at | datetime |
4) 工程ごとの可変型プロンプト
prompts/morning.md / prompts/remind_ask.md / prompts/reflection.md は、
共通で {{input_value}} などのプレースホルダを持ちます。
input_value にJSONを入れれば、その日だけの特別条件や個別のリマインド内容を渡せます。
さらに last_result / last_error を渡しているので、失敗時リトライの指示変更も可能です。
5) 他CLI Agentへの置き換え可能性
現状は codex exec を呼んでいますが、main.py の run_codex() を差し替えるだけで、 理屈上は gemini CLI や claude code にも置き換え可能です。
ClaudeCode,GeminiCLIで試したい方は開いてください
- 現状、main.pyに以下のようにハードコーディングしているため実行コマンドの修正が必要です。
def run_codex(self, prompt: str) -> subprocess.CompletedProcess:
cmd = ["codex", "exec", prompt]
self.log(f"codex exec: {self.format_command(cmd)}")
return subprocess.run(cmd, text=True, check=False
-
skillsの配置がcodex仕様に固定しているため使用したいCLI Agentの仕様に合わせてリネーム、配置移動をお願いします
-
GeminiCLIの場合は、AGENTS.mdをGEMINI.mdにリネームしてください
3.5 課題
-
codex CLIの場合、コマンド実行のタイムアウト設定がLLMの判断に依存するため、稀にslackが二重に飛んでくる
⇨slack送信前にsleepつけて対策しました -
ローカル端末を常時アクティブにしないと成立しないためクラウドサーバーに移行したい
⇨conoha VPSを契約してサーバー環境にデプロイ済です - daily_punishment.dateを起点に罰回数を管理しているが、日付起因にすると
repentance実行後にscripts/add_slack_ignore_eventsが発生した時にdaily_punishment.state = doneに1加算されてしまい罪が正しく記録されない - morningと振り返りは1日1つであるべきだが、複数個登録される問題
- リマインドを無視すると
振り返りイベントとしてスケジュールに再登録される問題
4. 結び:現時点の効果と手応え
まだ運用して3日ほどで、二度寝率は 33%(3日中1日) と正直まだ変わっていません。
ただ、現時点で明確に感じている成果があります。
それは、時間を効率よく使う意識が久々に芽生えたことです。
具体的な変化の例
以前は、
サウナに行く際に車の中で YouTube をだらだら見てから入浴し、
帰宅が深夜になる、という悪習慣がありました。
そこで、
「サウナ前後はウダウダせずに行って帰ってくる」というルールを事前に決め、
AIエージェントのリマインドに対して
「すぐ帰る」と返信してからサウナに入るようにしました。
その結果、
これまで3時間以上かかっていた行動が、
1時間半ほどで完了するようになりました。
仕組みとして感じたこと
ストレスの少ない朝に1日の行動計画を立て、
その計画に従わざるを得ない強制力を持たせる仕組みは、
私にとって「時間効率」という大切な感覚を思い出させてくれました。
今後について
長期運用で人がどう変わるのかは、まだ分かりません。
ただし私は、この仕組みが
自分の QoL を最大限に高めるための手段になり得る
と感じています。
まずは1ヶ月間、
Pavlok を外さずにこのシステムを常時起動させ、
自分自身がどう変容するのかを引き続き検証していきます。
PS::参加募集(OSSです)
本構想はOSSです。
一緒に機能拡張してくれる方、募集中です⭐️
電気ショック受ける実験は私だけでも構いませんw
何か力になりたいと少しでも思いましたら、👇のいずれかに連絡ください!
- 本記事のコメント
- GitHub Issue: pavlok_CLI_agent
- X(旧Twitter)DM: @puchan_pig






