Agent Skills: agent-heartbeat — Agentic Task Dispatcher

>

UncategorizedID: danbrickey/edp-ai-expert-team/agent-heartbeat

Install this agent skill to your local

pnpm dlx add-skill https://github.com/danbrickey/exocortex/tree/HEAD/global-skills/agent-heartbeat

Skill Files

Browse the full folder contents for agent-heartbeat.

Download Skill

Loading file tree…

global-skills/agent-heartbeat/SKILL.md

Skill Metadata

Name
agent-heartbeat
Description
>

agent-heartbeat — Agentic Task Dispatcher

Poll the EXOcortex board for issues that are both Agentic (category) and Ready (status column), validate they're agent-ready, and dispatch them for autonomous execution.

Quick Reference

/agent-heartbeat              # single sweep — check queue, dispatch if work found
/loop 10m /agent-heartbeat    # recurring — poll every 10 minutes
/agent-heartbeat --dry-run    # show what would be dispatched without executing

Architecture

┌──────────┐     ┌─────────────────┐     ┌──────────────┐     ┌─────────────┐
│  /loop   │────▶│ /agent-heartbeat│────▶│ /prep-issue  │────▶│ /work-issue │
│ (timer)  │     │  (dispatcher)   │     │  (validator)  │     │ (executor)  │
└──────────┘     └─────────────────┘     └──────────────┘     └─────────────┘
                        │                                            │
                        ▼                                            ▼
                 GitHub Projects                              Branch + PR
                 Board mutations                              Issue comments
                 (status moves)                               Status updates

This skill is the dispatcher in the pipeline. It doesn't do the work itself — it finds work, validates it, and hands it to /work-issue.


Step 0: Parse Arguments

  • --dry-run — query and report what would be dispatched, but don't execute
  • No other arguments expected; the skill always queries the full Agentic queue

Step 1: Query the Agentic Queue

Find all project items where Category = Agentic AND Status = Ready.

gh api graphql -f query='
query {
  node(id: "PVT_kwHOCQ_h4c4BRFq6") {
    ... on ProjectV2 {
      items(first: 50) {
        nodes {
          id
          fieldValueByName(name: "Status") {
            ... on ProjectV2ItemFieldSingleSelectValue {
              name
              optionId
            }
          }
          fieldValues(first: 10) {
            nodes {
              ... on ProjectV2ItemFieldSingleSelectValue {
                field { ... on ProjectV2SingleSelectField { name } }
                name
                optionId
              }
            }
          }
          content {
            ... on Issue {
              number
              title
              state
              labels(first: 10) { nodes { name } }
              repository { name owner { login } }
            }
          }
        }
      }
    }
  }
}'

Filter criteria (applied client-side from the query results):

  1. Status field value = Ready (option ID: da247464)
  2. Category field value = Agentic (option ID: 203ea676)
  3. Issue state = OPEN

If no items match, report "No agentic work in queue" and exit cleanly.

Step 2: Prioritize the Queue

If multiple items match, pick one to dispatch per tick. Priority order:

  1. Oldest first — items that have been Ready longest get dispatched first (prevents starvation)
  2. Tie-break by issue number — lower number wins (deterministic)

Only dispatch one item per heartbeat tick. This keeps execution predictable and avoids parallel work that could conflict. The next tick picks up the next item.

Step 3: Validate Agent-Readiness

Before dispatching, run a lightweight readiness check (subset of /prep-issue criteria):

Required (all must pass)

  • [ ] Issue has a body (not empty)
  • [ ] Issue body contains an Objective section (or clearly stated goal)
  • [ ] Issue body contains Acceptance Criteria (or testable done conditions)

Recommended (warn if missing, but don't block)

  • [ ] Execution instructions or playbook reference
  • [ ] Target location / scope boundary
  • [ ] Dependencies section

If required criteria fail:

  1. Move the issue to Blocked column
  2. Add a comment explaining what's missing:
    🤖 Agent-heartbeat: This issue is labeled Agentic + Ready but isn't
    agent-ready. Missing: [list]. Moving to Blocked.
    
    Run `/prep-issue <number>` to fill in the gaps, then move back to Ready.
    
  3. Continue to next item in queue (if any), or exit

If required criteria pass: Proceed to dispatch.

Step 4: Dispatch

4a: Update board state

Move the issue from ReadyIn Progress on the project board:

# Get the item ID from Step 1 results
# Status field ID for Project #3: query dynamically or use known field
gh api graphql -f query='
mutation {
  updateProjectV2ItemFieldValue(
    input: {
      projectId: "PVT_kwHOCQ_h4c4BRFq6"
      itemId: "<ITEM_ID>"
      fieldId: "<STATUS_FIELD_ID>"
      value: { singleSelectOptionId: "118f092d" }
    }
  ) {
    projectV2Item { id }
  }
}'

Add a status label to the issue:

gh issue edit <NUMBER> --repo <OWNER>/<REPO> --add-label "status: In Progress"
gh issue edit <NUMBER> --repo <OWNER>/<REPO> --remove-label "status: Ready" 2>/dev/null

4b: Add dispatch comment

gh issue comment <NUMBER> --repo <OWNER>/<REPO> --body "$(cat <<'EOF'
🤖 **Agent-heartbeat dispatch**
Picked up from Agentic queue at $(date -u +"%Y-%m-%d %H:%M UTC").
Handing off to /work-issue for autonomous execution.
EOF
)"

4c: Execute via /work-issue

Invoke the work-issue skill with the issue number and repo:

/work-issue <NUMBER> --repo <OWNER>/<REPO>

This is where execution transfers to /work-issue. The heartbeat's job is done once /work-issue takes over. /work-issue handles:

  • Branch creation
  • Implementation
  • Verification
  • Commit + PR
  • Completion report as issue comment
  • Moving to Review column

Step 5: Handle Outcomes

After /work-issue completes (or fails), the heartbeat records the result:

Success path

/work-issue handles its own completion — PR created, issue moved to Review, completion comment posted. No additional action needed from heartbeat.

Failure path

If /work-issue encounters a blocker or fails:

  1. Move the issue to Blocked column:

    # Update project board status to a blocked/stalled state
    gh issue edit <NUMBER> --repo <OWNER>/<REPO> --add-label "status: Blocked"
    gh issue edit <NUMBER> --repo <OWNER>/<REPO> --remove-label "status: In Progress" 2>/dev/null
    
  2. Post a failure comment:

    🤖 Agent-heartbeat: Execution failed or was blocked.
    Reason: <summary of what went wrong>
    Moving to Blocked. Needs human review before re-dispatch.
    
  3. Do NOT retry automatically. Failed items require human review. The heartbeat will skip Blocked items on subsequent ticks.


Guard Rails

Concurrency

  • One item per tick. Never dispatch multiple items in parallel. The next tick handles the next item.
  • Skip if already working. Before dispatching, check if any Agentic item is currently In Progress. If so, skip this tick — the previous dispatch is still running.

Scope limits

  • Only Agentic + Ready items. Never auto-dispatch items without the Agentic category, even if they're Ready. The Agentic label is the explicit opt-in.
  • Only open issues. Skip closed issues even if they're still on the board.
  • Cross-repo aware. The board can contain items from any repo. Always pass the correct --repo owner/name to downstream skills.

Safety

  • No force pushes. /work-issue already has this guard, but reinforce: the heartbeat never instructs force operations.
  • No issue closure. The heartbeat and /work-issue never close issues. Dan reviews and closes manually.
  • Dry-run default for first use. When the heartbeat is first invoked, suggest running with --dry-run to verify the queue query works correctly before enabling live dispatch.

Rate limiting

  • Respect GitHub API limits. The GraphQL query in Step 1 is a single call. At 10-minute intervals, this is ~144 calls/day — well within GitHub's 5,000 points/hour limit.
  • Backoff on errors. If the GitHub API returns an error, log it and exit cleanly. The next /loop tick will retry automatically.

Dry-Run Output

When invoked with --dry-run, output:

## 🤖 Agent Heartbeat — Dry Run

### Queue Status
- Agentic + Ready items: <count>
- Agentic + In Progress: <count> (would skip tick if > 0)
- Agentic + Blocked: <count>

### Would Dispatch
- **Issue #<number>**: <title>
  - Repo: <owner>/<repo>
  - Agent-ready: Yes/No (<missing fields if No>)
  - Action: Would move to In Progress → invoke /work-issue

### Skipped
- **Issue #<number>**: <title> — <reason skipped>

Integration with /loop

The intended usage pattern:

/loop 10m /agent-heartbeat

This tells /loop to invoke /agent-heartbeat every 10 minutes. Each tick:

  1. Queries the board (~1 second)
  2. If nothing to dispatch, exits immediately
  3. If work found, validates + dispatches (~seconds for validation, minutes for /work-issue execution)

The /loop skill handles the timer. The heartbeat handles the per-tick logic.

Recommended intervals

  • 10m — good default for active development sessions
  • 30m — lighter touch, good for background operation
  • 5m — aggressive, useful when loading up the queue with multiple items

Example Session

Dan: /loop 10m /agent-heartbeat

[tick 1]
🤖 Agent Heartbeat: No agentic work in queue. Sleeping.

[Dan creates an issue, labels it Agentic, moves to Ready via Nerve Center]

[tick 2]
🤖 Agent Heartbeat: Found 1 item in queue.
  → Issue #47: "feat: backlog parser — extract todos from markdown"
  → Agent-ready: ✓ (objective, acceptance criteria, execution instructions)
  → Dispatching to /work-issue...

[/work-issue takes over, creates branch, implements, opens PR]

[tick 3]
🤖 Agent Heartbeat: 1 Agentic item In Progress (Issue #47). Skipping tick.

[/work-issue completes, moves #47 to Review]

[tick 4]
🤖 Agent Heartbeat: No agentic work in queue. Sleeping.

Design Philosophy

The heartbeat turns the exocortex from a pull system (Dan manually invokes /work-issue) into a push system (issues labeled Agentic + Ready get auto-dispatched). The human remains in control through:

  1. Explicit opt-in — only Agentic-labeled items are eligible
  2. Ready gate — items must be moved to Ready (manually or via Nerve Center)
  3. Prep gate — the heartbeat validates agent-readiness before dispatch
  4. Review gate/work-issue opens a PR, never merges. Dan reviews.
  5. No auto-retry — failures require human review before re-dispatch

This is the "dark factory" pattern applied conservatively: agents do the work, humans control the queue and review the output.