Environment Variable Reference

Every environment variable the TFactory backend reads, in one place. A fresh operator installing TFactory from scratch should be able to find each required credential, each pipeline gate, each feature flag, and each tuning knob here — with its default, whether it is required, what it does, and where it is read.

This reference covers both the backend service (apps/backend) and the web-server portal (apps/web-server). Backend variables come first; the portal’s APP_* settings, SSO (OIDC), secret-encryption (KMS), and email-OAuth variables are grouped at the end under Portal variables. The portal also has its own apps/web-server/.env.example.

How to set variables


Pipeline auto-fire gates

Each pipeline stage auto-advances to the next when its gate is 1 (the default). Pin a gate to 0 to stop the pipeline before that stage so you can inspect the intermediate output. Test fixtures set these to 0.

Variable Default Required On/Off Purpose Read in
TFACTORY_AUTO_PLAN 1 No Default ON Planner auto-fires from task creation. Set 0 to stop after intake. agents/planner.py
TFACTORY_AUTO_GENERATE 1 No Default ON Gen-Functional auto-fires from the Planner. Set 0 to stop after planning. agents/gen_functional.py
TFACTORY_AUTO_EVALUATE 1 No Default ON Evaluator auto-fires from Gen-Functional. Set 0 to stop after generation. agents/evaluator.py
TFACTORY_AUTO_TRIAGE 1 No Default ON Triager auto-fires from the Evaluator. Set 0 to stop after evaluation. agents/triager.py
TFACTORY_REVIEW_LANE 0 No Default OFF Enable the additive adversarial review lane (writes findings/review.json; never blocks the verdict). Set 1 to enable. agents/review_lane.py

Triager side-effects

The Triager can write back to git and to GitHub. All write paths default to dry-run except template harvest, which writes low-risk local files.

Variable Default Required On/Off Purpose Read in
TFACTORY_TRIAGER_GIT_WRITE off (dry-run) No Default OFF [write] Commit accepted tests to the feature branch. Set 1 to actually commit. agents/triager.py, tools/git_writer.py, integrations/pfactory/run.py
TFACTORY_TRIAGER_PR_COMMENT off (dry-run) No Default OFF [write] Post the triage report via gh pr comment. Set 1 to actually post. agents/triager.py, integrations/pfactory/run.py
TFACTORY_PR_STATUS off (dry-run) No Default OFF [write] Publish the quality-gate commit status on the PR. Set 1 to actually publish. agents/triager.py
TFACTORY_TRIAGER_GIT_SIGN off No Default OFF GPG-sign the commits made by the git-writer. Opt in with 1. tools/git_writer.py
TFACTORY_TRIAGER_HARVEST on No Default ON [write] Promote high-confidence accepts into the project template library at <project>/.tfactory/templates/. Set 0 to skip. agents/triager.py
TFACTORY_TRIAGER_HARVEST_GLOBAL off No Default OFF [write] Also write harvested templates to the cross-project global library at ~/.tfactory/templates/. Opt in with 1. agents/triager.py

Completion and stage events

Best-effort notifications emitted when a run reaches a terminal status or when a stage transitions. All are OFF by default; a missing or failing target never affects the run.

Variable Default Required On/Off Purpose Read in
TFACTORY_COMPLETION_WEBHOOK unset No Default OFF [write] URL POSTed with the completion envelope when a run completes. agents/triager.py, agents/completion_outbox.py
TFACTORY_COMPLETION_WEBHOOK_TIMEOUT 5 No Timeout (seconds) for the completion webhook POST. agents/triager.py, agents/completion_outbox.py
TFACTORY_COMPLETION_SENTINEL off No Default OFF Write findings/COMPLETED.json on completion for a same-host watcher to stat. agents/triager.py
TFACTORY_COMPLETION_OUTBOX off No Default OFF Enable the durable completion-event outbox (retries the webhook with backoff). agents/completion_outbox.py
TFACTORY_COMPLETION_OUTBOX_BACKOFF_BASE 5.0 No Outbox retry backoff base (seconds). agents/completion_outbox.py
TFACTORY_COMPLETION_OUTBOX_BACKOFF_CAP 3600.0 No Outbox retry backoff ceiling (seconds). agents/completion_outbox.py
TFACTORY_COMPLETION_OUTBOX_MAX_ATTEMPTS 20 No Maximum outbox delivery attempts before giving up. agents/completion_outbox.py
TFACTORY_STAGE_EVENT_SENTINEL off No Default OFF Write a per-stage sentinel file on each stage transition. agents/stage_events.py
TFACTORY_STAGE_EVENT_WEBHOOK unset No Default OFF [write] URL POSTed on each stage transition. agents/stage_events.py
TFACTORY_STAGE_EVENT_WEBHOOK_TIMEOUT 5 No Timeout (seconds) for the stage-event webhook POST. agents/stage_events.py
TFACTORY_EVENT_SOURCE derived No Override the CloudEvents source field in the completion envelope. agents/completion_envelope.py
TRACEPARENT unset No W3C trace-context parent, inherited into the completion envelope for distributed tracing. Normally injected by the caller. agents/completion_envelope.py
TRACESTATE unset No W3C trace-context state, inherited into the completion envelope. Normally injected by the caller. agents/completion_envelope.py

Handback loop

When verification fails, TFactory can prepare and (optionally) send a correction bundle back to AIFactory, then re-verify, up to a cycle cap.

Variable Default Required On/Off Purpose Read in
TFACTORY_HANDBACK_PREPARE on No Default ON Prepare the handback bundle on a failing verdict. Disable with a falsy value. agents/handback/trigger.py
TFACTORY_HANDBACK_SEND off No Default OFF [write] Actually send the handback to AIFactory (triggers a re-build). Opt in with 1. agents/handback/trigger.py
TFACTORY_HANDBACK_MAX_CYCLES 2 No Correction-cycle cap for the handback loop. Values <= 0 fall back to the default. agents/handback/loop.py

VAL-3 disposable target

VAL-3 is the highest verification-assurance level: tests run against a real, disposable deploy target. These flags select which target shape TFactory provisions. They are read from the run environment.

Variable Default Required On/Off Purpose Read in
TFACTORY_VAL3_LOCAL_VM off No Default OFF Provision a local VM as the disposable target. agents/disposable_target.py
TFACTORY_VAL3_K8S_JOB off No Default OFF Provision a Kubernetes Job as the disposable target (see agents/k8s_job_target.py). agents/disposable_target.py
TFACTORY_VAL3_K8S_JOB_IMAGE unset Required when TFACTORY_VAL3_K8S_JOB=1 Runner image for the k8s-job disposable target (e.g. the tfactory-runner-nix image). agents/k8s_job_target.py
TFACTORY_VAL3_CLOUD unset No Default OFF Provision a cloud target; value names the cloud/target profile. agents/disposable_target.py
TFACTORY_VAL3_TARGET_IS_PROD off No Default OFF Assert the target is production (guardrail flag; also inferred from the contract). agents/disposable_target.py
TFACTORY_TARGET_URL injected No The live target URL, set by TFactory into the test runtime (first wait_for URL) and read by the runner’s network guard. Operators do not set this. tools/runners/lane_dispatch.py, tools/runners/net_guard.py

Nix runner and verify backend

Select how the pytest/verify lane executes: the legacy host/docker runner, or the per-task Nix Kubernetes Job (RFC-0005 / RFC-0016). See docs/nix-reproducible-testing.md for the full picture.

Variable Default Required On/Off Purpose Read in
TFACTORY_VERIFY_BACKEND auto No Force the verify lane: nixjob (per-task Nix Job), docker, or host. Empty = auto (nixjob when a Nix image is configured and the contract declares a nix env). agents/evaluator.py
TFACTORY_RUNNER_MODE auto No Legacy-runner mode: host, docker, or empty (auto: host when no container runtime is available). agents/evaluator.py
TFACTORY_NIX_RUNNER_IMAGE unset Required for Nix lane Container image for the per-task Nix verify Job. Without it, the Nix lane is unavailable and the lane falls back to host/docker. agents/evaluator.py, agents/nix_env.py, agents/verify_dispatch.py
TFACTORY_NIX_IN_IMAGE off No Default OFF The Nix store is baked into the runner image (node-agnostic); skip mounting the Nix store PVC. agents/nix_env.py, agents/verify_dispatch.py
TFACTORY_NIX_STORE_PVC unset No PVC name holding the shared Nix store (ignored when TFACTORY_NIX_IN_IMAGE is set). agents/nix_env.py, agents/verify_dispatch.py
TFACTORY_WORKSPACES_PVC unset No PVC name for the shared workspaces / data root mounted into the Nix Job. agents/nix_env.py, agents/verify_dispatch.py
TFACTORY_SANDBOX_NAMESPACE factory No Kubernetes namespace the Nix/verify Jobs are created in. agents/nix_env.py, agents/verify_dispatch.py
TFACTORY_NIX_JOB_CONCURRENCY 4 No Max Nix verify Jobs dispatched in parallel in the image-local regime (the fan-out is S x (3 + M) Jobs per spec). Clamped to a minimum of 1. agents/nix_env.py
TFACTORY_DATA_ROOT unset No Data-root path used to derive the Nix Job’s co-mount subPath. agents/nix_env.py
TFACTORY_VERIFY_EXEC inpod No Verify execution mode: kubejob dispatches a separate verify Job; anything else runs in-pod. agents/verify_dispatch.py
TFACTORY_EQUIVALENCE_LANE off No Default OFF Enable the source-vs-port equivalence lane. Truthy to enable. agents/evaluator.py
TFACTORY_EQUIVALENCE_BACKEND docker No Equivalence-lane backend (docker, or a Nix backend). agents/equivalence_lane.py
TFACTORY_EQUIVALENCE_IMAGE tfactory-runner-nix:latest / tfactory-runner-pytest:latest No Image for the equivalence lane (default depends on backend). agents/equivalence_lane.py
TFACTORY_VERDICT_VOTES 3 No Best-of-N independent evaluation passes for the verdict. agents/evaluator.py
TFACTORY_CI_PARITY 1 No Default ON Apply CI-parity defaults in the docker runner. Set 0 to disable. tools/runners/docker_runner.py
TFACTORY_CONTAINER_BIN docker No Container CLI used by the docker runner and evaluator (docker or podman). tools/runners/docker_runner.py, agents/evaluator.py

DEFAULT_NIXPKGS is a pinned constant, not an environment variable (tools/runners/nix_provisioner.py, currently github:NixOS/nixpkgs/567a49d…). Every generated per-task flake and the pre-baked warm-up closure resolve against it, and it is pinned together with the flake narHash/lastModified so the Nix lane realises byte-identical store paths. Change it in the source, not the environment.


Verify-Job credential injection

When TFACTORY_VERIFY_EXEC=kubejob, TFactory builds a separate Kubernetes Job and forwards a specific allow-list of provider/config variables into it (always as env, never as argv). These control the Job image and how secrets are sourced. Provider credentials (OPENAI_API_KEY, GITHUB_TOKEN, etc.) are forwarded from the pod env, or sourced via secretKeyRef when a provider Secret is named.

Variable Default Required On/Off Purpose Read in
TFACTORY_VERIFY_IMAGE fallback image No Explicit image for the verify Job (overrides the running image). agents/verify_dispatch.py
TFACTORY_IMAGE unset No The currently-running control-plane image, reused for the verify Job when no explicit verify image is set. agents/verify_dispatch.py
APP_BACKEND_PATH /home/projects/MagesticAI/apps/backend No Backend path baked into the verify Job’s PYTHONPATH (web-server sibling derived from it). agents/verify_dispatch.py
TFACTORY_VERIFY_OAUTH_SECRET_NAME unset No Kubernetes Secret name holding the Claude OAuth token for the verify Job. agents/verify_dispatch.py
TFACTORY_VERIFY_OAUTH_SECRET_KEY oauth-token No Key within the OAuth Secret. agents/verify_dispatch.py
TFACTORY_VERIFY_PROVIDER_SECRET_NAME unset No Secret name from which non-Claude provider keys are sourced via secretKeyRef (key = lower-kebab of the var, e.g. OPENAI_API_KEY -> openai-api-key). When unset, keys forward as resolved pod-env values. agents/verify_dispatch.py
TFACTORY_VERIFY_CLI_CREDS_SECRET unset No Secret name holding CLI credentials mounted into the verify Job. agents/verify_dispatch.py
DATABASE_URL unset No Database URL forwarded into the verify Job when the pipeline’s terminal store write needs it. agents/verify_dispatch.py

Note: ANTHROPIC_API_KEY is intentionally never forwarded into the verify Job — this prevents silent API billing when OAuth is the intended auth path.


Infrastructure, paths, and auth

Variable Default Required On/Off Purpose Read in
TFACTORY_WORKSPACE_ROOT ~/.tfactory No Root the portal endpoints and agents read/write workspaces from. agents/liveness_sweep.py, agents/completion_outbox.py, agents/handback/rerun.py, agents/tools_pkg/tools/task_control.py
TFACTORY_DATA_ROOT unset No See Nix runner. agents/nix_env.py
TFACTORY_SPEC_DIR unset No Spec directory the MCP server operates on. mcp_server/tfactory_server.py
TFACTORY_PROJECT_DIR CLAUDE_PROJECT_DIR No Project directory for the MCP server (falls back to CLAUDE_PROJECT_DIR). mcp_server/tfactory_server.py
CLAUDE_PROJECT_DIR unset No Project dir set by Claude Code; used as the TFACTORY_PROJECT_DIR fallback. mcp_server/tfactory_server.py
TFACTORY_API_URL built-in default No Base URL of the TFactory HTTP API the agent tools call. agents/tools_pkg/http_client.py
TFACTORY_SELF_API_URL http://localhost:3103 No TFactory’s own API base URL used by the handback sender. agents/handback/send.py
TFACTORY_API_TOKEN_FILE built-in default No Path to the file holding the TFactory API token. agents/tools_pkg/http_client.py
TFACTORY_MCP_KEY unset No API key sent by the agent HTTP client to the TFactory API/MCP. agents/tools_pkg/http_client.py
TFACTORY_PORTAL_PORT 3103 No Portal port used when building portal task-detail links. agents/tools_pkg/tools/task_control.py
TFACTORY_AIFACTORY_ROOT unset No Local path to the AIFactory checkout the snapshotter operates on. workspaces/snapshotter.py
TFACTORY_AIFACTORY_API_URL built-in default No AIFactory API base URL used by the snapshotter. workspaces/snapshotter.py
TFACTORY_CLOUD_ASSESSMENT_ROOT derived No Override the root path for stored cloud-assessment artifacts. agents/cloud/store.py
TFACTORY_VISUAL_INSPECTION_ROOT derived No Override the root path for stored visual-inspection artifacts. agents/visual_inspection/store.py
TFACTORY_STALL_DEADLINE_SECONDS 900 No Idle budget before an active stage is considered stalled (liveness). agents/liveness.py
TFACTORY_GEN_SESSION_TIMEOUT_S 480 No Wall-clock budget (seconds) for a single Gen-Functional agent session before it is bounded and terminated (#792). agents/gen_functional.py
TFACTORY_DEP_AGE_CHECK 1 No Default ON Dependency freshness/age check in the dependency-review gate. Set 0 to disable. agents/dependency_review.py
TFACTORY_EGRESS_ENABLED off No Default OFF Allow network egress from the secrets/egress guard. Truthy to enable. tfactory_secrets/egress.py
TFACTORY_BATCH_MIN_JOBS 2 No Minimum jobs before insight-extraction batches. analysis/insight_extractor.py
TFACTORY_BATCH_TIMEOUT 120 No Insight-extraction batch flush timeout (seconds). analysis/insight_extractor.py
TFACTORY_BATCH_DISABLE off No Default OFF Disable batched insight extraction. Truthy to disable. analysis/insight_extractor.py
KUBECONFIG in-cluster No Kubeconfig for the k8s evaluator target (falls back to in-cluster config). agents/evaluator_targets.py
DEFAULT_BRANCH repo default No Default branch used by worktree/workspace git operations. core/worktree.py, cli/workspace_commands.py
AIFACTORY_BASH_SANDBOX true No Default ON OS-level bash sandbox (bubblewrap) for agent bash commands. Set falsy on k3d/Kind clusters where bwrap cannot mount /proc. core/client.py
VAULT_ADDR unset Required for Vault backend HashiCorp Vault address for the Vault secrets backend. tfactory_secrets/backends/vault.py
VAULT_TOKEN unset Required for Vault backend Vault token for the Vault secrets backend. tfactory_secrets/backends/vault.py
AWS_REGION / AWS_DEFAULT_REGION unset Required for AWS Secrets backend AWS region for the AWS Secrets Manager backend. tfactory_secrets/backends/aws_secrets_manager.py

Backstage integration

Variable Default Required On/Off Purpose Read in
BACKSTAGE_BASE_URL unset No Backstage base URL; also enables the Backstage docs target when set. emit/docs/targets/backstage.py, emit/docs/emit_docs.py
TFACTORY_BACKSTAGE_TECHINSIGHTS_URL unset No Backstage TechInsights endpoint for publishing verification facts. agents/backstage_integration.py
TFACTORY_BACKSTAGE_TOKEN unset No Auth token for Backstage TechInsights. agents/backstage_integration.py
TFACTORY_BACKSTAGE_COMPONENT derived No Override the Backstage component ref facts are attached to. agents/backstage_integration.py

Docs emission

Controls where TFactory publishes the docs it generates.

Variable Default Required On/Off Purpose Read in
TFACTORY_DOCS_DIR derived No Override the local output directory for emitted docs. emit/docs/emit_docs.py
TFACTORY_DOCS_BACKSTAGE off No Default OFF Enable the Backstage TechDocs emission target (also on when BACKSTAGE_BASE_URL is set). emit/docs/emit_docs.py
TFACTORY_DOCS_CONFLUENCE off No Default OFF Enable the Confluence emission target (also on when CONFLUENCE_BASE_URL is set). emit/docs/emit_docs.py
CONFLUENCE_BASE_URL unset Required for Confluence target Confluence base URL. emit/docs/targets/confluence.py
CONFLUENCE_API_TOKEN unset Required for Confluence target Confluence API token. emit/docs/targets/confluence.py
CONFLUENCE_SPACE unset Required for Confluence target Confluence space key. emit/docs/targets/confluence.py

Providers and credentials

At least one LLM provider must be configured for the pipeline to run. Claude via OAuth (CLAUDE_CODE_OAUTH_TOKEN) is the primary path; ANTHROPIC_API_KEY is a fallback (and is never forwarded to verify Jobs, to avoid silent billing).

Claude / Anthropic

Variable Default Required Purpose Read in
CLAUDE_CODE_OAUTH_TOKEN unset One provider required Claude Code OAuth token (preferred auth). Also set via the UI OAuth flow. core/auth.py, core/client.py, core/simple_client.py, scripts/sdk_hello.py
ANTHROPIC_AUTH_TOKEN unset No CCR/proxy token for enterprise setups; passed through to the SDK. core/auth.py, agents/verify_dispatch.py
ANTHROPIC_API_KEY unset Fallback Anthropic API key (fallback when OAuth is absent). Never forwarded to verify Jobs. integrations/graphiti/config.py, runners/changelog_runner.py
ANTHROPIC_BASE_URL unset No Custom Anthropic/SDK endpoint. cli/utils.py, core/auth.py (SDK passthrough)
ANTHROPIC_MODEL unset No Model override passed to the SDK. core/auth.py, agents/verify_dispatch.py
ANTHROPIC_DEFAULT_HAIKU_MODEL unset No Maps the haiku shorthand to a concrete model ID. phase_config.py, core/auth.py
ANTHROPIC_DEFAULT_SONNET_MODEL unset No Maps the sonnet shorthand to a concrete model ID. phase_config.py, core/auth.py
ANTHROPIC_DEFAULT_OPUS_MODEL unset No Maps the opus / opus-1m shorthands to a concrete model ID. phase_config.py, core/auth.py

SDK runtime knobs (passed through to the Claude agent subprocess)

Variable Default Required Purpose Read in
NO_PROXY unset No Standard no-proxy list, forwarded to the SDK subprocess. core/auth.py
DISABLE_TELEMETRY unset No Disable SDK telemetry, forwarded to the SDK subprocess. core/auth.py
DISABLE_COST_WARNINGS unset No Suppress SDK cost warnings, forwarded to the SDK subprocess. core/auth.py
API_TIMEOUT_MS unset No SDK API timeout (ms), forwarded to the SDK subprocess. core/auth.py

OpenAI and OpenAI-compatible

Variable Default Required Purpose Read in
OPENAI_API_KEY unset One provider required OpenAI API key. phase_config.py, integrations/graphiti/config.py, runners/changelog_runner.py
OPENAI_MODEL gpt-5-mini No OpenAI model for the Graphiti knowledge graph. integrations/graphiti/config.py
OPENAI_COMPATIBLE_API_KEY unset No API key for an OpenAI-compatible endpoint. phase_config.py, providers/ollama_cloud_check.py
OPENAI_COMPATIBLE_BASE_URL unset No Base URL for an OpenAI-compatible endpoint. phase_config.py, providers/ollama_cloud_check.py
OPENAI_COMPATIBLE_MAX_TOKENS unset No Max-tokens override for the OpenAI-compatible agentic provider. providers/openai_compatible_agentic.py
OPENAI_COMPATIBLE_REASONING_EFFORT unset No Reasoning-effort override for the OpenAI-compatible agentic provider. providers/openai_compatible_agentic.py

Google / Gemini

Variable Default Required Purpose Read in
GOOGLE_API_KEY unset One provider required Google API key (also used as a Gemini key). phase_config.py, integrations/graphiti/config.py
GEMINI_API_KEY unset No Gemini API key (alternative to GOOGLE_API_KEY). phase_config.py
GOOGLE_LLM_MODEL gemini-2.0-flash No Google LLM model for Graphiti. integrations/graphiti/config.py

Azure OpenAI

Variable Default Required Purpose Read in
AZURE_OPENAI_API_KEY unset No Azure OpenAI API key. integrations/graphiti/config.py
AZURE_OPENAI_BASE_URL unset No Azure OpenAI base URL. integrations/graphiti/config.py
AZURE_OPENAI_LLM_DEPLOYMENT unset No Azure OpenAI LLM deployment name. integrations/graphiti/config.py

Ollama (local and cloud)

Variable Default Required Purpose Read in
OLLAMA_BASE_URL built-in default No Ollama server base URL. integrations/graphiti/config.py
OLLAMA_CLOUD_BASE_URL unset No Ollama Cloud base URL (cloud detection). providers/ollama_cloud_check.py
OLLAMA_API_KEY unset No Ollama (cloud) API key. providers/ollama_cloud_check.py
OLLAMA_LLM_MODEL unset No Ollama LLM model for Graphiti. integrations/graphiti/config.py
OLLAMA_EMBEDDING_MODEL unset No Ollama embedding model for Graphiti. integrations/graphiti/config.py
OLLAMA_EMBEDDING_DIM 0 No Ollama embedding dimension for Graphiti. integrations/graphiti/config.py

Other providers

Variable Default Required Purpose Read in
OPENROUTER_API_KEY unset No OpenRouter API key (Graphiti). integrations/graphiti/config.py
VOYAGE_API_KEY unset No Voyage AI embeddings key (Graphiti). integrations/graphiti/config.py
VOYAGE_EMBEDDING_MODEL voyage-3 No Voyage embedding model. integrations/graphiti/config.py
GITHUB_TOKEN unset No GitHub token for GitHub Models, Copilot dispatch, and GitLab provider ops. phase_config.py, agents/copilot_dispatch.py, agents/verify_dispatch.py
GH_TOKEN unset No Fallback GitHub token, read when GITHUB_TOKEN is unset (e.g. resolving a spec’s PR context). apps/web-server/server/routes/specs.py
GITHUB_MODELS_DEFAULT openai/gpt-4.1 No Default model when using the GitHub Models provider. phase_config.py
QA_LLM_PROVIDER unset No Force a specific provider for the QA/verify phase. phase_config.py, agents/verify_dispatch.py
AUTO_BUILD_MODEL unset No Model for the auto-build CLI path (CLI --model overrides). cli/main.py
UTILITY_MODEL_ID built-in default No Model ID for small utility LLM calls (e.g. commit messages). core/model_config.py
UTILITY_THINKING_BUDGET unset No Thinking-token budget for utility calls. core/model_config.py

Knowledge graph (Graphiti / Graphiti-MCP)

Variable Default Required On/Off Purpose Read in
GRAPHITI_ENABLED off No Default OFF Enable the Graphiti knowledge-graph integration. integrations/graphiti/config.py
GRAPHITI_LLM_PROVIDER openai No LLM provider for Graphiti. integrations/graphiti/config.py
GRAPHITI_EMBEDDER_PROVIDER derived No Embedder provider for Graphiti. integrations/graphiti/config.py, query_memory.py
GRAPHITI_DATABASE built-in default No Graphiti database name/type. integrations/graphiti/config.py
GRAPHITI_DB_PATH built-in default No Graphiti database path. integrations/graphiti/config.py
GRAPHITI_MCP_URL http://localhost:3102/mcp/ No Graphiti MCP server URL; presence enables the MCP-backed memory client. core/client.py, agents/tools_pkg/models.py
INSIGHT_EXTRACTION_ENABLED true No Default ON Enable post-run insight extraction into memory. analysis/insight_extractor.py
INSIGHT_EXTRACTOR_MODEL built-in default No Model used for insight extraction. analysis/insight_extractor.py

Miscellaneous and diagnostics

Variable Default Required On/Off Purpose Read in
DEBUG off No Default OFF Enable debug logging across the backend. core/debug.py, core/client.py, core/phase_event.py, ui/status.py
DEBUG_LEVEL 1 No Debug verbosity level. core/debug.py
DEBUG_LOG_FILE unset No Path to write the debug log file. core/debug.py
QUICK_MODE off No Default OFF Use shorter/faster prompts (true to enable). prompts_pkg/prompts.py
USE_CLAUDE_MD off No Default OFF Load repo CLAUDE.md into the agent context (true to enable). core/client.py
ENABLE_FANCY_UI true No Default ON Enable the rich terminal UI. ui/capabilities.py
NO_COLOR unset No Standard: disable colored output when set. ui/capabilities.py, cli/mcp_commands.py
FORCE_COLOR unset No Standard: force colored output when set. ui/capabilities.py
TERM unset No Terminal type, used for UI capability detection. ui/capabilities.py
CI unset No When true, the reviewer runs in non-interactive CI mode. review/reviewer.py
EDITOR unset No Editor invoked by the interactive reviewer. review/reviewer.py
FACTORY_SERVICE_NAME the Factory No Service name used in GitLab-provider messages. runners/github/providers/gitlab_provider.py
JOB_ID injected No Job identifier; injected into the verify pipeline / gen-functional by the dispatcher. agents/verify_pipeline.py, agents/gen_functional.py
CORRELATION_KEY injected No Correlation key for a run; injected into the verify pipeline by the dispatcher. agents/verify_pipeline.py

Portal variables (web-server)

These belong to the web-server portal app (apps/web-server). The docker-compose deployment sets them on the same container, so they also appear in the root .env.example. The portal’s pydantic Settings class uses env_prefix = "APP_", so a field FOO is set with APP_FOO. See apps/web-server/.env.example for the compose-oriented list.

Server, TLS, and CORS

Variable Default Required On/Off Purpose Read in
HOST_PORT 3102 No Host port the docker-compose web server is published to. docker-compose.yml
APP_HOST 0.0.0.0 No Bind address for the portal. Use a loopback host with APP_DISABLE_AUTH. server/config.py
APP_PORT 3103 No Portal listen port. server/config.py
APP_DEBUG off No Default OFF Portal debug mode. server/config.py
APP_SSL_ENABLED off No Default OFF Serve HTTPS; generates a self-signed cert if no cert/key path is given. server/config.py
APP_SSL_CERTFILE generated No Path to the TLS certificate (self-signed under the data dir if unset). server/config.py
APP_SSL_KEYFILE generated No Path to the TLS private key. server/config.py
APP_CORS_ORIGINS localhost set No Extra CORS origins (comma-separated string or JSON list). server/config.py
TFACTORY_DATA_DIR ./data No Bind-mounted host dir for the container’s /home/nonroot/.tfactory. docker-compose.yml

Authentication and sessions

Variable Default Required On/Off Purpose Read in
APP_API_TOKEN auto-generated No Portal API bearer token (generated + persisted to .token on first run if unset). server/config.py
APP_DISABLE_AUTH off No Default OFF [security] Inject a default admin into every request (dev only). The portal refuses to boot with this on a non-loopback APP_HOST unless APP_ALLOW_INSECURE_AUTH is also set. server/config.py
APP_ALLOW_INSECURE_AUTH off No Default OFF [security] Escape hatch that permits APP_DISABLE_AUTH on a non-loopback host. Not recommended. server/config.py
APP_JWT_SECRET auto-generated No HMAC secret for portal JWTs (persisted to .jwt_secret so tokens survive restarts). server/config.py
APP_JWT_ACCESS_TOKEN_EXPIRE_MINUTES 15 No Access-token lifetime (minutes). server/config.py
APP_JWT_REFRESH_TOKEN_EXPIRE_DAYS 7 No Refresh-token lifetime (days). server/config.py
APP_JWT_ALGORITHM HS256 No JWT signing algorithm. server/config.py

SSO / OIDC

Single-sign-on via an external OpenID Connect provider. Off unless APP_OIDC_ENABLED is truthy.

Variable Default Required On/Off Purpose Read in
APP_OIDC_ENABLED off No Default OFF Enable the OIDC login flow. server/oidc/client.py
APP_OIDC_PROVIDER unset When OIDC on Provider preset name (selects issuer defaults and default scope). server/oidc/client.py
APP_OIDC_ISSUER_URL preset When OIDC on OIDC issuer URL (overrides the preset). server/oidc/client.py
APP_OIDC_CLIENT_ID unset When OIDC on OAuth client ID. server/oidc/client.py
APP_OIDC_CLIENT_SECRET unset When OIDC on [secret] OAuth client secret. server/oidc/client.py
APP_OIDC_REDIRECT_URI derived No OAuth redirect/callback URI. server/oidc/client.py
APP_OIDC_SCOPE preset default No OAuth scopes requested at login. server/oidc/client.py
APP_OIDC_GROUP_TO_ROLE unset No Mapping from IdP group claims to portal roles. server/oidc/provisioning.py
APP_OIDC_DEFAULT_ROLE member No Role assigned when no group mapping matches. server/oidc/provisioning.py
APP_OIDC_DEFAULT_ORG_NAME unset No Org name new SSO users are provisioned into. server/oidc/provisioning.py
APP_OIDC_DEFAULT_ORG_SLUG unset No Org slug for provisioned SSO users. server/oidc/provisioning.py
APP_OIDC_POST_LOGIN_REDIRECT unset No Where to send the browser after a successful login. server/oidc/client.py
APP_OIDC_POST_LOGOUT_REDIRECT unset No Where to send the browser after logout. server/oidc/client.py
APP_OIDC_USERINFO_CACHE_TTL_S unset No TTL (seconds) for the cached userinfo response. server/oidc/userinfo_cache.py

Secret encryption (KMS)

Envelope-encryption backend for secrets the portal stores at rest. Selected by APP_KMS_BACKEND (or the unprefixed KMS_BACKEND); each backend reads its own provider config.

Variable Default Required On/Off Purpose Read in
APP_KMS_BACKEND / KMS_BACKEND fernet No KMS backend: fernet, aws, gcp, azure, or vault. server/crypto/kms/__init__.py
APP_KMS_FERNET_KEY / KMS_FERNET_KEY generated For fernet backend [secret] Fernet key for the local-key backend. server/crypto/kms/fernet.py
AWS_KMS_KEY_ID unset For aws backend KMS key ID/ARN for the AWS backend. server/crypto/kms/aws.py
AWS_ENDPOINT_URL unset No Custom AWS endpoint (e.g. LocalStack) for the AWS KMS backend. server/crypto/kms/aws.py
GCP_KMS_KEY_NAME unset For gcp backend Full resource name of the GCP KMS key. server/crypto/kms/gcp.py
AZURE_KEYVAULT_URL unset For azure backend Azure Key Vault URL. server/crypto/kms/azure.py
AZURE_KEYVAULT_KEY unset For azure backend Key name within the Azure Key Vault. server/crypto/kms/azure.py
VAULT_TRANSIT_KEY default key For vault backend Vault Transit key name for envelope encryption. server/crypto/kms/vault.py
VAULT_TRANSIT_MOUNT default mount For vault backend Vault Transit mount point. server/crypto/kms/vault.py
VAULT_NAMESPACE unset No Vault namespace (Vault Enterprise). server/crypto/kms/vault.py

The Vault KMS backend reuses VAULT_ADDR / VAULT_TOKEN from the Infrastructure group for its connection.

Email OAuth (portal mailbox integration)

Variable Default Required On/Off Purpose Read in
APP_EMAIL_GOOGLE_CLIENT_ID unset For Google mail Google OAuth client ID for the mailbox integration. server/_get_email_oauth_credentials.py
APP_EMAIL_GOOGLE_CLIENT_SECRET unset For Google mail [secret] Google OAuth client secret. server/_get_email_oauth_credentials.py
APP_EMAIL_MICROSOFT_CLIENT_ID unset For Microsoft mail Microsoft OAuth client ID. server/_get_email_oauth_credentials.py
APP_EMAIL_MICROSOFT_CLIENT_SECRET unset For Microsoft mail [secret] Microsoft OAuth client secret. server/_get_email_oauth_credentials.py
EMAIL_OAUTH_REDIRECT_URI derived No Override the email OAuth redirect URI. server/routes/email.py

Portal runtime, data, and lifecycle

Variable Default Required On/Off Purpose Read in
APP_DATABASE_URL sqlite (derived) No Portal database URL (defaults to sqlite+aiosqlite:///… under the data dir). server/config.py
APP_MIGRATIONS_AUTO_APPLY on No Default ON Run alembic upgrade head at boot. Set 0 in K8s where a Helm Job migrates out-of-band. server/config.py
APP_PROJECTS_DATA_DIR data dir No Directory for project metadata. server/config.py
APP_PROJECTS_BACKEND json No Project persistence backend: json (legacy) or db (org-scoped rows). server/config.py
APP_BACKEND_PATH derived No Path to apps/backend (auto-detected as a sibling if unset). server/config.py
PROJECT_WORKSPACE_ROOT derived No Root for per-project workspaces the portal manages. server/services/project_workspace_service.py
APP_DEFAULT_SHELL /bin/bash No Shell for portal terminals. server/config.py
APP_MAX_TERMINALS 20 No Max concurrent portal terminals. server/config.py
APP_MAX_CONCURRENT_TASKS 5 No Max concurrent task executions. server/config.py
APP_LIVENESS_SWEEP_ENABLED off No Default OFF Periodic watchdog that flags a silent in-flight stage as stalled (#95). server/config.py
APP_LIVENESS_SWEEP_INTERVAL_SECONDS 300 No How often the liveness sweep runs. server/config.py
APP_LIVENESS_SWEEP_DEADLINE_SECONDS 600 No Idle budget before the sweep marks a stage stalled. server/config.py
APP_INLINE_ORPHAN_RECONCILE_ENABLED on No Default ON One-shot boot reconcile: fail specs stranded at planning/generating by a control-plane roll (#774). Set 0 under --reload dev servers. server/config.py
APP_WORKTREE_GC_ENABLED on No Default ON One-shot boot GC of per-spec git worktrees for terminal specs, reclaiming PVC disk (#742/#781). server/config.py
APP_COMPLETION_RELAY_ENABLED off No Default OFF [write] Drain the durable completion-event outbox to CFactory (#281). Enqueue also needs TFACTORY_COMPLETION_OUTBOX. server/config.py
APP_COMPLETION_RELAY_INTERVAL_SECONDS 30 No How often the completion relay drains the outbox. server/config.py
APP_INBOUND_HANDBACK_ENABLED off No Default OFF Accept AIFactory’s inbound completion webhook to close the fail→handback→re-test loop (#182). server/config.py
APP_INBOUND_HANDBACK_SECRET unset When inbound handback on [secret] Shared secret validated against the X-TFactory-Handback-Token header. server/config.py
CFACTORY_SEARCH_URL in-cluster default No CFactory cockpit base URL the portal proxies its cross-portal search to. Empty disables federated search. server/config.py
CFACTORY_READ_KEY unset No [secret] Read-scoped cockpit key for the federated-search proxy. server/config.py

Portal integrations and access

Variable Default Required On/Off Purpose Read in
APP_SKILLS_PATH .claude/skills No Directory of Claude skills the portal exposes. server/services/skills_service.py
TFACTORY_SKILLS_DIR derived No Override the skills directory (tests inject a tmp dir); falls back to the resolved default. server/routes/tfactory_skills.py
METRICS_SCRAPE_TOKEN unset No [secret] Bearer token required to scrape /metrics. Empty leaves the endpoint open (behind auth). server/observability/metrics.py
COPILOT_MCP_TFACTORY_TOKEN unset For Copilot MCP [secret] Bearer token the GitHub Copilot MCP endpoint requires. server/routes/mcp_copilot.py
TFACTORY_MCP_REMOTE_ENABLED off No Default OFF Enable the remote MCP server transport. server/mcp_remote/__init__.py
TFACTORY_MCP_LOOPBACK_URL built-in default No Loopback base URL the remote MCP tools call back into. server/mcp_remote/tools.py
TFACTORY_MULTI_TENANT off No Default OFF Enable multi-tenant mode; honours the X-Tenant-Id header. server/routes/_tenancy.py
TFACTORY_RMUX_ENABLED off No Default OFF Enable the rmux (remote-mux) integration. server/rmux/integration.py
TFACTORY_TEST_AGENT_CMD unset No Override the agent command the portal spawns (test harness only). server/services/agent_service.py

Completeness

This reference was produced by grepping the entire apps/backend and apps/web-server trees for every environment read (os.environ, os.getenv, getenv(, plus pydantic Settings fields under env_prefix = "APP_" and indirection through _ENV_* constants), then reconciling every distinct name against a documented row.

Intentionally excluded (incidental)

Variable Why excluded
PORT Not TFactory config. Appears only in analysis/analyzers/port_detector.py as a comment describing the pattern the analyzer scans for in the target application under test.
PYTHONPATH Not read as configuration. TFactory only sets it when building subprocess/verify-Job environments (agents/evaluator.py, agents/verify_dispatch.py).
SHELL System-provided. Fallback for the portal terminal shell when APP_DEFAULT_SHELL is unset (server/pty/session.py).
XDG_RUNTIME_DIR System-provided. Locates the rmux socket dir when the rmux integration is enabled (server/rmux/wrapper.py).

The following variables appear in .env.example for the test/e2e harness or the web-server app and are not read by the backend service code; they are listed here for completeness and are safe to ignore for a production install: TFACTORY_E2E_STATE_DIR, TFACTORY_AIFACTORY_BRANCH, TFACTORY_AIFACTORY_PR, and TFACTORY_DOCKER_IMAGE_PYTHON (test/e2e harness).

Two names that showed up in the raw grep but are not real variables: VAR and VAR_NAME — both are placeholder strings inside docstrings/error messages (security/git_validators.py, analysis/analyzers/context/env_detector.py).