Skip to main content
Version: Next

Agent Task Automation-Action Step (agent_task)

The bundle ships an automation-action step, agent_task, for the Pimcore Copilot bundle's automation actions (Generic Execution Engine). It is the first consumer of the headless agent task facade and the reason the concurrency cap below exists. The step registers itself and appears in the step picker automatically whenever the Copilot bundle is installed, with no configuration in the Copilot bundle needed.

Naming note. "Copilot" here is the Pimcore Copilot bundle (automation actions / Generic Execution Engine), not the GitHub Copilot SDK this bundle's own Core Concepts uses as its LLM adapter. The two are unrelated products that happen to share a name.

The step runs the agent exactly like a Pimcore Studio chat session does - same tools, same permissions - except no human is watching: it must finish the task itself and call finalize_task exactly once.

Configuration

agent: 'data-management'               # Required: agent configuration name
instructions: | # Required: task instructions, in addition to selected elements
Review the selected products and fix any missing SEO meta descriptions.
output_schema: # Optional JSON Schema (written as YAML) the output must validate against
type: object
additionalProperties: false
required: [processed, summary]
properties:
processed: { type: integer }
summary: { type: string }
reviewer: 'jdoe' # Optional Pimcore username who reviews; falls back to the acting user when empty
timeout_seconds: 900 # How long the step waits, including time queued for a free task slot
context_key: 'agent_result' # Job-run context key the result envelope is written under
continue_session_from: '' # Optional: context_key of an earlier agent_task step to resume
  • Writing output_schema. The whole automation action is YAML, so output_schema is written as YAML that maps to a JSON Schema. The bundle parses it to a PHP array and validates the agent's output with opis/json-schema. The example above is equivalent to this JSON Schema:

    { "type": "object", "additionalProperties": false, "required": ["processed", "summary"],
    "properties": { "processed": { "type": "integer" }, "summary": { "type": "string" } } }

    Values must be real YAML types (false, not "false"). A common mistake when editing the schema in the Studio automation-action editor is quoting booleans or strings, which produces an invalid schema and fails the step early.

  • reviewer is a Pimcore username, not a user id. The step resolves the configured username to a user id when it runs (UserResolverInterface::getByName()). A non-empty but unresolvable username aborts the step. Leaving it empty is valid - the session owner then falls back to the task's acting user, per Agent Tasks → Access and review. (The PHP facade and the pimcore-agent:task:run command instead take a numeric user id in designatedUserId / --reviewer; only this step takes a username, because that is what reads naturally in an automation-action editor.)

  • Selection mode. The step processes all of a job run's selected elements (data objects, assets, documents) as one task (SelectionProcessingMode::ONCE). A separate task per element (FOR_EACH) is not wired up.

  • Resuming a prior step's task. Set continue_session_from to the context_key of an earlier agent_task step in the same job run. The step reads that step's {context_key}__task_id context entry and calls continueTask() instead of starting a fresh task. This is valid only in ONCE mode - a shared context key cannot address one of several parallel FOR_EACH tasks. A resuming step still applies its own output_schema (and instructions); the continuation validates finalize_task against the schema configured on the continuing step, never the schema of the step it resumes.

  • Concurrency cap. start() (and continueTask()) enforce pimcore_agent.tasks.max_concurrent (default 5) across the whole bundle. While the cap is hit, the step retries every 10 seconds, sharing its own timeout_seconds budget with the subsequent wait. Size the Generic Execution Engine worker pool with blocking agent steps in mind.

  • Runs end to end, no pause-for-input. Generic Execution Engine steps have no suspend/resume primitive, so the step blocks on start() (or continueTask()) plus waitFor(), like the built-in webhook step blocks on HTTP. With direct-write tools the whole workflow runs without a human in the loop. With propose tools the step still captures the turn's summary and proposals, but nothing is applied until the reviewer (or a participant with access) approves it in Pimcore Studio.

  • Failure and timeout. A failed result, or a client-side wait timeout (which also cancels the task), calls throwUnRecoverableException(); ordinary Generic Execution Engine error handling (STOP_ON_FIRST_ERROR / CONTINUE_ON_ERROR) applies from there. The result envelope is written to the job run's context under context_key before that happens either way, so later steps and the run history still see it.

The step's own dispatch (AgentTaskStepMessage, #[AsMessageHandler]) is the Generic Execution Engine's normal messenger path for automation-action steps. It is unrelated to how the task's own settlement publishes AgentTaskCompletedEvent inline (see Architecture → Announcing completion).