System Tasks
System tasks are background operations that run outside the normal pipeline execution cycle. They handle AI-powered content operations (alt text, meta descriptions, internal linking), media processing (image generation, optimization), and agent housekeeping (daily memory synthesis, agent ping). All system tasks share a common base class with standardized job management, effect tracking, and undo support.
Overview
The system tasks framework consists of:
- SystemTask base class — abstract base with job completion, failure handling, rescheduling, and undo
- SystemAgentServiceProvider — registers task handlers and Action Scheduler hooks
- TaskRegistry — central registry of available task types
- TaskScheduler — schedules and dispatches tasks via Action Scheduler
- SystemTaskStep — pipeline step type that bridges system tasks into pipeline workflows
- Seven built-in tasks — each implementing a specific AI or system operation
Note:
GitHubIssueTaskwas extracted to thedata-machine-codeextension plugin (see PR #926). It is no longer part of core data-machine.
SystemTask Base Class
Note: GitHubIssueTask was extracted to the data-machine-code extension plugin (see PR #926). It is no longer part of core data-machine.
Note: GitHubIssueTask was extracted to the data-machine-code extension plugin (see PR #926). It is no longer part of core data-machine.
abstract class SystemTask {
abstract public function execute(int $jobId, array $params): void;
abstract public function getTaskType(): string;
}Job Lifecycle Methods
| Method | Description |
|---|---|
completeJob(int $jobId, array $result) | Store result in engine_data and mark job as completed. Logs success. |
failJob(int $jobId, string $reason) | Store error in engine_data and mark job as failed. Logs error. |
reschedule(int $jobId, int $delaySeconds) | Reschedule for later execution via Action Scheduler. Tracks attempt count with a default max of 24 attempts. |
Task Metadata
Source: inc/Engine/AI/System/Tasks/SystemTask.php
Since: v0.22.4
public static function getTaskMeta(): array {
return [
'label' => 'Human-readable task name',
'description' => 'What this task does',
'setting_key' => 'wp_option_key_to_enable', // null if always available
'default_enabled' => true,
'trigger' => 'How it gets triggered',
'trigger_type' => 'cron|event|tool|manual',
'supports_run' => false, // Can be manually triggered?
];
}AI Model Resolution
All system tasks extend this abstract class:
$system_defaults = $this->resolveSystemModel($params);
$provider = $system_defaults['provider'];
$model = $system_defaults['model'];Tasks declare UI metadata via the static getTaskMeta() method:
Editable Prompts
Tasks that need an AI provider use resolveSystemModel():
This resolves the effective model from agent-specific configuration, falling back to the global system context defaults.
public function getPromptDefinitions(): array {
return [
'generate' => [
'label' => 'Generation Prompt',
'description' => 'Prompt used for generation',
'default' => 'Generate a {{type}} for: {{context}}',
'variables' => [
'type' => 'What to generate',
'context' => 'Input context',
],
],
];
}Since: v0.41.0
- Check
datamachine_task_promptsoption for a per-task override - Fall back to the default template from
getPromptDefinitions()
Tasks with AI prompts can expose editable prompt templates via getPromptDefinitions(). Each prompt has a key, label, description, default template, and named variables for interpolation:
| Method | Description |
|---|---|
resolvePrompt(string $key) | Get the effective prompt template (override or default) |
interpolatePrompt(string $template, array $variables) | Replace {{variable}} placeholders |
buildPromptFromTemplate(string $key, array $variables) | Resolve + interpolate in one call |
Resolution chain:
// Set an override
SystemTask::setPromptOverride('alt_text_generation', 'generate', 'Custom prompt...');
// Clear all overrides for a task (revert to defaults)
SystemTask::resetPromptOverrides('alt_text_generation');
// Get all overrides
SystemTask::getAllPromptOverrides();Convenience methods:
Undo System
Override management:
Overrides are stored in the datamachine_task_prompts WordPress option, keyed by task_type then prompt_key.
Opting In
Since: v0.33.0
- Returning
truefromsupportsUndo() - Recording effects in
engine_data.effects[]during execution
Effect Types
Tasks that modify WordPress content can opt into undo support. The system provides generic handlers for common effect types, so most tasks don’t need custom reversal logic.
| Effect Type | What It Undoes | How |
|---|---|---|
post_content_modified | Content changes to a post | Restores from WP revision (revision_id in effect) |
post_meta_set | Post meta updates | Restores previous value or deletes the meta key |
attachment_created | Media library additions | Deletes the attachment (force delete) |
featured_image_set | Featured image assignments | Restores previous thumbnail or removes it |
A task supports undo by:
Effect Recording
The base class provides undo handlers for four standard effect types:
$effects[] = [
'type' => 'post_content_modified',
'target' => ['post_id' => 42],
'revision_id' => 123,
'previous_value' => null, // optional, for meta/featured image
];Undo Execution
Unknown effect types are skipped (not failed), so tasks with mixed reversible/irreversible effects degrade gracefully.
$result = $task->undo($jobId, $engineData);
// {
// 'success' => true, // false if any effect failed to revert
// 'reverted' => [...], // successfully reversed effects
// 'skipped' => [...], // unknown effect types
// 'failed' => [...], // effects that couldn't be reversed
// }CLI
# Undo a job's effects
wp datamachine jobs undo <job_id> [--task-type=<type>] [--dry-run] [--force]SystemAgentServiceProvider
During execution, tasks record effects as an array in engine_data:
Effects are reversed in reverse order (last effect undone first). The undo method returns a structured result:
Task Registration
Source: inc/Engine/AI/System/SystemAgentServiceProvider.php
Since: v0.22.4
| Task Key | Class |
|---|---|
agent_ping | AgentPingTask |
image_generation | ImageGenerationTask |
image_optimization | ImageOptimizationTask |
alt_text_generation | AltTextTask |
internal_linking | InternalLinkingTask |
daily_memory_generation | DailyMemoryTask |
meta_description_generation | MetaDescriptionTask |
Action Scheduler Hooks
| Hook | Handler | Description |
|---|---|---|
datamachine_task_handle | handleScheduledTask | Dispatches a scheduled task job |
datamachine_task_process_batch | handleBatchChunk | Processes a batch chunk |
datamachine_system_agent_set_featured_image | handleDeferredFeaturedImage | Retries featured image assignment (up to 12 × 15s = 3 minutes) |
datamachine_recurring_<task_type> | closure → TaskScheduler::schedule() | One hook per registered recurring schedule. Fires on the cadence defined by the schedule and enqueues an ephemeral DM job for the bound task. |
Recurring Task Schedule Management
Registers all task infrastructure on instantiation:
- If the schedule’s
enabled_settingresolves to true and no AS action is pending → schedule viaRecurringScheduler::ensureSchedule(). - If the setting resolves to false → unschedule.
Hooks the datamachine_tasks filter to register the seven built-in task types:
SystemTaskStep
Schedules are registered separately from task handlers via the
datamachine_recurring_schedules filter (see
recurring-scheduler.md). On action_scheduler_init
the service provider reconciles every registered schedule with Action
Scheduler:
On upgrade, any pending AS action queued under the pre-refactor hook
datamachine_system_agent_daily_memory is unscheduled during the first
reconciliation so no zombie recurring action remains in the queue.
Source: inc/Core/Steps/SystemTask/SystemTaskStep.php
How It Works
- Reads
handler_config.taskto determine the task type - Creates a child DM job for independent tracking
- Injects pipeline context (e.g.,
post_idfrom a preceding Publish step) into task params - Executes the task handler synchronously
- Reads the child job result and returns it as a
DataPacket
Configuration
A pipeline step type that bridges system tasks into the pipeline engine. This allows any system task to be used as a step in a pipeline workflow.
- Task (select dropdown) — chooses from registered task types via
TaskRegistry - Params (JSON editor) — task-specific parameters, defaults to
{}
Settings
Step Type: system_task
Position: 70
Configured via the pipeline step UI with two fields:
Built-In Tasks
DailyMemoryTask
Source: inc/Core/Steps/SystemTask/SystemTaskSettings.php
Defines the admin UI fields. The task dropdown is populated from TaskRegistry::getHandlers(), using each task’s getTaskMeta()['label'] for display.
Type: daily_memory_generation
Source: inc/Engine/AI/System/Tasks/DailyMemoryTask.php
Undo: No
| Property | Value |
|---|---|
| Setting | daily_memory_enabled |
| Trigger | Daily at midnight UTC (cron) |
| Manual run | Yes |
| Prompts | daily_summary, memory_cleanup |
InternalLinkingTask
AI-generated daily summary of agent activity plus automatic MEMORY.md cleanup. Two-phase execution: Phase 1 synthesizes the day’s jobs and chat sessions into a daily entry; Phase 2 uses AI to split MEMORY.md into persistent knowledge and session-specific content, archiving the latter to the daily file.
See Daily Memory System for complete documentation.
| Property | Value |
|---|---|
| Setting | internal_linking_auto_enabled |
| Trigger | Manual (via CLI or ability) |
| Manual run | No |
| Prompts | generate |
| Default links per post | 3 |
Type: internal_linking
Source: inc/Engine/AI/System/Tasks/InternalLinkingTask.php
Undo: Yes (post_content_modified via WP revision, post_meta_set)
- Get post categories and tags
- Parse post into
core/paragraphblocks - Find related posts scored by taxonomy overlap + title similarity
- Filter out posts already linked in the content
- For each related post, find a candidate paragraph and send to AI with linking instructions
- Validate the AI inserted a link (URL detection)
- Apply block replacements and record effects for undo
- Store link metadata in
_datamachine_internal_linkspost meta
MetaDescriptionTask
Semantically weaves internal links into post content. Finds related posts via shared taxonomy terms (categories and tags) with title similarity scoring. For each related post, identifies a candidate paragraph block and uses AI to insert an anchor tag naturally into the text via block-level editing (ReplacePostBlocksAbility).
Process:
| Property | Value |
|---|---|
| Setting | meta_description_auto_generate_enabled |
| Trigger | Manual |
| Manual run | No |
| Prompts | generate |
| Max length | 155 characters |
AltTextTask
Type: meta_description_generation
Source: inc/Engine/AI/System/Tasks/MetaDescriptionTask.php
Undo: Yes (post_meta_set — restores previous excerpt)
Generates AI-powered SEO meta descriptions for WordPress posts. Gathers post title, content excerpt (up to 1500 characters), categories, and tags as context. Normalizes the AI response (strips quotes and markdown formatting, truncates at word boundary to 155 characters) and saves to post_excerpt.
| Property | Value |
|---|---|
| Setting | alt_text_auto_generate_enabled |
| Trigger | Auto on image upload (event) |
| Manual run | Yes |
| Prompts | generate |
ImageGenerationTask
Type: alt_text_generation
Source: inc/Engine/AI/System/Tasks/AltTextTask.php
Undo: Yes (post_meta_set — restores previous alt text)
Generates AI-powered alt text for WordPress image attachments using a vision model. Sends the actual image file (with MIME type) plus contextual information (attachment title, caption, description, parent post title) to the AI. Normalizes the response (capitalizes first character, ensures trailing period) and saves to the _wp_attachment_image_alt post meta.
featured— sets as the post’s featured image. If the pipeline hasn’t published the post yet, schedules a deferred retry (up to 12 × 15s = 3 minutes).insert— inserts acore/imageblock into the post content, using smart auto-placement to find the largest gap between existing image blocks.
| Property | Value |
|---|---|
| Setting | None (always available) |
| Trigger | AI tool call |
| Manual run | No |
| Prompts | None |
| Max attempts | 24 |
| JPEG quality | 85 |
ImageOptimizationTask
Type: image_generation
Source: inc/Engine/AI/System/Tasks/ImageGenerationTask.php
Undo: Yes (attachment_created, featured_image_set, post_content_modified)
Handles async image generation through the Replicate API. Polls a prediction ID for status (starting → processing → succeeded/failed/canceled), rescheduling itself every 5 seconds up to 24 attempts (~120 seconds). On success, downloads the image, converts to JPEG (quality 85), and sideloads into the WordPress media library. Supports two modes:
| Property | Value |
|---|---|
| Setting | None (default disabled) |
| Trigger | On-demand via CLI or ability |
| Manual run | No |
| Prompts | None (not an AI task) |
AgentPingTask
Type: image_optimization
Source: inc/Engine/AI/System/Tasks/ImageOptimizationTask.php
Undo: Yes (attachment_file_modified, file_created)
Compresses oversized images and generates WebP variants using WordPress’s native image editor (Imagick or GD). No external API dependencies. Follows a diagnose-then-fix pattern: ImageOptimizationAbilities::diagnoseImages() identifies issues, and this task fixes individual images. Compresses JPEG/PNG/WebP in-place at a configurable quality level, then optionally generates a .webp sibling file.
| Property | Value |
|---|---|
| Setting | None (always available) |
| Trigger | On-demand via CLI, REST, or pipeline step |
| Manual run | Yes |
| Prompts | None (not an AI task) |
Task Registration
Type: agent_ping
Source: inc/Engine/AI/System/Tasks/AgentPingTask.php
Since: v0.60.0
Undo: No
add_filter('datamachine_tasks', function(array $tasks): array {
$tasks['my_custom_task'] = MyCustomTask::class;
return $tasks;
});Sends pipeline context to external webhook endpoints (Discord, Slack, custom HTTP collectors). Delegates HTTP transport to SendPingAbility (inc/Abilities/AgentPing/SendPingAbility.php). When dispatched as a pipeline step via SystemTaskStep, supports queue popping so a single ping configuration can be reused across queued runs.
Architecture Diagram
CLI Pipeline Engine AI Tool Call
| | |
v v v
TaskScheduler SystemTaskStep TaskScheduler
| | |
v v v
TaskRegistry -----> resolve task class <----- TaskRegistry
|
v
SystemTask
.execute()
|
+-------------------+-------------------+
| | |
v v v
completeJob() failJob() reschedule()
| | |
v v v
Jobs table Jobs table Action Scheduler
(engine_data) (failed status) (retry in N sec)Source Files
| File | Purpose |
|---|---|
inc/Engine/AI/System/Tasks/SystemTask.php | Abstract base class with job lifecycle, undo, and prompt management |
inc/Engine/AI/System/SystemAgentServiceProvider.php | Task registration, Action Scheduler hooks, schedule management |
inc/Engine/AI/System/Tasks/DailyMemoryTask.php | Daily memory synthesis and MEMORY.md cleanup |
inc/Engine/AI/System/Tasks/InternalLinkingTask.php | AI-powered internal link insertion |
inc/Engine/AI/System/Tasks/MetaDescriptionTask.php | AI-powered SEO meta description generation |
inc/Engine/AI/System/Tasks/AltTextTask.php | AI-powered image alt text generation |
inc/Engine/AI/System/Tasks/ImageGenerationTask.php | Async image generation via Replicate API |
inc/Engine/AI/System/Tasks/ImageOptimizationTask.php | Image compression and WebP generation |
inc/Engine/AI/System/Tasks/AgentPingTask.php | Send pipeline context to external webhook endpoints |
inc/Core/Steps/SystemTask/SystemTaskStep.php | Pipeline step type bridging system tasks |
inc/Core/Steps/SystemTask/SystemTaskSettings.php | Admin UI settings for the SystemTask step |