設定リファレンス
以下の設定はすべて環境変数です。バックエンドは backend/.env から読みます(backend/.env.example が注釈つきのテンプレートです)。フロントエンドの 2 つは、フロントエンド自身のプロセス環境から読みます。モデルと API キーの設定は LLM の設定に別ページとしてまとめてあります。
サーバーの設定
| 変数 | 既定値 | 役割 |
|---|---|---|
HOST | 0.0.0.0 | バックエンドがバインドするアドレス |
PORT | 8000 | バックエンドがバインドするポート |
RELOAD | false | ローカル開発用の uvicorn オートリロード。バックエンドを python -m backend.main で起動したときだけ読まれます。Docker イメージの起動コマンドには、どちらにしても影響しません |
TIMEZONE | UTC | デプロイの現地タイムゾーンを表す IANA の名前。運用メトリクスでカレンダー上の 1 日がどこで始まるか(「今日」の件数と、リードタイムの推移の日別バケット)を決めます。タスクの実行時刻の要件にタイムゾーンが書かれていないとき、ワークフローのエージェントはこのタイムゾーンで時刻を解釈します。認識できない名前は起動を止めず UTC にフォールバックします。つまり打ち間違いはアプリを止めるのではなく、現地時刻をずらします |
フロントエンドの設定
| 変数 | 既定値 | 役割 |
|---|---|---|
BACKEND_BASE_URL | http://localhost:8000 | フロントエンドのサーバー側プロキシが /api/* を転送する先。プロセス起動時に一度だけ読まれます。Docker Compose の構成では、公開アドレスではなく内部ネットワーク上のバックエンドのアドレスです |
FRONTEND_PORT | 3000 | Docker Compose 専用。フロントエンドを公開するホスト側のポートです。コンテナ内部では 3000 で待ち受けたままで、バックエンドの CORS_ORIGINS は自動的にこれに追従します |
アプリケーションのデータベース
| 変数 | 既定値 | 役割 |
|---|---|---|
DB_URL | sqlite:///a2flow.db | データベース URL。SQLite(作業ディレクトリからの相対)と PostgreSQL に対応します |
非同期ドライバーのサフィックス(sqlite+aiosqlite / postgresql+asyncpg)は自動で付くので、素のスキームで足ります。
DB_URL=postgresql://user:password@localhost:5432/a2flow
スキーマの変更はバージョン管理された Alembic のマイグレーションとして扱われ、起動時に自動で適用されます。つまりアプリを再デプロイすることがスキーマを最新にする操作です。バックエンドを 2 レプリカ以上で動かすには PostgreSQL が必要です(水平スケーリング)。各テーブルの中身はデータベースにあります。
初期投入されるユーザー
起動時、バックエンドは隠れたシステムユーザーと、実在の 2 アカウントを投入します。それぞれ、対象のレコードが無いことを見つけた最初の起動でのみ作られます。
super_adminロールを持つ初期のrootユーザー(認可を参照)。プラットフォーム全体のスコープです(tenantId: null)。実在の(システム以外の)ユーザーが1 人でもいればスキップされるので、実質的にいちばん最初の起動でだけ走ります。- Default テナント(
slug: default)と、その中のadminロールを持つ初期のadminユーザー。テナント(slugで判定)とユーザー(そのテナント内のusernameで判定)は独立に確認されるので、片方だけを再作成しても、もう片方が重複することはありません。
隠れたシステムユーザーはブートストラップのレコードを所有します(ログインできず、ユーザー一覧にも出ません)。
| 変数 | 既定値 | 役割 |
|---|---|---|
ROOT_PASSWORD | 自動生成 | 投入される root ユーザーのパスワード |
ADMIN_PASSWORD | 自動生成 | Default テナントに投入される admin ユーザーのパスワード |
どちらかが未設定(または空)なら、ランダムなパスワードが生成され、そのユーザーの作成時に WARNING レベルで一度だけログに出ます。そのログ行が流れてしまうと、もう取り戻せません。ローカルでの試用を超える用途では、最初の起動より前に両方を明示的に設定するか、起動ログから生成されたパスワードをすぐ控えて、あとで変更してください。ユーザー名は root と admin で固定です。
セッションの有効期間
| 変数 | 既定値 | 役割 |
|---|---|---|
SESSION_IDLE_TIMEOUT_SECONDS | 28800(8 時間) | スライドするアイドルタイムアウト。認証済みリクエストのたびに最終アクティブ時刻が更新され、これより長く放置されたセッションは拒否されて削除されます |
SESSION_COOKIE_SECURE | false | セッションと CSRF のクッキーに Secure(HTTPS のみ)を付けます。HTTPS の背後に置くデプロイでは true にしてください |
クッキー自体はセッションクッキー(Max-Age も Expires もなし)なので、ブラウザを閉じたときにも消えます。フロントエンドは同一オリジンの書き換え(/api/*)でバックエンドに届くため、クッキーはファーストパーティとなり SameSite=Lax がきれいに効きます。
CORS
| 変数 | 既定値 | 役割 |
|---|---|---|
CORS_ORIGINS | http://localhost:3000 | バックエンド API を呼び出せる origin のカンマ区切りリスト |
フロントエンドを配信する origin をすべて追加します。
CORS_ORIGINS=https://app.example.com,http://localhost:3000
* は起動時に拒否されます。allow_credentials=True が常に有効で、ワイルドカードの origin と組み合わせることは CORS の仕様上できないからです。
エージェントスキルストア
| 変数 | 既定値 | 役割 |
|---|---|---|
SKILLS_DIR | backend/.skills | Agent Skill のリポジトリを浅くクローンして置くストアのルート。docker compose では /var/lib/a2flow/skills で、skills という名前付きボリュームが実体です |
SKILLS_PRUNE_GRACE_SECONDS | 3600 | 参照の有無にかかわらずリビジョンのディレクトリを残す時間。取得のたびに、どの実行からも固定されていないリビジョンを削除しますが、実行が現在のリビジョンを読んでからそれを指す行を挿入するまでの隙間を、この猶予が埋めます |
SKILLS_CLONE_TIMEOUT_SECONDS | 120 | クローンの個々の HTTP リクエストにかけられる時間の上限。これがないと応答しないリモートでクローンが止まり続け、スキルが pending のままになります |
ストアはリビジョンごとに 1 つの不変なディレクトリを持ちます。公開されたリビジョンがあとから変更されることはないので、取得処理が既存のリビジョンを読み込み中のエージェントを妨げることはありません。
$SKILLS_DIR/<agent_skill_id>/<commit_sha>/
これはキャッシュではなく永続的な状態です。ワークフロー実行は開始時のリビジョンに固定されるため、ディレクトリを消すと、既存の実行は管理者がスキルを取得し直すまでスキルを読み込めません(HTTP 409 SKILL_NOT_READY)。しかも取得はリポジトリの現在の HEAD を取るので、固定されていたリビジョンは戻りません。バックアップを取り、すべてのバックエンドレプリカに同じディレクトリを与えてください(水平スケーリング)。
ナレッジベース
| 変数 | 既定値 | 役割 |
|---|---|---|
KNOWLEDGE_SOURCE_MAX_BYTES | 20971520(20 MiB) | ナレッジベースにアップロードできる文書と、取得する Web ページの上限サイズ。これを超えた時点でアップロードを拒否します |
KNOWLEDGE_INGEST_CHUNK_CHARS | 40000 | LLM が 1 回に読むソースの文字数。これより長いソースは何回かに分けて順番に読みます。コンテキストウィンドウの小さいモデルでは下げてください |
KNOWLEDGE_FETCH_TIMEOUT_SECONDS | 30 | Web ページのソースを取得する 1 リクエストあたりの制限時間 |
ソースとページはセッションのファイルと同じくデータベースに保存されるので、専用のボリュームは要りません。ソースの読み込みにはエージェントと同じ LLM(LLM の設定)を使い、大きな文書では何度も呼び出します。
セッションのファイル
| 変数 | 既定値 | 役割 |
|---|---|---|
SESSION_FILE_MAX_BYTES | 20971520(20 MiB) | ワークフローセッションに添付できる 1 ファイルの上限。これを超えた時点でアップロードを拒否するので、大きすぎる本文を丸ごと抱え込むことはありません |
SESSION_FILES_MAX_TOTAL_BYTES | 209715200(200 MiB) | 1 つのセッションが持てるファイルの合計サイズ。ファイルが消えるのは実行が削除されるときだけなので、長く続くセッションの上限はここで決まります |
セッションのファイルはディスクではなくデータベースに保存されます。専用のディレクトリも、レプリカ間で共有するボリュームも要らず、バックアップもデータベースのもの以外に増えません(バックアップと復元)。この上限を上げると、1 回の実行が占めうるデータベースの容量と、1 回のアップロードやダウンロードが使うメモリが増えます。バイト列は丸ごと読むためです。
シークレットの管理
| 変数 | 既定値 | 役割 |
|---|---|---|
SECRET_ENCRYPTION_KEY | — | local タイプのシークレットを保存前に暗号化する Fernet キー |
SECRET_KEY_FILE | .secret_key | ディスク上のキーファイルのパス。SQLite のデータベースファイルの隣です。docker compose では /var/lib/a2flow/secret-key/.secret_key で、バックエンドとメールワーカーが共有する secret-key という名前付きボリュームに置かれます |
暗号化キーは最初の使用時に、次の順で解決されます。
SECRET_ENCRYPTION_KEY。有効な Fernet キーである必要があります。SECRET_KEY_FILEのキーファイル。- どちらもなければ、キーを生成してそのファイルに保存し、WARNING をログに出します。
キーはバックアップしてください。 失うと保存済みのローカルシークレットがすべて復号できなくなり、同じキーが守っている承認 CA の署名キーも使えなくなります。
HashiCorp Vault 用の環境変数はありません。テナント専用の Vault はテナントの admin が Tenant Settings で、グローバル Vault のアドレスは Super Admin が System Settings で、各テナントのその資格情報はテナントのページで設定します。テナント専用の Vault のアドレスには、ユーザーが入力するほかの URL と同じ SSRF チェックがかかるので、公開アドレスである必要があります。グローバル Vault のアドレスはこのチェックの対象外です。設定できるのは Super Admin だけで、Vault は通常プライベートアドレスにあるからです。
MCP ツールと承認
MCP ツールの呼び出しはどれも、そのタスク向けに発行された短命の X.509 証明書を提示しなければなりません。証明書が出るのは、そのタスクの承認が許可されたとき、あるいは誰にも承認を求めないタスクが始まったときです。署名のルートは最初の使用時に生成され、ローカルシークレットと同じキーで暗号化して保存されるので、この機能を動かすためにここを設定する必要はありません。
| 変数 | 既定値 | 何を決めるか |
|---|---|---|
MCP_TOOL_CERT_TTL_SECONDS | 3600 | タスクの証明書が有効な時間。そのタスクがツールを呼べる窓の長さです |
MCP_TOOL_CERT_SIGNATURE_WINDOW_SECONDS | 60 | プロキシ経由の各呼び出しに付く所持証明の署名について、許容する時刻のずれ |
MCP_CA_COMMON_NAME / MCP_CA_VALIDITY_DAYS | A2Flow MCP Approval CA / 3650 | 生成されるルートのサブジェクトと有効期間。ルートの初回生成時にだけ読まれ、あとから変えても既存のルートには影響しません |
MCP_REGISTRY_URL | https://registry.modelcontextprotocol.io | レジストリを見るダイアログが検索するレジストリのベース URL |
MCP_ELICITATION_TIMEOUT_SECONDS | 900 | MCP サーバーが求める確認に実行の申請者が答えるのを、ツール呼び出しが待つ時間。過ぎると質問は期限切れになります。申請者はタスクを再開した直後なので、これが効くのは放置された質問だけです |
AGENT_TURN_TIMEOUT_SECONDS | 3600 | 実行のエージェントの 1 ターンが続けられる最長の時間で、待ち時間も含みます。ツール呼び出しが人を待っている間もターンは実行中なので、MCP_ELICITATION_TIMEOUT_SECONDS より十分長くしてください |
MCP プロキシ
登録された MCP サーバーは A2Flow のコードではないので、エージェントとその秘密とは別の場所で動きます。Docker Compose の構成ではこれらは設定済みです。コンテナを自前で組む場合はここで設定します。
未設定のまま — ローカルでそのまま起動したときの状態 — だと、エージェントが自分のプロセスの中で MCP サーバーに到達します。開発では手軽ですが、誰でもサーバーを登録できる環境で望ましい状態ではありません。
| 変数 | 既定値 | 何をするか |
|---|---|---|
MCP_PROXY_URL | 未設定 | プロキシの場所。設定することで MCP サーバーがエージェントのプロセスの外に出ます |
MCP_PROXY_SERVER_NAME / MCP_PROXY_PORT | mcp-proxy / 8443 | プロキシに到達するための名前と、待ち受けるポート。名前は証明書の一部なので、両端で一致している必要があります |
MCP_PROXY_TLS_DIR | アプリケーションの隣のディレクトリ | プロキシが身元を示すために必要なものを、エージェントが書き出す場所。プロキシは同じディレクトリを読み取り専用で参照します |
MCP_BACKEND_TLS_DIR | アプリケーションの隣のディレクトリ | エージェントが自分の鍵を置く場所。上のディレクトリとは意図的に分けています。プロキシで動くものに読めてはいけないためです |
MCP_TRANSPORT_CERT_VALIDITY_DAYS | 365 | それらの資材の有効期間。残り 30 日を切ると自動で再発行されるので、手を入れる必要はありません |
MCP_SANDBOX_DIR | 未設定 | サンドボックス化したサーバー起動で使う、テナントごとのホームディレクトリを置く場所。テナントのサーバーがダウンロードしたパッケージは、テナントごとに分かれてここに保存されます。設定すると、ローカルで起動するサーバーはすべて専用のサンドボックスで動きます。プロキシはこれが無いと起動しません。素のローカル実行では未設定で、サーバーはサンドボックスなしで起動します |
通知メール
ここにある値は、管理 UI のシステム設定が編集するものと同じです。環境変数からも設定できるので、メールの設定を手作業の手順ではなくデプロイ設定として持てます。
| 変数 | 既定値 | 役割 |
|---|---|---|
APP_BASE_URL | — | 利用者がブラウザでこのデプロイに到達する URL(例 https://a2flow.example.com)。通知メールに埋めるリンクの組み立てに使われ、未設定だとリンクなしで送られます |
SMTP_ENABLED | false | メール配信のマスタースイッチ。明示的に true にする必要があり、他の変数が設定されていることから推測されることはありません |
SMTP_HOST / SMTP_PORT | — / 587 | メッセージを渡すリレー。ここは内部のホスト名でも構いません。取得しに行く URL ではなく SMTP クライアントに渡す値だからです |
SMTP_SECURITY | starttls | none、starttls、ssl のいずれか |
SMTP_USERNAME / SMTP_PASSWORD | — | SMTP AUTH の認証情報。パスワードは暗号文としてのみ保存され、ログにも出ず、どの API レスポンスにも返りません |
SMTP_FROM_EMAIL / SMTP_FROM_NAME | — | 送信元アドレス(配信を有効にするなら必須)と、その横に表示される任意の表示名 |
このページの他の設定と違い、これらは使うたびに読み直されるのではなく、単一の設定レコードに書き込まれます。そのため独自の規則があります。
- 毎回の起動で再適用されます。 初回だけではないので、リレーのパスワードのローテーションは再デプロイで行えます。
- 実際に設定した変数だけが書き込まれます。 未設定のものは保存済みの値をそのまま残します。管理者が UI で手作業で設定した内容も含みます。
- 不正な値は警告をログに出して、まるごとスキップされます。 ポートが不正、アドレスが不正、
SMTP_ENABLED=trueなのにホストがない、といった場合は保存済みの設定に手を触れません。アプリはそのまま起動します。
有効化のフラグが独立しているので、リレーのホストと認証情報を先のデプロイで用意しておき、配信を有効にするのは後のデプロイ、という進め方ができます。
送信メールのキュー
ここにあるのは、リレーへ流し込むキューの調整つまみです。挙動は配信キューを参照してください。通常のデプロイで設定が必要なものはありません。
| 変数 | 既定値 | 役割 |
|---|---|---|
EMAIL_WORKER_IN_PROCESS | true | API プロセスがキューの処理も行うかどうか。true なら uvicorn main:app だけでメールが届きます。専用のワーカープロセスを動かす場合は false にします(プロセス構成)。両方を有効にしても、アドバイザリロックがデプロイ全体でちょうど 1 つの送信者を選ぶので安全です。単に無意味なだけです |
EMAIL_SEND_RATE_PER_SECOND | 5.0 | リレーに渡す 1 秒あたりのメッセージ数。ワーカーは 1 通送るごとに 1 / rate 秒待ちます。リレーの制限が厳しいときは下げてください |
EMAIL_QUEUE_BATCH_SIZE / EMAIL_QUEUE_POLL_INTERVAL_SECONDS | 20 / 5.0 | 1 回の処理で取り出す通数と、キューが空のときにワーカーが眠る時間。ポーリング間隔は、ワーカーが眠っているあいだに発生した通知の配信遅延の下限になります |
EMAIL_MAX_ATTEMPTS | 9 | デッドレターになるまでの配信試行回数。バックオフは 15 秒、30 秒、1 分、2 分…と伸びて 1 時間で頭打ちなので、既定値でリレーの停止をおよそ 1 時間乗り切れます。リレーが恒久的な失敗と報告したものは、回数にかかわらず初回で切り捨てます |
EMAIL_SENT_RETENTION_DAYS | 30 | 配信済みメッセージをワーカーが削除するまでの保持期間。これらはキューの状態ではなく、何を送ったかの記録です。デッドレターは削除されません |
エージェント
| 変数 | 既定値 | 役割 |
|---|---|---|
EXECUTION_MAX_PARALLEL_SESSIONS | 4 | 1 つのワークフロー実行が同時に使うセッションの最大数。メインセッションと、タスクグラフの分岐でフォークされるブランチセッションの合計です。上限に達すると、準備の整ったタスクは新たにフォークせず担当セッションを待ちます。1 にするとフォークしません。1 以上 |
ROLE_DESCRIPTION | 一般的なアシスタントの説明 | エージェントのシステムプロンプトを組み立てる土台になる役割の説明。ワークフローのルールとインターフェースのスキーマと並べて使われます |
SESSION_RUNNER_CONCURRENCY | 4 | 1 つのレプリカが実行自身のために同時に動かすターンの数。対象はキックオフと、承認が判断されたあとの再開です。どれもモデルとの生きた会話なので、誰も見ていない実行が 1 つのレプリカで使うモデル呼び出しの数を抑えます。1 以上 |