すくらっぷ あんど びるどー(したい)

AI・Obsidian・個人開発の試行錯誤ログ。 作業メモを、あとで使える知識に変えるための記録。

ObsidianにAI提案を直接書かせない。Canvas付箋で“仮置き”する方法

はじめに

ObsidiaをAIとの共同で使用する場所としていて、今回はAIと人間が協力してあつかう場所を設定した。

これは元々AIに考えの元となる調べたことやコードなど保存、メモリ管理などの観点からObsidiaを使用していたが、それとは別に僕の方でも使用していて、AIと協力してやる時にチャット欄だけだと非常にやり難いことがあったからである。

またもともとObsidiaでのCanvasをフォルダの代わりに使用していて、ここにメモを集め、構造を考えて、そこからまとめるといったことを行っていたという理由もある。

そこで今回は、Obsidian Canvasを「人間とAIの中間レイヤー」として使う仕組みを作った。 中味の運用として簡単にまとめるとこうなる。

  • 正式な記録はMarkdownに残す。
  • 曖昧な考えやAIの提案はCanvasに置く。
  • AIが参照するのは、Canvas本体ではなく、システム側で生成した軽量Indexに限定する。

この設計により、Obsidianを「人間が考える場所」として保ちながら、ローカルLLMの提案も扱えるようにした。

やりたかったこと

  • まだ言語化しきれていない考え
  • ローカルAIとの会話から出た候補
  • 後で整理したい問い
  • 何かにつながりそうな仮説
  • 採用するかどうか未定の提案
  • 案件ごとのCanvasに置きたい小さな気づき

これをMarkdown本文に直接書き込むと、正式なノートと未確定なAI出力が混ざる。

そのため、今回の方針はこうした。

Markdown = 正式な記録
Map(Canvas) = 曖昧な考えとAI提案の作業場
System Index = AIが読む軽量データ

図にすると、こういう分担になる。

flowchart TD
    A["人間が書くMarkdown"] --> B["正式な記録"]
    C["Map / Canvas"] --> D["曖昧な考え・AI提案・仮説"]
    D --> E["人間が採用判断"]
    E -->|採用| B
    E -->|保留・却下| C
    C --> F["Pythonで軽量Index化"]
    F --> G["System Index"]
    G --> H["AIが参照"]

Obsidian Canvasは、ノートとは違って二次元に配置できる。

フォルダ構成

実際のVaultでは、Canvas置き場を Map/ にした。

<VAULT_PATH>/
├─ Map/
│  ├─ AI提案.canvas
│  ├─ 思考台帳.canvas
│  └─ その他のCanvas
│
└─ 90_System/
   ├─ canvas/
   │  ├─ config/
   │  ├─ inbox/
   │  └─ indexes/
   ├─ scripts/
   └─ output/

ここで大事なのは、AIに Map/*.canvas をそのまま正式入力として渡さないこと。

AIが読むのは、Pythonで生成した軽量Indexだけにする。

Map/*.canvas
↓
Pythonで検証・Index化
↓
90_System/canvas/indexes/canvas_index.jsonl
90_System/canvas/indexes/canvas_catalog.md
↓
AIが参照

Canvasそのものは人間の作業場。
IndexはAIが読むための整理データ。
ここではCanvasはあくまでも仮置きの場所としている。

AI提案をCanvas付箋にする

まず実装したのは、AI提案をCanvasに付箋として追加する仕組み。

最初は既定の置き場として Map/AI提案.canvas を用意した。

コマンドは次のようにした。

90_System/scripts/run_ai_memory.cmd canvas_suggest "提案の要約"

このコマンドを実行すると、Canvasに未レビューのAI提案付箋が追加される。

付箋には、必ず次の情報を入れる。

[AI提案]
node_origin: ai
source
created
review_status
suggestion_type
summary
reason
next_action

特に重要なのは review_status

AIが作ったものは、最初は必ず unreviewed にする。

unreviewed = 未確認
review = 確認中
accepted = 採用
hold = 保留
rejected = 却下

状態遷移は、次のように考える。

flowchart LR
    A["AI提案付箋を作成"] --> B["unreviewed / 未確認"]
    B --> C["review / 確認中"]
    C --> D["accepted / 採用"]
    C --> E["hold / 保留"]
    C --> F["rejected / 却下"]
    E --> C
    D --> G["MarkdownやSystemへ反映"]

AIが勝手に accepted にすることはない。
最終判断は人間がする。

ボタン一つで空の付箋を作る

毎回コマンドを打つのは面倒なので、Obsidian側の操作パネルからRunshで呼べるようにした。

ボタン用のコマンドはこれ。

90_System/scripts/run_ai_memory.cmd canvas_quick_suggest

これを押すと、Map/AI提案.canvas に「未記入のAI提案付箋」が追加される。

使い方としては、まず空の付箋を置く。
そのあと、Canvas上で人間が内容を書き換える。

この「空の付箋を置くだけ」のボタンがあると、AI提案だけでなく、人間側の曖昧な考えを仮置きする入口としても使いやすい。

どのCanvasにも付箋を貼れるようにする

基本的にやりたかったことは、仮置きのCanvasに考えをはり、それに対してAIと対話をしつつ、考えを深めることがやりたかった。なのでそれぞれに付箋を貼れるように変更をした。これで 案件ごとのCanvas、学習用のCanvas、ブログ構成用のCanvasなど、それぞれの文脈に直接付箋を置きたい。

そこで、指定したCanvasへ付箋を追加できるコマンドも作った。

90_System/scripts/run_ai_memory.cmd canvas_suggest_to "Map/対象.canvas" "提案の要約"
90_System/scripts/run_ai_memory.cmd canvas_quick_suggest_to "Map/対象.canvas"

これで、たとえばブログ記事の構成を考えているCanvasに、直接AI提案の付箋を追加できる。

ブログ用Canvas
↓
AI提案付箋を追加
↓
人間が並べ替える
↓
採用する構成だけMarkdown記事へ反映する

ただし、どこにでも書けるようにはしていない。

対象は Map/ 配下の .canvas だけに制限した。

OK  = Map/任意の名前.canvas
NG  = Map/README.md
NG  = 00_人間用/
NG  = 20_Assets/
NG  = .obsidian/

これは、柔軟性と安全性の折り合いとしてかなり大事だった。

Canvasは中間レイヤーとして使いたい。
でも、AIやスクリプトが人間用ノートや素材原本へ自由に書き込む状態にはしたくない。

だから「Map配下のCanvasには貼れる。ただしMarkdown本文や素材フォルダには貼れない」というルールにした。

付箋を書き込んでよいかは、次のように切り分ける。

flowchart TD
    A["付箋を追加したい"] --> B{"対象はMap配下か"}
    B -->|No| X["書き込み禁止"]
    B -->|Yes| C{"拡張子は.canvasか"}
    C -->|No| X
    C -->|Yes| D{"人間用・素材・設定ではないか"}
    D -->|No| X
    D -->|Yes| E["付箋追加OK"]
    E --> F["review_status: unreviewed"]

ローカルAIとの対話を付箋化する

次に作ったのが、ローカルAIとの対話を付箋に変換する仕組み。

流れはこう。

ローカルAIとの会話や考えを貼る
↓
System側Inboxに保存
↓
ローカルLLMが1〜5個の付箋案に整理
↓
Map/AI提案.canvasに未レビュー付箋として追加

貼り付け先は次のファイル。

90_System/canvas/inbox/local_ai_dialogue.md

実行コマンドはこれ。

90_System/scripts/run_ai_memory.cmd canvas_ai_dialogue

指定したCanvasに出したい場合は、こちらを使う。

90_System/scripts/run_ai_memory.cmd canvas_ai_dialogue_to "Map/対象.canvas"

このコマンドでは、ローカルLLMにVault全体を渡さない。

渡すのは、System側Inboxに貼られた本文だけ。

local_ai_dialogue.md
↓
ローカルLLM
↓
付箋案JSON
↓
Map/対象.canvas

たとえば、ローカルAIとの会話から次のような付箋案を作れる。

summary: 未整理情報を「問い・仮説・次アクション」に分ける
reason: 後で人間が判断しやすくなるため
next_action: Map上で分類ごとの置き場を作るか検討する

AIとの対話をそのままノートに貼るのではなく、後で扱える粒度に分解してCanvasへ置く。

検証ルールを入れる

Canvasは自由度が高い。
自由度が高いぶん、壊れたデータやルール外の付箋も入りやすい。

そこで、validate_canvas.py で検証するようにした。

検証する内容は主に以下。

  • Canvas JSONとして正しいか
  • ノードIDが重複していないか
  • edgeの参照先が存在するか
  • AI提案ノードに必須項目があるか
  • review_status が許可値か
  • node_origin が許可値か
  • review_status とCanvas colorが一致しているか
  • raw assetへの参照が混ざっていないか

色もルール化した。

unreviewed/review = 6
accepted = 4
hold = 3
rejected = 2

この色ルールにより、Canvasを見たときに提案の状態がわかりやすくなる。

ハマったところ

一番ハマったのは、Windowsの .cmd に日本語の長い引数を直接書いたところだった。

最初は、ボタン用のコマンドに日本語の既定文をそのまま入れていた。

run_ai_memory.cmd canvas_quick_suggest "未記入のAI提案付箋"

ところが、cmdの解釈が崩れた。

そのため、バッチファイル側はできるだけASCIIに寄せた。

run_ai_memory.cmd canvas_quick_suggest

日本語の既定文はPython側の定数として持たせる。

.cmd = 実行ルーティングだけ
Python = 日本語本文や既定値を扱う

この分離にしてから安定した。

Windowsで日本語を含む自動化を組むときは、地味だけれどかなり重要なポイントだと思う。

セキュリティ面の考え方

今回の設計では、AIに何でも読ませない。

特に、次のものは通常のAI処理対象から外す。

.obsidian/
00_人間用/
00_人間用/AI立入禁止/
20_Assets/
raw asset

スクリプトが付箋を書き込める場所も、Map/*.canvas に限定する。

付箋追加OK  = Map/*.canvas
付箋追加NG  = Markdown本文、素材フォルダ、Obsidian設定、立入禁止フォルダ

ローカルAIに渡すのは、あくまでSystem側に置いた軽量データだけ。

90_System/output/
90_System/canvas/indexes/
90_System/canvas/inbox/local_ai_dialogue.md

もちろん、これはOSレベルの完全な権限制御ではない。
あくまで運用ルールとスクリプト上の制限である。

これらは元々ガチガチにやるつもりだったが、それをやると柔軟性がなくなるし、そもそも個人のデータでいじらないものはいれないようにするためには現在使用しているPC内部に無い方がいいという事で、PC内部にはあまりいれないようにする方がいいだろうという事になった。ではなぜここに触らないようのフォルダを作成したかたといえば、

  • そもそも書き込みをさせないほうが自分の考えと混ざらない。
  • AIに明示しているときに、仮に触った場合はどこから触ったかといった時に現在の挙動がどのようなものであるかを知ることができる。明示していないと全てを触っていいとして、自由に触る可能性がある。
  • 触る領域を限定することによる挙動を安定させる。

こういった理由がある。

全体の流れ

今回できた仕組みをまとめると、こうなる。

人間が考える
↓
MapのCanvasに置く
↓
必要ならローカルAIと対話する
↓
対話をSystem側Inboxに貼る
↓
ローカルLLMが付箋案に分解する
↓
指定したMap Canvasに未レビュー付箋として追加
↓
人間がaccepted / hold / rejectedを判断する
↓
採用したものだけ正式なMarkdownやSystemへ反映する

この流れにすると、AIは「勝手に知識ベースを書き換える存在」ではなくなる。

AIは提案を出す。
Canvasは提案を並べる。
人間が意味づけをする。

この役割分担が気に入っている。

まとめ

Obsidian Canvasを使うと、AIとの関係をかなり柔らかく設計できる。

Markdownに直接AIコメントを混ぜると、ノートがAI出力で汚れやすい。
一方で、Canvasに付箋として置けば、AIの提案を正式記録から切り離したまま扱える。

今回作った仕組みでは、次のことができるようになった。

  • AI提案をCanvas付箋として追加する
  • ボタン一つで空の付箋を作る
  • 任意の Map/*.canvas に付箋を貼る
  • ローカルAIとの対話を付箋案に変換する
  • 付箋の状態を review_status で管理する
  • AIが読むデータをSystem側の軽量Indexに限定する

やりたかった事は基本的にはできたと思う。あとはこれをもっと簡易にし、簡単にメモ・資料を集め、そこから提案を受け、更に考えを深めるといったことがやりたいと思っている。

基本的にはあやふやな考え・どこからかもってきたアイディアなどを置く・思考を整理しまとめる為の場所と考えているのでその方向性でこれからも進めていきたい。