subaco-hive
Officialsubaco-hive
Subaco のメモリプレーンを担う MCP サーバー+ops CLI。 SQLite(メッセージング)と Zvec(長期記憶)に対する唯一のライターとして、 マルチエージェント協業のエピソード記憶とチーム内メッセージングを提供する。 agmsg の「SQLite ファイルが床、エージェントがプレイヤー」という薄さを踏襲しつつ、 床の管理人を一人だけ置く(first-writer-wins)構図。
論理名: subaco-hive(本文中では hive-mcp とも呼称)
パッケージ:
subaco_hive/ ライセンス: Apache-2.0 / 対象 Python: 3.11+
エントリポイント
コマンド | 実体 | 役割 |
|
| stdio MCP サーバーを起動( |
|
| ops/admin CLI(set-trust / reset-token / backup / restore / reembed / stats / migrate) |
stdout は JSON-RPC(MCP stdio トランスポート)専有。診断ログは stderr(
HIVE_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 状態機械を動作・テスト可能。ZvecBackendは zvec 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 reembedでintfloat/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 ツール一覧
ツール | 引数 | 概要 |
|
| 参加。members 登録・メンバートークン発行/照合・セッション束縛 |
|
| 送信(recipient 省略でブロードキャスト・指定時は実在検証)。秘密検査あり |
|
| 未読取得。既定は trust≥1 本文+未信頼はメタデータ一度きり通知 |
| — | 登録メンバー一覧(CLI 参加者は現れない) |
|
| ルーム履歴の再生(ブロードキャストのみ・文脈シード用) |
|
| 長期記憶へ書き込み(二段書き)。秘密検査あり |
|
| セマンティック検索(固定フィルタ・出所ラベル付与) |
| — | 利用統計(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を一度実行すれば、 既存の記憶を新モデルで再埋め込みして原子的に切り替えられる。
環境変数
変数 | 既定 | 用途 |
|
| SQLite のパス。未設定時は CWD から上位へ |
|
| チーム名。導出はせず読むだけ(正規化は devShell の |
|
| 診断ログのレベル。ログは stderr、stdout は JSON-RPC 専有 |
subaco_hive は HIVE_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.toml の mcp_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.json の mcpServers)
{
"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_zvec…pytest.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 / audit。
hive_meta に schema_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 リポジトリ共通)。