Skip to main content
Version: 2026.1

Agents

Agents are defined on the Pimcore PHP side. They come from three sources - Pimcore Studio edits, project container config, or bundle presets - and all of them are served to the agent-server through a single export endpoint. The agent-server image itself ships no built-in agent definitions.

Three-layer merge model with user-wins semantics: see README → The merge model. For the full mechanism - export endpoint, reload paths, skill materialization - see Architecture → Configuration System.

Editing an agent in Pimcore Studio

Open System → Pimcore Agent → Agent Configuration, pick an agent from the tree on the left, and use the tabbed editor. Saving an agent automatically calls the agent-server reload endpoint so the change takes effect on the next message - no restart needed.

Bundle presets live alongside the CRUD DAO, not inside it, so they do not appear in the Pimcore Studio tree. To customize a preset, create a new agent with the same name; the merge rules guarantee the new user-scoped entry wins. To revert, delete the user entry - the bundle preset will resurface automatically on the next reload.

YAML schema

Whether an agent lives in Pimcore Studio, in a project config/packages/*.yaml, or in a bundle preset file, it has the same shape. The example below shows every field an agent supports.

name: data-management                # Unique identifier (required)
displayName: Data Management # Shown in the agent dropdown (required)
description: >- # Shown as tooltip, used in cross-agent (required)
Search and edit Pimcore data. # awareness block
All writes go through proposals.
icon: edit # Icon name for the UI (e.g. chat, edit, search, image)
default: false # Exactly one agent may be the default
provider: anthropic-cloud # Named inference provider; omit to use default_provider
model: claude-haiku-4-5-20251001 # Per-agent LLM model; resolved within the chosen provider
streamThinking: true # Stream model reasoning as collapsible bubbles
allowAgentSwitch: true # Offer the cross-agent awareness block + switch widget (chat only)
reasoningEffort: medium # Reasoning-effort level (model-specific); omit for provider default
group: editors # Optional folder grouping in the Pimcore Studio tree

systemMessage: >- # Prepended to the SDK's system sections
You are a Pimcore data management assistant. All write operations
require user approval - follow the proposal skills for the correct
propose → review → approve workflow.

skills: # Skill names. See 02_Skills.md
- pql-search
- general
- data-object-proposals

includeSdkTools: # Opt-in SDK tools. See 04_Tool_Security_Reference.md
- web_fetch
- ask_user

richChatWidgets: # LLM-callable display widgets only
- pimcore_open_element
- show_data_object_preview
- show_data_table

pimcoreMcpServers: # Direct Pimcore MCP tool groups. See 03_MCP_Servers.md
- pimcore-data-objects-read
- pimcore-data-objects-write

allowedFileStagingSets: # File-set names this agent may stage; non-empty
- cms_layouts # also auto-enables the stage_file_set tool

pimcoreMetaGroups: # Pimcore tool groups via the meta-tool
- pimcore-tags-read

mcpServers: # Third-party MCP servers. See 03_MCP_Servers.md
pimcore-datahub:
type: http
url: ${MCP_PIMCORE_URL}
headers:
Authorization: "Bearer ${MCP_PIMCORE_TOKEN}"
tools: "*"

pauseAfter: # Interactive "continue or stop" checkpoint
toolCalls: 25
timeoutMinutes: 2

Only name, displayName, and description are required. Everything else is optional.

Field reference

FieldTypeMeaning
namestringUnique id. For a bundle preset file, the filename (minus extension) is used if this field is omitted.
displayNamestringLabel shown in the agent dropdown.
descriptionstringTooltip + used in the cross-agent awareness block in every agent's system prompt.
iconstringIcon name (e.g. chat, edit, search, image).
defaultbooleanExactly one agent can be default: true. Listed first in the dropdown and used when no agent is specified.
providerstringNamed inference provider from pimcore_agent.inference.providers. Omit to use default_provider. If set to an unknown name, session creation fails. Selectable in the Pimcore Studio agent editor. See Inference Providers.
modelstringPer-agent LLM model. Resolved within the chosen provider - must be a model id present in that provider's available_models (byok) or the Copilot catalog (github). Omit to use the provider's default_model. Validated on reload; unknown models block session creation.
streamThinkingbooleanStream reasoning / thinking events to the chat UI as collapsible bubbles.
allowAgentSwitchbooleanWhether this agent takes part in agent switching in interactive chat. Default true. When false, the cross-agent awareness block is left out of the system message and the pimcore_switch_agent widget is never offered for this agent. Chat only; it has no effect on agent tasks, where switching is unsupported regardless of this field. Editable in Pimcore Studio on the agent's Behavior tab.
reasoningEffortstringReasoning-effort level for this agent. Must be one of the levels the selected model advertises (e.g. low, medium, high). Empty or absent means the model's default is used. The Pimcore Studio shows this field only when the selected model has reasoning-effort levels; in github mode the levels come from the Copilot catalog. An incompatible value (level not in the model's supported set) fails the chat turn (at session creation or resume) with an explicit error.
groupstringFolder grouping in the Pimcore Studio config tree.
systemMessagestringPrepended to the SDK's own system sections. Append mode - SDK guardrails remain in place.
skillsstring[]Skill names. Unknown names are silently dropped. See Skills.
includeSdkToolsstring[]Opt-in SDK tools beyond the default read-only set. See Tool Security Reference.
richChatWidgetsstring[]LLM-callable display widgets this agent may emit. Proposal widgets are auto-emitted by the server when a propose_* tool succeeds and do not need to be listed here - only the display widgets do.
pimcoreMcpServersstring[]Direct Pimcore MCP group names. See MCP Servers.
allowedFileStagingSetsstring[]File-set names this agent may stage. A non-empty value auto-enables stage_file_set. See File Staging.
pimcoreMetaGroupsstring[]Meta-tool Pimcore groups. See MCP Servers.
mcpServersobjectThird-party MCP servers. See MCP Servers.
pauseAfterobjectInteractive pause thresholds. See below.
permissionsobjectOptional per-agent visibility and access restriction (run/update per user or role). See below.
executionUserstringOptional Pimcore username the whole session runs as instead of the chat initiator. Admin only. See Execution user.

pauseAfter sub-schema

KeyTypeDefaultPurpose
toolCallsinteger50Pause after this many tool calls.
timeoutMinutesinteger5Pause after this much active processing time. User-wait time is excluded.

Whichever threshold fires first triggers the pause. Both keys are optional; omit one to use its default. For the user-facing flow and when to tune these values, see Features → Interactive Input → pauseAfter.

Permissions

Agent configurations can optionally carry a permissions field that restricts which Pimcore users may see, run, and manage a given agent. When the field is absent, the agent is governed only by the two global permissions - pimcore_agent_use to run any agent, pimcore_agent_config to configure any agent - and every user who holds them can use every agent equally.

permissions:
user:
- { name: jdoe, run: true, update: true }
role:
- { name: editors, run: true, update: false }

Each entry under user or role identifies a Pimcore user or role by name, not id, so a configuration stays portable across Pimcore instances where numeric ids differ. Two independent booleans control what that user or role may do with this specific agent:

LevelGrants
runSee the agent in the Pimcore Studio tree and in the chat agent selector, and start chat sessions with it. Together with the global pimcore_agent_config permission, also allows opening its configuration read only.
updateChange the agent configuration, edit its permissions, clone it, and delete it. Implies run.

update is the top per-agent level: it grants full management of the agent (including editing this same permissions block and deleting the agent), so there is no separate delete level to escalate to. A user who can create or clone an agent therefore holds update on it and can restrict it themselves.

Evaluation rules

Evaluation mirrors the Data Hub permission model:

  • Admin users are always allowed everything, regardless of permissions.
  • When both the user and role lists are empty, the agent carries no per-agent restriction and is governed only by the global permissions.
  • When any entry exists, a direct user entry decides on its own: an explicit false blocks that user even when one of their roles would grant the same level.
  • If no direct user entry matches, the user's roles are unioned: any role that grants a level is enough.
  • Per-agent permissions only ever restrict within the global permission; they never extend it. A user without pimcore_agent_use cannot run any agent regardless of permissions.

Where run is enforced

The run permission is enforced everywhere an agent can be used, not only in the configuration tree:

  • The Pimcore Studio agent configuration tree hides agents the user cannot run.
  • The chat agent selector lists only runnable agents, and the agent-server omits non-runnable agents from the switch-suggestion prompt so an agent is never proposed as a switch target the user cannot use.
  • Starting a chat session with, or switching a session to, an agent the user cannot run is rejected server side.

The agent-server obtains the per-user runnable set from a Pimcore endpoint gated by pimcore_agent_use, so the permission logic stays authoritative in one place.

Editing permissions in Pimcore Studio

Open the agent in System → Pimcore Agent → Agent Configuration and switch to the Permissions tab. The tab lists users and roles with the run and update checkboxes and only appears for users who may update the agent. The clone and delete tree actions are likewise available only to users who may update the agent. The picker behind the tab is backed by a listing endpoint gated by pimcore_agent_config.

Presets and portability

Bundle-shipped preset agents carry no permission sets unless their YAML explicitly declares them, so presets stay open to every user with the global permissions by default. To restrict a preset on a given instance, override it by name in Pimcore Studio and add a permissions block to the override; the merge rules guarantee the new user-scoped entry wins. See Editing an agent in Pimcore Studio above for how overrides work.

Execution user

Agent configurations can optionally carry an executionUser field: a Pimcore username the whole session runs as, instead of the user who started the chat.

executionUser: reporting-service-account

When the field is empty (the default), the agent runs as the chat initiator, exactly as it does without this field set at all. When it is set, every tool call, MCP call, and permission check in that session runs with the configured user's permissions rather than the initiator's. This works because the effective user is resolved once at session creation and the MCP access token is minted for that user - the tools already derive their acting user from the token, so no further wiring is needed. See Architecture → Authentication → Execution user resolution for the mechanism.

Session ownership stays with the initiator: the chat session, its history, its entry in the session listing, and resume all remain the initiating user's. Only the acting identity changes for the duration of the session.

Fail closed

If executionUser is set to a name that does not resolve to an active Pimcore user, session creation fails with an error rather than silently falling back to the initiator. Fix the typo or reactivate the user before sessions with that agent can start again.

Admin only

Only administrators can set, change, or clear executionUser. Non-admin users see the field read only in Pimcore Studio, and the server rejects a changed value coming from a non-admin request.

Editing in Pimcore Studio

Open the agent in System → Pimcore Agent → Agent Configuration and find the field on the General tab. Pimcore Studio shows a warning next to the field once it carries a value, calling out the permission implications described below.

Security implications

The execution user can hold more permissions than the users who chat with the agent. Because the agent acts as the execution user, its responses can surface information (object content, listings, search results, proposal values) that the chatting users cannot access directly - an information disclosure risk. HITL proposals created during such a session are computed with the execution user's permissions too, so an approver may see proposed values derived from data outside their own visibility.

The recommended mitigation is to combine an execution user with the agent's own run permission so only an intended audience can start sessions with that agent at all. See Architecture → Tool Security and Tool Security Reference for the full security note.

Agent tasks

pimcore_agent.tasks.* bounds the whole headless-task subsystem used by headless agent tasks - work delegated to an agent from PHP rather than through a Studio chat session. Whether a given agent writes autonomously or through HITL proposals inside a task is not a task-specific setting at all; it follows directly from which MCP tool group the agent configuration grants it, see Features → Agent Tasks → Autonomy and HITL.

pimcore_agent:
tasks:
max_concurrent: 5 # bundle-wide cap on concurrently `running` tasks
retention_days: 30 # terminal tasks are reaped this many days after finishing
default_deadline_minutes: 30 # soft per-task deadline, unless the caller overrides it
default_max_auto_continues: 5 # auto-continue budget, unless the caller overrides it
KeyTypeDefaultMeaning
max_concurrentinteger5Hard cap on tasks in queued/running at once, enforced at start(). A caller over the cap gets TooManyTasksException; the Copilot step retries with backoff instead of failing outright.
retention_daysinteger30How long a terminal task (and its session) survives before the maintenance watchdog deletes it.
default_deadline_minutesinteger30Soft deadline applied to a task when its request does not set deadlineMinutes itself.
default_max_auto_continuesinteger5Auto-continue budget applied to a task when its request does not set maxAutoContinues itself.

These are container parameters, not per-agent YAML fields - set them once under pimcore_agent.tasks in config/packages/pimcore_agent.yaml. See Architecture → Agent Tasks for how the concurrency cap, deadline, and retention window are enforced.

Model validation

The model field is validated on startup, on every reload, and periodically (AGENT_SERVER_MODEL_CHECK_INTERVAL_MS, default 1 h). An agent that references a model the provider does not serve logs a warning and blocks at session-creation time - no silent fallback. Mechanism: Architecture → Agent Framework → Model configuration.

Inspect the current agent / model pairings:

curl -H "Authorization: Bearer $AGENT_SERVER_ADMIN_TOKEN" \
http://localhost/agent-server/api/admin/models

BYOK providers: the SDK has no built-in model catalog in BYOK mode. Define the model list in the provider's available_models block so validation can run and the Pimcore Studio model dropdown is populated. See Inference Providers.

Reloading changes

Saving in Pimcore Studio auto-triggers a reload on the agent-server - the change takes effect on the next message with no restart. To trigger a reload manually (for debugging, or after editing a preset YAML in a bundle):

curl -X POST -H "Authorization: Bearer $AGENT_SERVER_ADMIN_TOKEN" \
http://localhost/agent-server/api/admin/reload-agents

The response body includes modelWarnings and toolWarnings. For the three paths the registry can be repopulated (Studio CRUD push, background retry after startup failure, manual reload), see Architecture → Configuration System → Reload & recovery paths.