beginnercoretask-looptask-decompositiontask-queueexecution

Task Loop

Task-oriented iteration, decomposition patterns, and how coding agents manage task queues.

What Is a Task Loop?

A task loop is a purpose-scoped iteration cycle designed to complete a single, well-defined unit of work within an agent system. While the Agent Loop is the general execution engine (Perceive, Reason, Plan, Act, Observe), a task loop applies that engine to one specific objective with concrete success criteria.

Think of the relationship this way:

  • Agent Loop = the engine that runs on every turn (model reasons, calls tools, observes results)
  • Task Loop = a specific journey the engine takes to accomplish one goal

A single agent session may process multiple task loops sequentially or in parallel. Each task loop has its own lifecycle, its own state, and its own completion criteria.

Agent Loop vs Task Loop

AspectAgent LoopTask Loop
ScopeSession-level; spans the entire agent sessionTask-level; scoped to a single unit of work
LifecycleLives for the duration of the agent sessionStarts when a task begins, ends when the task completes
StateMaintains global session stateMaintains task-specific state
GoalThe overall objective of the agent sessionA specific sub-goal contributing to the overall objective
AutonomyDecides what to do next based on reasoningFollows a defined plan with clear success criteria
CompletionEnds when the session concludesEnds when the specific task criteria are met
NestingContains multiple task loopsCan contain sub-task loops (hierarchical)

How Leading Coding Agents Manage Tasks

Claude Code (github.com/anthropics/claude-code)

Claude Code handles tasks through several concrete mechanisms:

  • The /goal command runs the agent in a loop until a verifiable stopping condition is met. After every turn, a separate, smaller model checks whether the goal has actually been achieved -- so the model that wrote the code is not the one grading it.
  • Sub-agents can be spawned to handle individual tasks in isolated git worktrees, each with their own context and completion criteria.
  • The CLAUDE.md file persists project knowledge across sessions so that each new task loop does not start from zero. A typical CLAUDE.md includes project structure, coding conventions, and test commands.
# Example: Claude Code /goal with verifiable stopping condition
claude "/goal 'All TypeScript tests pass with zero errors'"

A practical production pattern documented by practitioners: schedule Claude Code to triage overnight work and write findings to persistent files.

# Claude Code: run a recurring triage prompt every weekday at 9am
# /loop fires the agent, triages CI failures and open issues,
# then writes results to TODO.md -- a task loop without human intervention
/loop "Read yesterday's CI failures and open issues, write findings
to TODO.md, and draft fixes for anything labeled quick-win"
--schedule "0 9 * * 1-5"

OpenAI Codex (github.com/openai/codex)

OpenAI Codex approaches task loops through its Automations system:

  • Scheduled automations fire on a cadence (cron), surface work from CI failures or open issues, and triage findings into an inbox.
  • The /goal command (added in Codex CLI 0.128.0 in April 2026) works identically to Claude Code's version: run until a condition you defined is verifiably true.
  • Sub-agents defined as TOML files in .codex/agents/ handle specialized task roles: one explores, one implements, one verifies.

Aider (github.com/paul-gauthier/aider)

Aider, a Git-first CLI AI coding tool with 30K+ GitHub stars, implements task loops differently. It uses a git-commit-based conversation history, where each coding action is recorded as a commit. The task loop is implicit: Aider reads the git diff, reasons about what to change, edits files, commits, and repeats.

# Aider task loop: fix a specific issue, auto-committing each change
aider --model claude-3.5-sonnet "Fix the authentication bug in src/auth.ts, ensure all tests pass"

The key difference: Aider's task state is the git log itself. Each commit represents one iteration of the loop, providing full reproducibility.

Windsurf / Cascade (windsurf.ai)

Windsurf's Cascade agent provides multi-step execution with an implicit task loop. It maintains a running context of file changes and can handle multi-file edits within a single task, similar to Claude Code's approach but with a more visual IDE integration.

  1. Pick the next unfinished task from a list (prd.json or equivalent)
  2. Build a prompt with the task, relevant context, and any persistent notes
  3. Call the agent (Claude Code, Codex, Aider, etc.)
  4. Run tests or other checks
  5. Append what happened to progress.txt
  6. Update the task list (done, failed, blocked)
  7. Go back to step 1

The key insight: each iteration starts fresh and reads enough state from disk to keep going. The agent itself is amnesiac, but the filesystem is not.

Task Decomposition Patterns

Breaking complex goals into well-defined tasks is the foundational skill of loop engineering. Andrew Ng's DeepLearning.AI course on agentic AI defines decomposition as "the strategic process of breaking a high-level, complex user goal into a sequence of smaller, manageable, and executable sub-tasks."

Sequential Decomposition

Tasks that must be completed in order:

[Setup Environment] -> [Install Dependencies] -> [Run Tests] -> [Fix Failures] -> [Verify]

Each task cannot start until the previous one succeeds. This pattern is common in CI/CD pipelines where each stage depends on the prior stage's output. In OpenHands (github.com/All-Hands-AI/OpenHands), the autonomous coding agent platform, sequential decomposition is the default: the agent must resolve environment setup before attempting code modifications.

Parallel Decomposition

Independent tasks that can run simultaneously:

[Fix auth tests]  --+
                     +-> [Run full test suite]
[Fix API tests]   --+

Both tasks can run in parallel because they operate on different areas of the codebase. Claude Code's worktree isolation and Cursor 2.0's parallel agents (up to 8) make this practical: each agent gets its own checkout on its own branch. MetaGPT (github.com/geekan/MetaGPT, 45K+ stars) implements this at the framework level with role-based agents that can execute in parallel on decomposed tasks.

Hierarchical Decomposition

Complex tasks broken into sub-tasks, each with their own task loop:

[Migrate API to v2]
|-- [Update endpoint paths]
|   |-- [Update /users endpoints]
|   +-- [Update /posts endpoints]
|-- [Update request/response schemas]
+-- [Update client integrations]

Each leaf task runs its own task loop, and the parent task coordinates their completion. SWE-Agent (github.com/princeton-nlp/SWE-Agent, 15K+ stars) implements this pattern for resolving GitHub issues: it decomposes a bug report into investigation, patch, and verification sub-tasks.

Dynamic Decomposition

Tasks discovered during execution:

[Research topic] -> discover subtopics -> [Research subtopic 1] -> [Research subtopic 2] -> ...

The loop discovers new tasks as it works, adding them to the task queue dynamically. CrewAI (github.com/crewAIInc/crewAI) supports this through its dynamic task creation, where agents can generate new tasks based on intermediate findings. LangGraph (github.com/langchain-ai/langgraph) implements conditional branching that enables runtime task discovery.

Defining a Good Task

A well-defined task in a loop engineering system has four properties, identified by practitioners across Claude Code, Codex, Aider, and the broader agentic AI community.

1. Clear Objective

The task must have a specific, measurable goal. Vague tasks lead to loops that never converge.

Vague:    "Make the code better"
Good:     "Refactor the authentication module to use JWT tokens
           instead of session cookies, ensuring all existing
           tests pass"

2. Testable Success Criteria

The task must define what "done" looks like. This is the acceptance criteria the evaluator checks:

  • Functional criteria: "All tests pass"
  • Quality criteria: "TypeScript compiles without errors"
  • Behavioral criteria: "Response time under 200ms"
  • Completeness criteria: "All endpoints migrated"

3. Bounded Scope

The task should be achievable within a reasonable number of loop iterations:

Too large:  "Rebuild the entire backend"
Better:     "Add pagination to the /api/users endpoint"

4. Available Resources

The task should specify what tools and context are available:

  • Which files can be read or modified
  • Which APIs can be called
  • Which tests can be run
  • What constraints exist (e.g., "do not modify the database schema")

In practice, a .cursorrules file or CLAUDE.md file encodes these constraints, ensuring every agent session operates within defined boundaries.

Task Queue Management

In systems that process multiple task loops, a task queue manages the workflow. Both Claude Code and Codex implement queue-like behavior through their automation and scheduling systems. OpenHands and Devin (github.com/cognition-labs/Devin) also implement internal task queues for managing multi-step autonomous work.

Here is a simplified task queue implementation:

from dataclasses import dataclass, field
from typing import Optional
import json

@dataclass
class Task:
    id: str
    description: str
    acceptance_criteria: list[str]
    status: str = "pending"  # pending -> running -> completed | failed
    iterations: int = 0
    max_retries: int = 3
    error_history: list[str] = field(default_factory=list)

class TaskQueue:
    def __init__(self, tasks_file: str = "tasks.json"):
        self.tasks_file = tasks_file
        self.tasks: list[Task] = []
        self._load()

    def _load(self):
        """Load tasks from persistent storage."""
        try:
            with open(self.tasks_file) as f:
                data = json.load(f)
                self.tasks = [Task(**t) for t in data]
        except FileNotFoundError:
            self.tasks = []

    def save(self):
        """Persist current task state to disk."""
        with open(self.tasks_file, "w") as f:
            json.dump(
                [vars(t) for t in self.tasks],
                f,
                indent=2
            )

    def next_pending(self) -> Optional[Task]:
        """Get the next task that hasn't been completed."""
        for task in self.tasks:
            if task.status == "pending":
                return task
            elif task.status == "failed" and task.iterations < task.max_retries:
                return task
        return None

    def mark_completed(self, task_id: str):
        for t in self.tasks:
            if t.id == task_id:
                t.status = "completed"
                self.save()

    def mark_failed(self, task_id: str, error: str):
        for t in self.tasks:
            if t.id == task_id:
                t.status = "failed"
                t.iterations += 1
                t.error_history.append(error)
                self.save()

The key principle: task state lives on disk, not in the agent's context window. This is what makes the Ralph loop pattern work across multiple agent sessions.

Failure Modes in Task Loops

  1. Exception handling failure: An unhandled error crashes the loop without updating task state, leaving the system in an unknown state. Mitigate with try/catch wrappers that always persist state before exiting.

  2. Blind retries: The agent repeats the same failing approach without learning from previous errors. Mitigate by appending error history to the prompt on each retry (as the error_history field in the queue implementation above demonstrates).

  3. Context overflow: Accumulated context from failed iterations exceeds the model's window. Mitigate by following context engineering principles -- compress old iterations, replace full logs with summaries, and use the InfoQ principles of retention and merging.

  4. Infinite loops: The task criteria are never satisfied, and the loop runs indefinitely. Mitigate with hard iteration limits (the max_retries field) and timeout guards.

Real-World Task Loop Examples

// prd.json - task definition file
[
  {
    "id": "spec-1",
    "title": "User Authentication Flow",
    "description": "Write a detailed product spec for OAuth2 login flow",
    "status": "pending",
    "acceptance_criteria": ["Covers happy path", "Covers error cases", "Includes API contracts"]
  },
  {
    "id": "spec-2",
    "title": "Payment Integration",
    "description": "Write a detailed product spec for Stripe payment integration",
    "status": "pending",
    "acceptance_criteria": ["Covers webhook handling", "Includes retry logic", "Documents error codes"]
  }
]

LangChain Verification Loop for Documentation

LangChain's internal docs agent at github.com/langchain-ai/langchain wraps task loops in a verification cycle:

  1. The agent receives a request for a documentation improvement
  2. The model drafts changes and opens a PR
  3. A grader runs tests, checks that links resolve, and verifies CI passes
  4. If the grader finds issues, the output goes back with feedback
  5. The agent retries until the grader passes

This is a task loop with built-in auto-correction. LangGraph (github.com/langchain-ai/langgraph) implements the orchestration for this pattern using graph-based agent workflows with explicit state transitions.

Cline with MCP Protocol for Extended Tool Access

Cline (github.com/cline/cline), a VS Code plugin supporting the MCP protocol, implements task loops by giving the agent access to external tools through MCP servers. A task loop in Cline might: read a GitHub issue via MCP, create a branch, implement the fix, run tests, and open a PR -- all within a single task loop iteration. The MCP protocol (used by both Claude Code and Cline) standardizes how agents discover and invoke tools, making task loops more portable across agent platforms.

Best Practices

Next Steps

Prerequisites