Files
maestro/config.yaml.example
oss-sync 57702b4f34
CI / build-and-test (push) Canceled after 0s
sync: update from private repo (2336949a)
2026-09-17 11:29:31 +00:00

826 lines
55 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MAESTRO 設定ファイル (v2 layout)
#
# このファイルを config.yaml にコピーして編集してください:
# cp config.yaml.example config.yaml
#
# ─── v2 への移行 (v1 → v2) ─────────────────────────────────────
# 旧構造 (provider.* / 平置きの worktree_dir 等) は 1 リリース分だけ
# 読み取り互換が残っています。手元の config.yaml が旧形式の場合は:
#
# scripts/migrate-config.sh --dry-run # 変換後を確認
# scripts/migrate-config.sh # in-place で書き換え (.bak を自動保存)
#
# v3.0 で v1 形式は起動 fatal になる予定です。
# v2 schema バージョン (必須)。
# - 2 : このリリースの正規形 (= 本ファイル)
# - 1 / 未指定 : v1 互換読み取り + 起動 warning
# - その他 : 起動 fatal (typo / 未来形式の混入防止)
config_version: 2
# ─── LLM ─────────────────────────────────────────────────────
# ジョブ実行時に LLM 呼び出し先として使う接続群と、retry / timeout / metrics。
llm:
timeout_minutes: 10 # アイドルタイムアウト (分)。チャンク受信ごとにリセットされる。default 10
# max_stream_minutes: 20 # 1 LLM 呼び出しの総時間ハードキャップ (分)。timeout_minutes と違い
# チャンクが届いてもリセットしない。停止トークンを出さずにトークンを
# 吐き続ける暴走 (反復生成など) を確実に打ち切る。未指定なら
# timeout_minutes の2倍。0 で無効 (非推奨: 暴走時に中断するまでハングする)
# max_thinking_chars: 100000 # 1 LLM 呼び出しで受け取る思考 (reasoning) の文字数の上限。上限を超えた時点で
# 本文もツール呼び出しも 1 つも来ていなければ、思考の中で堂々巡りしていると
# 見なしてストリームを打ち切り、会話の末尾に短い問いかけを 1 件足して送り直す。
# 送り直しは retry.max_attempts を 1 消費し、使い切ったらエラーで中断する。
# 未指定なら 100000。0 で無効
# retry — LLM 1 呼び出しあたりの投げ直し。**既定値のまま使うならこのブロックごと
# コメントアウトしたままにしておくこと。**ここに書いた値は既定値の変更より優先
# されるので、書き写しただけで将来の改善が届かなくなる (issue #1160)。
#
# 既定 (未指定時): max_attempts 10 / backoff_ms [500, 500, 1000, 2000, 3000,
# 5000, 7000, 10000, 10000] / retryable_status [429, 500, 502, 503, 504]
#
# backoff_ms は「投げ直す直前に待つ ms」を先頭から順に使い、足りなければ最後の値を
# 使い回す。max_attempts が 10 なら待つのは 9 回。合計 39 秒。
#
# 429 (混雑) だけは別扱い。応答に Retry-After があればその値を待ち、60 秒を超える
# 指定なら投げ直しをやめる。指定が無い 429 は 5 秒を下回らない。5xx と接続失敗は
# 並びの値をそのまま使う。
#
# retry:
# max_attempts: 10
# backoff_ms: [500, 500, 1000, 2000, 3000, 5000, 7000, 10000, 10000]
# retryable_status: [429, 500, 502, 503, 504]
# workers[] — この AAO がジョブ実行時に呼ぶ接続先。
#
# connection_type:
# direct — Ollama / llama.cpp / vLLM 等の OpenAI 互換 backend に直接接続
# 生存確認は /slots → /health。**api_key は送らない**
# (自前サーバーのアクセスログに平文で残るのを避けるため)
# aao_gateway — 別 AAO Gateway 経由で接続 (Gateway Key 必須)
# 生存確認は /health。api_key を送る
# external_api — 事業者が運用する外部の OpenAI 互換サービス (api_key 必須)
# 生存確認は /v1/models。api_key を送る
#
# 種別は自動判定しない。鍵を送るか送らないかの判断なので、必ず明示すること。
# 未指定は direct 扱い (=鍵を送らない側) で、従来の挙動と同じ。
#
# トップレベル `gateway.*` (この AAO 自身が gateway として動く設定) と
# 単語衝突を避けるため、worker 側は `aao_gateway` と prefix 付き。
#
# model はワーカーごとに明示。`default_model` は廃止された。
# roles: 用途別 (auto / fast / quality / dictionary / document_question /
# title / reflection 等) のフィルタ。
# max_concurrency: 1ワーカーが同時実行するジョブ数 (A1スロット方式)。デフォルト1。
# >1 はオプトイン。注意: shutdown drain は粗く、fairness は低下し、
# LLM provider 側の rate limit は別途。browser を使うワーカーで >1 にする場合は
# セッション作成は mutex 済みだが本番投入前に dogfooding すること。
# capabilities はモデルが扱える種類。image はその会話に画像を渡せるかを指定。
# audio / video は対応情報の保存用(直接入力・委譲・動画ツールは未対応)。
# 古い vlm は capabilities.image として読み続ける。両方あると新しい指定を優先。
# 画像を扱えないワーカーの画像認識を、capabilities.image: true のワーカーへ回す。
# 空き枠のある候補を選び、1回きりの説明文を受け取る。画像自体は元の会話に載せない。
# offload:
# image: false
# audio: false
# video: false
workers:
- id: local-ollama
connection_type: direct
endpoint: http://localhost:11434/v1
model: qwen3:32b
roles: [auto, fast, quality]
max_concurrency: 1
enabled: true
capabilities:
image: false
audio: false
video: false
streaming: true
# 例: Markdown の辞書モード専用ワーカー。短い回答の速度を優先する。
# dictionary が未設定または利用できない場合は、必要条件を満たす
# fast → title の順で自動的に代替する。辞書回答には endpoint、model、
# streaming 対応が必要(未指定の既存設定は許容、明示 false は不可。
# tool calling、tokenizer は不要)。
# - id: dictionary-fast
# connection_type: direct
# endpoint: http://localhost:11434/v1
# model: qwen3:8b
# roles: [dictionary]
# max_concurrency: 4
# enabled: true
# capabilities:
# streaming: true
# 例: Markdown の「文書について質問」専用ワーカー。
# streaming と tool_calling の両方に対応するモデルを割り当てる。
# context_window は 8192 以上にし、実際のモデル上限と一致させる。
# - id: document-question
# connection_type: direct
# endpoint: http://localhost:8080/v1
# model: document-chat-model
# roles: [document_question]
# max_concurrency: 2
# enabled: true
# capabilities:
# streaming: true
# tool_calling: true
# context_window: 32768
# tokenizer_endpoint: http://localhost:8080/tokenize
# # tokenizer_api_key: ${DOCUMENT_TOKENIZER_API_KEY}
#
# 上の例は `llama-server --port 8080 --alias document-chat-model ...` と対応する。
# document_question が未設定または利用できない場合は、以下の必要条件を
# すべて満たす quality → auto → fast の順で自動的に代替する。
# 互換ワーカーがない場合は、Settings と質問パネルに不足設定が表示される。
# tokenizer_endpoint は POST `{ "content": "...", "add_special": false }` を受け、
# `{ "tokens": [...] }` を返す llama.cpp server の API。Ollama の `/tokenize` ではない。
# 回答と異なる数え方を避けるため、回答モデルと同じ tokenizer/model を使う。
# HTTPS endpoint は常に利用できる。HTTP は loopback、または回答 worker の
# endpoint と同じ hostname なら利用でき、ポートは異なっていてもよい。
# 認証が必要な場合は tokenizer_api_key に専用キーを設定する。このキーだけが
# tokenizer へ送られ、未指定でも LLM 用 api_key は代用・転送されない。
# 例: 別 AAO Gateway 越しに共有 GPU プールを使う
# - id: team-gateway
# connection_type: aao_gateway
# endpoint: http://gateway.example.com:9876/v1
# api_key: ${TEAM_AAO_GATEWAY_KEY} # gateway 発行の sk-aao-*** virtual key
# model: qwen3:32b
# roles: [quality]
# max_concurrency: 2
# enabled: true
# 例: 事業者が運用する外部の OpenAI 互換サービスを使う
# api_key は必須。生存確認 (/v1/models) と実行時の呼び出しの両方で送られる。
# - id: external-llm
# connection_type: external_api
# endpoint: https://api.example.com/v1
# api_key: ${EXTERNAL_LLM_API_KEY}
# model: <サービスが公開しているモデル名>
# roles: [quality]
# max_concurrency: 4
# enabled: true
# 例: タイトル生成用ワーカー (chat ジョブは受け付けない)。
# 注意: タスク作成時にタイトル用 LLM はもう呼ばれない (実行中にエージェントが
# Mission Brief の goal からタイトルを派生する)。このワーカーは
# 「AIでタイトルを再生成」ボタン (POST /api/local/tasks/:id/regenerate-title)
# のオンデマンド生成にのみ使われる。未設定なら先頭ワーカーが代替する。
# - id: title-worker
# connection_type: direct
# endpoint: http://localhost:11434/v1
# model: qwen3:8b
# roles: [title]
# max_concurrency: 4
# enabled: true
# 例: Reflection 専用ワーカー (cheap モデルで memory 更新を回す)
# - id: reflector
# connection_type: direct
# endpoint: http://localhost:11434/v1
# model: qwen3:8b
# roles: [reflection]
# max_concurrency: 1
# enabled: true
# 例: extra_body / reasoning_efforts / reasoning_effort_mode
# (vLLM で reasoning effort を渡す)。
#
# extra_body: OpenAI 互換リクエストボディへそのまま浅くマージされる任意 JSON。
# model / messages / stream / stream_options / tools / tool_choice /
# temperature は予約キーとしてクライアント側で無視される。
# ここに API キー等の秘密情報を書かないこと — /api/config はこの値を
# マスクしない (config.yaml に平文で残る)。
# reasoning_efforts: このワーカーが対応する effort の宣言リスト (後続フェーズで
# ジョブ単位の effort 指定に使われる)。
# reasoning_effort_mode: effort をリクエストボディへ注入する形。
# body (既定) = トップレベル reasoning_effort。vLLM 向け。
# chat_template_kwargs = chat_template_kwargs.reasoning_effort。
# llama-server (llama.cpp) 向け — llama-server はトップレベルの
# reasoning_effort を黙って無視するため、llama-server を使う場合は
# chat_template_kwargs を明示すること。
# reasoning_replay: 返ってきた思考を、会話に残る assistant 発話の `reasoning` 欄に
# 載せ直して以後の呼び出しにも見せる (既定 false)。
# 注意 1: 入にした直後の 1 回だけ、進行中の会話の prefix cache が落ちる。
# 注意 2: 思考が履歴に積み上がるので、呼び出しごとの入力量が増える。
# 欄名が `reasoning` なのは、vLLM v0.16〜v0.21 が入力側の
# `reasoning_content` を黙って捨てるため。
# false のワーカーが思考入りの会話を継続で拾ったときは、そのまま送る
# (剥がすと接頭辞が変わってキャッシュが落ちる)。
# - id: vllm-reasoning
# connection_type: direct
# endpoint: http://localhost:8000/v1
# model: deepseek-r1
# roles: [quality]
# max_concurrency: 1
# enabled: true
# extra_body:
# reasoning_effort: max
# reasoning_efforts: [low, medium, high, max]
# reasoning_effort_mode: body
# reasoning_replay: false
# 例: backend_metrics — バックエンドの Prometheus /metrics の在りか (issue #1104)。
#
# ノードの速さ (prefill / decode) と prefix cache・KV cache の状態は、
# バックエンドの /metrics を 2 回読んで累積カウンターの差分から出す。
# 直結ワーカーは endpoint の隣 (<endpoint>/metrics) を既定で読むので、
# 通常この欄は要らない。書くのは次の 2 つの場合:
#
# 1. ゲートウェイ (connection_type: aao_gateway / proxy: true) 経由。
# ゲートウェイの /health は上流の /metrics を中継しないので、
# 実機の URL を node_id (ゲートウェイが名乗るデプロイ名) に紐づける。
# 2. 直結でも /metrics が既定の場所に無いとき。
#
# ここに書かなかったノードは未計測のまま表示される (0 とは区別される)。
#
# 資格情報の欄は無い。この URL へ Authorization を送ることは一切しない
# ——ワーカーの api_key はゲートウェイの認証面に向けて発行されたもので、
# 実機へ横流しすると上流のアクセスログに平文で残る。認証が必要な
# /metrics は対象外とし、到達制御はネットワーク側で行うこと。
#
# vLLM 側に必要な起動オプション:
# --enable-prefix-caching prefix cache のカウンターを出す
# --enable-prompt-tokens-details 1 コールごとの再利用トークン数を返す
# --enable-per-request-metrics 1 コールごとの TTFT / 生成時間 / 間隔を返す (任意)
# per-request metrics は高並行時に CPU を食う可能性があるので、必要なときだけ。
#
# - id: pool
# connection_type: aao_gateway
# endpoint: http://litellm:4000/v1
# model: qwen3-32b
# roles: [task]
# max_concurrency: 4
# enabled: true
# backend_metrics:
# - node_id: vllm-a
# url: http://10.0.0.5:8000/metrics
# - node_id: vllm-b
# url: http://10.0.0.6:8000/metrics
# Prometheus exporter (worker side). default で enabled。
# /metrics が bridge HTTP server (PORT, default 9876) に mount される。
# access control: default では localhost (127.0.0.1 / ::1) のみ通る。
# 本番では (a) bearer_token を設定するか、(b) allowed_hosts で前段 IP を許可。
# env: AAO_WORKER_METRICS_BEARER_TOKEN / AAO_WORKER_METRICS_ALLOWED_HOSTS (CSV) でも上書き可。
metrics:
enabled: true
prefix: aao_worker # /^[a-z][a-z0-9_]*$/
# bearer_token: env:AAO_WORKER_METRICS_BEARER_TOKEN
# allowed_hosts:
# - 127.0.0.1
# - ::1
# - localhost
# # - 0.0.0.0 # 全許可。前段で firewall を必ず使う運用前提
# ─── Markdown 文書質問チャット ───────────────────────────────
# 上の workers[] から document_question 専用ワーカーを優先する。
# 専用ワーカーが利用できなければ、全要件を満たす quality → auto → fast の順で
# 自動的に代替する。context_window は 8192 以上、output_tokens は 2048 以上が必要。
document_chat:
role: document_question
output_tokens: 2048
max_concurrent_per_user: 1
max_concurrent_total: 4
# ─── 辞書モード ──────────────────────────────────────────────
# Markdown プレビューで単語を選んだときの回答設定 (#998)。
# 単語の意味を出すだけの軽い用途なので、推論強度の既定は low。
# off にすると何も指定せず、接続先の既定に任せる。
# 実際に送られるのは、そのワーカーが reasoning_efforts で対応を宣言している
# 値だけ。宣言に無い値は送らない(受け付けない接続先で拒否されるため)。
dictionary:
reasoning_effort: low # off / low / medium / high など
# ─── AAO Gateway Server ──────────────────────────────────────
# この AAO 自身を OpenAI 互換 LLM Gateway として公開する設定。
# 有効化すると `/v1/chat/completions` などが同 process で立ち上がる。
#
# Virtual Keys (sk-aao-*** 形式) は **admin REST API での発行を推奨**:
# POST /api/admin/gateway/keys
# config.yaml の virtual_keys[] は bootstrap / backup 用途のみで、
# DB に自動 import される (source='config-import')。rotation は admin API 経由でのみ。
#
# 同 process / separate process の deploy 方法は docs/aao-gateway-overview.md を参照。
# UI からは Settings → LLM → Gateway Server で全て編集可能。
# gateway:
# enabled: false # true で同 process gateway が即時起動
# # (ConfigManager hot reload 対応、再起動不要)
# listen_port: 4000 # separate-deploy 時のみ有効 (default LiteLLM 互換)
# request_timeout_sec: 600 # 1 リクエスト全体 (streaming 込み)
# upstream_timeout_sec: 30 # 各 upstream fetch の TTFB 上限
# shutdown_graceful_sec: 30 # SIGTERM 後、in-flight SSE の drain 上限秒
#
# # この AAO 自身が自分の gateway を db virtual key で叩く構成のときだけ指定。
# # ここに挙げた team の下流リクエストは「使用量」ダッシュボードの時間粒度集計
# # (source=gateway_downstream) に二重計上しない (自分の分は source=gateway で
# # 既に記録済み)。判定は認証済み team で行うのでクライアントからは偽装不可。
# # internal_teams: [orchestrator]
#
# backends:
# # role ベース routing: worker はジョブの role (auto/fast/quality/reflection)
# # を routing key として送り、Gateway はその role を担う最も空いている
# # backend に振る。異なる model 名の GPU でも同じ role でまとめられる。
# # roles 未指定の backend は全 role を担当 (アップグレード後も従来どおり動く)。
# - id: gpu-a # `x-aao-backend-id` に出る ID
# endpoint: http://gpu-a:11434/v1
# model: qwen3:32b # backend が積むモデル (role が無い時の fallback 一致キー)
# roles: [quality] # この backend は quality ティア専用
# max_slots: 2 # llama-server -np と合わせる
# api_key: ${GPU_A_API_KEY} # backend が bearer 必須な場合のみ
# - id: gpu-b
# endpoint: http://gpu-b:11434/v1
# model: qwen3:8b # 別 GPU は別モデルでも OK
# roles: [fast, auto] # fast/auto ティアを担当
# max_slots: 2
#
# # Bootstrap / Backup 専用 virtual_keys (新規発行は admin API 経由を推奨)。
# # virtual_keys:
# # - key: ${TEAM_ALPHA_KEY} # 起動時に DB へ idempotent import
# # team: alpha
# # allowed_models: [qwen3:32b]
# # # tokens_budget: 1000000 # 月次 token 上限 (UTC 月初に reset)
# # # rate_limit_rpm: 60 # 1 分あたり最大リクエスト数
#
# # Prometheus exporter (gateway side)。default enabled。
# # team / key_prefix / backend ラベルが出るので auth 必須運用 (default localhost のみ)。
# # env: AAO_GATEWAY_METRICS_BEARER_TOKEN / AAO_GATEWAY_METRICS_ALLOWED_HOSTS (CSV) で上書き可。
# # metrics:
# # enabled: true
# # prefix: aao_gateway
# # bearer_token: env:AAO_GATEWAY_METRICS_BEARER_TOKEN
# # allowed_hosts:
# # - 127.0.0.1
# # - ::1
# # # - 0.0.0.0 # 前段 firewall 必須
# ─── Storage / Paths ─────────────────────────────────────────
# 旧 worktree_dir / custom_pieces_dir / user_folder_root /
# tools.task_upload_max_size_mb / tools.trash_retention_days
# は normalizer により storage.* に集約された。
storage:
worktree_dir: ./data/workspaces # ジョブ実行時の作業ディレクトリのベース
# custom_pieces_dir: ./custom-pieces # リポジトリ内の pieces/ に加えて読みに行く Piece dir (任意)
user_folder_root: ./data/users # {root}/{userId}/ 配下に AGENTS.md/browser-macros 等を保存
task_upload_max_size_mb: 50 # /api/local/tasks と /comments の body 上限 (MB)
# base64 で乗るので実ファイル目安は値 × 0.75。範囲 [1, 1000]
trash_retention_days: 30 # data/users/{userId}/trash/ の自動 sweep (起動時 + 24h 周期)
# 0 で sweep 毎に全削除
file_trash_retention_days: 30 # タスクのファイルのごみ箱を残す日数 (起動時 + 24h 周期)
# 画面から消したファイル/フォルダは物理削除せず
# 作業場の外のごみ箱へ退避し、ここで指定した日数を
# 過ぎたものだけを掃除が本当に消す。
# 0 以下で掃除しない (上の trash_retention_days とは
# 別の置き場・逆の意味なので注意)
llm_call_log_retention_days: 30 # LLM へ送った本文の記録 (logs/llm-calls-*.jsonl) を残す日数
# (起動時 + 24h 周期)。過ぎたファイルは丸ごと消える
# (途中で切らないので、記録が半分だけ読めない状態にならない)
# 0 以下で掃除しない = 期限なし
# system_agents_path: ./data/system/AGENTS.md # システム共通の指示 (設定 → システム共通の指示) の保存先
# data/system/ 配下のファイルのみ許可 (外・ディレクトリ・
# user_folder_root 配下を指すと警告して既定へフォールバック)
# 変更はサーバー再起動で反映
# ─── Execution ───────────────────────────────────────────────
# ジョブ全体の並列度・movement 上限・ジョブ retry。
concurrency: 4 # 全 worker 合算の最大並列ジョブ数 (env: CONCURRENCY)
max_movements: 200 # 1 ジョブ内の最大 movement 数 (loop 防止)
retry:
max_attempts: 3 # ジョブ失敗時の最大再試行回数
backoff_seconds: [60, 300, 900] # 各 attempt 間の待機秒
# 利用者ごとの実行枠 (issue #1191 段 1)
# ワーカー 1 台ごとの上限 (外側) とは別に、1 人が同時に走らせられる本数を用途ごとに絞る。
# 数え方は「全体で」。ワーカーの台数が増えても 1 人の取り分は増えない。
# 数えるのは実行中のものだけで、待ち行列・回答待ち・サブタスク待ち・再試行待ちは数えない。
# 0 は「その枠では数えない」。agent と reflection はそれで無制限になる。
# dictionary だけは無制限にならず、この設定を入れる前の歯止めへ戻る
# ——辞書引きはワーカー 1 台あたり 2 本、資料への質問は document_chat の
# max_concurrent_per_user (既定 1)。3 つとも 0 にしたときも同じ戻り方をする。
# 認証を使っていない環境では、この枠そのものが効かない (持ち主が全員 local になるため)。
user_concurrency:
agent: # 人が起こしたタスク・定期実行・切り出し・サブタスク
user: 1
admin: 2
dictionary: # 辞書引きと資料への質問が共有する枠 (合算して数える)
user: 1
admin: 2
reflection: # 内省の実行
user: 1
admin: 2
# ASK (ユーザーへの質問) 制御
ask:
max_per_job: 2 # 1 Job あたりの ASK 上限
# Subtask 制御
subtasks:
max_depth: 2 # SpawnSubTask のネスト最大深度
max_per_parent: 10 # 1 ジョブが生成できるサブタスクの最大数
spawn_stagger_ms: 1000 # SpawnSubTask の連続発火を間引く遅延(ms)。一斉着地で GPU 優先順位を飛び越えるのを防ぐ。0 で無効
# ─── Python パッケージ(ワークスペース単位の wheel オーバーレイ)────────
# 既定 OFF。有効化すると、各ワークスペースの設定 → Python から admin/オーナーが
# wheel を追加でき、そのワークスペースのエージェントだけが import できる。
# インストールはネットワークを許可した分離 bwrap で out-of-band 実行(ワークスペース /
# シークレットには触れない)。wheels のみ(--only-binary=:all:)で sdist の任意コード
# 実行を回避。エージェント自身の sandbox は従来どおりネットワーク遮断のまま。
# python_packages:
# enabled: false # true で機能を有効化
# dir: ./data/python-packages # オーバーレイの保存先ルート
# index_url: https://pypi.org/simple # 固定 index(リクエストで上書き不可)
# install_timeout_sec: 180 # 1 回のインストールの上限秒(最大 1800)
# max_packages_per_space: 30 # 1 ワークスペースが固定できるパッケージ数
# ─── Context (LLM コンテキスト管理) ───────────────────────────
# context:
# limit_tokens: 128000 # 省略時は接続先へ自動で問い合わせる(Ollama /api/show → llama.cpp
# # /props → OpenAI 互換 /v1/models の max_model_len)。全部駄目なら 128000
# thresholds:
# - ratio: 0.7
# action: warn
# - ratio: 0.85
# action: prompt
# - ratio: 0.95
# action: force_transition
# ─── Safety (エージェント自爆防止) ────────────────────────────
# safety:
# max_iterations: 200 # 1 movement 内の最大イテレーション
# max_revisits: 3 # 同一 movement の最大再訪問
# max_tool_loop_repeats: 5 # 全く同じツール呼び出し(名前+引数)を連続で繰り返した回数がこの値に達したらループとみなし強制中断 (2以上)
# max_thinking_only_retries: 6 # 思考だけ(本文もツール呼び出しも無い)の応答が連続でこの回数に達したら中断 (1以上)。
# 思考が返っている=バックエンドは健全なので、空応答(3回固定)とは別に数える
# max_job_minutes: 180 # 1 ジョブの実行時間ハードデッドライン (分)。これを超えたジョブは
# 強制 abort し、占有していた同時実行スロットを解放する (プロセス
# 再起動不要)。サブタスク待機に入るジョブは即座にスロットを返すため
# これに達するのは真のハングのみ。**default 180**。0 で無効。
# 設定 → セーフティ からも変更できる
# prompt_guard_ratio: 0.8 # コンテキスト上限の何 % まで prompt を許容するか (0.5–0.95)
# history_summarization: # 古い turn を構造化要約に置換して粘る (Opencode 方式)
# enabled: true # default true
# tail_turns: 2 # 末尾何 turn を必ず保護するか
# preserve_recent_budget: 8000 # 末尾保護の最大トークン数
# bash_unrestricted: false # true: コマンドホワイトリストを撤廃し任意コマンド実行可。
# # 代わりに bwrap サンドボックスで workspace 単位の
# # ファイルシステム隔離を強制 (タスク間の横断アクセス防止)。
# # 前提: コンテナで user namespace が有効 (nesting=1)。
# # 起動時に bwrap の動作確認を行い、失敗時はエラー終了。
# # Bash サンドボックス機構:
# # auto (既定) bwrap があれば sandbox、無ければ hardened-whitelist にフォールバック
# # always sandbox を強制。bwrap 不在なら起動失敗(本番推奨)
# # off bwrap を使わない(env スクラブは維持)。デバッグ用、非推奨
# # ⚠ 下の 2 行をこのまま外すと、bwrap の無いホストでは起動しない (#1235)。
# # auto の hardened フォールバックには外向き通信を遮断する仕組みが無いので、
# # 遮断を選んだまま (bash_allow_network: false) だと起動時に断られる。
# # bwrap を入れるか、bash_allow_network: true を明示するか、bash_sandbox: off にする。
# bash_sandbox: auto
# bash_allow_network: false # true: サンドボックスで host network を許可
# # (--unshare-net を外す)。pip/npm install/curl 等が
# # 可能になる。⚠ 隔離が弱まり情報漏えい/SSRF のリスク。
# # 既定 false (ネット遮断)。sandboxed 時のみ有効。
# # 表明ではなく生きたスイッチ。bwrap が無い間の
# # 逃げ道として true にしたら、bwrap を入れた時点で
# # false へ戻すこと(戻さないと通信が本当に開く)。
# ─── Search Filter (WebSearch の機密情報漏洩防止) ─────────────
# search_filter:
# blocked_patterns: # カスタムブロックパターン (完全一致で除去)
# - secret-project
# - internal-codename
# auto_block: # 自動検出 (default: 全 true)
# private_ip: true # 10.* / 172.16-31.* / 192.168.* / 127.*
# internal_domain: true # .local / .internal / .lan / .intranet / .corp / .home
# email: true
# phone: true # 日本の電話番号
# ─── Browser Runtime (BrowseWeb / BrowserAction) ──────────────
# browser:
# page_timeout: 60000 # ms
# action_timeout: 30000 # ms
# display_mode: novnc # 'headless' (default) / 'novnc'
# # novnc = Browser タブのライブ表示 / InteractiveBrowse /
# # CAPTCHA 解決を有効化 (ホストに Xvfb/x11vnc/websockify 必須)。
# # 旧 'captcha_solve' は自動で display_mode に移行される (非推奨)。
# max_captcha_pages: 5 # 人が解けるように残す CAPTCHA ページの上限 (display_mode: novnc 時のみ)。
# # 閉じられなかったページもこの枚数に数える。上限の 2 倍に達したら
# # ブラウザ検索を止めて SearXNG のみで応答する
# max_captcha_sessions: 3 # CAPTCHA を人が解く画面をスペースごとに持つときの同時枚数上限。
# # 1 枚につき Xvfb / x11vnc / websockify / Chromium の 4 プロセスが常駐する。
# # 上限に達したら最も古い画面を捨てる。閉じ損ねが居座って 2 倍に達したら
# # 新しい画面を作らず headless に落とす (max_captcha_pages とは別の歯止め)
# captcha_session_idle_ttl: 1800 # 画面を何秒アイドルしたら捨てるか。検索・閲覧のたびに延命される
# captcha_block_threshold: 3 # ブラウザ検索が CAPTCHA で全滅した連続回数。ここに達したら休止する
# captcha_block_cooldown_sec: 600 # 休止する秒数。検索が 1 回でも通れば即解除される
# captcha_engine_cooldown_sec: 1800 # 確認画面を出した検索先 1 つを、次の検索から何秒飛ばすか。
# # 上の 2 つ (全部塞がれたときの休止) とは別の歯止めで、
# # 検索先 1 つだけが塞がれている状態を止める。
# # 人が「解決した」を押すとそのワークスペースぶんは即座に戻る。0 で無効
# channel: chrome # 'chromium' (default) / 'chrome' / 'msedge'
# executable_path: /usr/bin/google-chrome # channel と排他
# ─── Tool packs (環境全体で群ごと止める) ─────────────────────
#
# ツールを「群」の単位で、この環境から丸ごと外す。書いた群のツールは
# エージェントに渡るツール一覧からも、ワークスペースの設定画面のツール一覧からも
# 消える。ワークスペース側で入れ直すことはできない (層の向きは環境が上)。
#
# **反映は再起動時のみ。** 走行中のジョブのツール一覧を入れ替えると、
# LLM 側のプロンプトキャッシュが全損する (遷移ごとに約 2 万トークンの再評価)。
# 設定を保存しただけでは何も変わらない。サーバーを再起動すること。
#
# 書ける名前 (2026-08-15 時点):
# x X (旧 Twitter) の検索・投稿取得 (XSearch / XUserPosts / XPostDetail /
# XTimeline / XFetchCardMedia)
# youtube YouTube の字幕取得・検索 (GetYouTubeTranscript / SearchYouTube)
# maps 地図の検索・経路・逆ジオコーディング (SearchPlaces / GetDirections / ReverseGeocode)
# amazon Amazon の商品検索と Keepa の価格 (SearchAmazon)
# speech 音声を文字にする (TranscribeAudio)
# speak 文章を音声にする (Speak)
# ms-learn Microsoft Learn の文書検索 (SearchMicrosoftLearn ほか 3 本)
# slide .pptx を組み立てる (SetTheme / AddSlide / BuildPptx / ResetSlides)
#
# 一覧に無い名前を書くと、起動時のログに ERROR で出る (何も止まらない)。
# 一覧に無い群 (Web / ブラウザ / Office / SSH など) は、ここでは止められない。
# 名前の定義は src/engine/tools/tool-pack-ledger.ts。
#
# tool_packs:
# disabled:
# - x
# - youtube
# ─── Tools (Web & Search / Media / External) ────────────────
# UI 上は 4 カテゴリに分かれて編集可能 (Web & Search / Browser Runtime /
# Media & Documents / External Services)。YAML は
# 互換のため `tools` 1 ブロックで管理。
tools:
# Web & Search
searxng_url: http://localhost:8080 # WebSearch フォールバック先 (通常は Playwright + Google)
webfetch_timeout: 30 # WebFetch / DownloadFile timeout (sec)
# websearch_timeout: 15
# webfetch_allowed_hosts: # SSRF 例外 (private IP / .local 等を許可する場合)
# - my-internal-host.local
# ページの魚拓 (BrowseWeb が開いたページの画像を source/images/ に溜める)
# どれも中身の意味は見ない歯止め。0 にすると実質その歯止めで全部落ちる
# browse_image_max_per_page: 20 # 1 ページあたりに残す枚数 (default 20)
# browse_image_max_size_mb: 5 # 画像 1 枚あたりの容量上限 (default 5)
# browse_image_min_bytes: 1024 # これ未満のバイト数は落とす (default 1024)
# browse_image_min_dimension: 32 # 縦横どちらかがこれ未満の px なら落とす (default 32)
# Media & Documents
# modality_endpoints:
# image:
# model: qwen2-vl:8b-instruct
# base_url: http://localhost:11434/v1
# api_key: sk-xxxx # 認証が必要な場合のみ。画像対応ワーカーは自身のキーを優先
# timeout: 60
# max_tokens: 1024
# audio: {} # 音声モデルへの直接入力・委譲用の予約設定
# video: {} # 動画ツール用の予約設定
# ocr_model: glm-ocr # OCR用モデル(画像接続先へ問い合わせる)
# office_excel_max_size_mb: 10 # ReadExcel / SplitExcelSheets / 画面のセル保存の上限 (default 10)
# office_docx_max_size_mb: 10 # ReadDocx / SplitDocxSections 上限
# office_pdf_max_size_mb: 10 # ReadPdf 上限
# office_pptx_max_size_mb: 50 # ReadPPTX 上限
# office_preview_max_size_mb: 50 # 画面の Excel プレビュー専用の上限 (default 50)。眺めるだけの経路なのでエージェント側とは別のつまみ
# office_pptx_max_uncompressed_mb: 200 # ZIP 展開後上限 (zip-bomb 検知)。OOXML を開く経路すべてで共有 (Read 系 3 種・分割 2 種・Edit 系 3 種・画面の Excel プレビュー / セル保存)
# office_max_entries: 10000 # ZIP 内の項目数上限 (zip-bomb 検知)。展開後上限と同じ経路で共有。申告件数と実際に並んでいる件数の両方に効く
# office_msg_max_size_mb: 25 # ReadMsg 上限 (default 25)
# speech_server_url: http://localhost:8000/v1
# speech_timeout: 300
# speech_language: ja
# 読み上げ (Speak)。文字起こしとは別の接続先を指定できる
# speak_server_url: http://localhost:8001/v1 # 未設定なら Speak は使えない
# speak_model: tts-1
# speak_voice: alloy # 使える名前はサーバーごとに違う(選択肢は持たない)
# speak_format: mp3 # mp3 / opus / aac / flac / wav / pcm はサーバー次第
# speak_timeout: 120
# speak_max_chars: 4096 # 超えたら断る(黙って切り詰めない)
# External Services
# x_cli_command: ["twitter"] # twitter-cli 実行コマンド
# x_timeout: 90
# x_auth_token: "..." # 任意: auth_token cookie
# x_ct0: "..." # 任意: ct0 cookie
# x_proxy: http://127.0.0.1:7890 # 任意: twitter-cli 用 proxy
# x_chrome_profile: "Profile 2" # Chrome cookie 抽出 profile
# x_download_media: auto # 'auto' (default) / 'never'
# x_download_video: thumbnail # 'thumbnail' (default) / 'full' / 'never'
# x_media_max_mb: 25
# x_media_fetch_timeout_seconds: 15
# google_maps_api_key: "..." # 未設定なら Nominatim / OSRM
# maps_timeout: 30
# amazon_affiliate_tag: "your-tag-22"
# keepa_api_key: "..."
# User browser-macros (RunUserScript)
# user_scripts_enabled: false # true で browser-macros の実行を許可
# user_scripts_allow_userids: # 未指定 = 全ユーザー許可 (user_scripts_enabled に従う)
# - alice-id
# - bob-id
# ─── サーバー TLS (オプション) ───────────────────────────────
# 【フレッシュインストール】setup.sh が server.tls.enabled: true を自動書き込む。
# 【アップグレード】server ブロック未記載の場合は false のまま(既存デプロイを壊さない)。
# 【リバースプロキシ構成】このブロックを省略するか enabled: false のままにすること。
# プロキシが TLS を終端しているので、ここで有効にすると二重終端になり接続が壊れる。
#
# server:
# port: 9876 # HTTP(S) 待ち受けポート (default 9876)。環境変数 PORT (.env 含む) が優先。反映には再起動が必要
# # 外から見えているアドレス。外部サービスとの接続 (OAuth) で使う折り返し先
# # (redirect_uri) を組み立てる、いちばん強い出どころ。画面に表示する値も
# # 実際に送る値もここから作られるので、両者が食い違うことはない。
# # OAuth で省略時は次の順に探す:
# # 1. auth のコールバック URL (auth.providers.*.callback_url) のアドレス部分
# # 2. 届いたリクエスト (X-Forwarded-Proto / X-Forwarded-Host、無ければ Host)
# # 3. http://localhost:{待ち受けポート}
# # リバースプロキシがこれらのヘッダを転送しない構成では、ここに明示すること。
# # パスは無視され scheme + ホスト + ポートだけを使う。
# # webhooks / chat の個別 public_base_url が空欄なら、この値をリンクに使う。
# # OAuth への反映は再起動不要。通知・チャット連携への反映は再起動後。
# public_base_url: "https://maestro.example.com"
# tls:
# enabled: true # フレッシュインストールのデフォルト; ブロック未記載=アップグレード時 false
# cert_file: null # PEM 証明書パス (任意); cert_file と key_file は両方設定するか両方省略
# key_file: null
# min_version: TLSv1.2
# self_signed_dir: ./data/tls
# self_signed_hosts: [] # localhost / 127.0.0.1 / ::1 / hostname は常に含まれる
# http_redirect: true
# http_redirect_port: 9080 # HTTP→HTTPS リダイレクトの待ち受けポート。単一値か配列で複数指定可 (例: [80, 9876])。
# # 各ポートは HTTPS ポートと異なる必要があり、1024 未満 (80 等) の bind には権限が必要
# redirect_host: null # リダイレクト先のホスト; null かつワイルドカード bind の場合はリクエストの Host ヘッダから導出
# hsts: false # 既定 false。HSTS (Strict-Transport-Security) を送るかどうか。
# # true にするとブラウザを HTTPS に固定し、後からオフにしても解除できなくなる
# # (自己署名証明書では害だけ大きい)。正式な証明書がある場合のみ true。
# # false の間は TLS 応答で max-age=0 を送り、過去に固定されたブラウザを解除する
# # リバースプロキシ構成: このブロックを省略するか enabled: false のままにすること。
# # プロキシが TLS を終端している場合に native TLS を有効にすると二重終端になり壊れる。
# # noVNC / SSH コンソールを wss で使う場合は「信頼済み証明書」が必要
# # (自己署名の wss はブラウザに click-through がない) —
# # cert_file / key_file で実証明書を指定するか、OS の信頼ストアに自己署名 CA を登録すること。
# ─── 認証 (オプション) ────────────────────────────────────────
# 未設定なら認証なしで動作 (従来互換)。
# auth:
# # 空のままだと data/secrets/session-secret.key に固定値を自動生成して使う (再起動でセッション維持)。
# # 明示設定したい場合は `openssl rand -hex 32` 等で生成した固定値を入れる (複数ノードで共有する場合は必須)。
# # ⚠ プレースホルダ文字列をそのまま使わない (公開された secret は偽造・改ざんに使われる)。
# session_secret: ""
# session_max_age: 86400000 # 無操作タイムアウト (ms)。アクセスごとに延長 (rolling)。未設定時は30日
# secure_cookie: false # HTTPS 環境では true (TLS 終端の背後では必須)
# admin_emails:
# - "[email protected]"
# # primary_provider: gitea # 'google' | 'gitea' | 'local'。複数有効時に明示
# providers:
# google:
# client_id: ""
# client_secret: ""
# callback_url: "http://localhost:3000/auth/google/callback"
# gitea:
# client_id: ""
# client_secret: ""
# base_url: "https://gitea.example.com"
# callback_url: "http://localhost:3000/auth/gitea/callback"
# # ローカルアカウント (email + password)。OAuth を立てずにパスワード保護したい時。
# # ここが未設定のまま新規インストールが loopback 以外で待ち受ける場合 (Docker 等) は、
# # 起動時に enabled: true が自動で書き込まれ、admin のパスワードが生成・出力される
# # (#1024)。パスワードは DB にハッシュで入り、ここには書かれない — bootstrap_admin は
# # 毎起動 DB へ再適用されるので、生成値を置くと変更が再起動で巻き戻るため。
# # 既存の no-auth デプロイに後付け可: 起動時に bootstrap_admin を id='local' で冪等 seed し、
# # no-auth 時代に 'local' 所有で溜まったデータをそのまま admin が引き継ぐ。
# local:
# enabled: true
# allow_signup: false # true でセルフ登録 (status=pending → admin 承認)
# bootstrap_admin: # 初回 admin (id='local')。seed 後は Settings/CLI で変更
# email: "[email protected]"
# password: "強いパスワードを設定" # 平文保存される。初回ログイン後に変更推奨
# ─── Branding (オプション) ────────────────────────────────────
# config.yaml / data/branding/ は .gitignore 済みで git pull 影響なし。
# Settings → System → Branding で GUI 編集可 (admin)。
# branding:
# app_name: "My Team AI"
# primary_color: "#2563eb"
# login_page_title: "My Team AI"
# logo_url: "/branding/logo-abc123.svg"
# favicon_url: "/branding/favicon-def456.png"
# footer_text: "© 2026 Your Team"
# ─── Secrets ─────────────────────────────────────────────────
# secrets:
# master_key_path: ./data/secrets/master.key # 32-byte key, auto-generated on first start (mode 0600)
# session_secret_path: ./data/secrets/session-secret.key # auth.session_secret 未設定時の自動生成先 (mode 0600)
# ─── Reflection ("Hermes" mode) ──────────────────────────────
# default OFF。ON にすると毎ジョブ完了後に user memory を LLM が自動更新する。
# snapshot は data/users/{userId}/.reflection-history/ に残り UI から revert 可。
# reflection:
# enabled: false
# max_memory_changes_per_job: 3
# piece_edit_cooldown_hours: 24
# snapshot_retention_days: 90
# per_user_daily_budget_tokens: 200000
# ─── MCP (Model Context Protocol) ────────────────────────────
# Individual servers は admin UI (global) または各ユーザー (self-hosted) で管理。
# MCP_ENCRYPTION_KEY env (64 hex chars) が必須。
# mcp:
# call_timeout_seconds: 60
# max_binary_size_mb: 20
# max_output_files_per_job: 10
# max_output_size_mb_per_job: 200
# tool_cache_ttl_seconds: 600
# oauth_pending_ttl_minutes: 10
# # allow_private_addresses: false # 自前 MCP server を private 網に置く場合 true
# ─── SSH (off by default) ────────────────────────────────────
# 有効化手順は docs/ssh.md / config.yaml.example のコメント (旧版) を参照。
# Operator runbook: docs/ssh.md
# Sample piece: pieces/ssh-console.yaml
#
# ssh:
# enabled: false
#
# # allow_private_addresses: false # global default。admin は per-connection で grant 可
# # call_timeout_seconds: 30
# # max_output_bytes: 32768
# # max_upload_size_mb: 100
# # max_download_size_mb: 100
# # audit_retention_days: 90
# # admin_bypasses_grants: true
# # abuse_window_minutes: 10
# # abuse_failure_threshold: 5
# # abuse_lock_minutes: 30
#
# # ── Interactive SSH Console (live PTY-backed shell) ──
# console:
# enabled: false # true で SshConsole* tools + UI Terminal タブを公開
# idle_timeout_seconds: 1800 # 30min I/O-less = auto close
# max_session_duration_seconds: 14400 # 4h hard cap
# scrollback_bytes: 524288 # 512KB scrollback / session
# max_sessions_per_connection: 3
# max_sessions_per_task: 5 # 同一タスクが開ける同時コンソール数の上限
# max_sessions_per_user: 20 # ユーザー単位の同時コンソール数の上限 (0 = 無制限)
# max_input_bytes_per_send: 16384
# auto_inject_screen_lines: 24
# default_cols: 120
# default_rows: 32
# ── Browser Notifications V2 (Web Push) ───────────────────────────────
# Requires HTTPS hosting + (for iOS) PWA installation on the client side.
# notifications:
# push:
# enabled: false # true で V2 を有効化
# vapid_subject: "https://maestro.example.com/" # RFC 8292 — operations URL preferred (運用サイトの URL か mailto:)
# vapid_current_path: "./data/secrets/vapid.json" # 自動生成 (mode 0600)
# vapid_history_dir: "./data/secrets/vapid-history"
# payload_max_bytes: 3072 # JSON byte length cap (上限 4096)
# queue_concurrency: 8
# per_send_timeout_ms: 10000
#
# 起動時に vapid_current_path に鍵が無ければ自動生成、mode 0600 で保存。
# 鍵をローテーションする場合: npm run vapid-rotate
# ── ワークスペース Webhook 通知 (Discord / Slack / Teams) ────────────────────
# Spec: issue #797(Discord / Slack / Teams いずれも実装済み)。
# 通知先 URL はワークスペースごとに設定 UI から登録し、DB に AES-256-GCM で
# 暗号化して保存する(config.yaml には書かない)。
# このブロックは 設定 → Webhook 通知 からも編集できる(反映には再起動が必要)。
# 数値は範囲外(0・負数・数値以外)だと起動時に既定値へ戻し、警告をログに出す。
# 0 に意味があるのは max_redirects と retry.max_attempts の 2 つだけ。
# webhooks:
# enabled: false # true で有効化。false のときは送信を no-op する
# timeout_ms: 10000 # 1 送信あたりの HTTP タイムアウト(1 以上)
# payload_max_bytes: 8192 # 送信 payload の上限(バイト・1 以上)
# max_redirects: 5 # ssrfSafeFetch が辿るリダイレクト上限(0 で追わない)
# queue_concurrency: 8 # 送信キューの同時実行数(1 以上)
# retry:
# max_attempts: 2 # 429 / 5xx / timeout 時の再試行回数(初回 + 2 = 最大 3 回送信。0 で再試行しない)
# backoff_ms: 500 # 再試行のベース backoff(指数バックオフ + jitter・1 以上)
# public_base_url: "https://maestro.example.com" # 通知本文のタスクリンクに使う絶対 URL
# # 空欄なら server.public_base_url を使う。
# # 両方未設定ならリンクを省く。反映には再起動が必要。
# ── A2A OAuth2 Authorization Server ──────────────────────────────────────────
# Requires auth to be active (consent screen uses req.user).
#
# a2a:
# enabled: false
# issuer: "https://localhost:8080/oidc" # 認可サーバーの issuer(公開 URL)
# resource_audience: "https://localhost:8080/a2a" # トークン audience(A2A endpoint)
# limits:
# rate_per_minute: 30 # ingress requests/min per delegation (token bucket)
# max_concurrent_tasks: 5 # simultaneous in-flight A2A tasks per delegation
# max_payload_bytes: 65536 # HTTP body + message size cap
# max_stream_seconds: 600 # max SSE stream duration (task + resubscribe)
# skill_budget_per_hour: 100 # accepted tasks per rolling hour per delegation
# max_concurrent_resubscribe: 5 # simultaneous tasks/resubscribe streams per delegation