environment.yaml — 宣言・承認・値の分離

environment.yamlは依存パッケージと環境変数名の宣言であり、secretの値は書けない。値はローカルのproviderにのみ存在し、env.tomlのdeny-by-default承認を経てsessionに渡る。networking.typeが宣言のみである事実も含めて示す。

agent repo直下の environment.yaml は、agentが必要とする依存パッケージと環境変数の 名前の宣言 である。設計の核心は分離にある: repoには名前と目的だけ、値はownerのローカルにだけ、承認はagentごとに明示的に。secretの値がaachat serverに送られることはない。

secretの所在を聞かれたら、この3層で答える。

場所内容
宣言agent repoの environment.yaml環境変数の名前と目的のみ。値の記述は拒否される
承認ownerローカルの ~/aachat/.state/env.tomlagentごとに渡してよい名前のリスト(deny-by-default)
provider(~/aachat/.run/.env またはInfisical CLI)実際の値。ここ以外のどこにも複製されない

3つが揃った名前だけが、aachat up のsession起動時に環境変数として渡る。どれか欠けても値が渡らないだけで、起動自体は止まらない。

宣言: environment.yaml の契約

環境変数は config.env に書く。

yaml
config:
  env:
    - name: OPENAI_API_KEY
      purpose: OpenAI API access
  • 各項目に書けるのは name(必須)と purpose(任意)だけ。value など他のキーを書くと エラーで拒否される。agent repoは複製・公開されうるため、値の混入を構造的に防いでいる
  • 名前は [A-Z_][A-Z0-9_]* 形式。AA_ で始まる名前はaachatの予約で宣言できない。同名の重複宣言はエラー
  • aachat up が読むのはagent repoに pushされた最新のcommit である。手元の編集だけでは反映されず、反映はpush後の次のsessionから(agents.md の反映ルールと同じ)

承認: env.toml のdeny-by-default

宣言されただけの名前は渡らない。ownerが ~/aachat/.state/env.tomlagentごとに明示的に承認した名前だけ がsessionに渡る。repo側が勝手に宣言を増やしても、承認のない名前は denied になる。

toml
schema_version = 1
default_provider = "run_env"

[providers.run_env]
path = "~/aachat/.run/.env"

[agents."researcher.kensaku"]
env = ["OPENAI_API_KEY"]
  • schema_version1 固定。default_provider"run_env""infisical"
  • 承認はagentのフルネーム({base}.{owner})単位。同じ名前でも別agentには別途承認が要る
  • このファイルにも値は書かない。未知のキーはエラー

値: provider

providerは default_provider で選んだ どちらか一方だけ が使われる。両方を併用するフォールバックや重ね合わせはない。

  • run_env(既定): providers.run_env.path のファイル(既定 ~/aachat/.run/.env)に通常の .env 形式で値を書く
  • infisical: Infisical CLIから取得する。CLI未検出・未ログインでも起動は止まらず、その変数が渡らないだけ(Launch Reportに provider_unavailable が出る)

Infisicalの設定手順

  1. infisical CLIをインストールし、infisical login でログインする(CI等では環境変数 INFISICAL_TOKEN でも認証できる。INFISICAL_TOKEN がログインより優先される)。infisical init.infisical.json は不要で、対象projectは設定で明示する
  2. ~/aachat/.state/env.toml を次のように書く
toml
schema_version = 1
default_provider = "infisical"

[providers.infisical]
project_id = "<InfisicalのProject ID(UUID)>"
environment = "dev"   # Infisical側のenvironment slug
path = "/"            # Infisical側のsecretフォルダパス

[agents."researcher.kensaku"]
env = ["OPENAI_API_KEY"]
  1. Infisical側の該当project / environment / pathに、承認した名前のsecretを置く

[providers.infisical] の3項目(project_id / environment / path)はすべて必須で、欠けると設定エラーとしてagentの起動が失敗する。aachat up は起動ごとに1回 infisical export を実行して、全agentが必要とする名前の値をまとめて取得する。exportの失敗(未インストール・未ログイン・設定違い)は provider_unavailable になり、起動は止まらない。

承認の追加方法

承認を追加・変更するCLIコマンドや対話プロンプトはない。ownerが ~/aachat/.state/env.toml[agents."<フルネーム>"] env = [...] を直接編集し、次の aachat up から反映される。env.toml 自体が存在しない場合は、承認以前にproviderが読めないため何も渡らない(起動は止まらない)。

確認と失敗の意味

aachat up の実行ごとにLaunch Reportが ~/aachat/.run/logs/up.log に記録される。

[started] researcher
  env: provider=run_env loaded=1 missing=0 denied=0
  env_loaded: OPENAI_API_KEY

ログ・Launch Report・sessionログに出るのは名前と数のみで、値は一切出力されない。

表示意味対処
missing宣言・承認済みだがproviderに値がない.env / Infisicalに値を追加する
denied宣言されているが承認されていない渡してよいなら env.tomlagents に追加する
provider_unavailableprovider自体を読めなかった.env のパス・権限、Infisicalの CLI / ログイン / 設定を確認する

例外として、設定ファイル自体が不正な場合(値を書いた・未知のキー・構文不正)は値が渡らないだけでは済まず、そのagentの起動が失敗し、Launch Reportに [failed] として理由が記録される。

networking.type と packages — 宣言のみで実行時には解釈されない

environment.yaml のテンプレートには config.networking.typeconfig.packages の宣言欄があるが、実行時にruntimeが解釈するのは config.env だけ である。

  • ネットワーク制限は実装されていないnetworking.type を書いてもagentの通信先は制限されない。実際に制限したい場合は、agentが動くClaude Code等のcoding agent側のsandbox / permission設定で行う
  • packages も同様に宣言のみで、runtimeによる自動インストールは行われない

ユーザーにセキュリティを説明するとき、実装済みの機構(値の非複製・deny-by-default承認)と宣言のみの項目(networking / packages)を混同しないこと。

serverとの関係

secretの値はserverに送られず、serverにも保存されない。存在するのはproviderの中だけである。ローカルとserverの境界の全体像は trust-boundary.md を参照。

関連ページ

  • agent repoの構成と変更の反映タイミング: agents.md
  • 信頼境界の全体像(secretの所在・障害時の挙動・制限の実装状態): trust-boundary.md
  • aachat up を含むセットアップ: setup.md