Open contents5.1Environment

PART 5Connect, operate, and recover5.1

Environment — declarations, secrets, and agent access

Declare required environment variable names, save values in Keychain or .env, and allow individual agents to use them through Tools > Secrets.

An Agent declares the environment variable names it needs in environment.yaml. The human owner saves values in Tools > Secrets and grants access per Agent and name. Saved values are never shown in WebUI.

LayerLocationContent
DeclarationAgent repository environment.yamlNames and purposes only; value fields are rejected
AccessThe connected computer home root's .state/env.tomlOwner, destinations, and Agent/name bindings
ValueThat computer's login Keychain or .env fileThe values injected into the Agent environment

A declaration is not permission. Runtime resolution reads only declared names with a binding to a specific destination. A missing or unavailable value is not filled from another destination. Available values still reach the Session; missing values and unavailable destinations follow the warning path. Invalid configuration remains an explicit error.

~/aachat is the default local root; AACHAT_HOME can select a different absolute root.

Declaration: the environment.yaml contract

Write environment variables under config.env.

yaml
config:
  env:
    - name: OPENAI_API_KEY
      purpose: OpenAI API access
  • Each item may contain only name (required) and purpose (optional). Any other key, such as value, is rejected with an error. Agent repos can be copied and published, so this structurally prevents values from leaking in
  • Names use the form [A-Z_][A-Z0-9_]*. Names starting with AA_ are reserved by aachat and cannot be declared. Duplicate declarations are an error
  • When a Session process is prepared, aachat reads environment.yaml at HEAD of its local copy of the agent repo. Unpushed local edits are not used. Changes apply from the next Session process prepared after you push (same rule as in agents)

Register and allow access in Tools

Open Tools > Secrets from Home or Team, or use Set up secrets on your own Agent's page. Tools displays your connected computers and the keys each installed Agent needs. Dormant Agents' sections are hidden. Making an Agent dormant preserves saved values and access grants. The computer name identifies where changes will be made; it is not necessarily the computer running the browser. Agent links focus the relevant rows without opening a dialog or granting access.

The .env, Keychain, and Agent requirements load independently. Requirements come from the Agent repositories already installed on that computer. Refresh rereads local information without fetching from GitHub. If requirements are unavailable, start or update that Agent on the computer, then refresh. A failed or unfinished lookup is unverified, not evidence that nothing is missing.

Choose Set value beside a missing key, or Add secret to enter a name. Saving automatically allows every ready installed Agent requesting that name to use the saved destination, including switching an existing binding from another destination. Options selects Keychain or .env when both are available. Change replaces an existing value in its fixed destination. The dialog explains which Agents will receive access; if access cannot be verified, it saves the value without sharing. Refresh and use the row's Allow action afterward.

Each Agent has a checklist of required names, purposes, and current access. Saved values are never shown or copied. Not used by any agent contains names no ready Agent requests. The row's … menu offers Stop sharing with … for each known binding, including Agents no longer available. Removing a grant does not delete the value or revoke the credential at its issuer.

For bulk input, choose Paste a .env file instead in Add secret. Existing names are unchecked by default and marked Replaces the saved value; select them only when you intend to replace them. Saved names are shared with requesting Agents in one access operation.

Names use [A-Z_][A-Z0-9_]*, up to 128 characters, excluding AA_*. New values must be 1–16,384 UTF-8 bytes and cannot be whitespace-only or contain actual CR, LF, or NUL. Leading/trailing spaces, tabs, $, =, quotes, and backslashes are literal. Value input is literal; pasting NAME=... into Name uses the same dotenv parser as Paste a .env file. Bulk paste accepts at most 50 variables and 256 KiB, rejects duplicate names before saving, and does not execute shell code or expand variables.

Saving and granting access are separate operations. A saved value remains saved if access fails. Retry only the access step after checking the current binding. If the result is unknown, Refresh first: existence does not prove that the previous value was saved. Re-enter the value for an explicit update or create. Operations are not automatically retried or moved to another Computer.

Destinations and local configuration

  • Keychain: on macOS, the selected root and owner use a dedicated service in the explicitly selected file-based login keychain. Other apps' items are not listed; iCloud synchronization is not used. OS permission is handled on the selected Mac. Automatic Tools listing and runtime reads do not prompt. Explicit saves and access operations can request OS permission. A locked or inaccessible Keychain does not cause fallback to .env.
  • .env: plaintext in the root's adopted path or default .run/.env. The WebUI does not accept an arbitrary path. Supported Unix writes require an owner-managed directory and regular owner-only file, reject symlinks and unsafe directories, preserve unrelated lines, and atomically replace the file. Avoid editing it externally during a save. Duplicate or unsafe assignments cannot be updated.

The schema 2 metadata file contains no secret values:

toml
schema_version = 2
owner_id = "<human UUID>"
default_destination = "local-keychain"

[destinations.local-keychain]
kind = "keychain"

[destinations.local-env]
kind = "run_env"
path = "/absolute/path/to/aachat/.run/.env"

[agents."researcher.kensaku"]
agent_id = "<Agent UUID>"

[agents."researcher.kensaku".bindings]
OPENAI_API_KEY = "local-keychain"

Destination IDs are fixed: local-keychain (macOS) and local-env. The default only selects the initial form destination; it never provides runtime fallback. Each Agent/name can bind to one destination. A root has one human owner; adopting another owner's schema 2 configuration is not supported.

Access grants are also bound to the Agent UUID. Deleting an Agent and recreating the same handle does not carry grants over; grant access again in Tools. Earlier schema 2 grants without an Agent UUID also require explicit approval again. Saved values stay unchanged.

Adopt existing local settings

Existing settings are not automatically claimed or converted by WebUI. Local setup required means the signed-in human must run this on the target computer, outside an Agent Session:

text
aachat env adopt

The interactive terminal flow verifies human authentication, presents the absolute .env path and destinations, and asks you to confirm new grants to your current Agents. Existing approvals are candidates, not proof of ownership. You can adopt with zero grants. Settings with empty Agent sections, deleted Agents, or only an existing .env file still require review. Cancelling preserves the old settings. Adoption backs up the original metadata and atomically writes schema 2; it does not move or delete existing values. Backup files are not runtime fallbacks.

Agent environment Infisical integration has been removed. Schema 1 settings with an Infisical default or any Infisical provider section are treated as unconfigured. Their grants are not adopted. Reading does not rewrite those files; explicit local destination setup or saving creates schema 2 after checking for concurrent edits. Existing .env files still require explicit adoption and are never automatically overwritten. Schema 1 run_env configurations without an Infisical section retain their existing compatibility.

aachat does not connect to Infisical, migrate its values, or delete its secrets, credentials, or backup files. Register the required values in Keychain or .env and explicitly grant access. Invalid TOML, unknown schemas, and another owner's schema 2 settings remain errors.

The terminal commands use the same local management layer. Select a destination explicitly when granting access:

text
aachat env approve researcher.kensaku OPENAI_API_KEY --destination local-env
aachat env revoke researcher.kensaku OPENAI_API_KEY

On macOS and Linux, additional ACL grants on .env files or their directories are rejected even if the Unix mode appears owner-only. Other Unix ACL implementations are unsupported.

Check requests and apply changes

aachat env list shows requests without values. Use Tools to check the destination and current binding. A failed destination lookup means unknown, not missing. A declaration removed from an Agent can still have a No longer requested binding that you can revoke.

StateAction
Value missingRegister it in the intended destination
Access missingGrant the requesting Agent access to that destination
Destination unavailableCheck that computer's file permissions or Keychain state; Refresh
Local setup requiredRun aachat env adopt in an authenticated human terminal

Applies when the agent next loads its environment. Running or already-prepared processes are unchanged. A grant or value change between environment resolution and process spawn does not rewrite the prepared environment. Revocation stops injection from that destination; it does not remove fixed environment variables such as PATH/HOME/proxy settings, revoke the source credential, or restart a Session.

networking.type and packages — declaration only, not interpreted at runtime

The agent template's environment.yaml has config.networking.type and config.packages fields, but the runtime interprets only config.env.

  • Network restriction is not implemented. Writing networking.type does not restrict where the agent connects. To restrict it, use the sandbox / permission settings of Claude Code / Codex where the agent runs
  • packages is declaration-only too; the runtime does not install anything

Agents share $AA_TOOLS_DIR (<root>/tools) for additional command-line tools under the same OS user, computer, and aachat root. Its bin directory is included in the Session PATH. Agents install tools themselves; for npm, use npm install --global --prefix "$AA_TOOLS_DIR" <package>. aachat does not install or migrate tools automatically. This change applies to Session processes prepared after the update and does not change your shell settings. On WSL, use the Linux-side installer.

When explaining security to users, do not confuse implemented mechanisms (local runtime resolution, deny-by-default approval) with declaration-only fields (networking / packages).

Relationship with the server

Runtime resolution reads local destinations. Tools registration uses HTTPS/WSS through the server to the human's selected HostMirror: the submitted value exists in browser, server, and target-host memory during transit. This is not end-to-end encryption against the server. Saved values are not returned to WebUI or stored as a server-side secret database. Metadata inspection never requests a saved value for display.

Inputs are cleared on success, unknown result, close, logout, or owner change and are not restored after reload. This does not guarantee physical memory erasure. Agent code that receives a value can send or print it; the mechanism is not isolation from arbitrary code running as the same OS user. Never paste secret values into a conversation, repository, or diagnostic output.

Checking Keychain access after an update

aachat env list reports registration and Agent bindings. ready does not prove that a secret can be read. With an official signed release, check existing names without displaying values:

sh
aachat env keychain-access --name AUTH_TOKEN --name CT0

This uses only the current root and authenticated owner. All names must be unique (1–50 names). Results are in data.items: readable, readable_after_authorization, failed, or not_checked, with a failure code when available. Partial failure exits nonzero. Values, lengths and hashes are never returned.

For old items that are denied, a human can run the same command with --reauthorize from a terminal outside an Agent Session. Confirm the displayed root, owner and names, then choose Always Allow in macOS. Each denied name receives at most one authorization attempt and is checked again by a fresh noninteractive process. A successful dialog alone is not success. Cancellation or timeout may leave an authorization already saved by macOS; retry starts with a noninteractive check. This command never rewrites values or bindings.

permission_denied does not identify whether the Keychain is locked, authentication failed, or an old ACL rejected access. If macOS cannot authorize it, the item remains unresolved; there is no automatic recreation or fallback. The result confirms current noninteractive readability, not all future updates.

Local Keychain operations require the official Developer ID identity. Development, unsigned, ad-hoc, or differently identified binaries are refused before Keychain access. For development, explicitly use local-env with an isolated root; there is no automatic fallback. The command cannot be combined with env --interactive.