{
  "schemaVersion": "1.0",
  "item": {
    "slug": "autonomous-task-runner",
    "name": "Autonomous Task Runner",
    "source": "tencent",
    "type": "skill",
    "category": "AI 智能",
    "sourceUrl": "https://clawhub.ai/chunhualiao/autonomous-task-runner",
    "canonicalUrl": "https://clawhub.ai/chunhualiao/autonomous-task-runner",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/autonomous-task-runner",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=autonomous-task-runner",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "CHANGELOG.md",
      "README.md",
      "SKILL.md",
      "STATUS.json",
      "references/queue-schema.md",
      "references/task-types.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "slug": "autonomous-task-runner",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T00:29:37.360Z",
      "expiresAt": "2026-05-07T00:29:37.360Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=autonomous-task-runner",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=autonomous-task-runner",
        "contentDisposition": "attachment; filename=\"autonomous-task-runner-2.1.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "autonomous-task-runner"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/autonomous-task-runner"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/autonomous-task-runner",
    "agentPageUrl": "https://openagent3.xyz/skills/autonomous-task-runner/agent",
    "manifestUrl": "https://openagent3.xyz/skills/autonomous-task-runner/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/autonomous-task-runner/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Task Runner Skill",
        "body": "A persistent, daemon-style task queue. Users add tasks at any time. A dispatcher runs on every\nheartbeat to check the queue and execute pending work via subagents. Tasks accumulate, complete,\nand are archived — the queue itself never closes."
      },
      {
        "title": "Two Operating Modes",
        "body": "This skill has two distinct modes with different triggers and behaviors:\n\nModeTriggerPurposeINTAKEUser message containing task intentParse message → add tasks to queue → confirm → immediately run DISPATCHERDISPATCHERAfter INTAKE (primary) · Heartbeat/cron (backup)Read queue → dispatch pending tasks → report completions\n\nBoth modes read and write the same persistent queue file."
      },
      {
        "title": "Mode 1: INTAKE (user message)",
        "body": "Activate INTAKE mode when the user's message matches any of the following patterns:\n\nPatternExamplesExplicit task add\"add task\", \"add these tasks\", \"task:\", \"new task\"Delegation\"do this for me\", \"do these for me\", \"handle these\", \"can you do X\"Framing\"I need you to\", \"help me with\", \"I need\", \"I want you to\"List framing\"task list\", \"my tasks\", \"queue these\", \"work on these\"Control commands\"skip T-03\", \"retry T-02\", \"mark T-01 done\", \"cancel T-04\"Status check\"show tasks\", \"task status\", \"what's in the queue\", \"what are my pending tasks\"Compound askAny message with 2+ distinct action items (bullets, numbers, \"and also\", \"then\")\n\nDo NOT activate INTAKE for:\n\nPure single-question lookups answered in one sentence (\"what time is it?\")\nScheduling-only requests with no actual task (\"remind me in 20 min\")\nSingle web search requests (\"google X\")\nThe heartbeat systemEvent (that's DISPATCHER mode)"
      },
      {
        "title": "Mode 2: DISPATCHER (inline after INTAKE, heartbeat, or cron)",
        "body": "Activate DISPATCHER mode when triggered by:\n\nImmediately after INTAKE — runs in the same turn, right after tasks are queued (primary path)\nHEARTBEAT.md check during a heartbeat poll (backup: catches retries and completions)\nsystemEvent: \"TASK_RUNNER_DISPATCH: check queue and run pending tasks\" (backup)\nAny scheduled/cron trigger registered for task-runner (backup)"
      },
      {
        "title": "Configuration",
        "body": "VariableLocationDefaultDescriptionTASK_RUNNER_DIRTOOLS.md~/.openclaw/tasks/Directory for queue file and deliverablesTASK_RUNNER_MAX_CONCURRENTTOOLS.md2Max tasks running simultaneouslyTASK_RUNNER_MAX_RETRIESTOOLS.md or env3Max retry attempts before marking blockedTASK_RUNNER_ARCHIVE_DAYSTOOLS.md7Days after which done/blocked tasks are archived\n\nHow to configure — add to TOOLS.md:\n\n## Task Runner\nTASK_RUNNER_DIR=~/.openclaw/tasks/\nTASK_RUNNER_MAX_CONCURRENT=2\nTASK_RUNNER_MAX_RETRIES=3\nTASK_RUNNER_ARCHIVE_DAYS=7\n\nQueue file path: ${TASK_RUNNER_DIR}/task-queue.json\n(single persistent file, NOT dated — accumulates all tasks over time)"
      },
      {
        "title": "A3 — Outputs",
        "body": "OutputPath / ChannelDescriptionQueue file${TASK_RUNNER_DIR}/task-queue.jsonSingle persistent queue; all tasksPer-task completion messageChat notificationSent immediately when a task finishes (done or blocked)Deliverable filesTask-specific pathsFiles produced by tasks (when applicable)INTAKE confirmationChatSent after adding tasks to queue"
      },
      {
        "title": "Mode 1: INTAKE — Step-by-Step",
        "body": "Goal: Convert user message into structured task objects, append to queue, confirm."
      },
      {
        "title": "Step 0 — First Run Setup (auto-configure on first use)",
        "body": "Run this check before anything else, every INTAKE invocation:\n\nCHECK whether ${TASK_RUNNER_DIR}/task-queue.json exists\nIF file does NOT exist:\n  → This is the first run. Auto-configure everything silently before proceeding.\n\n  [1] Create directory:\n      exec: mkdir -p ${TASK_RUNNER_DIR}\n\n  [2] Initialize queue file:\n      WRITE ${TASK_RUNNER_DIR}/task-queue.json with default structure:\n      { \"lastId\": null, \"tasks\": [], \"archivedCount\": 0 }\n\n  [3] Register heartbeat entry:\n      READ HEARTBEAT.md (create it if missing)\n      IF \"Task Runner Dispatcher\" is NOT already in the file:\n        APPEND the following block (with a blank line before it):\n\n        ## Task Runner Dispatcher\n        Every heartbeat: check ${TASK_RUNNER_DIR}/task-queue.json\n        - If pending or running tasks exist → run DISPATCHER mode (task-runner skill)\n        - If nothing pending → HEARTBEAT_OK (skip)\n\n      WRITE the updated HEARTBEAT.md\n\n  [4] Register backup cron job:\n      CALL cron tool with:\n        action: \"add\"\n        job:\n          name: \"Task Runner Dispatcher\"\n          schedule: { kind: \"every\", everyMs: 900000 }\n          payload: { kind: \"systemEvent\", text: \"TASK_RUNNER_DISPATCH: check queue and run pending tasks\" }\n          sessionTarget: \"main\"\n          enabled: true\n\n  [5] Notify user:\n      \"⚙️ Task Runner initialized.\n       Heartbeat dispatcher registered in HEARTBEAT.md.\n       Backup cron job registered (runs every 15 minutes).\n       Your tasks will execute automatically.\"\n\n  → THEN continue with normal INTAKE steps below.\n\nIF file already exists:\n  → Skip Step 0 entirely. Proceed directly to Step 1.\n\nIdempotency rule: Step 0 only fires on true first run (queue file absent).\nIt will never double-register the heartbeat entry or create duplicate cron jobs."
      },
      {
        "title": "Step 1 — Load queue",
        "body": "READ ${TASK_RUNNER_DIR}/task-queue.json\nIF file does not exist:\n  Initialize with default structure (see references/queue-schema.md)\n  Set lastId = null"
      },
      {
        "title": "Step 2 — Parse tasks from message",
        "body": "Split user message into individual tasks using these cues:\n\nNumbered lists (1., 2., 3.)\nBulleted lists (-, *, •)\nExplicit separators (\"first\", \"also\", \"and then\", \"next\")\nCompound sentences with multiple imperatives\nSingle task: entire message is one task"
      },
      {
        "title": "Step 3 — Assign IDs",
        "body": "Continue from lastId in the queue file:\n\nIf lastId = \"T-05\", next task is T-06\nIf lastId = null, start at T-01\nFormat: T-NN (zero-padded, minimum 2 digits; expand to 3 when N > 99)"
      },
      {
        "title": "Step 4 — Build task objects",
        "body": "For each parsed task, create a JSON object (schema in references/queue-schema.md):\n\nSet id, description, goal, status = \"pending\", added_at\nSet retries = 0, maxRetries from config\nLeave execution fields null"
      },
      {
        "title": "Step 5 — Append to queue and save",
        "body": "APPEND new task objects to queue.tasks[]\nUPDATE queue.lastId to the last assigned ID\nWRITE updated queue file to disk"
      },
      {
        "title": "Step 6 — Confirm to user",
        "body": "Added T-06: [description]. Starting now...\n\nFor multiple tasks:\n\n📋 Added 3 tasks to queue:\n• T-06: [description]\n• T-07: [description]\n• T-08: [description]\nStarting dispatcher now...\n\nThen immediately run DISPATCHER mode (Steps 1–5 below) in the same turn.\nDo not exit and wait for the next heartbeat. Tasks must start executing immediately.\nThe heartbeat/cron dispatcher is a backup for retries and completion checks — not the primary execution path."
      },
      {
        "title": "Step 7 — Handle control commands",
        "body": "CommandActionskip T-NNSet status = \"skipped\"; save; confirmretry T-NNReset status = \"pending\", retries = 0; save; confirmcancel T-NNSet status = \"skipped\", blocked_reason = \"cancelled by user\"; save; confirmmark T-NN doneSet status = \"done\", completed_at = now; save; confirmshow tasks / task statusRead queue; render status table (see A5 templates)"
      },
      {
        "title": "Mode 2: DISPATCHER — Step-by-Step",
        "body": "Goal: Check queue, dispatch pending tasks, track running tasks, report completions."
      },
      {
        "title": "Step 1 — Load queue",
        "body": "READ ${TASK_RUNNER_DIR}/task-queue.json\nIF file does not exist OR tasks array is empty:\n  → HEARTBEAT_OK (silent, nothing to do)\n  → EXIT"
      },
      {
        "title": "Step 2 — Check for work",
        "body": "pending_tasks = tasks where status = \"pending\"\nrunning_tasks = tasks where status = \"running\"\n\nIF pending_tasks is empty AND running_tasks is empty:\n  → HEARTBEAT_OK (silent)\n  → EXIT"
      },
      {
        "title": "Step 3 — Check running tasks for completion",
        "body": "For each task with status = \"running\":\n\nIF subagent_session is set:\n  CHECK subagent session status\n\n  IF session is DONE:\n    READ deliverable from session output\n    RUN verification (see references/verification-guide.md)\n    IF verification passes:\n      SET status = \"done\"\n      SET deliverable, deliverable_path, completed_at\n      NOTIFY user: ✅ T-NN done — [summary]\n    ELSE (verification failed):\n      TREAT as failure (see retry logic below)\n\n  IF session is FAILED or ERROR:\n    IF retries < maxRetries:\n      INCREMENT retries\n      ADD to strategies_tried\n      SET status = \"pending\"  ← will be re-dispatched this cycle\n    ELSE:\n      SET status = \"blocked\"\n      SET blocked_reason, user_action_required, completed_at\n      NOTIFY user: 🚫 T-NN blocked — [reason + unblock steps]\n\n  IF session is STILL RUNNING:\n    Leave as-is (will check again next heartbeat)"
      },
      {
        "title": "Step 4 — Dispatch pending tasks",
        "body": "currently_running = count of tasks with status = \"running\"\nslots_available = maxConcurrent - currently_running\n\nFOR EACH pending task (in order of added_at), up to slots_available:\n  PICK execution strategy (see references/task-types.md)\n  SPAWN subagent with task description and strategy\n  SET status = \"running\"\n  SET subagent_session = spawned session ID\n  SET started_at = now\n\nSubagent instructions template:\n\nYou are executing task [T-NN] for the task-runner skill.\n\nTask: [description]\nGoal: [goal]\nType: [task_type]\nStrategy: [selected strategy from task-types.md]\n\nExecute the task. When complete:\n1. Report the result clearly\n2. Note any deliverable file path if a file was created\n3. If blocked, explain exactly why and what the user needs to do\n\nDo not start any other tasks. Focus only on this one."
      },
      {
        "title": "Step 5 — Save and exit",
        "body": "WRITE updated queue file (status changes, subagent_session IDs)\n\nIf any notifications were sent (done/blocked), this is an active heartbeat response.\nIf only silent dispatching occurred, this is still a heartbeat response (not HEARTBEAT_OK).\nOnly return HEARTBEAT_OK when there was truly nothing to do (no pending, no running tasks)."
      },
      {
        "title": "INTAKE confirmation (single task)",
        "body": "Added T-06: [description]. Queue now has N pending tasks."
      },
      {
        "title": "INTAKE confirmation (multiple tasks)",
        "body": "📋 Added N tasks to queue:\n• T-06: [description]\n• T-07: [description]\n\nStarting now..."
      },
      {
        "title": "Task status table (on demand)",
        "body": "📋 Task Queue — [N total, N pending, N running, N done, N blocked]\n\nID    Status      Description\nT-01  ✅ done      [description] → [deliverable summary]\nT-02  🔄 running   [description] (started [time ago])\nT-03  ⏳ pending   [description]\nT-04  🚫 blocked   [description] — [blocked_reason short]\nT-05  ⏭️ skipped   [description]"
      },
      {
        "title": "Task done notification",
        "body": "✅ T-NN done — [one-sentence summary of what was accomplished]\n[deliverable: link or file path, if applicable]"
      },
      {
        "title": "Task blocked notification",
        "body": "🚫 T-NN blocked after [N] attempts\n\nWhat was tried:\n- [Strategy 1]: [result]\n- [Strategy 2]: [result]\n\nWhy it's blocked:\n[Clear plain-English explanation]\n\nTo unblock:\n1. [Concrete step #1]\n2. [Concrete step #2 if needed]\n\nReply \"retry T-NN\" once ready."
      },
      {
        "title": "Task skipped",
        "body": "⏭️ T-NN skipped — as requested."
      },
      {
        "title": "A6 — Heartbeat Integration",
        "body": "Heartbeat and cron setup is automatic. Step 0 of INTAKE mode handles this on first use —\nno manual configuration required."
      },
      {
        "title": "Role of heartbeat/cron (backup only)",
        "body": "Tasks are dispatched immediately after INTAKE — heartbeat and cron are backups only.\n\nThe backup dispatcher handles:\n\nRetry dispatch: tasks that failed and were reset to pending\nCompletion checks: polling running subagent sessions for done/blocked status\nRecovery: tasks that were pending when no user message triggered INTAKE\n\nUsers should never need to wait for a heartbeat for a freshly added task."
      },
      {
        "title": "What gets configured automatically",
        "body": "HEARTBEAT.md entry (injected on first INTAKE):\n\n## Task Runner Dispatcher\nEvery heartbeat: check ${TASK_RUNNER_DIR}/task-queue.json\n- If pending or running tasks exist → run DISPATCHER mode (task-runner skill)\n- If nothing pending → HEARTBEAT_OK (skip)\n\nBackup cron job (registered on first INTAKE):\n\nevery 15 min → systemEvent: \"TASK_RUNNER_DISPATCH: check queue and run pending tasks\"\nsessionTarget: main"
      },
      {
        "title": "Manual setup (if needed)",
        "body": "If for any reason auto-setup did not run (e.g., queue file was pre-created externally),\ndelete ${TASK_RUNNER_DIR}/task-queue.json and send any task — Step 0 will fire."
      },
      {
        "title": "INTAKE mode succeeds when:",
        "body": "All tasks from user message parsed and assigned IDs\nTasks appended to queue file (file saved to disk)\nConfirmation sent to user with task IDs and count\nDISPATCHER mode triggered immediately in the same turn\nSubagents spawned for pending tasks before INTAKE turn ends"
      },
      {
        "title": "DISPATCHER mode succeeds when:",
        "body": "Queue file read without error\nAll running tasks checked for completion (done/blocked notifications sent as needed)\nPending tasks dispatched up to maxConcurrent slots\nQueue file saved with updated states\nUser notified for every task that reached a terminal state this cycle"
      },
      {
        "title": "Ongoing system health:",
        "body": "Queue file is never corrupted (always valid JSON)\nTasks older than archiveDays days with terminal status are archived/removed\nlastId always increments (no ID reuse)\nmaxRetries respected before any task is marked blocked"
      },
      {
        "title": "Edge Cases",
        "body": "SituationBehaviorQueue file missing (first run)Run Step 0 auto-setup: create dir, init queue, register heartbeat + cron; notify userQueue file missing (manually deleted)Step 0 re-fires: re-initializes queue; does NOT re-register heartbeat/cron (idempotent check)Queue file corrupt/invalid JSONLog error, notify user, do not overwrite; ask user to inspectTask description is ambiguousAssign unknown type; dispatcher will attempt classification + fallbackmaxConcurrent already reachedDispatcher skips dispatching; checks again next heartbeatUser adds task while dispatcher is runningRace-safe: dispatcher reads, processes, writes atomically per cycleTask depends on another task's outputSet blocked_reason = \"depends on T-NN-1 which is pending/blocked\"User says \"retry T-NN\"Reset to pending, retries = 0, strategies_tried = []All tasks blockedNotify user: \"All tasks are blocked. Review unblock instructions above.\"20+ tasks added at onceDispatcher dispatches in batches of maxConcurrent; all tasks eventually runSubagent session ID lostMark task as pending again; will re-dispatch next cycleArchive: done tasks > archiveDays oldMove to ${TASK_RUNNER_DIR}/archive/YYYY-MM.json; remove from main queue"
      },
      {
        "title": "A8 — File Organization",
        "body": "${TASK_RUNNER_DIR}/\n  task-queue.json          ← single persistent queue (all active tasks)\n  archive/\n    2026-01.json           ← archived tasks (done/blocked, older than archiveDays)\n    2026-02.json\n\nQueue file schema is documented in references/queue-schema.md."
      },
      {
        "title": "References",
        "body": "references/queue-schema.md — Queue JSON format (complete field reference)\nreferences/task-types.md — Task type catalog and strategy selection\nreferences/verification-guide.md — Verification logic per task type\ntests/test-triggers.json — Trigger test cases (positive and negative)"
      }
    ],
    "body": "Task Runner Skill\n\nA persistent, daemon-style task queue. Users add tasks at any time. A dispatcher runs on every heartbeat to check the queue and execute pending work via subagents. Tasks accumulate, complete, and are archived — the queue itself never closes.\n\nTwo Operating Modes\n\nThis skill has two distinct modes with different triggers and behaviors:\n\nMode\tTrigger\tPurpose\nINTAKE\tUser message containing task intent\tParse message → add tasks to queue → confirm → immediately run DISPATCHER\nDISPATCHER\tAfter INTAKE (primary) · Heartbeat/cron (backup)\tRead queue → dispatch pending tasks → report completions\n\nBoth modes read and write the same persistent queue file.\n\nA1 — Triggers\nMode 1: INTAKE (user message)\n\nActivate INTAKE mode when the user's message matches any of the following patterns:\n\nPattern\tExamples\nExplicit task add\t\"add task\", \"add these tasks\", \"task:\", \"new task\"\nDelegation\t\"do this for me\", \"do these for me\", \"handle these\", \"can you do X\"\nFraming\t\"I need you to\", \"help me with\", \"I need\", \"I want you to\"\nList framing\t\"task list\", \"my tasks\", \"queue these\", \"work on these\"\nControl commands\t\"skip T-03\", \"retry T-02\", \"mark T-01 done\", \"cancel T-04\"\nStatus check\t\"show tasks\", \"task status\", \"what's in the queue\", \"what are my pending tasks\"\nCompound ask\tAny message with 2+ distinct action items (bullets, numbers, \"and also\", \"then\")\n\nDo NOT activate INTAKE for:\n\nPure single-question lookups answered in one sentence (\"what time is it?\")\nScheduling-only requests with no actual task (\"remind me in 20 min\")\nSingle web search requests (\"google X\")\nThe heartbeat systemEvent (that's DISPATCHER mode)\nMode 2: DISPATCHER (inline after INTAKE, heartbeat, or cron)\n\nActivate DISPATCHER mode when triggered by:\n\nImmediately after INTAKE — runs in the same turn, right after tasks are queued (primary path)\nHEARTBEAT.md check during a heartbeat poll (backup: catches retries and completions)\nsystemEvent: \"TASK_RUNNER_DISPATCH: check queue and run pending tasks\" (backup)\nAny scheduled/cron trigger registered for task-runner (backup)\nConfiguration\nVariable\tLocation\tDefault\tDescription\nTASK_RUNNER_DIR\tTOOLS.md\t~/.openclaw/tasks/\tDirectory for queue file and deliverables\nTASK_RUNNER_MAX_CONCURRENT\tTOOLS.md\t2\tMax tasks running simultaneously\nTASK_RUNNER_MAX_RETRIES\tTOOLS.md or env\t3\tMax retry attempts before marking blocked\nTASK_RUNNER_ARCHIVE_DAYS\tTOOLS.md\t7\tDays after which done/blocked tasks are archived\n\nHow to configure — add to TOOLS.md:\n\n## Task Runner\nTASK_RUNNER_DIR=~/.openclaw/tasks/\nTASK_RUNNER_MAX_CONCURRENT=2\nTASK_RUNNER_MAX_RETRIES=3\nTASK_RUNNER_ARCHIVE_DAYS=7\n\n\nQueue file path: ${TASK_RUNNER_DIR}/task-queue.json (single persistent file, NOT dated — accumulates all tasks over time)\n\nA3 — Outputs\nOutput\tPath / Channel\tDescription\nQueue file\t${TASK_RUNNER_DIR}/task-queue.json\tSingle persistent queue; all tasks\nPer-task completion message\tChat notification\tSent immediately when a task finishes (done or blocked)\nDeliverable files\tTask-specific paths\tFiles produced by tasks (when applicable)\nINTAKE confirmation\tChat\tSent after adding tasks to queue\nMode 1: INTAKE — Step-by-Step\n\nGoal: Convert user message into structured task objects, append to queue, confirm.\n\nStep 0 — First Run Setup (auto-configure on first use)\n\nRun this check before anything else, every INTAKE invocation:\n\nCHECK whether ${TASK_RUNNER_DIR}/task-queue.json exists\nIF file does NOT exist:\n  → This is the first run. Auto-configure everything silently before proceeding.\n\n  [1] Create directory:\n      exec: mkdir -p ${TASK_RUNNER_DIR}\n\n  [2] Initialize queue file:\n      WRITE ${TASK_RUNNER_DIR}/task-queue.json with default structure:\n      { \"lastId\": null, \"tasks\": [], \"archivedCount\": 0 }\n\n  [3] Register heartbeat entry:\n      READ HEARTBEAT.md (create it if missing)\n      IF \"Task Runner Dispatcher\" is NOT already in the file:\n        APPEND the following block (with a blank line before it):\n\n        ## Task Runner Dispatcher\n        Every heartbeat: check ${TASK_RUNNER_DIR}/task-queue.json\n        - If pending or running tasks exist → run DISPATCHER mode (task-runner skill)\n        - If nothing pending → HEARTBEAT_OK (skip)\n\n      WRITE the updated HEARTBEAT.md\n\n  [4] Register backup cron job:\n      CALL cron tool with:\n        action: \"add\"\n        job:\n          name: \"Task Runner Dispatcher\"\n          schedule: { kind: \"every\", everyMs: 900000 }\n          payload: { kind: \"systemEvent\", text: \"TASK_RUNNER_DISPATCH: check queue and run pending tasks\" }\n          sessionTarget: \"main\"\n          enabled: true\n\n  [5] Notify user:\n      \"⚙️ Task Runner initialized.\n       Heartbeat dispatcher registered in HEARTBEAT.md.\n       Backup cron job registered (runs every 15 minutes).\n       Your tasks will execute automatically.\"\n\n  → THEN continue with normal INTAKE steps below.\n\nIF file already exists:\n  → Skip Step 0 entirely. Proceed directly to Step 1.\n\n\nIdempotency rule: Step 0 only fires on true first run (queue file absent). It will never double-register the heartbeat entry or create duplicate cron jobs.\n\nStep 1 — Load queue\nREAD ${TASK_RUNNER_DIR}/task-queue.json\nIF file does not exist:\n  Initialize with default structure (see references/queue-schema.md)\n  Set lastId = null\n\nStep 2 — Parse tasks from message\n\nSplit user message into individual tasks using these cues:\n\nNumbered lists (1., 2., 3.)\nBulleted lists (-, *, •)\nExplicit separators (\"first\", \"also\", \"and then\", \"next\")\nCompound sentences with multiple imperatives\nSingle task: entire message is one task\nStep 3 — Assign IDs\n\nContinue from lastId in the queue file:\n\nIf lastId = \"T-05\", next task is T-06\nIf lastId = null, start at T-01\nFormat: T-NN (zero-padded, minimum 2 digits; expand to 3 when N > 99)\nStep 4 — Build task objects\n\nFor each parsed task, create a JSON object (schema in references/queue-schema.md):\n\nSet id, description, goal, status = \"pending\", added_at\nSet retries = 0, maxRetries from config\nLeave execution fields null\nStep 5 — Append to queue and save\nAPPEND new task objects to queue.tasks[]\nUPDATE queue.lastId to the last assigned ID\nWRITE updated queue file to disk\n\nStep 6 — Confirm to user\nAdded T-06: [description]. Starting now...\n\n\nFor multiple tasks:\n\n📋 Added 3 tasks to queue:\n• T-06: [description]\n• T-07: [description]\n• T-08: [description]\nStarting dispatcher now...\n\n\nThen immediately run DISPATCHER mode (Steps 1–5 below) in the same turn. Do not exit and wait for the next heartbeat. Tasks must start executing immediately. The heartbeat/cron dispatcher is a backup for retries and completion checks — not the primary execution path.\n\nStep 7 — Handle control commands\nCommand\tAction\nskip T-NN\tSet status = \"skipped\"; save; confirm\nretry T-NN\tReset status = \"pending\", retries = 0; save; confirm\ncancel T-NN\tSet status = \"skipped\", blocked_reason = \"cancelled by user\"; save; confirm\nmark T-NN done\tSet status = \"done\", completed_at = now; save; confirm\nshow tasks / task status\tRead queue; render status table (see A5 templates)\nMode 2: DISPATCHER — Step-by-Step\n\nGoal: Check queue, dispatch pending tasks, track running tasks, report completions.\n\nStep 1 — Load queue\nREAD ${TASK_RUNNER_DIR}/task-queue.json\nIF file does not exist OR tasks array is empty:\n  → HEARTBEAT_OK (silent, nothing to do)\n  → EXIT\n\nStep 2 — Check for work\npending_tasks = tasks where status = \"pending\"\nrunning_tasks = tasks where status = \"running\"\n\nIF pending_tasks is empty AND running_tasks is empty:\n  → HEARTBEAT_OK (silent)\n  → EXIT\n\nStep 3 — Check running tasks for completion\n\nFor each task with status = \"running\":\n\nIF subagent_session is set:\n  CHECK subagent session status\n\n  IF session is DONE:\n    READ deliverable from session output\n    RUN verification (see references/verification-guide.md)\n    IF verification passes:\n      SET status = \"done\"\n      SET deliverable, deliverable_path, completed_at\n      NOTIFY user: ✅ T-NN done — [summary]\n    ELSE (verification failed):\n      TREAT as failure (see retry logic below)\n\n  IF session is FAILED or ERROR:\n    IF retries < maxRetries:\n      INCREMENT retries\n      ADD to strategies_tried\n      SET status = \"pending\"  ← will be re-dispatched this cycle\n    ELSE:\n      SET status = \"blocked\"\n      SET blocked_reason, user_action_required, completed_at\n      NOTIFY user: 🚫 T-NN blocked — [reason + unblock steps]\n\n  IF session is STILL RUNNING:\n    Leave as-is (will check again next heartbeat)\n\nStep 4 — Dispatch pending tasks\ncurrently_running = count of tasks with status = \"running\"\nslots_available = maxConcurrent - currently_running\n\nFOR EACH pending task (in order of added_at), up to slots_available:\n  PICK execution strategy (see references/task-types.md)\n  SPAWN subagent with task description and strategy\n  SET status = \"running\"\n  SET subagent_session = spawned session ID\n  SET started_at = now\n\n\nSubagent instructions template:\n\nYou are executing task [T-NN] for the task-runner skill.\n\nTask: [description]\nGoal: [goal]\nType: [task_type]\nStrategy: [selected strategy from task-types.md]\n\nExecute the task. When complete:\n1. Report the result clearly\n2. Note any deliverable file path if a file was created\n3. If blocked, explain exactly why and what the user needs to do\n\nDo not start any other tasks. Focus only on this one.\n\nStep 5 — Save and exit\nWRITE updated queue file (status changes, subagent_session IDs)\n\n\nIf any notifications were sent (done/blocked), this is an active heartbeat response. If only silent dispatching occurred, this is still a heartbeat response (not HEARTBEAT_OK). Only return HEARTBEAT_OK when there was truly nothing to do (no pending, no running tasks).\n\nA5 — Output Format Templates\nINTAKE confirmation (single task)\nAdded T-06: [description]. Queue now has N pending tasks.\n\nINTAKE confirmation (multiple tasks)\n📋 Added N tasks to queue:\n• T-06: [description]\n• T-07: [description]\n\nStarting now...\n\nTask status table (on demand)\n📋 Task Queue — [N total, N pending, N running, N done, N blocked]\n\nID    Status      Description\nT-01  ✅ done      [description] → [deliverable summary]\nT-02  🔄 running   [description] (started [time ago])\nT-03  ⏳ pending   [description]\nT-04  🚫 blocked   [description] — [blocked_reason short]\nT-05  ⏭️ skipped   [description]\n\nTask done notification\n✅ T-NN done — [one-sentence summary of what was accomplished]\n[deliverable: link or file path, if applicable]\n\nTask blocked notification\n🚫 T-NN blocked after [N] attempts\n\nWhat was tried:\n- [Strategy 1]: [result]\n- [Strategy 2]: [result]\n\nWhy it's blocked:\n[Clear plain-English explanation]\n\nTo unblock:\n1. [Concrete step #1]\n2. [Concrete step #2 if needed]\n\nReply \"retry T-NN\" once ready.\n\nTask skipped\n⏭️ T-NN skipped — as requested.\n\nA6 — Heartbeat Integration\n\nHeartbeat and cron setup is automatic. Step 0 of INTAKE mode handles this on first use — no manual configuration required.\n\nRole of heartbeat/cron (backup only)\n\nTasks are dispatched immediately after INTAKE — heartbeat and cron are backups only.\n\nThe backup dispatcher handles:\n\nRetry dispatch: tasks that failed and were reset to pending\nCompletion checks: polling running subagent sessions for done/blocked status\nRecovery: tasks that were pending when no user message triggered INTAKE\n\nUsers should never need to wait for a heartbeat for a freshly added task.\n\nWhat gets configured automatically\n\nHEARTBEAT.md entry (injected on first INTAKE):\n\n## Task Runner Dispatcher\nEvery heartbeat: check ${TASK_RUNNER_DIR}/task-queue.json\n- If pending or running tasks exist → run DISPATCHER mode (task-runner skill)\n- If nothing pending → HEARTBEAT_OK (skip)\n\n\nBackup cron job (registered on first INTAKE):\n\nevery 15 min → systemEvent: \"TASK_RUNNER_DISPATCH: check queue and run pending tasks\"\nsessionTarget: main\n\nManual setup (if needed)\n\nIf for any reason auto-setup did not run (e.g., queue file was pre-created externally), delete ${TASK_RUNNER_DIR}/task-queue.json and send any task — Step 0 will fire.\n\nA7 — Success Criteria\nINTAKE mode succeeds when:\nAll tasks from user message parsed and assigned IDs\nTasks appended to queue file (file saved to disk)\nConfirmation sent to user with task IDs and count\nDISPATCHER mode triggered immediately in the same turn\nSubagents spawned for pending tasks before INTAKE turn ends\nDISPATCHER mode succeeds when:\nQueue file read without error\nAll running tasks checked for completion (done/blocked notifications sent as needed)\nPending tasks dispatched up to maxConcurrent slots\nQueue file saved with updated states\nUser notified for every task that reached a terminal state this cycle\nOngoing system health:\nQueue file is never corrupted (always valid JSON)\nTasks older than archiveDays days with terminal status are archived/removed\nlastId always increments (no ID reuse)\nmaxRetries respected before any task is marked blocked\nEdge Cases\nSituation\tBehavior\nQueue file missing (first run)\tRun Step 0 auto-setup: create dir, init queue, register heartbeat + cron; notify user\nQueue file missing (manually deleted)\tStep 0 re-fires: re-initializes queue; does NOT re-register heartbeat/cron (idempotent check)\nQueue file corrupt/invalid JSON\tLog error, notify user, do not overwrite; ask user to inspect\nTask description is ambiguous\tAssign unknown type; dispatcher will attempt classification + fallback\nmaxConcurrent already reached\tDispatcher skips dispatching; checks again next heartbeat\nUser adds task while dispatcher is running\tRace-safe: dispatcher reads, processes, writes atomically per cycle\nTask depends on another task's output\tSet blocked_reason = \"depends on T-NN-1 which is pending/blocked\"\nUser says \"retry T-NN\"\tReset to pending, retries = 0, strategies_tried = []\nAll tasks blocked\tNotify user: \"All tasks are blocked. Review unblock instructions above.\"\n20+ tasks added at once\tDispatcher dispatches in batches of maxConcurrent; all tasks eventually run\nSubagent session ID lost\tMark task as pending again; will re-dispatch next cycle\nArchive: done tasks > archiveDays old\tMove to ${TASK_RUNNER_DIR}/archive/YYYY-MM.json; remove from main queue\nA8 — File Organization\n${TASK_RUNNER_DIR}/\n  task-queue.json          ← single persistent queue (all active tasks)\n  archive/\n    2026-01.json           ← archived tasks (done/blocked, older than archiveDays)\n    2026-02.json\n\n\nQueue file schema is documented in references/queue-schema.md.\n\nReferences\nreferences/queue-schema.md — Queue JSON format (complete field reference)\nreferences/task-types.md — Task type catalog and strategy selection\nreferences/verification-guide.md — Verification logic per task type\ntests/test-triggers.json — Trigger test cases (positive and negative)"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/chunhualiao/autonomous-task-runner",
    "publisherUrl": "https://clawhub.ai/chunhualiao/autonomous-task-runner",
    "owner": "chunhualiao",
    "version": "2.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/autonomous-task-runner",
    "downloadUrl": "https://openagent3.xyz/downloads/autonomous-task-runner",
    "agentUrl": "https://openagent3.xyz/skills/autonomous-task-runner/agent",
    "manifestUrl": "https://openagent3.xyz/skills/autonomous-task-runner/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/autonomous-task-runner/agent.md"
  }
}