Synopsis
Configuration has two layers, and which one you edit depends on the deployment target.
On Kubernetes,
charts/agentarea/config.yaml is the source of truth. It declares
one group per service; each group lists configVars (plain values),
secrets (pulled from a Secret by name and key), and envExtras (values
composed from other variables). make helm-gen regenerates the per-group
templates under charts/agentarea/templates/configs/ from it, and CI fails if
the generated files drift from config.yaml.
Every group below maps to a generated ConfigMap named
<release>-env-<group>.
Naming
Every variable AgentArea reads isAGENTAREA_<DOMAIN>_<KEY>, at most 40
characters, with at most three segments after the domain. The domain comes from
a closed list: DB S3 AUTH AUTHZ SECRET MCP SANDBOX TEMPORAL
WORKER TASK TRIGGER CHANNEL EVENT CORS LOG REDIS KAFKA TOOL K8S
API HTTP OTEL BILLING METRICS A2A SPEND ANALYTICS. Domains are whole words; only
established acronyms are abbreviated. A handful of
app-level names carry no domain — AGENTAREA_ENV, AGENTAREA_API_URL,
AGENTAREA_APP_URL, AGENTAREA_EDITION.
Durations carry their unit in the value, not the name: 30s, 500ms, 5m,
2h, 7d. A bare number is rejected rather than assumed to be seconds. Two
exceptions are named ..._SECONDS and take plain integers, listed below.
An unprefixed name belongs to somebody else and keeps the name its owner
expects: the postgres image (POSTGRES_USER), the AWS SDK
(AWS_ACCESS_KEY_ID), OpenTelemetry (OTEL_*), the Ory SDK (ORY_SDK_URL),
OpenFGA (OPENFGA_AUTHN_PRESHARED_KEY), the Next.js build (NEXT_PUBLIC_*),
and the platform that starts the process (PORT, HOST). Where a library
reads its own connection settings, we use its names rather than inventing
ours: the Temporal client is TEMPORAL_ADDRESS / TEMPORAL_NAMESPACE
(with TEMPORAL_API_KEY and TEMPORAL_TLS_* for Temporal Cloud or mTLS),
and the execution cluster is KUBECONFIG.
scripts/check_env_naming.py enforces the split and runs in CI; a name owned by
a third party goes in that script’s whitelist.
Upgrading from a release before this scheme: Environment variable
migration lists every old name and its replacement.
Parameters
Database (group database)
Consumed by the backend, worker, and event service.
AGENTAREA_DB_TENANT_SCOPE is required and has no default in the platform. It
decides what an ORM query on a workspace-scoped table does when nothing bound a
workspace: log runs it unfiltered and logs one warning per call site, enforce
refuses it. Deploy with log, clear the warnings, then switch to enforce.
global.database.maxConnections and global.database.connectionTimeout exist in
values.yaml but are not rendered into any environment variable by
config.yaml. Setting them changes nothing.
Redis (group redis)
Every broker topic and broker key is
<namespace>.<domain>.<dataset>, for
example agentarea.channel.inbound or agentarea.streams.events.3.
AGENTAREA_EVENT_NAMESPACE is that first segment (lowercase letters, digits
and -); the broker adapters of every service put it in front, so two
deployments sharing one Redis need different namespaces. Stream events travel
on AGENTAREA_EVENT_PARTITIONS partitions of streams.events, each stream on
one of them. The API and the worker must agree on it, and changing it moves
streams to other partitions: let the router and events-view groups drain
first.
AGENTAREA_REDIS_URL is emitted by templates/_redis-url.tpl, not by the redis group,
in this order:
global.redis.existingSecretset — read from that Secret’sglobal.redis.existingSecretKey(defaulturl). Use this in production; managed Redis URLs carry credentials.global.redis.urlset — used literally.- Neither — derived as
redis://:$(AGENTAREA_REDIS_PASSWORD)@$(AGENTAREA_REDIS_HOST):$(AGENTAREA_REDIS_PORT)against the bundled Valkey subchart.
global.redis.database, ssl, maxConnections, and connectionTimeout are
present in values.yaml but are not rendered into environment variables.
Object storage (group storage)
The bundled RustFS by default. With rustfs.enabled=false the same variables
name your own store, and global.storage.endpoint and
global.storage.existingSecret are required; the chart refuses to render
without them, and refuses them while RustFS is enabled.
global.storage.publicEndpoint is rendered in the backend group as
AGENTAREA_S3_PUBLIC_ENDPOINT, not here.
Backend API (group backend)
The API serves
/health on its normal port unconditionally. Metrics and traces
are pushed over OTLP; see Telemetry and
observability.
AGENTAREA_ANALYTICS_ENABLED sends anonymous usage statistics to AgentArea from the
backend and the worker; false sends nothing. It is not OpenTelemetry. The fields
sent are listed in usage analytics.
AGENTAREA_ANALYTICS_SIGNUP_HOOK_KEY is the key an Ory Kratos after-registration
web hook presents, as its Authorization header, to
POST /internal/analytics/signups. The backend then records which channel brought
each sign-up (see usage analytics). Unset, the
endpoint answers 404.
AGENTAREA_ANALYTICS_OWN_DOMAINS lists the domains of your own sites, comma-separated,
such as example.com,example.org. A sign-up referred from one of them or from a
subdomain of one is not credited to a referrer. Empty, no site is your own. An
entry that is not a domain name (a URL, a port, a wildcard, an IP address) stops
the API and the worker at startup.
AGENTAREA_API_URL is the URL the backend advertises for itself — provider icon URLs,
OAuth protected-resource metadata, and the MCP WWW-Authenticate header. It must
be reachable by the client, not by the pod.
AGENTAREA_A2A_AGENT_URL is where each agent is served over A2A: one host per agent, with
the agent id as the host’s first label, so the agent card sits at
/.well-known/agent-card.json on its own origin. The API answers that host
itself; the deployment provides a wildcard DNS record and a wildcard
certificate for the zone, and routes it to the backend. The value must be an
http(s) origin whose host starts with {agent_id}., such as
https://{agent_id}.a2a.example.com; anything else stops the API at startup.
See agent-to-agent communication.
AGENTAREA_MCP_OAUTH_APPS holds the operator’s OAuth apps for remote MCP
servers whose authorization server has no Dynamic Client Registration, such as
GitHub. It is a JSON list of objects with issuer, client_id,
client_secret, authorization_endpoint, token_endpoint, and
resource_origins (exact https origins). A workspace connecting an MCP server
at one of resource_origins through issuer then authorizes with that app
without registering its own; tokens minted through it are sent only to
resource_origins. Unset, such providers need the workspace’s own OAuth app.
The same list serves one-click catalog API connections (Google Search Console,
Yandex Metrica and the like): a catalog connection uses the app whose
authorization_endpoint and token_endpoint equal its own and whose
resource_origins include every API origin it calls. Register
<API URL>/v1/oauth/callback — the one callback for every OAuth connection,
MCP and catalog API alike — as a redirect URI with each app’s provider. A malformed value stops the API and the worker at startup. Both read
it, the worker to refresh tokens.
Worker (group worker)
The three
OUTAGE durations decide how a run rides out a service it cannot
reach (see waiting for a service):
how long a call retries before the run starts waiting, the pauses between
retries while it waits (comma-separated, the last repeats), and how long it
waits before it fails with dependency_unavailable. Each must be positive. A
run keeps the values it was configured with. AGENTAREA_TASK_SKILLS_WINDOW_SHARE
is the share of the model’s context window all of a run’s activated skills may
take together, above 0 and at most 1; one skill takes at most a tenth.
global.temporal.worker.maxConcurrentActivityExecutions,
maxConcurrentWorkflowTaskExecutions, and maxConcurrentSessionExecutions in
values.yaml do not feed these variables — config.yaml hardcodes 10 and 5. To
change worker concurrency, use worker.extraEnv.
Neither the API nor the worker configures on-demand MCP start any more. Every
container-backed call goes through the manager’s demand gateway, which starts a
cold workload itself; there is nothing for the Python side to agree on. See the
MCP Manager group below.
Temporal client (group temporal)
Consumed by the backend and the worker.
global.temporal.client.connectionTimeout, rpcTimeout, and longPollTimeout
are not rendered into environment variables.
Temporal server (group temporalServer)
MCP Manager (group mcpManager)
An empty
AGENTAREA_MCP_PACKAGE_REPO uses the local Docker image store only when
the manager’s backend is Docker; Kubernetes and data-plane backends require a
repository.
mcpManager.packageImages.registrySecret names an existing
kubernetes.io/dockerconfigjson Secret. The manager projects its
.dockerconfigjson key as config.json in a read-only mount at
/etc/agentarea/mcp-registry, and DOCKER_CONFIG points at that directory.
All four gateway durations are required — the manager refuses to start when
one is missing or unparseable, and only AGENTAREA_MCP_IDLE_TIMEOUT may be zero
(LoadPolicyFromEnv in internal/mcpgateway/gateway.go). Failing to boot is the
intended outcome: a gateway with an unset lease TTL would hold workloads open
indefinitely.
serverless.enabled collapses to a single duration: enabled renders
idleTimeout, disabled renders 0, and 0 means “never reclaim”. The switch
controls idle reclaim only. On-demand start is not conditional — every
container-backed call passes through the gateway, which serializes cold starts
and brings the workload up regardless of this setting.
mcpManager.instancePod (labels, annotations, nodeSelector, tolerations,
affinity, imagePullSecrets, priorityClassName) is passed to the manager as a
single JSON environment variable, AGENTAREA_K8S_INSTANCE_POD. Platform security
invariants — the managed-by label, securityContext and seccomp, the withheld
ServiceAccount token, and the RuntimeClass clamp — are applied on top and cannot
be weakened from these values.
Frontend (group frontend)
ORY_SDK_URL is used for server-side calls from the frontend container;
ORY_BROWSER_URL is what the browser is redirected to. Set
kratos.urls.publicBrowser separately whenever pods cannot resolve the public
domain.
The Apps page renders each MCP App inside an iframe loaded from
AGENTAREA_MCP_APPS_ORIGIN. The frontend answers /app-sandbox only when the
request’s Host matches that origin, and the sandbox refuses to run unless it is
embedded by AGENTAREA_APP_ORIGIN. With AGENTAREA_MCP_APPS_ORIGIN empty, or equal
to the webapp origin, the Apps page lists apps but opens none. The ingress side
is in networking.
Error reporting to Sentry (or a Sentry-compatible server such as GlitchTip) is
off until you set SENTRY_DSN through frontend.envVars; SENTRY_ENVIRONMENT
labels the events. Both are read at runtime, so one image serves every
deployment. The frontend reports browser errors, errors caught by the page error
boundaries, and server rendering and server action failures. Browser reports go
through the frontend’s own /api/monitoring route, which forwards only to the
configured DSN and does not pass on the client IP. Events carry no user,
cookies, headers or request bodies, and URLs lose their query string and
fragment, which can hold invitation tokens and login flow ids.
Application secrets (group application)
Secret manager (not in config.yaml)
Read by SecretManagerSettings in the platform. On Kubernetes, set these through
backend.extraEnv and worker.extraEnv.
Event streams (not in config.yaml)
Read by EventStreamSettings inside both the backend (webhook intake, the
/streams routes) and the worker (the router and events-view consumer
groups and the partition maintainer). Not wired into any Helm group yet — set
these through backend.extraEnv and worker.extraEnv, matching values on
both, the same way as the secret manager settings just above.
These share the
EVENT domain with AGENTAREA_EVENT_POLL_INTERVAL and
AGENTAREA_EVENT_MAX_POLLERS just below, but are unrelated settings: those
two configure the event service’s poll sources; the five above configure the
event bus. See Event streams.
Stream events travel on Redis Streams (the partitions of streams.events, see
the Redis group above), so the API and the worker both refuse to start unless AGENTAREA_BROKER=redis
(the default, and what every chart and Compose file sets).
Trigger batches (not in config.yaml)
Read by TriggerSettings in the backend (it refuses a trigger whose batch asks
for more) and in the worker (the router’s trigger handler). Set the same value
on both through backend.extraEnv and worker.extraEnv.
Event service (group eventService values, chart keys only)
The event service polls every stream source of kind
poll at the interval its
catalog entry names, and registers the webhook of every webhook source whose
entry has a registration block (Telegram setWebhook). It publishes the raw
items to the streams.ingest topic, which the worker’s ingest group turns into
stream events. pollInterval is how often it reads the set of sources again.
It also reads, from the groups above:
AGENTAREA_API_URL: the public base of/webhooks/{webhook_id}, the URL it registers with a provider. Required; the chart sets the backend’s own value.AGENTAREA_SECRET_ENCRYPTION_KEY: source credentials are read from thedatabasesecret backend. Required; the event service refuses to start with any otherAGENTAREA_SECRET_BACKEND.AGENTAREA_HTTP_ALLOW_PRIVATE,AGENTAREA_HTTP_PRIVATE_ALLOWLIST: a host the member names (a feed URL, a mailbox) may reach only public addresses unless these open private ones, as for the backend.AGENTAREA_MCP_MANAGER_URL,AGENTAREA_MCP_GATEWAY_SECRET: MCP Events sources are polled and subscribed through the MCP manager’s gateway, which adds the MCP server’s credentials. Required; the chart sets both, the secret from the same Secret the backend reads.
Sandbox runner (mcpSandboxRunner)
The runner consumes sandbox execution requests from Redis Streams. In Docker
Compose there is no separate runner: the manager runs it in-process
(
AGENTAREA_SANDBOX_EMBEDDED_RUNNER=true) and delegates execution to the
sandbox-executor container over AGENTAREA_SANDBOX_EXECUTOR_URL.
Telemetry (every first-party Deployment)
Rendered into backend, worker, mcp-manager and event-service by theagentarea.telemetry.envs helper, only while telemetry.enabled is true.
AGENTAREA_OTEL_ENABLED=true with no OTEL_EXPORTER_OTLP_ENDPOINT (or no
per-signal endpoints) stops the process at startup. OTEL_METRICS_EXPORTER
picks otlp (the default), prometheus (a scrape endpoint on
OTEL_EXPORTER_PROMETHEUS_HOST:OTEL_EXPORTER_PROMETHEUS_PORT, default
localhost:9464) or none; OTEL_METRIC_EXPORT_INTERVAL sets the push interval
in milliseconds (default 15000). See observability.
Outbound TLS (not in config.yaml)
Read by HttpSettings in the backend and the worker.
Every request the platform sends to a host outside the deployment checks TLS
against one trust store: the system CAs and certifi’s bundle, plus the PEM file
this variable names. The file adds to the public roots and never replaces them.
Set it when members connect services whose chain those roots leave out, such as
hosts certified by the Russian Trusted Root CA, or a corporate CA. It covers
OpenAPI spec fetches and tool calls, URL MCP servers, OAuth discovery and token
endpoints, A2A delegates, model discovery and model calls, skill and registry
imports, and channel webhooks.
On Kubernetes, put the PEM text of one or more certificates in
global.http.extraCaCerts: the chart stores it in the ConfigMap
<release>-extra-ca-certs, mounts it into the backend and worker at
/etc/agentarea/extra-ca, and sets the variable to the file there. In Docker
Compose, mount the file into app and agentarea-worker with an override file
and set the variable to its path inside the container.
A path that does not exist, cannot be read, or holds no certificate stops the
API and the worker at startup.
Outbound URL policy (not in config.yaml)
Read by HttpSettings in the backend and the worker, by the event service, and
by the MCP manager for URL MCP servers reached through its gateway.
Every address a workspace member supplies is refused when it resolves to a
private, loopback, link-local or metadata address: a provider config’s
endpoint_url (model test, runs, compaction, trigger conditions, media), URL MCP
servers, OpenAPI connections, A2A delegates, bundle and skill sources. Platform-managed
provider configs are called as configured.
AGENTAREA_HTTP_PRIVATE_ALLOWLIST admits named exceptions, comma-separated host
globs and CIDRs (localhost,host.docker.internal, 192.168.1.50/32) for a model
server on the LAN or the host. Name each one: *.svc.cluster.local or a cluster
CIDR lets every member reach every in-cluster service, the platform’s own
included. AGENTAREA_HTTP_ALLOW_PRIVATE=true admits every private address and
belongs only on a single-tenant install. docker-compose.dev.yaml allows
localhost,host.docker.internal; docker-compose.yaml allows nothing.
Spend currency (not in config.yaml)
Read by SpendSettings in the backend and the worker.
The one currency spend caps count and tool costs are declared in, as an ISO 4217
code. Nothing converts other currencies: a tool cost declared in another currency is
recorded in that currency and shown as not covered by caps. With the enterprise
billing extension installed, billing’s ledger currency is the source of truth and
this must name it, or the backend and the worker refuse to start.
Docker Compose variables
Read from.env by docker-compose.yaml. Only the ones with no Kubernetes
equivalent are listed; the rest map onto the groups above.
The two sandbox secrets are declared
${VAR:?message}, so Compose aborts rather
than starting with them empty.
Errors
Example
Override a value thatconfig.yaml hardcodes, using the per-service extension
point:
Related
Requirements
Host, cluster, and dependency versions required to run AgentArea, per
deployment target
Deploy on Kubernetes with Helm
Install the agentarea Helm chart, decide which bundled dependencies to keep
Deploy with Docker Compose
Run the full AgentArea platform on one host with docker- compose.yaml
Choose a secrets backend
Configure where AgentArea stores workspace secrets
Collect logs and metrics
Read AgentArea’s structured JSON logs, enable OpenTelemetry tracing