Skip to main content

Configuration of Environment Variables

Agenta encodes the same nesting at three layers: the environment variable name, the Python env.py attribute path, and the Helm values.yaml path. Every section below lists the canonical names in those three forms.

For deprecated/legacy environment variable names that still work via fallback, see Deprecated environment variables at the bottom.

Kubernetes / Helm

For Helm deployments, set the values.yaml path instead of the env var. The chart maps every value to the same canonical env var internally.

Helm-only pre-existing Secret

The Helm chart accepts a single Helm-only key, secrets.existingSecret, that points at a pre-created Kubernetes Secret. When set, the chart will not create or update the Secret object; it just wires envFrom/secretKeyRef references to the name you provide. Your Secret must contain the canonical env-var keys (AGENTA_AUTH_KEY, AGENTA_CRYPT_KEY, POSTGRES_PASSWORD, and any optional keys such as SUPERTOKENS_API_KEY, OPENAI_API_KEY, OAuth client secrets, etc.). See Deploy to Kubernetes Secrets. This key has no env-var or env.py equivalent.

Agenta core

Env varenv.py pathvalues.yaml path
AGENTA_LICENSEagenta.licenseagenta.license
AGENTA_WEB_URLagenta.web_urlagenta.webUrl
AGENTA_SERVICES_URLagenta.services_urlagenta.servicesUrl
AGENTA_API_URLagenta.api_urlagenta.apiUrl
AGENTA_API_INTERNAL_URLagenta.api_internal_urlagenta.apiInternalUrl
AGENTA_AUTH_KEYagenta.auth_keyagenta.authKey
AGENTA_CRYPT_KEYagenta.crypt_keyagenta.cryptKey
AGENTA_RUNNER_TOKENn/a (read by the runner and its caller)agenta.runnerToken

AGENTA_AUTH_KEY, AGENTA_CRYPT_KEY, and AGENTA_RUNNER_TOKEN are required secrets: the examples ship them as replace-me and you must set a real value for each. See Agent runner for the runner token.

Agenta access

The first four variables (allowed/blocked domains and emails, allowed owner emails) apply to both the open source and Enterprise editions. See Restrict Sign-ups and Organization Creation for how they behave. The plan and role variables are Enterprise-only; see Dynamic Access Controls.

Env varenv.py pathvalues.yaml path
AGENTA_ACCESS_ALLOWED_DOMAINSagenta.access.allowed_domainsagenta.access.allowedDomains
AGENTA_ACCESS_ALLOWED_OWNER_EMAILSagenta.access.allowed_owner_emailsagenta.access.allowedOwnerEmails
AGENTA_ACCESS_BLOCKED_DOMAINSagenta.access.blocked_domainsagenta.access.blockedDomains
AGENTA_ACCESS_BLOCKED_EMAILSagenta.access.blocked_emailsagenta.access.blockedEmails
AGENTA_ACCESS_DEFAULT_PLANagenta.access.default_planagenta.access.defaultPlan
AGENTA_ACCESS_DEFAULT_PLAN_OVERLAYagenta.access.default_plan_overlayagenta.access.defaultPlanOverlay
AGENTA_ACCESS_EMAIL_DISABLEDagenta.access.email_disabledagenta.access.emailDisabled
AGENTA_ACCESS_PLANSagenta.access.plansagenta.access.plans
AGENTA_ACCESS_ROLESagenta.access.rolesagenta.access.roles
AGENTA_ACCESS_ROLES_OVERLAYagenta.access.roles_overlayagenta.access.rolesOverlay

Agenta AI services

Env varenv.py pathvalues.yaml path
AGENTA_AI_SERVICES_API_KEYagenta.ai_services.api_keyagenta.aiServices.apiKey
AGENTA_AI_SERVICES_API_URLagenta.ai_services.api_urlagenta.aiServices.apiUrl
AGENTA_AI_SERVICES_ENVIRONMENT_SLUGagenta.ai_services.environment_slugagenta.aiServices.environmentSlug
AGENTA_AI_SERVICES_REFINE_PROMPT_KEYagenta.ai_services.refine_prompt_keyagenta.aiServices.refinePromptKey

Agenta billing

Env varenv.py pathvalues.yaml path
AGENTA_BILLING_CATALOGagenta.billing.catalogagenta.billing.catalog
AGENTA_BILLING_PRICINGagenta.billing.pricingagenta.billing.pricing

Agenta API

Env varenv.py pathvalues.yaml path
AGENTA_API_CACHING_ENABLEDagenta.api.caching.enabledagenta.api.caching.enabled

Agenta extras

Env varenv.py pathvalues.yaml path
AGENTA_EXTRAS_DEMOSagenta.extras.demosagenta.extras.demos

Agenta logging

Env varenv.py pathvalues.yaml path
AGENTA_LOGGING_CONSOLE_ENABLEDagenta.logging.console_enabledagenta.logging.consoleEnabled
AGENTA_LOGGING_CONSOLE_LEVELagenta.logging.console_levelagenta.logging.consoleLevel
AGENTA_LOGGING_FILE_ENABLEDagenta.logging.file_enabledagenta.logging.fileEnabled
AGENTA_LOGGING_FILE_LEVELagenta.logging.file_levelagenta.logging.fileLevel
AGENTA_LOGGING_FILE_PATHagenta.logging.file_pathagenta.logging.filePath
AGENTA_LOGGING_OTLP_ENABLEDagenta.logging.otlp_enabledagenta.logging.otlpEnabled
AGENTA_LOGGING_OTLP_LEVELagenta.logging.otlp_levelagenta.logging.otlpLevel

Agenta OTLP

Env varenv.py pathvalues.yaml path
AGENTA_OTLP_MAX_BATCH_BYTESagenta.otlp.max_batch_bytesagenta.otlp.maxBatchBytes

Agenta redaction

The online redaction filter scrubs known credential/secret values out of error responses, persisted records, spans, and logs on the invoke path (detective control, not preventive; see docs/designs/online-redaction). The filter redacts a value only when it is a live secret the platform resolved for the request, never by guessing at shape or entropy.

Env varenv.py pathvalues.yaml path
AGENTA_REDACTION_MODEagenta.redaction.modeagenta.redaction.mode
AGENTA_REDACTED_PREFIXESagenta.redaction.prefixesagenta.redaction.prefixes
AGENTA_REDACTED_SUFFIXESagenta.redaction.suffixesagenta.redaction.suffixes
AGENTA_REDACTED_BLOCKLISTagenta.redaction.blocklistagenta.redaction.blocklist
AGENTA_REDACTED_ALLOWLISTagenta.redaction.allowlistagenta.redaction.allowlist
  • AGENTA_REDACTION_MODE: off or known (default known). pattern and full are accepted but currently behave as known; setting either logs a warning.
  • AGENTA_REDACTED_PREFIXES / _SUFFIXES / _BLOCKLIST select env var names, not values: any process env var whose name starts with a prefix, ends with a suffix, or equals/contains a blocklist entry has its value seeded into the deny-set. Each is comma-separated and merges onto its built-in default (concatenation, never a replace); you only ever add more names to catch, you can't narrow the defaults. The prefix default is empty (opt-in only, since a broad service prefix over-seeds non-secret config like hostnames/regions); the suffix default covers the common credential-shaped endings (_KEY, _SECRET, _TOKEN, _AUTHTOKEN, _PASSWORD, _CREDENTIALS, _KEY_ID, _SECRET_ID, _TOKEN_ID); the blocklist default is AWS_BEARER_TOKEN_BEDROCK (a real secret whose name matches no suffix).
  • AGENTA_REDACTED_ALLOWLIST is different: it's a list of literal values (booleans/flags such as true/false/1/0) that are never redacted even if a secret-named env var holds one. Otherwise a flag like SOME_FEATURE_KEY=true would redact every "true" in output. It also merges (union) onto its built-in default; add values here that your deployment uses as flags but that also happen to sit in a secret-suffixed env var.
  • Safe default is unset. Leaving all four unset keeps prefix empty, suffix/blocklist/allowlist at their built-in defaults.

Agenta services

Env varenv.py pathvalues.yaml path
AGENTA_SERVICES_CODE_SANDBOX_RUNNERagenta.services.code.sandbox_runneragenta.services.code.sandboxRunner
AGENTA_SERVICES_MIDDLEWARE_AUTH_ENABLEDn/a (SDK-side)agenta.services.middleware.authEnabled
AGENTA_SERVICES_MIDDLEWARE_CACHING_ENABLEDagenta.services.middleware.caching_enabledagenta.services.middleware.cachingEnabled
Custom-code evaluator runner

AGENTA_SERVICES_CODE_SANDBOX_RUNNER selects how custom-code evaluators execute:

  • local (default): raw execution in the services process with no sandbox. Any author who can create a custom-code evaluator can run arbitrary code on the host. This is what makes self-hosting work with zero configuration; the deployment logs a warning while it's active.
  • restricted: in-process Python sandbox with limited builtins and an allowlist of pure-standard-library imports. No filesystem, network, or host access. Set this to harden a shared/multi-tenant deployment.
  • daytona: isolated remote sandbox (strongest). Recommended when evaluator authors are not fully trusted. Requires the daytona credentials below.

The legacy AGENTA_SERVICES_SANDBOX_RUNNER is still accepted as a fallback.

Agent runner

Agent workflows run through a separate runner service that executes agent code, either inside its own container (local) or in a Daytona cloud sandbox. This section lists every operator-facing runner variable, its default, its Helm path, and the errors an invalid value produces.

The runner parses all of its AGENTA_RUNNER_* variables once before it starts listening. An invalid value fails startup with the error shown in Startup validation.

For the model behind these settings, see How agents run. The local subscription mount variables (PI_CODING_AGENT_DIR and CLAUDE_CONFIG_DIR) are covered by Use your own subscription.

AGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS and AGENTA_RUNNER_DEFAULT_SANDBOX_PROVIDER are read by both the runner and the Services API. Setting the enabled list to daytona only keeps agent code out of the runner container on a shared deployment. See Sandbox isolation and security.

The bundled Compose env examples group these variables under Agenta - Agent runner in the same order as the sections below, so the file and this page mirror each other.

Service

Set on the runner service.

VariableRoleDefaultSecretHelm
AGENTA_RUNNER_HOSTBind interface127.0.0.1noagentRunner.env.AGENTA_RUNNER_HOST
AGENTA_RUNNER_PORTBind port8765noChart-managed (8765)
AGENTA_RUNNER_CONCURRENCY_LIMITMaximum concurrent runs1000noagentRunner.env.AGENTA_RUNNER_CONCURRENCY_LIMIT
AGENTA_RUNNER_LOG_LEVELLog verbositysilentnoagentRunner.logLevel
AGENTA_RUNNER_REPLICA_IDReplica identity for logsGenerated when unsetnoagentRunner.env.AGENTA_RUNNER_REPLICA_ID

Every variable on this page treats an empty value as unset, so leaving a line blank selects the default rather than an empty string.

The code default host is 127.0.0.1. The bundled Compose files set AGENTA_RUNNER_HOST=0.0.0.0 so the Services container can reach the runner across the Compose network. AGENTA_RUNNER_PORT and AGENTA_RUNNER_CONCURRENCY_LIMIT must be positive integers.

Routing and authentication

These locate the runner and authenticate the call. Two of the three are caller-side: the Services API and its SDK read them, not the runner.

VariableRoleRead byDefaultSecretHelm
AGENTA_RUNNER_INTERNAL_URLRunner locatorServices API (caller-side)Compose: http://runner:8765noagentRunner.externalUrl, else derived from agentRunner.enabled
AGENTA_RUNNER_TOKENShared request credentialServices sends it; runner verifies itRequired — no defaultyesagenta.runnerToken, or agentRunner.auth.tokenSecretRef to source it from your own Secret
AGENTA_RUNNER_TIMEOUT_SECONDSIdle timeout the caller allows on the run requestServices API and SDK (caller-side)360non/a

AGENTA_RUNNER_TOKEN is required, like AGENTA_AUTH_KEY. The runner refuses to start without it and rejects an un-tokened request with 401, so there is no unauthenticated mode. It carries a run's plaintext provider keys, so set the same value on the runner and on the service that calls it:

openssl rand -hex 32

The bundled examples ship AGENTA_RUNNER_TOKEN=replace-me; replace it before you deploy. On Kubernetes, set agenta.runnerToken (the chart fails to render without it), or set agentRunner.auth.tokenSecretRef to read the value from a Secret your own vault populates.

The token is defense in depth on top of network isolation, not a replacement for it: keep the runner on a private network and never publish its port.

AGENTA_RUNNER_TOKEN is the same credential at both ends. It does not belong to a sandbox or a harness. The runner refuses to start without it and rejects any un-tokened request with 401; there is no unauthenticated mode. Set the same value on the runner and on the Services API; in Helm, point agentRunner.auth.tokenSecretRef at a Secret holding it — the chart injects the same value into both the runner and the Services deployment.

AGENTA_RUNNER_TIMEOUT_SECONDS bounds idle time on the caller's streaming transport, not the total run duration, and the runner never reads it. The runner enforces its own deadlines through Run limits. Set the caller timeout above the runner's idle timeout, or the caller gives up on a run the runner still considers healthy.

Sandbox providers

Read by both the runner and the Services API, so the operator sets each value once and hosting templates apply it to both.

VariableRoleDefaultHelm
AGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERSProviders this deployment can uselocalagentRunner.providers.enabled (list, rendered comma-joined)
AGENTA_RUNNER_DEFAULT_SANDBOX_PROVIDERProvider used when a run does not chooselocalagentRunner.providers.default

Rules:

  • Values are lowercase provider ids separated by commas. The known ids are local and daytona.
  • Unset enabled providers means exactly local.
  • An explicitly empty list is invalid, and so is an empty entry inside the list.
  • Unknown ids and duplicate ids are invalid.
  • The default must be one of the enabled providers.
  • A run may select any enabled provider. A run that selects a known but disabled provider fails before any working directory, mount, secret, or sandbox is created. There is no fallback to another provider.

The enabled list applies to the whole deployment, not to a user or a run. It decides what isolation a run can get; see Sandbox isolation and security.

Daytona

Read by the runner service. Required only when daytona is enabled.

VariableRoleDefaultSecretHelm
AGENTA_RUNNER_DAYTONA_API_KEYProvisioning credentialUnsetyesagentRunner.providers.daytona.apiKeySecretRef
AGENTA_RUNNER_DAYTONA_API_URLDaytona API locatorUnsetno...daytona.apiUrl
AGENTA_RUNNER_DAYTONA_TARGETRegion or targetUnsetno...daytona.target
AGENTA_RUNNER_DAYTONA_SNAPSHOTSnapshot to start fromRunner's pinned agenta-agent-sandbox-v1no...daytona.snapshot
AGENTA_RUNNER_DAYTONA_IMAGEImage to start fromUnsetno...daytona.image
AGENTA_RUNNER_DAYTONA_AUTOSTOP_MINUTESIdle minutes before stop15no...daytona.autostopMinutes
AGENTA_RUNNER_DAYTONA_AUTODELETE_MINUTESIdle minutes before delete30no...daytona.autodeleteMinutes

When neither AGENTA_RUNNER_DAYTONA_SNAPSHOT nor AGENTA_RUNNER_DAYTONA_IMAGE is set, the runner starts from its pinned default snapshot agenta-agent-sandbox-v1. The two variables are mutually exclusive. The autostop and autodelete values must be positive integers. See Run agents in a cloud sandbox (Daytona) for the setup flow, and Customize the agent runtime for the CPU, memory, and disk each sandbox gets.

The bare DAYTONA_* variables configure a different sandbox

DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET, DAYTONA_SNAPSHOT, and DAYTONA_SNAPSHOT_CODE configure the code evaluator's sandbox, which runs custom evaluator code. The agent runner reads only the AGENTA_RUNNER_DAYTONA_* names in the table above.

The two may point at the same Daytona account, so the key, the URL, and the target may hold the same values. The snapshot may not: the evaluator's snapshot (for example daytona-small) has no agent harness installed, so an agent booted into it cannot run.

Warm sessions and scale

A session stays warm between turns so a follow-up turn skips a cold start. Both providers pool sessions, but they budget different things: the Daytona pool budgets billed compute, and the local pool budgets host memory inside the runner container. All of these are read by the runner service, and all are safe to leave unset.

Daytona, one warm sandbox per parked session:

VariableRoleDefaultSecretHelm
AGENTA_RUNNER_DAYTONA_SESSION_IDLE_TTL_MSHow long a sandbox stays running with its live session after a clean turn120000 (2 minutes)no...daytona.sessionIdleTtlMs
AGENTA_RUNNER_DAYTONA_SESSION_MAX_WARMHow many idle sandboxes may stay running between turns20no...daytona.sessionMaxWarm

Set AGENTA_RUNNER_DAYTONA_SESSION_IDLE_TTL_MS to 0 to stop a sandbox after each turn. There is no separate enable flag. AGENTA_RUNNER_DAYTONA_SESSION_MAX_WARM bounds idle spend only; it never blocks an active turn. Overflow sandboxes park in the stopped state.

Keep the idle TTL below the autostop window

AGENTA_RUNNER_DAYTONA_SESSION_IDLE_TTL_MS must stay below AGENTA_RUNNER_DAYTONA_AUTOSTOP_MINUTES. Autostop is Daytona's own idle timer, and it does not know about the runner's warm pool. If the TTL is the longer of the two, Daytona stops a sandbox the runner still believes is warm: the next turn takes the cold path anyway, and you paid for the warm window without getting it. The defaults (2 minutes against 15) satisfy this. Raise autostop first whenever you raise the TTL.

Local, one pooled harness process per parked session inside the runner container:

VariableRoleDefaultSecretHelm
AGENTA_RUNNER_SESSION_POOL_MAXHow many local sessions may stay pooled8noagentRunner.env.AGENTA_RUNNER_SESSION_POOL_MAX
AGENTA_RUNNER_SESSION_TTL_MSIdle lifetime of a pooled local session60000 (1 minute)noagentRunner.env.AGENTA_RUNNER_SESSION_TTL_MS
AGENTA_RUNNER_SESSION_APPROVAL_TTL_MSIdle lifetime while a run waits for a human approval300000 (5 minutes)noagentRunner.env.AGENTA_RUNNER_SESSION_APPROVAL_TTL_MS
AGENTA_RUNNER_SESSION_KEEPALIVEWhether local sessions are reused at allEnablednoagentRunner.env.AGENTA_RUNNER_SESSION_KEEPALIVE

Local keep-alive is on by default. Set AGENTA_RUNNER_SESSION_KEEPALIVE=off (0, false, and no also work) to make every local turn take the cold path, which lowers the runner container's memory ceiling and raises the latency of a follow-up turn. The approval TTL applies while a run waits on a human approval, so it does not expire a session that is waiting on a person. These four apply to the local provider only; Daytona ignores them and uses the two variables above.

A Daytona sandbox moves through three states:

StateWhenBilling
RunningWhile a turn executes, and during the warm window after a clean turnCompute and disk
StoppedAfter AGENTA_RUNNER_DAYTONA_AUTOSTOP_MINUTES idle minutesDisk only; restart is cheap and the session reloads on the same instance
DeletedAfter AGENTA_RUNNER_DAYTONA_AUTODELETE_MINUTES idle minutesNone; the next turn creates a fresh sandbox and reloads the working directory from the store

Run limits

Four deadlines bound a single run. Whichever limit trips first aborts the run and releases its sandbox, its mount, and its socket. All four are read by the runner service and apply to every provider.

VariableRoleDefaultSecretHelm
AGENTA_RUNNER_RUN_TOTAL_TIMEOUT_MSHard deadline for one run, measured from the first message2700000 (45 minutes)noagentRunner.env.AGENTA_RUNNER_RUN_TOTAL_TIMEOUT_MS
AGENTA_RUNNER_RUN_IDLE_TIMEOUT_MSLongest gap between two progress events before the run is abandoned300000 (5 minutes)noagentRunner.env.AGENTA_RUNNER_RUN_IDLE_TIMEOUT_MS
AGENTA_RUNNER_RUN_TTFB_TIMEOUT_MSLongest wait for the first response after the run starts120000 (2 minutes)noagentRunner.env.AGENTA_RUNNER_RUN_TTFB_TIMEOUT_MS
AGENTA_RUNNER_TOOL_CALL_TIMEOUT_MSLongest a single tool call may take300000 (5 minutes)noagentRunner.env.AGENTA_RUNNER_TOOL_CALL_TIMEOUT_MS

Three rules govern how they interact:

  • A run paused for a human approval is exempt from all four. The pause freezes every timer.
  • The idle timeout must stay below the total deadline, or it could never fire first. A value at or above the total is clamped to half the total, and the runner logs the clamp rather than failing to start.
  • The TTFB timer only covers the wait for the first response. The first progress event of any kind cancels it and arms the idle timer instead.

An invalid value (not a number, or negative) falls back to the default for that variable. These are the runner's own deadlines and are unrelated to AGENTA_RUNNER_TIMEOUT_SECONDS, which is the caller's idle timeout on the streaming transport.

Callback API

Set on the runner service. It gives the runner the in-network address of the API for session heartbeats, working-directory mount signing, and the trace-export fallback.

VariableRoleDefaultHelm
AGENTA_API_INTERNAL_URLAPI locator for runner callbacksCompose: http://api:8000Wired by the chart

Point this at the API as reached from inside the runner container (its Compose or cluster service name, for example http://api:8000), not the public URL, which does not resolve inside a container. If it is unset, the runner falls back to the public AGENTA_API_URL and then to the base inferred from each request.

Internal settings

The runner reads two more variables that exist for debugging and for custom sandbox images. They are not part of the supported configuration surface and may change without notice. Leave them unset on a normal deployment.

  • AGENTA_RUNNER_DEBUG_TOOLS: when set to any value, the runner logs verbose tool-callback diagnostics to standard error. Unset by default.
  • AGENTA_AGENT_SANDBOX_PI_DIR: where the Pi agent directory lives inside a Daytona sandbox, defaulting to /home/sandbox/.pi/agent. This describes the sandbox image's own layout, not the deployment. Change it only if you build a custom snapshot that puts Pi somewhere else.

Startup validation

The runner fails to start when configuration is invalid, before it listens. The exact messages:

CauseError
Token not setAGENTA_RUNNER_TOKEN is required. Generate a secret (e.g. \openssl rand -hex 32`) and set the SAME value on the runner and on the service that calls it.`
Enabled list is set but emptyAGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS is set but empty; unset it for the default 'local', or list at least one provider.
Empty entry in the enabled listAGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS has an empty entry in '<list>'.
Unknown provider id in the enabled listAGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS lists unknown provider '<id>'; known providers: local, daytona.
Duplicate provider idAGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS lists provider '<id>' more than once.
Default is an unknown providerAGENTA_RUNNER_DEFAULT_SANDBOX_PROVIDER is unknown provider '<id>'; known providers: local, daytona.
Default not in the enabled setAGENTA_RUNNER_DEFAULT_SANDBOX_PROVIDER '<id>' is not in the enabled set [<list>]. Add it to AGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS or change the default.
Daytona enabled without a keyAGENTA_RUNNER_DAYTONA_API_KEY is required when 'daytona' is in AGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS.
Snapshot and image both setAGENTA_RUNNER_DAYTONA_SNAPSHOT and AGENTA_RUNNER_DAYTONA_IMAGE are mutually exclusive; set only one.
Non-integer positive value<variable> must be a positive integer, got '<value>'.

The last message covers AGENTA_RUNNER_PORT, AGENTA_RUNNER_CONCURRENCY_LIMIT, AGENTA_RUNNER_DAYTONA_AUTOSTOP_MINUTES, and AGENTA_RUNNER_DAYTONA_AUTODELETE_MINUTES.

On a valid start, the runner logs one redacted summary. No credential value or source path is logged.

runner providers enabled=[local,daytona] default=local
runner daytona target=eu artifact=snapshot:agenta-agent-sandbox-v1

The first line always prints. The second line appears only when daytona is enabled. target reads default when AGENTA_RUNNER_DAYTONA_TARGET is unset, and artifact reads snapshot:agenta-agent-sandbox-v1 (the pinned default), snapshot:<name>, or image:<name> depending on what is set.

Troubleshooting

A run fails with Sandbox provider '<id>' is not enabled on this deployment

Cause: The run requested a provider that is not in AGENTA_RUNNER_ENABLED_SANDBOX_PROVIDERS.

Solution: Add the provider and recreate the runner, or change the run to use an enabled provider.

A run fails with could not find runner CLI at /app/runner/src/cli.ts

Cause: AGENTA_RUNNER_INTERNAL_URL is unset on the Services API. With no runner URL, the SDK falls back to spawning the runner as a subprocess from its own image, which does not ship the runner source.

Solution: Set the locator on the services container and recreate it. On Compose:

AGENTA_RUNNER_INTERNAL_URL=http://runner:8765

The bundled Compose files already default to this value, and the Helm chart derives it from agentRunner.enabled. A hand-written deployment has to set it. Check that the Services container reaches the runner at that address:

docker compose exec services python -c \
"import urllib.request; print(urllib.request.urlopen('http://runner:8765/health').status)"

A 200 confirms the hop.

The API cannot reach the runner, or the runner rejects its calls

Cause: AGENTA_RUNNER_INTERNAL_URL does not point at the runner, or AGENTA_RUNNER_TOKEN is set on only one side.

Solution: Check the URL, and set the same token value on the API and on the runner or on neither.

A self-managed local run fails because the harness has no login

Cause: The subscription mount is missing, or PI_CODING_AGENT_DIR / CLAUDE_CONFIG_DIR does not point at it.

Solution: See Use your own subscription.

A self-managed run that requested Daytona fails

Cause: Personal subscriptions are local-only.

Solution: Run Daytona with a model API key. See Sandbox isolation and security.

The runner fails to start with a Daytona authentication error

Cause: AGENTA_RUNNER_DAYTONA_API_KEY is wrong, or it has no access to the target.

Solution: Check the key and AGENTA_RUNNER_DAYTONA_TARGET.

Working directories do not persist across turns on Daytona

Cause: The sandbox could not reach the store, so it mounted nothing. The runner logs a mount-degradation warning.

Solution: Make the store publicly reachable. See Run agents in a cloud sandbox (Daytona).

Store (durable object store)

Backs the durable working directory for sessions and agents. Files written by an agent run survive sandbox teardown and reappear in the next turn. The store is disabled until ACCESS_KEY and SECRET_KEY are set. Point these at any S3-compatible store: the bundled SeaweedFS, AWS S3, or MinIO. ENDPOINT_URL is always explicit (SeaweedFS defaults it to http://seaweedfs:8333; a remote store must set it).

The API holds the master credentials and never passes them to the runner. At run start it mints short-lived, prefix-scoped credentials and only those reach the sandbox, which mounts the durable prefix as its working directory. The STS mechanism depends on the backend (see the two-backend note below): bundled SeaweedFS uses AssumeRoleWithWebIdentity; a remote S3 store uses GetFederationToken.

Env varenv.py pathvalues.yaml path
AGENTA_STORE_ENDPOINT_URLstore.endpoint_urlstore.endpointUrl (auto-populated when store.seaweedfs.enabled=true)
AGENTA_STORE_STS_ENDPOINT_URLstore.sts_endpoint_urlstore.stsEndpointUrl
AGENTA_STORE_ACCESS_KEYstore.access_keystore.accessKey
AGENTA_STORE_SECRET_KEYstore.secret_keystore.secretKey
AGENTA_STORE_REGIONstore.regionstore.region
AGENTA_STORE_BUCKETstore.bucketstore.bucket
AGENTA_STORE_NAMESPACEstore.namespacestore.namespace
AGENTA_STORE_SIGNING_KEYstore.signing_keystore.signingKey
AGENTA_STORE_JWT_ISSUERstore.jwt_issuerstore.jwtIssuer
AGENTA_STORE_JWT_PRIVATE_KEYstore.jwt_private_keystore.jwtPrivateKey
n/an/astore.seaweedfs.enabled

store.seaweedfs.enabled=true bundles a SeaweedFS StatefulSet and auto-populates store.endpointUrl. Set it to false and supply store.endpointUrl to use an external S3-compatible store. This toggle mirrors postgresql.enabled.

AGENTA_STORE_NAMESPACE: sharing one bucket across environments

The key layout treats the store as a small database: the bucket is the cluster, an optional namespace is the database, the entity prefix (mounts/) is the table, and <project>/<mount> is the row, so a full key is <bucket>/[<namespace>/]mounts/<project_id>/<mount_id>/....

Leave NAMESPACE unset for a dedicated bucket; the key layout is then identical to a single-tenant store (no empty leading segment). Set it (typically to a deployment or environment id) when several ephemeral environments share one bucket. Each environment's keys are prefixed with its namespace, and the short-lived credentials the API signs are scoped to that namespace, so one environment can never read or write another's objects even though they live in the same bucket. The namespace narrows the credential scope; it never widens it, and it is orthogonal to the store backend (it works on remote S3 and on bundled SeaweedFS alike).

Two STS backends (selected by SIGNING_KEY presence)

The API narrows the master credentials to one mount prefix per run with an inline session policy. How it signs that scoped credential depends on the backend, and the backend is chosen by whether AGENTA_STORE_SIGNING_KEY is set, not by the endpoint:

  • SIGNING_KEY set → bundled SeaweedFS. SeaweedFS authorizes scoped credentials only through its OIDC IAM engine: the API acts as the OIDC issuer, mints a short-lived RS256 web-identity token, and serves the matching public JWKS at /.well-known/jwks.json; SeaweedFS fetches that JWKS to verify the token on each AssumeRoleWithWebIdentity call.
  • SIGNING_KEY unset → remote S3-compatible store (AWS S3, MinIO). The API already holds S3 credentials, so it signs a GetFederationToken request (SigV4) with them. No OIDC provider, no role. Cloudflare R2 is not supported: it does not implement AWS STS GetFederationToken.

AGENTA_STORE_STS_ENDPOINT_URL is the STS endpoint for the remote-S3 path. It defaults to the S3 endpoint (MinIO co-locates STS there); set it only when the store splits STS onto another host. For AWS: https://sts.<region>.amazonaws.com. It is ignored on the SeaweedFS path.

The SeaweedFS-only settings (SIGNING_KEY, JWT_ISSUER, JWT_PRIVATE_KEY):

  • AGENTA_STORE_SIGNING_KEY: base64 of exactly 32 bytes; the HMAC key SeaweedFS signs its own STS session tokens with (head -c 32 /dev/urandom | base64). Its presence also selects the SeaweedFS backend, so leave it unset for a remote S3 store.
  • AGENTA_STORE_JWT_ISSUER: the in-network API URL SeaweedFS fetches the JWKS from (e.g. http://api:8000).
  • AGENTA_STORE_JWT_PRIVATE_KEY: a stable RSA private key (PKCS#8 PEM) the API signs the web-identity token with. Required in production: every API replica must share one key, or SeaweedFS's cached JWKS desyncs and token validation fails intermittently. Generate with openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048. Local dev falls back to a built-in key when unset.

The bundled store and the API must agree on ACCESS_KEY and SECRET_KEY; in the Helm chart and docker-compose this is wired automatically.

Remote sandboxes (Daytona) need a reachable store endpoint

A local sandbox mounts durable storage on the runner host against the in-network store. A remote sandbox mounts from inside the cloud sandbox, so the store endpoint must be publicly reachable. Enable the ngrok tunnel (the compose with-tunnel profile) or point AGENTA_STORE_ENDPOINT_URL at a public S3 URL. Only the scoped, short-lived credentials ever cross into a remote sandbox.

Agenta egress

Env varenv.py pathvalues.yaml path
AGENTA_INSECURE_EGRESS_ALLOWEDagenta.webhooks.allow_insecure (API); read directly by the SDK for workflow hooks and custom model provider endpointsagenta.insecureEgressAllowed
SSRF protection

AGENTA_INSECURE_EGRESS_ALLOWED defaults to true, so outbound requests that Agenta itself makes to a tenant-configured endpoint (webhooks, workflow hooks, custom model provider URLs) are allowed even when they resolve to a private, loopback, or otherwise reserved IP address. The deployment logs a warning while this default is active.

If you're running a shared or multi-tenant deployment, set it to false. Agenta then blocks any such request that resolves to a private, loopback, or reserved IP address, regardless of who configured the URL. Public URLs are never affected either way.

The old per-surface names (AGENTA_WEBHOOKS_ALLOW_INSECURE, AGENTA_WEBHOOK_ALLOW_INSECURE, AGENTA_SERVICES_HOOK_ALLOW_INSECURE, AGENTA_CUSTOM_PROVIDER_ALLOW_INSECURE) are deprecated aliases and still work, but new configuration should use the canonical name.

alembic

Env varenv.py pathvalues.yaml path
ALEMBIC_AUTO_MIGRATIONSalembic.auto_migrationsalembic.autoMigrations
ALEMBIC_CFG_PATH_COREalembic.cfg_path_corealembic.cfgPathCore
ALEMBIC_CFG_PATH_TRACINGalembic.cfg_path_tracingalembic.cfgPathTracing

cloudflare

Env varenv.py pathvalues.yaml path
CLOUDFLARE_TURNSTILE_ALLOWED_HOSTNAMEScloudflare.turnstile.allowed_hostnamescloudflare.turnstile.allowedHostnames
CLOUDFLARE_TURNSTILE_SECRET_KEYcloudflare.turnstile.secret_keycloudflare.turnstile.secretKey
CLOUDFLARE_TURNSTILE_SITE_KEYcloudflare.turnstile.site_keycloudflare.turnstile.siteKey

composio

Env varenv.py pathvalues.yaml path
COMPOSIO_API_KEYcomposio.api_keycomposio.apiKey
COMPOSIO_API_URLcomposio.api_urlcomposio.apiUrl

crisp

Env varenv.py pathvalues.yaml path
CRISP_WEBSITE_IDcrisp.website_idcrisp.websiteId

daytona (code evaluator)

These configure the custom-code evaluator sandbox. The agent runner reads its own AGENTA_RUNNER_DAYTONA_* names instead; see Agent runner.

Env varenv.py pathvalues.yaml path
DAYTONA_API_KEYdaytona.api_keydaytona.apiKey
DAYTONA_API_URLdaytona.api_urldaytona.apiUrl
DAYTONA_SNAPSHOTdaytona.snapshotdaytona.snapshot
DAYTONA_SNAPSHOT_CODEdaytona.snapshot (takes precedence)n/a
DAYTONA_TARGETdaytona.targetdaytona.target

DAYTONA_SNAPSHOT sets the snapshot for the custom-code evaluator sandbox. Set DAYTONA_SNAPSHOT_CODE to override it for the evaluator specifically. The agent runner uses its own AGENTA_RUNNER_DAYTONA_SNAPSHOT; see the runner Daytona section.

docker

Env varenv.py pathvalues.yaml path
DOCKER_NETWORK_MODEdocker.network_modedocker.networkMode

identity (OIDC providers)

Env varenv.py pathvalues.yaml path
APPLE_OAUTH_CLIENT_IDidentity.apple.client_ididentity.apple.clientId
APPLE_OAUTH_CLIENT_SECRETidentity.apple.client_secretidentity.apple.clientSecret
APPLE_KEY_IDidentity.apple.key_ididentity.apple.keyId
APPLE_PRIVATE_KEYidentity.apple.private_keyidentity.apple.privateKey
APPLE_TEAM_IDidentity.apple.team_ididentity.apple.teamId
AZURE_AD_OAUTH_CLIENT_IDidentity.azure_ad.client_ididentity.azureAd.clientId
AZURE_AD_OAUTH_CLIENT_SECRETidentity.azure_ad.client_secretidentity.azureAd.clientSecret
AZURE_AD_DIRECTORY_IDidentity.azure_ad.directory_ididentity.azureAd.directoryId
BITBUCKET_OAUTH_CLIENT_IDidentity.bitbucket.client_ididentity.bitbucket.clientId
BITBUCKET_OAUTH_CLIENT_SECRETidentity.bitbucket.client_secretidentity.bitbucket.clientSecret
BOXY_SAML_OAUTH_CLIENT_IDidentity.boxy_saml.client_ididentity.boxySaml.clientId
BOXY_SAML_OAUTH_CLIENT_SECRETidentity.boxy_saml.client_secretidentity.boxySaml.clientSecret
BOXY_SAML_URLidentity.boxy_saml.urlidentity.boxySaml.url
DISCORD_OAUTH_CLIENT_IDidentity.discord.client_ididentity.discord.clientId
DISCORD_OAUTH_CLIENT_SECRETidentity.discord.client_secretidentity.discord.clientSecret
FACEBOOK_OAUTH_CLIENT_IDidentity.facebook.client_ididentity.facebook.clientId
FACEBOOK_OAUTH_CLIENT_SECRETidentity.facebook.client_secretidentity.facebook.clientSecret
GITHUB_OAUTH_CLIENT_IDidentity.github.client_ididentity.github.clientId
GITHUB_OAUTH_CLIENT_SECRETidentity.github.client_secretidentity.github.clientSecret
GITLAB_BASE_URLidentity.gitlab.base_urlidentity.gitlab.baseUrl
GITLAB_OAUTH_CLIENT_IDidentity.gitlab.client_ididentity.gitlab.clientId
GITLAB_OAUTH_CLIENT_SECRETidentity.gitlab.client_secretidentity.gitlab.clientSecret
GOOGLE_OAUTH_CLIENT_IDidentity.google.client_ididentity.google.clientId
GOOGLE_OAUTH_CLIENT_SECRETidentity.google.client_secretidentity.google.clientSecret
GOOGLE_WORKSPACES_OAUTH_CLIENT_IDidentity.google_workspaces.client_ididentity.googleWorkspaces.clientId
GOOGLE_WORKSPACES_OAUTH_CLIENT_SECRETidentity.google_workspaces.client_secretidentity.googleWorkspaces.clientSecret
GOOGLE_WORKSPACES_HDidentity.google_workspaces.hdidentity.googleWorkspaces.hd
LINKEDIN_OAUTH_CLIENT_IDidentity.linkedin.client_ididentity.linkedin.clientId
LINKEDIN_OAUTH_CLIENT_SECRETidentity.linkedin.client_secretidentity.linkedin.clientSecret
OKTA_OAUTH_CLIENT_IDidentity.okta.client_ididentity.okta.clientId
OKTA_OAUTH_CLIENT_SECRETidentity.okta.client_secretidentity.okta.clientSecret
OKTA_DOMAINidentity.okta.domainidentity.okta.domain
TWITTER_OAUTH_CLIENT_IDidentity.twitter.client_ididentity.twitter.clientId
TWITTER_OAUTH_CLIENT_SECRETidentity.twitter.client_secretidentity.twitter.clientSecret

llm (provider API keys)

Env varenv.py pathvalues.yaml path
ALEPHALPHA_API_KEYllm.alephalphallm.alephalpha
ANTHROPIC_API_KEYllm.anthropicllm.anthropic
ANYSCALE_API_KEYllm.anyscalellm.anyscale
COHERE_API_KEYllm.coherellm.cohere
DEEPINFRA_API_KEYllm.deepinfrallm.deepinfra
GEMINI_API_KEYllm.geminillm.gemini
GROQ_API_KEYllm.groqllm.groq
MINIMAX_API_KEYllm.minimaxllm.minimax
MISTRAL_API_KEYllm.mistralllm.mistral
OPENAI_API_KEYllm.openaillm.openai
OPENROUTER_API_KEYllm.openrouterllm.openrouter
PERPLEXITYAI_API_KEYllm.perplexityaillm.perplexityai
TOGETHERAI_API_KEYllm.togetheraillm.togetherai

loops

Env varenv.py pathvalues.yaml path
LOOPS_API_KEYloops.api_keyloops.apiKey

newrelic

Env varenv.py pathvalues.yaml path
NEWRELIC_LICENSE_KEYnewrelic.license_keynewrelic.licenseKey

postgres

Env varenv.py pathvalues.yaml path
POSTGRES_USERpostgres.userpostgres.user
POSTGRES_PASSWORDpostgres.passwordpostgres.password
POSTGRES_PORTpostgres.portpostgres.port
POSTGRES_URI_COREpostgres.uri_corepostgres.uriCore
POSTGRES_URI_SUPERTOKENSpostgres.uri_supertokenspostgres.uriSupertokens
POSTGRES_URI_TRACINGpostgres.uri_tracingpostgres.uriTracing

posthog

Env varenv.py pathvalues.yaml path
POSTHOG_API_KEYposthog.api_keyposthog.apiKey
POSTHOG_API_URLposthog.api_urlposthog.apiUrl

redis

Env varenv.py pathvalues.yaml path
REDIS_URIredis.uriredis.uri
REDIS_URI_DURABLEredis.uri_durableredis.uriDurable
REDIS_URI_VOLATILEredis.uri_volatileredis.uriVolatile

smtp

SMTP is preferred for email delivery. It is enabled only when host, port, and sender are configured. SendGrid remains supported as a fallback when SMTP is not fully configured.

For local Mailpit from an API container, use SMTP_HOST=host.docker.internal when Mailpit runs on the host, or SMTP_HOST=mailpit only when Mailpit is on the same Docker network.

Env varenv.py pathvalues.yaml path
SMTP_HOSTsmtp.host(not mapped)
SMTP_PORTsmtp.port(not mapped)
SMTP_USERNAMEsmtp.username(not mapped)
SMTP_PASSWORDsmtp.password(not mapped)
SMTP_FROM_EMAILsmtp.from_email(not mapped)
SMTP_USE_TLSsmtp.use_tls(not mapped)
SMTP_USE_SSLsmtp.use_ssl(not mapped)
SMTP_TIMEOUTsmtp.timeout(not mapped)

sendgrid

SendGrid is used only when SMTP is not fully configured.

Env varenv.py pathvalues.yaml path
SENDGRID_API_KEYsendgrid.api_keysendgrid.apiKey
SENDGRID_FROM_EMAILsendgrid.from_emailsendgrid.fromEmail

stripe

Env varenv.py pathvalues.yaml path
STRIPE_API_KEYstripe.api_keystripe.apiKey
STRIPE_WEBHOOK_SECRETstripe.webhook_secretstripe.webhookSecret
STRIPE_WEBHOOK_TARGETstripe.webhook_targetstripe.webhookTarget

supertokens

Env varenv.py pathvalues.yaml path
SUPERTOKENS_API_KEYsupertokens.api_keysupertokens.apiKey
SUPERTOKENS_APPLICATIONsupertokens.applicationsupertokens.application
SUPERTOKENS_PASSWORD_MAX_LENGTHsupertokens.password_max_lengthsupertokens.passwordMaxLength
SUPERTOKENS_PASSWORD_MIN_LENGTHsupertokens.password_min_lengthsupertokens.passwordMinLength
SUPERTOKENS_PASSWORD_POLICYsupertokens.password_policysupertokens.passwordPolicy
SUPERTOKENS_PASSWORD_REGEXsupertokens.password_regexsupertokens.passwordRegex
SUPERTOKENS_TENANTsupertokens.tenantsupertokens.tenant
SUPERTOKENS_URI_COREsupertokens.uri_coresupertokens.uriCore

Deprecated environment variables

The following legacy names still work via fallback (the Pydantic env loader reads the new name first, then the legacy one). They will be removed in a future major release.

Legacy env varCanonical replacement
AGENTA_ALLOWED_DOMAINSAGENTA_ACCESS_ALLOWED_DOMAINS
AGENTA_ORG_CREATION_ALLOWLISTAGENTA_ACCESS_ALLOWED_OWNER_EMAILS
AGENTA_ACCESS_ORG_CREATION_ALLOWLISTAGENTA_ACCESS_ALLOWED_OWNER_EMAILS
AGENTA_ACCESS_ALLOWED_ORGANIZATION_OWNERSAGENTA_ACCESS_ALLOWED_OWNER_EMAILS
AGENTA_BLOCKED_DOMAINSAGENTA_ACCESS_BLOCKED_DOMAINS
AGENTA_BLOCKED_EMAILSAGENTA_ACCESS_BLOCKED_EMAILS
AGENTA_DEFAULT_PLANAGENTA_ACCESS_DEFAULT_PLAN
SUPERTOKENS_EMAIL_DISABLEDAGENTA_ACCESS_EMAIL_DISABLED
AGENTA_PRICINGAGENTA_BILLING_PRICING
STRIPE_PRICINGAGENTA_BILLING_PRICING
AGENTA_CACHE_ENABLEDAGENTA_API_CACHING_ENABLED
AGENTA_CACHING_ENABLEDAGENTA_API_CACHING_ENABLED
AGENTA_DEMOSAGENTA_EXTRAS_DEMOS
AGENTA_LOG_CONSOLE_ENABLEDAGENTA_LOGGING_CONSOLE_ENABLED
AGENTA_LOG_CONSOLE_LEVELAGENTA_LOGGING_CONSOLE_LEVEL
AGENTA_LOG_FILE_ENABLEDAGENTA_LOGGING_FILE_ENABLED
AGENTA_LOG_FILE_LEVELAGENTA_LOGGING_FILE_LEVEL
AGENTA_LOG_FILE_PATHAGENTA_LOGGING_FILE_PATH
AGENTA_LOG_OTLP_ENABLEDAGENTA_LOGGING_OTLP_ENABLED
AGENTA_LOG_OTLP_LEVELAGENTA_LOGGING_OTLP_LEVEL
AGENTA_SERVICES_SANDBOX_RUNNERAGENTA_SERVICES_CODE_SANDBOX_RUNNER
AGENTA_SERVICE_MIDDLEWARE_AUTH_ENABLED (singular SERVICE)AGENTA_SERVICES_MIDDLEWARE_AUTH_ENABLED
AGENTA_SERVICE_MIDDLEWARE_CACHE_ENABLED (singular SERVICE)AGENTA_SERVICES_MIDDLEWARE_CACHING_ENABLED
AGENTA_WEBHOOK_ALLOW_INSECUREAGENTA_INSECURE_EGRESS_ALLOWED
AGENTA_WEBHOOKS_ALLOW_INSECUREAGENTA_INSECURE_EGRESS_ALLOWED
AGENTA_SERVICES_HOOK_ALLOW_INSECUREAGENTA_INSECURE_EGRESS_ALLOWED
AGENTA_CUSTOM_PROVIDER_ALLOW_INSECUREAGENTA_INSECURE_EGRESS_ALLOWED
AGENTA_AUTO_MIGRATIONSALEMBIC_AUTO_MIGRATIONS
AGENTA_RUNTIME_PREFIX(removed; no consumer in API)
ACTIVE_DIRECTORY_OAUTH_CLIENT_IDAZURE_AD_OAUTH_CLIENT_ID
ACTIVE_DIRECTORY_OAUTH_CLIENT_SECRETAZURE_AD_OAUTH_CLIENT_SECRET
ACTIVE_DIRECTORY_DIRECTORY_IDAZURE_AD_DIRECTORY_ID
NEW_RELIC_LICENSE_KEYNEWRELIC_LICENSE_KEY
NRIA_LICENSE_KEYNEWRELIC_LICENSE_KEY
POSTHOG_HOSTPOSTHOG_API_URL
AGENTA_AUTHN_EMAIL_FROMSMTP_FROM_EMAIL (preferred) or SENDGRID_FROM_EMAIL fallback
AGENTA_SEND_EMAIL_FROM_ADDRESSSMTP_FROM_EMAIL (preferred) or SENDGRID_FROM_EMAIL fallback
STRIPE_TARGETSTRIPE_WEBHOOK_TARGET
SUPERTOKENS_CONNECTION_URISUPERTOKENS_URI_CORE