Skip to main content

Environment variables

The API server reads configuration from environment variables. Set them in a .env file referenced by agentflow.json or as process environment variables.

Setting variables

Via .env file

In agentflow.json:

{
"agent": "graph.react:app",
"env": ".env"
}

In .env:

GOOGLE_API_KEY=your-key
JWT_SECRET_KEY=your-secret
MODE=production

At the process level

MODE=production agentflow api --no-reload

Application variables

VariableDefaultDescription
APP_NAMEMyAppApplication name shown in logs
APP_VERSION0.1.0Application version
MODEdevelopmentdevelopment or production. Normalized to lowercase. Drives several defaults, including the authorization backend and whether the CORS check is fatal.
LOG_LEVELINFOLogging level: DEBUG, INFO, WARNING, ERROR
IS_DEBUGtrueEnable debug mode. Set false in production; leaving it on logs a startup warning.
SUMMARYAgentflow BackendOne-line service summary shown in the OpenAPI schema
LOGGER_NAMEagentflow-cliName of the root logger the server writes under. Read at import time, so it must be a process environment variable; setting it in .env is too late.
GRAPH_PATHagentflow.jsonPath to the config file the ASGI app loads. agentflow api --config sets this for you; set it directly when running the app under an external server such as Gunicorn or Uvicorn.

The settings model allows extra variables, so unknown names in the environment are tolerated rather than rejected.


Security headers

Applied by the security-headers middleware when SECURITY_HEADERS_ENABLED is true.

VariableDefaultDescription
SECURITY_HEADERS_ENABLEDtrueAdd security headers to all responses
HSTS_ENABLEDtrueAdd Strict-Transport-Security
HSTS_MAX_AGE31536000HSTS max age in seconds (one year)
HSTS_INCLUDE_SUBDOMAINStrueAdd includeSubDomains to the HSTS header
HSTS_PRELOADfalseAdd preload to the HSTS header. Only enable if you intend to submit the domain to the preload list; it is hard to undo.
FRAME_OPTIONSDENYX-Frame-Options value: DENY, SAMEORIGIN, or ALLOW-FROM
CONTENT_TYPE_OPTIONSnosniffX-Content-Type-Options value
XSS_PROTECTION1; mode=blockX-XSS-Protection value
REFERRER_POLICYstrict-origin-when-cross-originReferrer-Policy value
PERMISSIONS_POLICYnullPermissions-Policy value. Unset uses the middleware's built-in default.
CSP_POLICYnullContent-Security-Policy value. Unset uses the middleware's built-in default.

CORS variables

VariableDefaultDescription
ORIGINS*Comma-separated allowed origins. Set to specific domains in production.
ALLOWED_HOST*Allowed Host header values
CORS_ALLOW_CREDENTIALStrueWhether cross-origin requests may carry cookies or auth headers
Wildcard origins plus credentials refuses to start in production

ORIGINS=* on its own is a legitimate choice for a public, token-less API. The dangerous combination is wildcard origins together with credentials: Starlette reflects the caller's Origin back alongside Access-Control-Allow-Credentials: true, which turns every origin into a trusted, credentialed one.

With MODE=production, that combination raises InsecureCorsConfigError at startup and the server does not boot. There are exactly two ways forward:

# 1. Name the origins explicitly (the usual answer)
ORIGINS=https://yourapp.com,https://api.yourapp.com

# 2. Or serve a public, non-credentialed API from any origin
CORS_ALLOW_CREDENTIALS=false

In development the same combination only logs a warning, which tells you the deploy will fail before it does.


Authentication variables

VariableDescriptionRequired for
JWT_SECRET_KEYSecret key for JWT signing and verification. No default.auth: "jwt"
JWT_ALGORITHMJWT algorithm. Default HS256.auth: "jwt"

Both must be set when agentflow.json has "auth": "jwt"; the config load raises a ValueError otherwise and the server does not start. JWT support also needs the extra: pip install "10xscale-agentflow-cli[jwt]".


Redis variables

VariableDefaultDescription
REDIS_URLnullRedis connection URL, for example redis://localhost:6379/0

REDIS_URL is optional everywhere. Two things use it:

  • The ownership authorization cache (L2). The ownership and rbac backends resolve their Redis URL from the redis key in agentflow.json first, falling back to REDIS_URL. With neither set, or with the redis package not installed, the cache runs in-process only (L1) and the server logs a warning at startup. Nothing breaks; each worker just pays its own first lookup per thread.
  • PgCheckpointer. It can use Redis as a hot cache layer in front of Postgres. This is a performance choice, not a requirement: PgCheckpointer runs without it.

The rate limiter does not read REDIS_URL. Configure its connection under rate_limit.redis.url in agentflow.json.


Snowflake ID variables

Read only by SnowFlakeIdGenerator, and only when it is constructed with no arguments.

VariableDefaultDescription
SNOWFLAKE_EPOCH1723323246031Custom epoch in milliseconds
SNOWFLAKE_TOTAL_BITS64Total bits in the generated id
SNOWFLAKE_TIME_BITS39Bits reserved for the timestamp
SNOWFLAKE_NODE_BITS7Bits reserved for the node id
SNOWFLAKE_NODE_ID0This node's id
SNOWFLAKE_WORKER_BITS5Bits reserved for the worker id
SNOWFLAKE_WORKER_ID0This worker's id
Two different sets of SNOWFLAKE_* defaults exist

The settings model also declares SNOWFLAKE_* fields, with different defaults (SNOWFLAKE_EPOCH=1609459200000, SNOWFLAKE_NODE_ID=1, SNOWFLAKE_WORKER_ID=2, SNOWFLAKE_NODE_BITS=5, SNOWFLAKE_WORKER_BITS=8, and no SNOWFLAKE_TOTAL_BITS at all). The generator never reads that model; it reads os.environ directly. The table above is what actually takes effect.

The practical consequence: reading a default off get_settings() will not tell you what ids the generator produces. Set every variable explicitly in any deployment that runs more than one node or worker, and never rely on either set of defaults.

See ID Generator for the constructor contract.


Observability

VariableDefaultDescription
OTEL_ENABLEDfalseEnable OpenTelemetry tracing
OTEL_SERVICE_NAMEagentflow-apiService name reported in spans
OTEL_EXPORTER_OTLP_ENDPOINTnullOTLP collector endpoint
OTEL_LEVELstandardTrace detail: spans, standard, or full

OpenTelemetry needs the extra: pip install "10xscale-agentflow-cli[otel]", which also brings the FastAPI instrumentation and the OTLP exporter.

Logfire and LangSmith are configured through the observability block in agentflow.json; their secrets (LOGFIRE_TOKEN, LANGSMITH_API_KEY) come from the environment.


Media and multimodal

VariableDefaultDescription
MEDIA_STORAGE_TYPElocalmemory, local, cloud, or pg
MEDIA_STORAGE_PATH./uploadsDirectory used by the local store
MEDIA_MAX_SIZE_MB25.0Maximum upload size in megabytes
DOCUMENT_HANDLINGextract_textextract_text, pass_raw, or skip
MEDIA_ALLOWED_CONTENT_TYPES""Comma-separated MIME allowlist for uploads. Empty means allow every type. Entries may be exact (image/png) or wildcard subtype (image/*).
MEDIA_CLOUD_PROVIDERawsaws or gcp. Cloud storage only.
MEDIA_CLOUD_BUCKET""Bucket name
MEDIA_CLOUD_REGIONus-east-1Bucket region
MEDIA_CLOUD_PREFIXagentflow-mediaKey prefix inside the bucket
MEDIA_CLOUD_ACCESS_KEY_IDnullAWS access key
MEDIA_CLOUD_SECRET_ACCESS_KEYnullAWS secret key
MEDIA_CLOUD_SESSION_TOKENnullAWS session token
MEDIA_CLOUD_PROJECT_IDnullGCP project id
MEDIA_CLOUD_CREDENTIALS_JSONnullGCP service-account credentials JSON
MEDIA_SIGNED_URL_TTL_SECONDS3600Lifetime of a signed direct URL
MEDIA_SIGNED_URL_REFRESH_BUFFER_SECONDS60Re-sign this many seconds before expiry

Document text extraction needs the extra: pip install "10xscale-agentflow-cli[media]".

See Multimodal and vision for how these fit together.


Request limits

VariableDefaultDescription
MAX_REQUEST_SIZE10485760 (10MB)Maximum request body size in bytes

MAX_REQUEST_SIZE is enforced by HTTP middleware and applies to requests that declare a Content-Length. It does not cover WebSocket frames (bounded separately at 1 MiB per frame on /v1/graph/live) or chunked uploads (bounded by MEDIA_MAX_SIZE_MB as the body is read).


API path variables

VariableDefaultDescription
ROOT_PATH/Root path prefix (useful for reverse proxy sub-paths)
DOCS_PATH/docsSwagger UI path (set to empty to disable)
REDOCS_PATH/redocsReDoc path (set to empty to disable)
Disable docs in production

Consider disabling API docs in production by clearing DOCS_PATH and REDOCS_PATH:

DOCS_PATH=
REDOCS_PATH=

Error tracking

VariableDescription
SENTRY_DSNSentry DSN for error tracking (optional)

LLM provider variables

Set these based on the provider you use on your Agent. They are read at client creation time.

LLM timeout

VariableDefaultDescription
AGENTFLOW_LLM_TIMEOUT600.0Default request timeout in seconds applied to every LLM client. Must be a positive number. See Configure Agent for the programmatic API.

OpenAI (provider="openai")

VariableDescription
OPENAI_API_KEYAPI key from https://platform.openai.com

Google Gemini (provider="google")

The Google provider supports two backends: the Gemini API (default) and Vertex AI. See Using Vertex AI.

Gemini API (Google AI Studio):

VariableDescription
GEMINI_API_KEYAPI key from https://aistudio.google.com (preferred)
GOOGLE_API_KEYFallback name for the Gemini API key

Vertex AI (enable with use_vertex_ai=True on the agent or GOOGLE_GENAI_USE_VERTEXAI=true):

VariableDefaultDescription
GOOGLE_GENAI_USE_VERTEXAISet to true to route the Google provider through Vertex AI process-wide
GOOGLE_CLOUD_PROJECTRequired. GCP project ID with the Vertex AI API enabled
GOOGLE_CLOUD_LOCATIONus-central1GCP region for Vertex AI calls
GOOGLE_APPLICATION_CREDENTIALSPath to a service-account JSON key (Application Default Credentials)
Vertex AI authentication

Vertex AI authenticates via Application Default Credentials, not an API key. In local development point GOOGLE_APPLICATION_CREDENTIALS at a service-account key file. On GCP runtimes (Cloud Run, GKE, Compute Engine) the attached service account is picked up automatically.