Majlis — 鍵を渡さずに、エージェントへ人生のデータを預ける
Majlis は個人用の AI アドバイザー会議です。話し相手となるオーケストレーター、その配下で動く名前を持つ 専門家たち、そして名簿に適任者がいないときに新しい専門家を採用するパイプラインで構成されます。 Claude Code の中で動き、実体は Markdown、憲章、そしてシェルスクリプト 2 本だけです。
設計上の答えは、手渡す鍵が存在しないことです。
なぜ「会議」で、コーディングエージェントではないのか
Claude Code 向けのサブエージェント集は、ほぼすべてがソフトウェアを出荷するために作られています。 コードレビュー、テスト作成、git worktree の管理、PR の要約。ツールの熱量がそこに集まったのは、 そこが投資対効果の見えやすい場所だからです。
空白はそれ以外のすべてです。うまく回すのが本当に難しい人生の領域 — キャリアの方向、健康、お金、 習慣、送ろうと思い続けているフォローアップ — は、ソフトウェアプロジェクトを難しくしているのと同じ 性質を持っています。あなたの注意力より長く生き残る状態があり、レビューのリズムを必要とし、目に見える 指標を最適化すると罰を受けます。そして、言語モデルを無監督で動かすことなど絶対にしたくない領域でも あります。失敗の形がテストの失敗ではなく、半年間それに基づいて行動してしまう誤った判断だからです。
だから会議にしました。「エージェントのチーム」がデモ映えするからではありません。代替案 — 人生のすべてをコンテキストに入れた汎用アシスタント 1 体 — が、安全にも正確にもしようがない設計 だからです。キャリア・健康・財務を同時に抱えた単一エージェントには、鋭くあるべき範囲もなく、 強制すべき境界もなく、自分の主張のどれを実際に確認したのかを伝える手段もありません。
名前は装飾ではない
Majlis(مجلس)はアラビア語で「座る場所」 — アドバイザーが集まる評議の間であり、伝統的には 一人が発言権を持ち、他の者は指名されて話す場です。
その最後の部分こそ、この名前が装飾ではなく残った理由です。このアーキテクチャには、あなたが話す席が ちょうど 1 つあります。あなたはオーケストレーターに話しかけ、オーケストレーターが会議に話しかける。 専門家に直接話すことはなく、オーケストレーター自身が作業をすることもありません。実在する社会的形式 から借りた実在する制約であり、慣習として提案されるのではなく、憲章の中で最優先指令として強制されて います。
アーキテクチャ
この中で行数以上の価値があるものが 3 つあります。
オーケストレーターは作業できません。 Jarvis はルーティング、統合、報告を行い、コード・計画・ 調査そのものを書くことを明示的に禁じられています。制限のように聞こえて、実際には強制装置として働き ます。オーケストレーターが力不足のタスクをこっそり引き受けられないため、あらゆる依頼は担当者を 見つけるか、担当者が存在しないことを露呈させるかのどちらかになります。
もう一つ、ここまで効くとは思っていなかった指令があります。オーケストレーターは 要約し、転送しない — 専門家の回答を判断と行動に絞り込む義務があり、メンバーの出力を会話に コピペすることは明示的な失敗とされています。冗長さはメンバー階層と書かれた成果物の側に押し下げ られます。この規則がないと、オーケストレーターは中継器に退化し、専門家に直接聞いたほうが短かった という結果になります。
名簿は自分の欠員を埋めます。 誰も持たない専門性が必要になったとき、まず Researcher が 「その役割の優秀な人間が実際に何をしているか」 — コンピテンシー、ツール、方法論、語彙、成果物、 品質基準 — を調べ、Expertise Brief として返します。次に HR Lead がそのブリーフからペルソナを 設計し、エージェントファイルを書き、登録します。これを単なるプロンプト生成器以上のものにしている 規則は、HR Lead がスキルセットを発明してはならない点です。ペルソナは調査に接地しているので、新しい アドバイザーはモデルが漠然と抱くその役割の平均像ではなく、実在する役割を写します。
セッションが切れても状態は生き残ります。 2 つの受信箱が、オーナー自身の視点で受付と受け渡しを
担います — Team's Inbox/ はあなたが作業を投げる場所、Owner's Inbox/ は完成した成果物が届く
場所です。加えて Team's brain/<member>/ が各メンバーに私的な作業記憶を与えます。このフォルダが
あるのは、長いタスクがセッション上限で切られるからで、再開したメンバーはやり直すのではなく、
自分の書きかけの思考を見つけられるべきだからです。
ここからが本当にセキュリティの問題
これが役に立つためにデータベースに何が入っていなければならないかを問うと、答えはすぐに不快になり ます。基準範囲付きの検査結果。身体指標。食事とサプリメント。口座残高、保有銘柄、取引、純資産の スナップショット、投資方針。誰を知っていて最後にいつ話したかという個人 CRM。日誌。
スキーマの 5 領域のうち 2 つはソース中で [SENSITIVE] と印が付いています。この印は飾りではなく、
暗号化の決定がこの方向に転んだ理由そのものです。
列単位ではなく、データベース全体の暗号化
素直な設計は、機微な列だけを暗号化して残りは検索可能に保つことです。そうしませんでした。理由は 3 つあります。
1 つ目は、列単位の暗号化が「正しく、そして恒久的に、前もって」分類することを強制する点です。一度
間違えれば — 退屈なテーブルの自由記述 notes 列に、たまたま診断結果が入ってしまえば — 何も
おかしくないという顔をしたまま平文が漏れます。データベース全体の暗号化には、間違える分類の工程が
そもそも存在しません。
2 つ目は、機微なのは値よりメタデータであることのほうが多い点です。値ごとに暗号化された
lab_results テーブルは、それでも「何回検査したか、いつ、どのくらいの頻度で再検査したか」を
攻撃者に伝えます。個人のデータセットでは、その形状こそが所見です。
3 つ目は、部分的な暗号化がこのストアを持つ価値そのものを壊す点です。日誌、会議、人、プロジェクト、 ゴール、文書 OCR を横断する統一 FTS5 インデックスが 1 つあり、任意のエンティティ同士を結ぶ関係 グラフが 1 つあります。暗号化された列に対する検索とバックリンクは、動かないか、平文の影インデックス を作る必要があるかのどちらかです。後者は要するに、安心できる名前の付いた「機微データの平文コピー」 です。
したがって SQLCipher で、退屈なテーブルも含めてファイル全体を暗号化しました。
エージェントはデータベースを開かない
これは私が最も強く擁護する設計判断であり、他のすべてを安全にしている土台です。
エージェントは接続を得ません。パスフレーズも、パスフレーズの入力プロンプトも、それを含む環境変数も
得ません。エージェントが生み出すのは、オーナーが後で鍵付きセッションで適用する
ステージングされた .sql ファイルです。
すべてのステージングファイルは 7 つの規則を満たす必要があり、興味深いのは自明なものではありません。
- まず
schema.sqlを確認し、列を推測しない。 正典の DDL は移行のたびに生きたデータベースから 再生成されるので、常に現実を反映しています。これが存在するのは、エージェントがもっともらしい列名を 自信たっぷりに発明することが、この種のシステムが壊れた書き込みを生む最も一般的な経路だからです。 - 鍵を含まない。 成果物の中に
PRAGMA keyも秘密も、決して入りません。 - 事前ガード。 変更が依存する前提条件を検証し、満たされなければ何も変更する前に
RAISE(ABORT, …)で読めるメッセージとともに停止します。 - 単一トランザクション。 ファイル途中の失敗が変更を半分だけ適用した状態にできないようにします。
- 冪等 — 2 回目の実行は no-op。
INSERT OR IGNORE、UPDATE … WHERE <未適用条件>、リンク行のNOT EXISTSガード。 - 通常のデータファイルでは DDL と
DELETEを禁止。 スキーマ変更は特定の専門家の担当領域であり、 破壊的な削除は独立して意図的にレビューされるファイルを必要とします。
-- --- 事前ガード:前提条件を検証し、満たされなければクリーンに中断 ----------------
SELECT CASE
WHEN (SELECT COUNT(*) FROM people WHERE id = 42) = 0
THEN RAISE(ABORT, 'PRECONDITION FAILED: people.id=42 not found — nothing applied')
END;
BEGIN;
-- 2 回目の実行では何にもマッチしないようスコープする
UPDATE people
SET relationship_strength = 4
WHERE id = 42
AND (relationship_strength IS NULL OR relationship_strength <> 4);
COMMIT;
これを本物にしているのはバリデーター
誰も検査しないプロトコルはコメントです。validate_staged.sh がゲートであり、冪等性を証明する
その方法が気に入っている部分です。
database/validate_staged.sh database/add_meeting_followups_20260901.sql
schema.sql から使い捨ての平文 SQLite データベースを構築し、必要ならフィクスチャを投入して
ガード付きの更新経路を実際に通し、.bail on の下でステージングファイルを読み、フル .dump を
取ります。そして同じファイルをもう一度適用し、再びダンプして、2 つを diff します。ダンプが
一致すれば、そのファイルは本当に再実行可能です。異なればそう報告し、何が変わったかを見せます。
その 2 回目の適用こそが全体の勘所です。「これは冪等か」は SQL を注意深く読んで検証できる主張では ありません。2 回実行して状態を比較することで検証します。スクラッチデータベースに対してそれを行う コストはゼロで、意図を性質に変えられます。
そして存在しない列は、本番データに対して夜 11 時に失敗するのではなく、一時ディレクトリの中で 失敗します。それが「面倒」と「インシデント」の差です。
リキーと、名前を付ける価値のあるバグ
平文データベースを暗号化版に変換するのは、オーナーが一度だけ実行する操作です。このスクリプトの 設計原則は、置き換え先が自らを証明するまで何も破壊しないことです。
ここには、実際に動かして初めて出てくる類の細部が 2 つあります。
パスフレーズはコマンドライン引数ではなく、here-doc で stdin から sqlcipher に渡されます。引数
にすればシェル履歴に残り、同じマシン上の他プロセスから ps で見えてしまいます — この演習全体を
静かに無効化するローカルな漏洩です。
2 つ目は、設計で回避しなければならなかった本物の偽陽性です。インストールされている SQLCipher CLI は、
PRAGMA key 文それ自体に対して stdout に ok を出力します。したがって自然な検証 — 鍵を適用し、
PRAGMA integrity_check を走らせ、出力に ok が含まれるかを見る — は間違った鍵でも通ります。
本当の整合性チェックは stderr に失敗し、stdout に残るのは PRAGMA key の余計な ok だけだから
です。間違った鍵で成功を返す検証ステップは、検証がないより悪いです。ゴミファイルをあなたのデータに
上書きすることを、嬉しそうに承認してしまうからです。
修正は地味です。すべての値を一意なマーカーの後ろに出力し、マーク付きの値だけを抽出します。
enc_check=$(sqlcipher "$ENC" <<SQL 2>/dev/null
PRAGMA key = '${KEY_ESC}';
SELECT 'ENCCHK:' || integrity_check FROM pragma_integrity_check;
SQL
)
[[ "$enc_check" == *"ENCCHK:ok"* ]] || abort
間違った鍵ではマーカーがまったく出力されないので、チェックは正しく失敗します。これは Watari について書いた RLS のバグと同じ種類の 間違いです。存在し、レビューされ、正しく読め、そして動かない制御です。
6 つのスキル
スキルは、エージェントが名前で呼び出す再利用可能な SKILL.md パッケージです。6 本が同梱されて
いて、まとめて眺めて印象的なのは、どれ一つも機能ではないことです。それぞれが、何かがうまく
いかなかった後に書き留められた規則です。
safe-staged-migration は上述の書き込みプロトコルです。6 本のうち最大で、データに触れる前に
他のすべてのメンバーが従わなければならないものです。
hire-team-member は成長パイプラインです。適任者のいないメンバーがもっともらしい何かを既に
生み出した後ではなく、試行の前に名簿を確認するという規則を持ちます。
owner-intake-interview は専門家が助言の前にベースラインを確立する方法です。オーナーについての
仮定に基づく計画は願望にすぎないため存在し、セキュリティモデルが後付けでないことを示す細部を 1 つ
持っています。平文の identity や嗜好の回答はオーナープロファイルに入りますが、
機微な健康と財務の回答は暗号化ストアへ直行し、Markdown ファイルには入りません。
goal-pace-check は、存在理由を自ら明言している唯一のスキルです。「on pace」が、その裏の
計算なしに主張されたことがあった。 いまは 4 つの入力 — ベースライン、現在値、目標値、実際の期限 —
を要求し、4 つ揃わなければ判定を拒否し、必要な週次レートと予測着地点を計算を見せながら出します。
run-review-cadence は日次から四半期までのループを回します。記憶からレビューせず現在の数字を
引くという指示と、レビューは記録されるだけでなく行動を変えなければならないという基準を持ちます。
collect-open-tasks は、本当にオーナー待ちになっているものを集めるオーケストレーターの
「一巡」です。重複を除き、優先順位を付け、すでに予定済みか回答済みのものは明示的に除外します。
正直な注記を 1 つ。CLAUDE.md はいまも「v1 ではスキルを同梱しない」と書いています。憲章が
リポジトリから乖離しているわけで、ドキュメントが 2 箇所目に存在するときに起きることです。直す
必要があり、schema.sql を手で維持せず生きたデータベースから再生成している理由の小さな実例でも
あります。
計画していなかった通し筋
スキルを書いていて、作っている間には気づいていなかったことが浮かびました。すべてが服を着替えた 同じ規則なのです。システムは、証明していないことを主張してはならない。
書き込みプロトコルは移行が安全だと主張しません — スクラッチデータベースに 2 回適用して実証します。
goal-pace-check は「on pace」と主張しません — 実際の期限に対する計算を見せます。そして習慣の
記録は、獲得していない数字を報告することを拒み、それがこのプロジェクトで一番好きなスキーマ設計を
生みました。
習慣の記録原本が紙の日誌なら、データベースはその定期的な転記です — つまり行がないことは、習慣を サボったことを意味しません。その日がまだ転記されていないことを意味します。カレンダー日でアドヒア ランスを採点すると、この 2 つを混同し、自信を持って誤った、しかも人を落ち込ませる方向の数字が 出ます。
スキーマはそれを分けます。その日に日次の日誌エントリがあれば観測済みとし、アドヒアランスは観測日
のみで採点します。観測済みの日の内側では、チェックがないことは本当にサボりです。観測集合の外側では、
ないことは何も意味しません。そこからカバレッジ — 転記の儀式が回っているかというツーリング指標 —
と、アドヒアランス — 行動の指標 — が得られます。観測日ゼロは 0 ではなく NULL を返し、
NULL のアドヒアランスをゼロや赤として描画することは何にも許されていません。
同じ本能は status の語彙にも現れます。accounts.status は真偽値ではなく 5 値の状態機械です。
「この口座は開いているか」に 3 つ目と 4 つ目の意味が育ち、それが notes の文字列の中に住んでいた
からです。そこから落ちてくる読み取り規則は、間違えて初めて学ぶ類のものです。お金を合計するものは
status = 'open' ではなく status <> 'closed' で絞らなければなりません。ブロック中や解約
手続き中の口座も残高を持っているからです。そして supplements.is_current はトリガー由来の互換列
として残され、下位の状態と食い違う書き込みは静かに受理されるのではなく拒否されます。危険な方向 —
古い 1 行の UPDATE によって臨床上の保留が「服用中」に反転すること — が、決して静かに通っては
ならないからです。
これが当てはまらない場所
これは単一オーナーの設計で、安全性の大半はその前提に依存しています。1 人が 1 つのパスフレーズを 持ち、すべての書き込みを自分で適用します。チームにはスケールしませんし、2 人がアクセスを必要とした 瞬間から鍵の配布と監査ログの世界に入ります。それは別の、そしてはるかに大きな問題です。
書き込み経路も意図的に遅いです。ジムにいるうちに自動でワークアウトを記録するエージェントが欲しい なら、手でレビューするステージングファイルは間違った形であり、そうでないふりをするべきではありません。 私がした取引は、自分の健康と財務データへの書き込みは稀で、影響が大きく、着地する前に読む価値がある というものです。高頻度・低影響のデータに同じプロトコルを当てれば、それはただの摩擦です。
そして、モデルが構造的に妥当なまま間違うことに対しては、何の防御にもなりません。ステージング移行は 完璧にガードされ、冪等で、検証済みで — それでも間違った数字を記録しえます。エージェントが検査結果を 読み間違えたなら。プロトコルが保証するのは、書き込みがレビュー可能で取り消し可能であることです。 それが真であることは保証しません。そのためにレビューのリズムがあり、だからオーナーは適用した後では なく前にファイルを読むのです。
リポジトリは GitHub 上で MIT です。5 人の例示専門家は 足場にすぎません。要点はその下の機構であり、この考えが成立するかを最も速く確かめる方法は、名簿の 誰にもまだできないことを頼んでみることです。