AgentSkillsCN

Task Coordination

借助内存与Task工具,在多个代理之间协调工作,确保上下文清晰、执行并行高效。

SKILL.md
--- frontmatter
description: Coordinate work across multiple agents using memory and Task tool for clean context and parallel execution

Task Coordination Skill

Purpose

Break work into small tasks, execute each in a clean subagent using the Task tool, and use memory as the coordination layer to track progress and enable parallel execution.

Critical Architecture Principles

1. ✅ Clean Context Per Task

Each task runs in a fresh subagent with minimal context:

  • Use Task tool to spawn clean agent
  • Agent loads ONLY what it needs from memory
  • No large context passed in prompts
  • Context window stays small and efficient

2. ✅ Memory as Coordination Layer

Memory is the single source of truth:

  • Task status tracked in memory
  • Results saved to memory immediately
  • Next agent loads from memory, not from previous agent
  • Enables pause/resume of work

3. ✅ Parallel Execution

Run multiple subagents simultaneously:

  • Independent tasks run in parallel
  • Use single message with multiple Task tool calls
  • Each subagent works on different task
  • All save to memory when complete

4. ✅ Verification Loop with Task Tracking

If user stops to correct:

  • Save current task status to memory
  • Fix the issue
  • Load pending tasks from memory
  • Continue with remaining tasks

Task Lifecycle

1. Break Work into Tasks

javascript
// High-level agent breaks work into tasks
const tasks = [
  {
    id: 'task_001',
    name: 'Plan feature structure',
    agent: 'work-planner-agent',
    dependencies: [],
    status: 'pending',
    context_needed: {
      feature_name: 'inventory',
      requirements: 'CRUD for products'
    }
  },
  {
    id: 'task_002',
    name: 'Implement backend API',
    agent: 'dotnet-engineer-agent',
    dependencies: ['task_001'], // Needs planning complete
    status: 'pending',
    context_needed: {
      service: 'inventory',
      load_from_memory: ['feature_plan', 'architectural_decisions']
    }
  },
  {
    id: 'task_003',
    name: 'Implement frontend UI',
    agent: 'ui-engineer-agent',
    dependencies: ['task_001'], // Needs planning, NOT backend (can run parallel)
    status: 'pending',
    context_needed: {
      service: 'inventory',
      load_from_memory: ['feature_plan', 'component_patterns']
    }
  },
  {
    id: 'task_004',
    name: 'QA backend',
    agent: 'qa-backend-engineer',
    dependencies: ['task_002'], // Needs backend complete
    status: 'pending',
    context_needed: {
      service: 'inventory',
      load_from_memory: ['service_api_info']
    }
  },
  {
    id: 'task_005',
    name: 'QA frontend',
    agent: 'qa-frontend-engineer',
    dependencies: ['task_003'], // Needs frontend complete
    status: 'pending',
    context_needed: {
      service: 'inventory',
      load_from_memory: ['service_ui_info', 'docker_ips']
    }
  },
  {
    id: 'task_006',
    name: 'Verify complete',
    agent: 'verification-agent',
    dependencies: ['task_004', 'task_005'], // Needs both QA complete
    status: 'pending',
    context_needed: {
      service: 'inventory',
      load_from_memory: ['qa_results_backend', 'qa_results_frontend']
    }
  }
]

// Save to memory
memory_save_task_list({
  feature: 'inventory_management',
  tasks: tasks,
  created: new Date().toISOString()
})

2. Execute Tasks in Parallel

javascript
// Get tasks ready to run (dependencies met)
const readyTasks = tasks.filter(t =>
  t.status === 'pending' &&
  t.dependencies.every(dep => isComplete(dep))
)

// Launch all ready tasks in PARALLEL using single message with multiple Task calls
// IMPORTANT: Use single message to launch all parallel tasks

if (readyTasks.length > 0) {
  console.log(`Launching ${readyTasks.length} tasks in parallel:`)
  readyTasks.forEach(task => {
    console.log(`- ${task.name} (${task.agent})`)
  })

  // Update status before launch
  readyTasks.forEach(task => {
    memory_update_task(task.id, {
      status: 'running',
      started: new Date().toISOString()
    })
  })

  // Launch ALL in single message (see example below)
}

Example Parallel Launch:

code
I'm launching 2 tasks in parallel:
- Task 002: Implement backend API (dotnet-engineer-agent)
- Task 003: Implement frontend UI (ui-engineer-agent)

[Use Task tool twice in SAME MESSAGE]

Task 1:
Use the dotnet-engineer-agent to:
1. Load feature plan from memory: memory_get_feature('inventory_management')
2. Load architectural decisions from memory: memory_get_decisions()
3. Implement inventory API with CRUD endpoints
4. Save API details to memory when complete
5. Mark task_002 as complete in memory

Context to load from memory:
- Feature plan: inventory_management
- Service: inventory
- Load only what's needed for backend

Task 2:
Use the ui-engineer-agent to:
1. Load feature plan from memory: memory_get_feature('inventory_management')
2. Load component patterns from memory: memory_get_component_patterns()
3. Implement inventory UI with CRUD interface
4. Save UI details to memory when complete
5. Mark task_003 as complete in memory

Context to load from memory:
- Feature plan: inventory_management
- Service: inventory
- Load only what's needed for frontend

3. Each Subagent Works with Minimal Context

javascript
// Inside dotnet-engineer-agent subagent (clean context)

// Step 1: Load ONLY what I need from memory
const featurePlan = memory_get_feature('inventory_management')
const decisions = memory_get_decisions()
const existingService = memory_get_service('inventory')

// Step 2: Do the work
// ... implement API ...

// Step 3: Save results to memory
memory_save_service({
  name: 'inventory',
  api: {
    endpoints: [...],
    database: 'stylemate_inventory',
    // ... other details
  }
})

// Step 4: Mark task complete
memory_update_task('task_002', {
  status: 'completed',
  completed: new Date().toISOString(),
  results: {
    endpoints_created: 5,
    tests_passing: true
  }
})

// Return summary (not full details, those are in memory)
return "✅ Task 002 complete: Inventory API created with 5 endpoints. Details saved to memory."

4. Verification Loop with Pause/Resume

javascript
// User interrupts: "Wait, the database schema needs a 'sku' field"

// Current state in memory:
// task_002: completed ✅
// task_003: running 🔄
// task_004: pending ⏸️
// task_005: pending ⏸️
// task_006: pending ⏸️

// Handle interruption:
console.log('User correction requested. Current state:')
const tasks = memory_get_task_list('inventory_management')
tasks.forEach(t => console.log(`${t.id}: ${t.status}`))

// Fix the issue
console.log('Fixing database schema...')
// ... add 'sku' field ...
memory_update_service('inventory', {
  api: {
    database_schema: {
      products: {
        columns: [..., 'sku: string']
      }
    }
  }
})

// Mark task as needs re-test
memory_update_task('task_002', {
  status: 'needs_retest',
  correction: 'Added sku field to schema'
})

// Continue with pending tasks
const pendingTasks = tasks.filter(t => t.status === 'pending')
console.log(`Continuing with ${pendingTasks.length} pending tasks...`)
// ... launch next batch ...

Task Tracking Schema

Task Schema

typescript
interface Task {
  id: string                    // task_001, task_002, etc.
  name: string                  // Human-readable task name
  agent: string                 // Which agent executes this
  dependencies: string[]        // Task IDs that must complete first
  status: 'pending' | 'running' | 'completed' | 'failed' | 'needs_retest'
  context_needed: {
    [key: string]: any         // Minimal context needed
    load_from_memory: string[] // What to load from memory
  }
  created: string               // ISO timestamp
  started?: string              // When execution started
  completed?: string            // When execution finished
  results?: any                 // Summary results (details in memory)
  error?: string                // Error if failed
  correction?: string           // If needs_retest, what was fixed
}

interface TaskList {
  feature: string               // Feature name
  tasks: Task[]                 // All tasks
  created: string               // When task list created
  status: 'in_progress' | 'completed' | 'paused'
  current_phase?: string        // planning, development, qa, verification
}

Memory Operations for Task Coordination

Save Task List

javascript
memory_save_task_list({
  feature: 'inventory_management',
  tasks: [...],
  status: 'in_progress',
  current_phase: 'planning'
})

Update Task Status

javascript
memory_update_task(task_id, {
  status: 'completed',
  completed: new Date().toISOString(),
  results: { summary: '...' }
})

Get Tasks Ready to Run

javascript
const tasks = memory_get_task_list('inventory_management')
const ready = tasks.tasks.filter(t =>
  t.status === 'pending' &&
  t.dependencies.every(dep =>
    tasks.tasks.find(d => d.id === dep)?.status === 'completed'
  )
)

Get Pending Tasks

javascript
const pending = memory_get_tasks_by_status('inventory_management', 'pending')
const running = memory_get_tasks_by_status('inventory_management', 'running')
const failed = memory_get_tasks_by_status('inventory_management', 'failed')

Orchestration Pattern

software-engineer-agent as Orchestrator

javascript
// Phase 1: Create task plan
const tasks = createTaskPlan(userRequest)
memory_save_task_list({ feature: featureName, tasks })

// Phase 2: Execute tasks in waves (respecting dependencies)
while (hasIncompleteTasks()) {
  // Get tasks ready to run
  const ready = getReadyTasks()

  if (ready.length === 0) {
    // Check for failures
    const failed = getFailedTasks()
    if (failed.length > 0) {
      console.log('Tasks failed:', failed)
      break
    }
    // All done!
    break
  }

  // Launch parallel tasks in SINGLE MESSAGE
  console.log(`Launching ${ready.length} tasks in parallel...`)

  // IMPORTANT: Use single message with multiple Task tool calls
  ready.forEach(task => {
    // Mark as running
    memory_update_task(task.id, { status: 'running' })
  })

  // Use Task tool for each (in same message)
  // ... Task tool calls ...

  // Wait for all to complete (they update memory)

  // Check results
  ready.forEach(task => {
    const updated = memory_get_task(task.id)
    if (updated.status === 'completed') {
      console.log(`✅ ${task.name} completed`)
    } else if (updated.status === 'failed') {
      console.log(`❌ ${task.name} failed: ${updated.error}`)
    }
  })
}

// Phase 3: Final verification
const allTasks = memory_get_task_list(featureName)
const completed = allTasks.tasks.filter(t => t.status === 'completed')
const failed = allTasks.tasks.filter(t => t.status === 'failed')

console.log(`Summary: ${completed.length}/${allTasks.tasks.length} tasks completed`)

if (failed.length === 0) {
  memory_update_task_list(featureName, { status: 'completed' })
  console.log('✅ All tasks completed successfully!')
} else {
  console.log('❌ Some tasks failed:', failed.map(t => t.name))
}

Benefits of This Architecture

✅ Small Context Windows

  • Each subagent loads only what it needs
  • No large prompts passed around
  • Context stays small and efficient
  • Better performance, less token usage

✅ Parallel Execution

  • Independent tasks run simultaneously
  • Faster completion
  • Better resource utilization
  • Scalable to many tasks

✅ Pause/Resume Capability

  • User can stop to correct
  • Work state preserved in memory
  • Other tasks continue or pause cleanly
  • No lost context

✅ Clean Separation

  • Each subagent is independent
  • No context pollution
  • Easier debugging
  • Clear responsibility

✅ Memory as Single Source of Truth

  • All state in memory
  • Agents coordinate through memory
  • No context passing between agents
  • Enables distributed execution

Example: Complete Feature with Parallel Tasks

javascript
// User request: "Add inventory management feature"

// software-engineer-agent:

// Step 1: Create task plan
const tasks = [
  { id: 'task_001', name: 'Plan feature', agent: 'work-planner-agent', dependencies: [] },
  { id: 'task_002', name: 'Backend API', agent: 'dotnet-engineer-agent', dependencies: ['task_001'] },
  { id: 'task_003', name: 'Frontend UI', agent: 'ui-engineer-agent', dependencies: ['task_001'] },
  { id: 'task_004', name: 'QA Backend', agent: 'qa-backend-engineer', dependencies: ['task_002'] },
  { id: 'task_005', name: 'QA Frontend', agent: 'qa-frontend-engineer', dependencies: ['task_003'] },
  { id: 'task_006', name: 'Verify', agent: 'verification-agent', dependencies: ['task_004', 'task_005'] }
]
memory_save_task_list({ feature: 'inventory', tasks })

// Step 2: Wave 1 - Planning (1 task)
// Launch: work-planner-agent via Task tool
// Planner loads decisions from memory, saves plan to memory, marks task_001 complete

// Step 3: Wave 2 - Development (2 tasks in PARALLEL)
// Launch: dotnet-engineer-agent + ui-engineer-agent in SINGLE MESSAGE
// Backend: loads plan from memory, implements API, saves to memory, marks task_002 complete
// Frontend: loads plan from memory, implements UI, saves to memory, marks task_003 complete

// Step 4: Wave 3 - QA (2 tasks in PARALLEL)
// Launch: qa-backend-engineer + qa-frontend-engineer in SINGLE MESSAGE
// Backend QA: loads API info from memory, tests, saves results, marks task_004 complete
// Frontend QA: loads UI info + Docker IPs from memory, tests, saves results, marks task_005 complete

// Step 5: Wave 4 - Verification (1 task)
// Launch: verification-agent via Task tool
// Verification: loads both QA results from memory, verifies, marks task_006 complete

// Done! All tasks completed with minimal context and maximum parallelism

User Correction During Execution

javascript
// Scenario: User stops after task_003 completes

// Current state:
// task_001: completed ✅
// task_002: completed ✅
// task_003: completed ✅
// task_004: running 🔄
// task_005: running 🔄
// task_006: pending ⏸️

// User: "Wait, the frontend needs a barcode scanner component"

// software-engineer-agent:
console.log('User correction requested.')
const taskList = memory_get_task_list('inventory')

console.log('Current task status:')
taskList.tasks.forEach(t => console.log(`${t.id}: ${t.status}`))

// Mark frontend task for correction
memory_update_task('task_003', {
  status: 'needs_correction',
  correction: 'Add barcode scanner component'
})

// QA tasks will need re-run
memory_update_task('task_005', {
  status: 'pending', // Reset to pending
  note: 'Waiting for frontend correction'
})

// Add barcode scanner
console.log('Adding barcode scanner component...')
// Launch ui-engineer-agent again via Task tool with correction
// UI engineer loads existing UI from memory, adds scanner, saves update

// Re-run frontend QA
console.log('Re-running frontend QA...')
// Launch qa-frontend-engineer via Task tool
// QA loads updated UI from memory, tests scanner, saves results

// Continue with verification
console.log('Continuing with verification...')
// Launch verification-agent via Task tool
// Verification loads all QA results from memory, verifies complete

Implementation Checklist

  • Task schema defined
  • Memory operations for tasks defined
  • Parallel execution pattern defined
  • Verification loop with pause/resume defined
  • Implement in software-engineer-agent
  • Update all agents to save/mark tasks
  • Test parallel execution
  • Test pause/resume capability

This skill enables efficient, parallel, pause-able work execution with minimal context per agent.