# --------------------------------------------------------------------------- # Smart Organization — sample environment file. # Copy to `.env` and fill in real values. NEVER commit a real `.env`. # Every external provider defaults to `mock` so the stack runs with zero # credentials. Flip the *_PROVIDER vars once real credentials exist. # --------------------------------------------------------------------------- APP_ENV=development APP_URL=http://localhost:3000 API_URL=http://localhost:8000 # Origins the browser is allowed to call the API from, comma-separated. # `localhost` and `127.0.0.1` are DIFFERENT origins to a browser: if you start # the dev server with `-H 127.0.0.1` and this list only has `localhost`, every # request fails with an opaque "Disallowed CORS origin". Both are listed here. # Production must set this explicitly — the dev default is rejected at boot. CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000 # --- Data stores ----------------------------------------------------------- DATABASE_URL=postgresql+psycopg://agy:agy@localhost:5432/agy_web REDIS_URL=redis://localhost:6379/0 # --- Security -------------------------------------------------------------- # Generate with: python -c "import secrets; print(secrets.token_urlsafe(48))" JWT_SECRET=change-me # Must be exactly 32 bytes, base64/hex encoded. ENCRYPTION_KEY=change-me-32-bytes # --- AI models (hidden from customers) ------------------------------------- # agy (Google Antigravity) is the only model provider. The setting is kept for # compatibility with older .env files; any value is ignored (with a warning). AI_DEFAULT_PROVIDER=agy # --- agy (Google Antigravity) ---------------------------------------------- # The only model provider. There are no API keys: accounts are Google # identities logged in via OAuth from the admin console # (/admin/agy-accounts → افزودن اکانت agy). Any number of accounts can be added — # the rotation pool spreads load across them and benches a rate-limited one # until its quota window resets. AGY_CLIENT_ID/SECRET default to the public # Antigravity CLI application; override them to use your own Google OAuth # client. AGY_REDIRECT_URI must stay a loopback URL. AGY_CLIENT_ID= AGY_CLIENT_SECRET= AGY_REDIRECT_URI=http://localhost:51121/oauth-callback # Seconds an account is benched after a 429 when Google sends no Retry-After. AGY_429_COOLDOWN_SECONDS=900 # --- Git provider ---------------------------------------------------------- # mock | gitea GIT_PROVIDER=mock GITEA_URL= GITEA_INTERNAL_URL= GITEA_ADMIN_TOKEN= # --- Preview domain routing ------------------------------------------------ # mock | caddy DOMAIN_ROUTER=mock PREVIEW_ROOT_DOMAIN=msa.artacloud.ir PREVIEW_PORT_START=8080 PREVIEW_PORT_END=8999 CADDYFILE_PATH=/etc/caddy/Caddyfile # --- Sandbox --------------------------------------------------------------- # mock | daytona | e2b SANDBOX_PROVIDER=mock DAYTONA_API_KEY= DAYTONA_API_URL= E2B_API_KEY= # --- Payments -------------------------------------------------------------- # mock | stripe PAYMENT_PROVIDER=mock STRIPE_SECRET_KEY= STRIPE_WEBHOOK_SECRET= # --- Error logging --------------------------------------------------------- # Every failure the platform catches is written to the `error_events` table and # is readable at /admin/errors (platform owner only). Errors are redacted before # they are stored — passwords, tokens, API keys, JWTs and DSN credentials are # stripped by app/core/redact.py. # # ERROR_LOG_ENABLED=0 turns persistence off entirely; failures still reach # stderr, but nothing is written to the database. ERROR_LOG_ENABLED=1 # Whether 4xx responses are recorded too. Off by default: a public API receives # a constant stream of 404s from scanners, and recording them all buries the # genuine bugs. Turn it on while debugging a misbehaving client. # 5xx responses are always recorded, whatever this is set to. ERROR_LOG_CLIENT_ERRORS=0 # =========================================================================== # v2 workstream settings. Each agent edits ONLY its own block. # =========================================================================== # >>> agent-1 (org platform) MCP_GATEWAY_HOST=127.0.0.1 MCP_GATEWAY_PORT=8765 MCP_GATEWAY_ENABLED=true MCP_TOKEN_TTL_DAYS=90 MCP_RATE_LIMIT_PER_MINUTE=60 MEMORY_ORG_CHAR_CAP=60000 PLATFORM_INVITE_TTL_HOURS=72 # <<< agent-1 # >>> agent-2 (AI workforce engine) ENGINE_MAX_TOOL_CALLS_PER_TURN=40 ENGINE_TURN_TIMEOUT_SECONDS=900 ENGINE_MAX_CYCLES=6 ENGINE_MAX_EMPLOYEES=20 ENGINE_TICK_SECONDS=10 # <<< agent-2 # >>> agent-3 (delivery & infra) SANDBOX_DOCKER_BIN=docker SANDBOX_WORKSPACES_ROOT=./.data/workspaces SANDBOX_DEFAULT_CPUS=1 SANDBOX_DEFAULT_MEMORY_MB=1024 DEMO_PORT_START=8100 DEMO_PORT_END=8999 DELIVERY_POLL_SECONDS=60 DEPLOY_ALLOW_PRIVATE_HOSTS=false ARTIFACTS_ROOT=./.data/artifacts # fake (default, no git on the host) | local (real git workspaces) GIT_WORKSPACE=fake ALLOW_CUSTOM_DOMAINS=false # `protocol.file.allow` for host git calls. The hardened default is `never`: a # repository must not be able to make git read a local path through a submodule # or `--upload-pack`. Set to true ONLY to test against a local bare repository. GIT_ALLOW_FILE_PROTOCOL=false # <<< agent-3