MINARA

ワークスペース

マークダウン形式の Agent アイデンティティとメモリ、および永続的な会話コンテンツを保持するアーティファクトとファイルのストア

Minara は、アイデンティティ・ペルソナ・精選済みメモリ・セッション間状態を、ワークスペースディレクトリ(デフォルト: ~/.minara/workspace/)内のプレーンなマークダウンファイルとして保存します。

ワークスペースは、Agent の人間が管理するグランドトゥルースです。推定されたユーザー嗜好・学習済みメソドロジー・シナリオプレイブックが MEMORY.md / SOUL.md / AGENTS.md の内容と矛盾する場合、ワークスペースが優先されます。エージェントループはその順序でシステムプロンプトを組み立てます。動的ブロックとキャッシュ済みブロックの構成については エージェントループ を参照してください。

ディスク上のレイアウトは OpenClaw 互換です。ファイル名・セクション・フロントマターは OpenClaw の AGENTS.default スキーマに合わせており、どちらのツール向けに作成したワークスペースも互いに移植できます(詳細は OpenClaw 互換性 を参照)。

ファイル一覧

ファイル役割ライフサイクル
SOUL.mdアイデンティティ・声のトーン・制約長期保持。編集するとユーザーへの1回限りの通知が発生
AGENTS.mdセッション起動ルール・セーフティデフォルト長期保持
IDENTITY.md表示名・絵文字・雰囲気(UI 表面)長期保持
USER.mdオペレータープロファイル(タイムゾーン・関心分野・リスク・ウォッチリスト)長期保持
MEMORY.md精選済みファクト / 嗜好 / 意思決定長期保持。ドリーミングタスクが ## Dreamed YYYY-MM-DD セクションを追記
BOOTSTRAP.md2ステージの初回オンボーディングプレイブックAgent が BOOTSTRAP_DONE を出力した後、.done.<timestamp> にアーカイブ
TOOLS.md環境固有のツール / スキルノート長期保持。オペレーターが管理
HEARTBEAT.mdセッション間メモ(last_seen・オープンループ・スケジュール)ターン終了ごとに Agent が書き直す(状態セクション)。## Schedule はユーザーが管理
memory/YYYY-MM-DD-<session>.mdセッション別デイリージャーナルN ターンごとに追記。ドリーミングタスクが統合

HEARTBEAT.md だけが毎ターン Agent によって書き直されます。それ以外はオペレーターが編集するか、ドリーミングタスクが提案するのみです。

起動時の自動シード

createApp() はワークスペースを読み込む前に seedWorkspaceIfMissing(workspaceDir) を呼び出し、apps/agent/src/workspace/templates/ から不足しているテンプレートをランタイムディレクトリにコピーします。シードは冪等です。オペレーターが編集済みのファイル、または既存のファイルは上書きされません。新規インストールでは、minara setup を手動で実行しなくても完全なファイルセットが揃います。

HEARTBEAT.md はシード対象に意図的に含まれていません。Agent が最初のターン終了時に新しいものを書き込むため、古い状態をシードするとセッション継続性について虚偽の情報を与えることになります。テンプレートファイルは apps/agent/src/workspace/templates/HEARTBEAT.md として、Web UI の restore-template ソースおよびスキーマリファレンスとしてのみ存在します。

ワークスペースの編集

ワークスペースファイルを編集する方法は3つあります。

  1. ディスク上で直接編集。Agent がセッションとセッションの間に、任意のエディターで開いて編集します。次のセッションで保存した内容が読み込まれます。
  2. REPL スラッシュコマンド/soul/identity/heartbeat/workspace [soul|agents|identity|user|memory|heartbeat|bootstrap] でライブファイルを表示します。完全なコマンドセットは スラッシュコマンドリファレンス を参照してください。
  3. Web UI の Settings → Workspace。ホワイトリストから任意のファイルを選択し、テキストエリアで編集して手動で保存します。保存は sha256 楽観的並行性制御付きのゲートウェイを経由します。PUT リクエストにはエディターが読み込んだ時点の sha256 が含まれており、ゲートウェイから 409 が返された場合は「上書きまたは再読み込み」モーダルが開きます。これにより、ブラウザタブ・セッションをまたいだ並行編集が黙って競合することはありません。

Web UI エディターはファイルシステムに直接触れません。すべての操作は /v1/workspace/files* を経由します(詳細は HTTP API リファレンス を参照)。

3つのメモリ層

ワークスペースは SQLite メモリストア(メモリシステム 参照)と3つの時間軸で連携します。

  • 短期記憶(デイリージャーナル)memory/YYYY-MM-DD-<session>.md は、デイリーログライターによって WORKSPACE_DAILY_LOG_INTERVAL ターンごとに追記されます。セッションごとにファイルを分けることで、REPL と HTTP ゲートウェイ間の追記競合を防ぎます。従来の集約形式 YYYY-MM-DD.md と新しいセッション別形式の両方が、次のセッションのローダーで読み込まれます。
  • 長期記憶(精選済み)MEMORY.md には ## Facts## Preferences## Decisions の3つのサブセクションがあり、オペレーターが管理します。ドリーミングタスクは ## Dreamed YYYY-MM-DD セクションとして追加を提案します(追記のみ)。
  • セッション間メモ(ハートビート)HEARTBEAT.md には last_seensession_idsurfaceturn_count・最近の open_loops、そしてユーザーが管理する ## Schedule が含まれます。ライターは ## Schedule セクションを書き込みをまたいで逐語的に保持します(schedule_raw ラウンドトリップ)。オペレーターのコメント・空行グループ・未知のフィールドもすべて維持されます。

ドリーミング統合

WORKSPACE_DREAM_ENABLED=1 のとき、setInterval タスクが WORKSPACE_DREAM_INTERVAL_HOURS ごとに起動し、以下を実行します。

  1. .dreamed-state.json のウォーターマークより新しいデイリーログを読み込む。
  2. 現在の MEMORY.md とともに、「持続的なシグナルとノイズを抽出し、既存のファクトと重複させない」というプロンプトを付けてアクティブな LLM に渡す。
  3. ## Dreamed YYYY-MM-DD セクションを MEMORY.md に追記する(追記のみ。オペレーターの編集は上書きされない)。
  4. ウォーターマークを更新し、同じログが次のティックで再処理されないようにする。

LLM がリテラル NOTHING_TO_PROMOTE を返した場合、セクションは書き込まれませんが、ウォーターマークは進みます。同じログセットが再処理されることはありません。

SOUL.md 変更通知

ランタイムは起動時に SOUL.md のハッシュを計算し、<workspaceDir>/.soul-state.json に保存します。セッション間でハッシュが変わった場合、エージェントループはプロンプトレベルの1回限りの通知を受け取り、次の返答でオペレーターに変更を通知するよう求められます。その1回の通知後、変更は再度言及されません。検出器は読み込みごとにベースラインを更新します。

BOOTSTRAP.md の2ステージオンボーディング

新しいワークスペースには BOOTSTRAP.md が含まれています。フローは以下のとおりです。

  1. ターン 1。Agent が BOOTSTRAP.md を読み込み、オペレーターにオンボーディングの質問をします(名前・タイムゾーン・関心分野・リスク許容度・デフォルト取引所)。この時点では BOOTSTRAP_DONE を出力しません。
  2. ターン 2。オペレーターが回答します。Agent は write_file を使って USER.md を記述し、書き込んだ内容を簡潔に確認した後、返答の末尾にリテラルトークン BOOTSTRAP_DONE を単独の行として出力します。

ブートストラップハンドラーフック(ターン終了時)がこのトークンを検出し、BOOTSTRAP.mdBOOTSTRAP.md.done.<timestamp> にリネームします(監査証跡は保持)。次のターンではファイルが存在しないため、動的プロンプトブロックがブートストラップ指示を自動的に除外します。

グランドトゥルースとしてのワークスペース(優先順位)

エージェントループは、派生レイヤーよりも先にワークスペースの md を先頭に置いてシステムプロンプトを組み立てます。

  1. identity ブロック(キャッシュ済み)。SOUL.mdAGENTS.md
  2. memorySnapshot(動的。動的ブロックの先頭)。USER.mdMEMORY.mdHEARTBEAT.md・最近のデイリージャーナルエントリ。
  3. bootstrapInstructions(動的。BOOTSTRAP.md が存在する場合のみ)。初回起動プレイブック。
  4. スキルカタログ・シナリオプレイブック・パーソナライゼーション・メソドロジーヒント・その他の派生レイヤーがその後に続く。

この順序には意図があります。MEMORY.md に「ユーザーは BTC に関して永続先物より現物を好む」と記載され、パーソナライゼーションレイヤーが「ユーザーは永続先物を好む」と推論した場合、MEMORY.md が優先されます。この優先順位は apps/agent/src/core/prompt-builder.ts で実施され、AGENTS.mdSoul セクションで成文化されています。

設定

デフォルトは、新規インストールでもすぐに使えるよう調整されています。

  • ハートビート: ON(WORKSPACE_HEARTBEAT_ENABLED=1
  • デイリーログ: OFF(WORKSPACE_DAILY_LOG_ENABLED=0
  • ドリーミング: OFF(WORKSPACE_DREAM_ENABLED=0

全設定項目とデフォルト値・効果の一覧は 環境変数リファレンス を参照してください。

アーティファクトとファイル

ワークスペースの Markdown は永続的な状態です。これと並んで、永続的なコンテンツを保持する2つのストアがあります。アーティファクト(Agent がターン中に生成するチャート、スプレッドシート、レポート)とファイル(ユーザーがアップロードするバイナリ)です。どちらもワークスペースやサンドボックスと並列ですが、契約は異なります。サンドボックスは Agent がターン中に自由に上書きできるスクラッチ領域である一方、アーティファクトとファイルはセッションをまたいで残り、安定した id を持ち、不用意な write_file で変更されてはなりません。これらはサンドボックスとパスを共有しないため、スクラッチ出力を書き込むツールが保存済みのチャートやユーザーアップロードを上書きすることはありません。

アーティファクトストア

アーティファクトは chat_artifacts SQLite テーブルに保存され、artifacts/artifact-store.ts が所有します。3つのタイプが同じ行構造を共有します。

タイプid プレフィックスdata ペイロードビルダー
chartx-{ charts: [...] } ECharts オプションchart-builder.ts
spreadsheetx-{ csvContent, title?, description? }CSV、.csv に物化
reportr-完全な HTML / markdown レポートディープリサーチ

各ビルダーは同じステータス経路をたどります。insert()running)→ markCompleted(data)completed)または markError(msg)error)。REPL は (running) プレースホルダーを表示してその場で更新し、監査ログがすべての遷移を記録します。

モデルは完成したアーティファクトを id の推測ではなく URI で参照します。chart://x-…report://r-…spreadsheet://x-… です。存在しない id は構造化された ArtifactNotFoundError に解決され、モデルはそれを見て自己修正します。ターン終了時、gateway/render/artifact-materializer.ts が最終メッセージ内のこれらの URI をスキャンし、閲覧可能なファイル(自己完結型 HTML ビューア、生の JSON、チャートごとに 2 倍 PNG、スプレッドシートごとに .csv)を $dataDir/artifacts/<id>/ に書き込みます。PNG レンダリングはベストエフォートです。Playwright Chromium がインストールされていない場合、マテリアライザーは chart_png_skipped を記録して続行します。

ファイルストア

ファイルは Agent が保存・参照するが解析はしない不透明なバイト列で、files/file-store.ts が所有します。デフォルトの LocalFileStore$dataDir/uploads/ に書き込み、キーは chat/files/<userId>/<unix_ms>-<random_id>.<ext> です(unix_ms プレフィックスでアップロードが自然に時刻順に並びます)。

StoredFilekey(チャットメッセージに書き込まれる安定した id)と url(LLM プロバイダーがマルチモーダルメッセージのために取得するアドレス)を持ちます。アップロード(POST /v1/files)は fileStore.put(...) を経由し、key を保留中メッセージに添付します。デフォルトの 20 MB 上限は各プロバイダーのマルチモーダル上限に合わせています。files/message-translator.ts は、ループへ入る際に添付の key を各プロバイダー優先のマルチモーダル形式へマッピングし、ストレージへ書き戻す際に key へ戻します。メッセージ本文は sessions 行に、バイナリコンテンツはファイルストアに保存され、トランスレーターが両者を橋渡しします。sessions に生のバイナリが保存されることはありません。アップロードされたスプレッドシートは files/spreadsheet-parser.ts によって構造化テキストに変換され、モデルは完全な添付のラウンドトリップなしにその内容を推論できます。

セキュリティ姿勢

  • ファイルは決して実行されません。このストアは blob キャッシュであり、アップロードされたコンテンツを eval するコードパスはありません。
  • key とアーティファクト id は機密ではなく安定した参照です。URL や chart:// id は所持者が利用できるケイパビリティとして扱ってください。ゲートウェイがその上にセッションレベルの認証を追加します。
  • 削除は明示的です。LocalFileStore.delete(key) がローカルファイルを削除します。GDPR 的な削除はこれを経由して行い、削除が意図的でたどれるようにしてください。

これらを返す HTTP エンドポイントについては、API → /files とアーティファクト取得ルートを参照してください。

OpenClaw 互換性

ワークスペース形式は OpenClaw の AGENTS.default スキーマとバイト互換です。ファイル名・セクション見出し・フロントマター形式がすべて同じです。どちらのツール向けに作成したワークスペースも、変換なしでそのまま移植できます。精神的に異なるファイルは、各ツールが個別に管理するランタイム専用アーティファクトだけです。

既存の OpenClaw ワークスペースを Minara に取り込む方法は3つあります。

  • 起動時に --workspace ~/.openclaw/workspace を指定する。
  • 環境変数 MINARA_WORKSPACE_DIR=~/.openclaw/workspace を設定する。
  • OpenClawWorkspaceImporter を実行して、Minara のデフォルトの場所にファイルをコピーする。

BOOTSTRAP.mdHEARTBEAT.md はインポーターによって意図的にスキップされます。前者は1回限りのオンボーディングプレイブックであり(Minara は独自のシードを持つ)、後者は Agent がターン終了ごとに書き直すため、古いハートビートをインポートするとセッション継続性について虚偽の情報を与えることになります。

目次