Skip to main content
Glama
subaco-dev
by subaco-dev

subaco-hive

Subaco のメモリプレーンを担う MCP サーバー+ops CLI。 SQLite(メッセージング)と Zvec(長期記憶)に対する唯一のライターとして、 マルチエージェント協業のエピソード記憶とチーム内メッセージングを提供する。 agmsg の「SQLite ファイルが床、エージェントがプレイヤー」という薄さを踏襲しつつ、 床の管理人を一人だけ置く(first-writer-wins)構図。

  • 論理名: subaco-hive(本文中では hive-mcp とも呼称)

  • パッケージ: subaco_hive / ライセンス: Apache-2.0 / 対象 Python: 3.11+

エントリポイント

コマンド

実体

役割

subaco-hive

subaco_hive.server:main

stdio MCP サーバーを起動(.mcp.json / hive-mcp ランチャが呼ぶ)

hive

subaco_hive.cli:main

ops/admin CLI(set-trust / reset-token / backup / restore / reembed / stats / migrate)

stdout は JSON-RPC(MCP stdio トランスポート)専有。診断ログは stderrHIVE_LOG_LEVEL)。

v0 の実装範囲

動くもの(本リポジトリ v0):

  • メッセージング層(純 stdlib sqlite3): hive_join / hive_post / hive_inbox / hive_members / hive_history。 メンバートークン・冪等キー(request_id)・trusted_agents 許可リスト・mcp_posts 台帳による trust 解決・ 未信頼本文の非配送+メタデータ一度きり通知・recipient 実在検証・秘密パターン検査(書込拒否/読出赤塗り)。

  • first-writer-wins(.hive/writer.lock の flock + .hive/hive.sock の NDJSON プロキシ)とフェイルオーバー。

  • 記憶層(hive_remember / hive_recall): 二段書き(pending→Zvec→committed)・起動時孤児掃除・ 固定フィルタ(source_trust≥1 かつ現在 trust≥1)。ベクタバックエンドは抽象化され、既定は Zvec(遅延 import)。 Zvec 未導入でも純 Python の InMemoryVectorBackend で SQLite 状態機械を動作・テスト可能。 ZvecBackendzvec 0.6 の実 API で実装済み(コレクション=<.hive>/memory/<name> ディレクトリ、 COSINE・HNSW、本文は STRING スカラー)。

  • 埋め込み抽象(EmbeddingProvider): 既定 fastembed(ローカル・遅延 import)/OpenAI 互換 API。hive reembed で原子的スワップ。 既定モデルは sentence-transformers/paraphrase-multilingual-mpnet-base-v2(768 次元 / 約 1.0GB。 M1-5 の日本語ベンチ〔benchmarks/ja_embedding〕で確定——運用指標 recall@5 が唯一両条件満点。 top-1 最優先なら hive reembedintfloat/multilingual-e5-large へ切替可)。

  • ops CLI・監査ログ(本文非記録)・hive_stats。 なお agmsg は着想元であり、agmsg 連携対応はスコープ外(同一 DB での無改変 agmsg 相互運用は 不成立と spike で確定したうえ、agmsg 自体が発展途上で互換性を破るスキーマ変更が短い間隔で 発生しており、ブリッジでも追随保守が見合わないため——docs 06_spike結果)。

繰延(TODO をコード内 docstring に明示):

  • ハイブリッド検索(Zvec の FTS/BM25 面)の活用。v0 は密ベクタ検索のみ。

  • 前方マイグレーション runner(v0 は hive_meta.schema_version の照合のみ)。

  • プロキシ↔ライターのスケール限界・管理チャネルの admin token ゲート・メンバー個別除去 等。

記憶系を有効にする:

pip install 'subaco-hive[memory]'   # zvec + fastembed

記憶系の統合テストは zvec が入っているときだけ走る(tests/test_memory_zvec.py)。 実モデルのダウンロード(数百 MB)を伴う日本語 E2E は SUBACO_HIVE_LIVE_EMBEDDING=1 のときのみ実行する。

Zvec の排他に関する運用上の制約(spike で実測): 常駐ライターがコレクションを開いている間は、 別プロセスからの read-only オープンも失敗するCan't lock read-only collection: .../LOCK)。 したがってバックアップは必ず常駐ライター経由(管理チャネル)か、ライター停止状態で行う。 一方、ライターが SIGKILL されても LOCK は OS が解放するため、残留ロックの手動解放は不要で 昇格したプロキシは待ちなしで開き直せる。

アーキテクチャ: 単一ライターと first-writer-wins

  • Zvec と memories/members への書き込みプロセスは常に 1 つ。各エージェントは stdio で MCP を起動するが、 実起動時に .hive/hive.sock を確認し、既存ライターがあれば薄いプロキシとして接続する。

  • ライターの正当性はソケットの存在ではなく .hive/writer.lock の flock 保持で担保する。 flock 対象は hive.sock とは別の恒久ロックファイルで、稼働中は unlink・再作成しない (unlink+flock レースによる二重ライターを排除)。

  • フェイルオーバー: プロキシがソケット EOF を検知したら flock を争奪し、勝者が新ライターへ昇格して SQLite/Zvec を開き直し socket を再作成、敗者は再接続する。書込系(join/post/remember)は request_id で冪等化し(processed_requests 台帳)、昇格後の新ライターも突合して重複実行を抑止する。

  • アクセス制御: .hive/ は 0700・hive.sock は 0600。接続受付時に SO_PEERCRED(macOS は LOCAL_PEERCRED)で 同一 UID のみ許可。同一 UID の悪意プロセスは脅威モデル外(.hive/ へ直接書けるため防御不能)。

  • CLI 直書きの境界: messages / message_reads への直接 INSERT のみ CLI 経路に許容。 WAL+busy_timeout で競合を吸収。CLI 直書きは mcp_posts 台帳に載らないため trust=0 扱い(本文は既定 inbox で非配送)。

MCP ツール一覧

ツール

引数

概要

hive_join

name, vendor?, team?, token?

参加。members 登録・メンバートークン発行/照合・セッション束縛

hive_post

body, recipient?

送信(recipient 省略でブロードキャスト・指定時は実在検証)。秘密検査あり

hive_inbox

since?, include_untrusted?

未読取得。既定は trust≥1 本文+未信頼はメタデータ一度きり通知

hive_members

登録メンバー一覧(CLI 参加者は現れない)

hive_history

limit=50

ルーム履歴の再生(ブロードキャストのみ・文脈シード用)

hive_remember

kind, text

長期記憶へ書き込み(二段書き)。秘密検査あり

hive_recall

query, kind?, top_k=5

セマンティック検索(固定フィルタ・出所ラベル付与)

hive_stats

利用統計(recall 回数・メッセージ往復数等)

trust は 0:未信頼 / 1:通常 / 2:高信頼。昇格・降格は人間の管理操作のみhive admin set-trust)。 v0 の機械フィルタ(recall・inbox 配送)は全て >=1 で判定する(2 と 1 を機械的に区別しない)。

ops/admin CLI(hive

hive admin set-trust <team> <name> <0|1|2> [--restamp]  # 昇格/降格(--restamp で過去記憶の source_trust も更新)
hive admin reset-token <team> <name>                     # メンバートークン紛失時の再発行
hive admin backup <dir>                                  # SQLite(.backup) + Zvec スナップショット + manifest
hive admin restore <dir>                                 # 整合照合の上で差し替え(不一致は fail-closed)
hive reembed [--provider fastembed|openai] [--model ..]  # 埋め込みモデル切替の原子的再埋め込み(下記注意)
hive stats                                               # 利用統計
hive migrate                                             # schema_version 照合(v0。runner は将来対応)

管理操作の経路: 常駐ライターがいれば hive.sock の管理チャネル経由、いなければ 一時ライターとして flock を取得して実行(一回限り・hive.sock は作成せず flock 解放で終了)。いずれも audit に記録。 (実測: hive.sock がクラッシュ跡としてファイルだけ残っていても、ライター正当性は flock で判定されるため 一時ライター経路が正しく選ばれる。)

既定埋め込みモデルを変更したときの移行(v0.1.0 未公開時点で MiniLM-L12-v2 → mpnet-base-v2 に変更済み): モデル名/次元は hive_meta に永続化され起動時に照合される。古いモデルで作った .hive/ をそのまま 使うと、メッセージング系は動いたまま記憶系ツール(hive_remember / hive_recall)のみが拒否される (環境変数の変更だけで共有記憶が静かに壊れないための設計)。hive reembed を一度実行すれば、 既存の記憶を新モデルで再埋め込みして原子的に切り替えられる。

環境変数

変数

既定

用途

HIVE_DB_PATH

$PWD/.hive/messages.db

SQLite のパス。未設定時は CWD から上位へ .hive/ を探索(git ルート/$HOME で打切)

HIVE_TEAM

.hive/team の内容

チーム名。導出はせず読むだけ(正規化は devShell の hive-team が担う)

HIVE_LOG_LEVEL

info

診断ログのレベル。ログは stderr、stdout は JSON-RPC 専有

subaco_hiveHIVE_DB_PATH 未設定時に上位方向へ既存 .hive/ を探索するのみで、暗黙に新規作成しない (作成は .envrc / bootstrap の責務。チームのサイレント分裂を防ぐ)。

MCP クライアントへの登録

重要: direnv 有効シェルからの起動でも、MCP 子プロセスへの環境変数伝播はクライアント実装依存であり 保証されない。そのため下記の登録雛形は HIVE_DB_PATH / HIVE_TEAM絶対パス・明示値で指定する。

Claude Code(プロジェクトスコープ .mcp.json

devShell の hive-mcp ラッパー(固定 requirements 経由で subaco-hive を起動)を指す:

{
  "mcpServers": {
    "subaco-hive": { "command": "hive-mcp", "args": [] }
  }
}

devShell 外・素の環境では uvx subaco-hive(下記 Codex/Gemini と同型)に置き換える。

Codex(~/.codex/config.tomlmcp_servers 節)

[mcp_servers.subaco-hive]
command = "uvx"
args = ["subaco-hive"]        # 再現性重視なら: ["--with-requirements", "/abs/requirements-hive.txt", "subaco-hive==<版>"]

[mcp_servers.subaco-hive.env]
HIVE_DB_PATH = "/abs/path/to/my-product/.hive/messages.db"  # 絶対パス明示(伝播はクライアント依存)
HIVE_TEAM    = "my-product"                                  # 絶対値明示(.hive/team と一致させる)

Gemini CLI(.gemini/settings.jsonmcpServers

{
  "mcpServers": {
    "subaco-hive": {
      "command": "uvx",
      "args": ["subaco-hive"],
      "env": {
        "HIVE_DB_PATH": "/abs/path/to/my-product/.hive/messages.db",
        "HIVE_TEAM": "my-product"
      }
    }
  }
}

公開前(PyPI 未登録)の dev では uvx --from /abs/path/to/subaco-hive subaco-hive(または SUBACO_HIVE_DEV)で ローカルの作業ツリーから起動できる。

エージェントハーネスの推奨権限(deny/ask 雛形)

「昇格は人間のみ」は技術的 enforce ではなく慣行+摩擦(Bash を持つエージェントは hive admin を実行し得る)。 補完として、ハーネス側の権限設定で管理コマンドを拒否する雛形を同梱する。Claude Code の settings.json 例:

{
  "permissions": {
    "deny": [
      "Bash(hive admin:*)",
      "Bash(hive reembed:*)"
    ]
  }
}

これは defense-in-depth であり、同一 UID の直接 DB 書換には無効(残余リスク)。

trusted_agents 許可リスト(リポジトリ外)

ホスト管理者が管理する ~/.config/subaco/<team>/trusted_agents(エージェント書換不能)に列挙した名義は、 members 行の新規作成時に限り trust=1 を自動付与する(リスト外は trust=0)。各行:

# 1 行 = name、または「name <token_hash>」(事前共有トークンのハッシュ併記)。# 以降はコメント。
alice
codex-1  3b1f...e9   # トークン併記名義は初回 join でも照合必須。未提示/不一致は行を作らず拒否(squatting 封じ)
  • 既存メンバーの trust は join では変更しない(変更手段は hive admin set-trust のみ)。

  • bootstrap はこのファイルを生成しない(作成手順の案内のみ)。.hive/ リセット後の最初の join で再適用される。

運用 runbook

リセット(チーム作り直し)

hive-mcp を停止してから .hive/ を削除し、.envrc / bootstrap で再初期化する。 trusted_agents(リポジトリ外)は消えないため、再 join 時に trust が再適用される。

# MCP サーバー(全エージェントのセッション)を止めてから:
rm -rf .hive/            # messages.db・team・hive.sock・writer.lock・memory/ を破棄
direnv reload            # .envrc が .hive/ を 0700 で再初期化し team を再生成

バックアップ

hive admin backup /path/to/backup-2026-07-08
# 生成物: messages.db(.backup 産物)/ memory/(Zvec スナップショット)/ manifest.json
#         manifest = { schema_version, embedding_model, embedding_dim, active_collection }

SQLite は WAL 下でもオンライン安全な .backup API を使う。Zvec スナップショットの静止は一時ライターの flock 取得で担保(常駐ライター稼働中は静止できない可能性を警告。管理チャネル quiesce は TODO)。

復元(fail-closed)

hive-mcp を停止した状態で行う(常駐ライターが flock 保持中なら拒否)。 schema_version / embedding_model / embedding_dim / active_collection の整合が取れる組み合わせだけを 受理し、不一致は fail-closed で拒否する(SQLite と Zvec を同一バックアップ時点の組で差し替え)。

hive admin restore /path/to/backup-2026-07-08

埋め込みモデル切替

環境変数を変えただけでは切り替わらない(共有記憶の静かな破壊を防ぐ)。必ず hive reembed で 一時コレクションを構築→hive_meta.active_collection を原子的に切替→旧コレクション削除、の順で行う。

# 単一ライターで行うため、先に MCP サーバー(subaco-hive)を停止する。
hive reembed --provider fastembed --model intfloat/multilingual-e5-base

開発

just test     # pytest(stdlib 層は外部依存なしで緑。並行性テストはプロセスレベルで自動化)
just lint     # ruff check
just fmt      # ruff format
just compile  # 構文チェックのみ(依存取得なし)

外部依存(mcp SDK / zvec / fastembed)は optional-dependencies[mcp] / [memory] / [all])に置き、 依存が未インストールでも各モジュールは import 可能(遅延 import)を守る。 CI(.github/workflows/ci.yml)は ubuntu / macos の両ランナーで ruff+pytest を実行し、 Zvec 統合は macOS(arm64) の別ジョブで走らせる(wheel が無ければ skip)。

テストの層構成

  • test_messaging / test_idempotency / test_normalize / test_secrets / test_memory / test_server_dispatch … stdlib のみで緑(外部依存不要)。

  • test_concurrencyプロセスレベル(subprocess)で first-writer-wins・フェイルオーバー・ WAL 並行(integrity_check・欠落/重複なし・busy_timeout 超過のエラー返却・書込昇格の再試行)を検証。

  • test_memory_zvecpytest.importorskip("zvec") でガード。wheel 無ければ skip。

固定 requirements の生成

テンプレート同梱の requirements-hive.txtリリース時に uv export で生成する産物(v0 はプレースホルダ)。 起動スクリプトは uvx --with-requirements requirements-hive.txt subaco-hive==<版> で推移依存(zvec / fastembed / mcp)を固定する。 生成手順は requirements-hive.txt 冒頭のコメントを参照(uv export --extra all --no-dev --frozen …)。

スキーマ

subaco_hive.db が保持する SQLite テーブル: members / messages / mcp_posts / message_reads / message_notified / processed_requests / memories / hive_meta / audithive_metaschema_version / active_collection(初期値 hive_{team})/ embedding_model / embedding_dim を保存し、 起動時に schema_version を照合する(不一致・未初期化は fail-closed)。

セキュリティ境界(要点)

  • author / trust ラベルは「同一 UID 内の協業エージェント間の出所追跡」であり、認証済み ID ではない。

  • 中核防御はサーバー側機構(trust フィルタ・未信頼本文の非配送・秘密パターン検査・本文の乱数タグ付きデリミタ)。 出所ラベルや .agents/core.md の階層化ポリシーは勧告的な defense-in-depth

  • 監査ログ(audit)には本文を記録しないbuild_summary が本文系キーを機械的に弾く)。

  • .hive/ は gitignore(記憶・メッセージはマシン間を移動しない。単一マシン前提)。

ライセンス

Apache-2.0(LICENSE を参照。3 リポジトリ共通)。