1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【狂気の実証実験4】AIエージェントに電撃自己調教権限を付与したら、浪費していた時間を取り戻した

Posted at

動作動画

本記事は以下を目的としたものではありません。

  • 医療行為・治療
  • 他人に対する行動強制

本記事で紹介する仕組みは、
「自分で決めたルールを、自分で破ったときだけ発動する」
個人実験・OSSとしての実装記録です。

はじめに

私は、意思だけでは行動を制御できない人間です。
ストレスが溜まると、どうしても報酬を求めて悪習慣に流れてしまいます。
習慣管理系の有料サービスを使っても、
スマホにいくらリマインドしても、結局は無視してしまいます。
なぜなら、守らないといけない強制力が低いからだと私は結論しました。

そこで、
ストレスの少ない状態で自分自身が決めたルールを、
1日中、仕組みとして自分に強制させ、
破ったら痛い、無視したら痛いという形で執行することで、
行動が本当に変わり、QoLを上げられるのかを試す仕組みを作りました。

この仕組みと、その実装・運用結果をまとめたのが本記事です。

想定読者

  • 自堕落な生活を是正したいけど治せない方
  • 習慣化アプリ・リマインダー・ToDo管理に何度も挫折してきた方
  • 「結局、人は痛い目を見ないと変わらないのでは?」と内心思っている方
  • LLM / Agent / CLIツールの実験的活用に興味がある方
  • 商用サービスでは絶対に実装できないアイデアをOSSで試したい方

目次

  1. 背景
  2. システム概要
  3. 実装解説
  4. 結び:現時点の効果と手応え

本記事の読み方

  • 概要だけ知りたい方(目安5分)
    → 「背景 / システム概要 / 結び」だけ読めばOKです(実装解説は読み飛ばし)
  • 仕組みまで理解したい方(目安10分)
    → 上記 + 「3. 実装解説」の前半(3.2 全体アーキテクチャ)をご覧ください
  • 実装を追いたい方(目安15分〜)
    → 「3. 実装解説」全体と、GitHub公開ソース・設計書をご参照ください

1. 背景

前回の記事
【狂気の実証実験1】AIエージェントに電気ショック権限を付与したら生活が更生した
では、懺悔すると電気ショックを受ける仕組みを作り、二度寝の改善を試みました。

その結果は以下の通りです。

  • 二度寝率:30%(17日中、5日二度寝)
    ※ 実証実験前は 57%

数値としては改善したものの、正直なところ、全然ダメダメという印象でした。

しかし、懺悔を通して日々の行動を振り返る中で、
「なぜ二度寝してしまうのか」という因果関係が見えてきました。

二度寝を誘発するサイクル

  1. 適切に休憩せずに集中し続けるため、ストレスが溜まる
  2. 業務時間後にストレスを発散しようと、報酬系を求める行動を取ってしまう
    (ギャンブル、ネットサーフィン、無駄な ChatGPT との対話など)
  3. 就寝が遅くなる
  4. 6時半起床では睡眠時間が足りず、二度寝する

こうして見ると、
原因は 12 にあり、その結果として 34 が発生していることが分かります。

そこで本記事では、
ストレスが溜まる前に決めた行動ルールに、
1日中、仕組みとして従わざるを得ない状態を作ることで、
このサイクルを断ち切れるのではないかと考えました。

その仮説を検証するために実装したのが、
本記事で解説するシステムです。

2. システム概要

image.png

※Pavlokについて知らない方は開いて下さい※

image.png

Pavlokは、行動変容(Behavior Change)を目的としたウェアラブルデバイスです。

主な特徴:

  • 手首に装着するリストバンド型デバイス

  • 以下の刺激をユーザーに与えることが可能

    • バイブレーション(vibe)
    • ビープ音(beep)
    • 電気刺激(zap)
  • スマートフォンアプリおよびAPI経由で外部から制御可能

本来は「禁煙 / 早起き / スマホ依存対策」などが想定用途ですが、
APIを公開しているという一点で、今回の構想と相性が良すぎるデバイスでした。

本記事では、
「AI Agentが人間を監視し、必要に応じて物理的な刺激を与える」
という用途でPavlokを使用します。

※電気刺激と書いていますが、強度は 1〜100で調整可能 です。
とはいえ、利用は自己責任でお願いします。

このシステムは、
「自分で決めた行動ルールを、1日中、AIに監視・執行させる」
ことを目的としています。

全体の流れは大きく以下の3工程に分かれています。

  • :その日の行動ルールに合意し、スケジュールを作成する
  • 日中:行動を定期的に確認し、必要に応じて即時介入する
  • :1日の振り返りと、溜まった負債(罰)の精算を行う

上の図は、この3工程が
Slack・AIエージェント・Pavlok・ローカルスクリプト
によってどのように連携しているかを表しています。

以降では、それぞれの工程について詳しく解説します。

0) 前提: AIエージェントの判断基準

AIエージェントの判断基準は
ユーザーが自身で定義した情報がベースになります。

私の場合は、以下のように定義しています。

AGENTS.md
## コーチング対象者情報
### 目標
生産性の高い時間の使い方ができるように習慣化したい

### 良い習慣
- 毎日6:30(JST)に起きる
- 毎朝ジムに行く、ないし運動する
- 毎日1時間、エンジニアリングに関わるInputをする
- 毎日1時間、何かしらのoutputをする
- 就寝前に瞑想をする
- 毎日22時(JST)に寝る
- 週に1度、子供と散歩する
- 週に1度、子供と公園に行く

### 悪い習慣
- ギャンブルをする
- 繁華街に遊びに行く
- スマホゲームをする
- ポルノサイトを見る
- ラーメン食べる
- 自身にコントロールできない他者依存の問題解決を考える

1) 合意とスケジューリング(計画作成)

image.png

👆の形で、以下を実施する工程です☀️

  • AIエージェント:決まった時間に当日の行動計画候補を立案しSlackへ送信
  • ユーザー:リマインド、振り返り、計画策定のスケジュールを決めてSlackへ返信
  • AIエージェント: ユーザーの指定通りにDBへスケジュールを登録しSlackへ返信

2) 監視と即時介入(リマインド)

image.png

👆の形で、以下を実施する工程です⚡️

  • AIエージェント:決まった時間にリマインドをSlackへ送信
  • ユーザー:今の状況を素直にSlackへ返信
  • AIエージェント:
    ユーザー返信をもとに、ユーザー自身が定義した「悪い習慣」に該当するかを判定
    • 該当した場合:電気ショックを実行
    • 該当しない場合:何も起きない
  • AIエージェント: 結果をSlackへ返信

なお、規定時間返信がない場合はPAVLOK POINTが1加算され次工程で精算されます。
また、無視した場合は15分後に再度同様のリマインドが来ます。

3) 振り返りと負債の精算

image.png

👆の形で、以下を実施する工程です⚡️⚡️

  • 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:強制力を継続させるための状態保持

概要図

image.png

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.pyScheduleExecutor が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実行の指示を出すだけで、実際の処理はスクリプトが実行します。

この「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.pyrun_codex() を差し替えるだけで、 理屈上は gemini CLIclaude code にも置き換え可能です。

ClaudeCode,GeminiCLIで試したい方は開いてください
  • 現状、main.pyに以下のようにハードコーディングしているため実行コマンドの修正が必要です。
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日) と正直まだ変わっていません。
ただ、現時点で明確に感じている成果があります。
それは、時間を効率よく使う意識が久々に芽生えたことです。

具体的な変化の例

image.png

以前は、
サウナに行く際に車の中で YouTube をだらだら見てから入浴し、
帰宅が深夜になる、という悪習慣がありました。

そこで、
「サウナ前後はウダウダせずに行って帰ってくる」というルールを事前に決め、
AIエージェントのリマインドに対して
「すぐ帰る」と返信してからサウナに入るようにしました。

その結果、
これまで3時間以上かかっていた行動が、
1時間半ほどで完了するようになりました。

仕組みとして感じたこと

ストレスの少ない朝に1日の行動計画を立て、
その計画に従わざるを得ない強制力を持たせる仕組みは、
私にとって「時間効率」という大切な感覚を思い出させてくれました。

今後について

長期運用で人がどう変わるのかは、まだ分かりません。
ただし私は、この仕組みが
自分の QoL を最大限に高めるための手段になり得る
と感じています。

まずは1ヶ月間、
Pavlok を外さずにこのシステムを常時起動させ、
自分自身がどう変容するのかを引き続き検証していきます。

PS::参加募集(OSSです)

本構想はOSSです。
一緒に機能拡張してくれる方、募集中です⭐️

電気ショック受ける実験は私だけでも構いませんw
何か力になりたいと少しでも思いましたら、👇のいずれかに連絡ください!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?