Skip to main content
Version: 2026.1

Environment Variables

Complete reference of every environment variable read by the bundle. If you are setting the bundle up for the first time, walk through the steps in Installation first - this page is the reference you return to when tuning a running system.

All agent-server-specific variables use the AGENT_SERVER_ prefix to avoid colliding with unrelated Symfony or Node variables. Standard Node conventions (PORT, HOST, NODE_ENV) and the PIMCORE_* shared variables stay un-prefixed.

Env vars are loaded into the agent-server container via Docker Compose's env_file directive pointing at .env.local. Env vars used by the PHP side are loaded the usual Symfony way.

Core runtime

VariableDefaultDescription
PORT3032Agent-server port
HOST0.0.0.0Bind host
NODE_ENVproductiondevelopment / production / test
PIMCORE_INTERNAL_URLhttp://nginxInternal URL the agent-server uses to reach Pimcore
PIMCORE_CONFIG_API_PATH/pimcore-studio/api/bundle/agent/configurations/exportPath (appended to PIMCORE_INTERNAL_URL) of PHP's agent-config export endpoint the agent-server reads at startup and on reload
AGENT_SERVER_LOG_LEVELinfoverbose / debug / info / warn / error
AGENT_SERVER_CORS_ORIGIN*Allowed CORS origins

Mercure (shared - reused, not new)

Live cross-client chat sync publishes turn events to Studio's per-user Mercure topic. The agent-server reuses the existing shared Mercure variables - the same secret and hub URL the rest of the stack already uses (root .env). These are deliberately un-prefixed (they are not agent-server internals) and must be forwarded into the agent-server service's environment: block in docker-compose.yaml.

VariableDefaultDescription
MERCURE_JWT_KEY-Shared HMAC key the agent-server signs its publisher JWT with - must equal the key the hub validates against. Blank/unset → live sync disabled (no-op publisher, startup warning); chat still works, PHP remains the record. Must be ≥ 32 chars.
MERCURE_SERVER_URLhttp://mercure/.well-known/mercureInternal hub publish endpoint the agent-server POSTs private updates to.

Do not introduce AGENT_SERVER_MERCURE_* variants - one secret, one source of truth. For the model these drive see Architecture → Real-time Sync and the publisher JWT in Architecture → Authentication.

LLM adapter

Provider and model configuration is defined in the Symfony config tree under pimcore_agent.inference, not as environment variables. The agent-server reads the provider config from PHP's config export endpoint at startup and on every reload. See Inference for the conceptual overview and Inference Providers for the full schema and examples.

The bundle ships a default copilot provider whose token references AGENT_SERVER_GH_TOKEN - a GitHub PAT with the Copilot Requests permission. It is the one inference value a fresh install must set. It carries the AGENT_SERVER_ prefix because it backs the shipped provider rather than being a user-named external secret.

VariableDefaultDescription
AGENT_SERVER_GH_TOKEN-GitHub PAT (Copilot Requests permission) used by the shipped copilot provider's ${AGENT_SERVER_GH_TOKEN} placeholder. Required only while the default GitHub-Copilot provider is in use.

Provider tokens for any further providers you add (API keys, other PATs) are referenced in provider blocks using the ${VAR_NAME} placeholder syntax and resolved against the agent-server container's own environment at session-config build time. Name those variables however you like:

# .env.local - forwarded into the agent-server container
AGENT_SERVER_GH_TOKEN=ghp_... # used by the shipped default copilot provider
ANTHROPIC_API_KEY=sk-ant-...
HF_ENDPOINT_URL=https://xyz.us-east-1.aws.endpoints.huggingface.cloud/v1
HF_API_TOKEN=hf_...
# config/packages/pimcore_agent.yaml
pimcore_agent:
inference:
default_provider: anthropic-cloud
providers:
anthropic-cloud:
auth_mode: byok
provider: anthropic
token: '${ANTHROPIC_API_KEY}' # resolved agent-server-side
default_model: claude-sonnet-4-5

The following variables remain relevant for the LLM layer:

VariableDefaultDescription
AGENT_SERVER_ADAPTERcopilotcopilot for real LLM sessions, dummy for local dev
AGENT_SERVER_DUMMY_MODEechoDummy adapter mode: echo / scripted / random
AGENT_SERVER_MODEL_CHECK_INTERVAL_MS3600000Periodic model validation interval in ms (0 to disable)

Provider configuration is required. The agent-server reads no AGENT_SERVER_COPILOT_* provider/model variables - all LLM provider, model, auth, and compat settings come from the pimcore_agent.inference config (Inference Providers). An agent that resolves to no provider (no provider: and no default_provider) fails with a clear error. See the migration reference if you previously used the AGENT_SERVER_COPILOT_* variables.

Sessions, files, and admin

VariableDefaultDescription
AGENT_SERVER_AUTH_CACHE_TTL60Auth-validation cache TTL in seconds
AGENT_SERVER_INACTIVITY_TIMEOUT_MS300000End the stream after this many ms with no SDK events (suppressed while an ask_user is pending)
AGENT_SERVER_FIRST_EVENT_DEADLINE_MS90000Per-inference first-output deadline: how long an accepted send() may stay silent (no first SDK event) before the turn fails fast
AGENT_SERVER_ASK_USER_TIMEOUT_MS600000How long to wait for a reply to an ask_user / pause prompt before auto-resolving and ending the turn. Min 10s, max 30 min (1800000). Kept finite: a parked prompt pins a session slot.
AGENT_SERVER_MAX_SESSIONS1000Max in-memory sessions retained; when exceeded, the oldest idle (non-active, non-ask_user-pending) session is evicted
AGENT_SERVER_UPLOAD_DIR/app/uploadsFile attachment directory (bind-mounted from ./var/tmp/agent-uploads in Compose)
AGENT_NODE_STAGING_BASE_DIR (PHP side)/app/uploadsBase path the PHP MCP tools hand the agent for staged files - must equal the agent-server's AGENT_SERVER_UPLOAD_DIR. Set on the php service. Override both (e.g. to /agent-uploads) when the dev override mounts uploads outside /app to avoid a nested bind mount - see Development.
AGENT_SERVER_SKILLS_MATERIALIZE_DIR/app/var/skillsTarget directory for materialized skill files
AGENT_SERVER_COPILOT_STATE_DIR/app/.copilot-stateStorage root for the Copilot runtime's own session state (event logs, session.db, checkpoints). Passed as the client baseDirectory, which sets COPILOT_HOME on the spawned runtime. Bind-mounted from ./var/tmp/copilot-state in Compose so SDK history survives container recreation and resumeSession can reload it - see Session Storage.
AGENT_SERVER_STAGED_FILE_MAX_AGE_MS86400000Max age of staged asset files before auto-cleanup (24 h default)
AGENT_SERVER_STAGED_FILE_CLEANUP_INTERVAL_MS3600000How often the cleanup job runs (1 h default; set to 0 to disable)
AGENT_SERVER_ADMIN_TOKEN-Shared bearer token for the reload and export endpoints

Setting either AGENT_SERVER_STAGED_FILE_MAX_AGE_MS or AGENT_SERVER_STAGED_FILE_CLEANUP_INTERVAL_MS to 0 disables periodic cleanup entirely. User-uploaded files (under uploaded/) are never auto-cleaned - only session deletion removes them. For the directory layout and why only staged/ is swept, see Features → File Attachments.

Pimcore Studio integration (PHP side)

These variables are set on the PHP side (Pimcore's .env / .env.local) and used by the Pimcore Studio configuration system.

VariableDefaultDescription
AGENT_SERVER_URLhttp://agent-server:3032Agent-server URL, used for reload triggers. Defaults to the compose-convention name; override only for a different name/port
AGENT_SERVER_ADMIN_TOKEN""Must match the agent-server container's AGENT_SERVER_ADMIN_TOKEN

Third-party MCP server credentials

Agent YAML files support ${VAR_NAME} placeholders in MCP URLs and headers (for third-party servers only - Pimcore-internal MCP servers use cookie forwarding). Placeholder names are user-defined: the agent-server interpolates whatever placeholders it finds, at session-resolve time, against its own container environment.

mcpServers:
pimcore-datahub:
type: http
url: ${MCP_PIMCORE_URL}
headers:
Authorization: "Bearer ${MCP_PIMCORE_TOKEN}"

Names here are user-defined - the convention in the bundled presets is MCP_<SERVICE>_URL / MCP_<SERVICE>_TOKEN, but any name works. They are not prefixed with AGENT_SERVER_ because they identify external services, not agent-server internals. See MCP Servers → Environment variable interpolation.

Migration from single-provider env vars

Projects that configured the LLM layer with AGENT_SERVER_COPILOT_* variables can migrate to named providers by adding a pimcore_agent.inference block and setting provider tokens as discrete env vars. The table below maps each old variable to its equivalent in the provider config.

Old environment variableEquivalent in pimcore_agent.inference.providers.<name>:
AGENT_SERVER_COPILOT_AUTH_MODEauth_mode: byok or auth_mode: github
AGENT_SERVER_COPILOT_PROVIDERprovider: openai|anthropic|azure
AGENT_SERVER_COPILOT_API_KEYtoken: '${YOUR_API_KEY_VAR}'
AGENT_SERVER_COPILOT_BASE_URLbase_url: '...' or base_url: '%env(VAR)%'
AGENT_SERVER_COPILOT_MODELdefault_model: ...
AGENT_SERVER_TITLE_MODELtitle_model: ...
AGENT_SERVER_AVAILABLE_MODELSavailable_models: map (one entry per model id)
AGENT_SERVER_COPILOT_PROVIDER_COMPATcompat: cerebras|openai-strict
AGENT_SERVER_GH_TOKENtoken: '${GH_TOKEN_VAR}' with auth_mode: github

The AGENT_SERVER_COPILOT_* variables are no longer read by the agent-server; configure providers via pimcore_agent.inference instead. Keep provider secrets as discrete env vars and reference them from a provider's token: with the ${VAR} placeholder syntax (resolved agent-server-side).

Known BYOK limitations (Copilot SDK upstream bugs)

These are upstream issues in the GitHub Copilot SDK, tracked at github/copilot-sdk#637:

  • No streaming deltas with Anthropic BYOK. Responses arrive as a single assistant.message when the LLM finishes, not word-by-word. The agent-server extracts the full text once the message arrives so chat still works - users just see the full response appear at once instead of streaming.
  • No thinking / reasoning events with Anthropic BYOK. The streamThinking agent field is effectively ignored; Anthropic extended thinking is not exposed via the SDK.
  • Model discovery requires available_models in BYOK mode. The SDK's built-in model catalog only works in GitHub mode. Without an available_models block in the provider config, the Studio UI model dropdown is empty and typos in agent model fields only surface at runtime.