# Task Cards

Small self-contained work items derived from a specification, each carrying enough context for an agent or person to execute independently.

**Rests on:** Product Requirements Documents

**Leads to:** Spec-to-Code Pipeline

*Software Engineering · Spec-Driven Development*


## Why learn this

Task cards are the next move in spec-driven development: the unit of delegated work. Once you master task cards, you can break a specification into small, self-contained pieces that an AI agent or a colleague can execute independently, in parallel, and you can review each piece as it comes back. This unlocks the rest of the spec-driven workflow: you will be able to write acceptance criteria that define 'done' for each card, set up review gates to check the work, and run a spec-to-code pipeline where an agent generates code from your cards. Without task cards, launching an AI agent at a specification produces a jumbled mess with no way to check progress; with them, you control the whole process.


## The intuition

Suppose you have to build a small website for a local shop: a product page, a shopping cart, and a checkout form. A specification for that might run to a few pages. You cannot hand that whole document to a colleague or an AI agent and say 'build this' — it is too much, and many decisions are left open. Instead, you break the specification into small work items, each of which says exactly what to do, what information is already available, and what will count as finished. Each work item is small enough that a person or an agent can finish it in a sitting, and it is self-contained: the person does not need to read the whole specification to know what to do. For example, one item might be 'Add an 'add to cart' button to the product page. When clicked, call the addToCart function (already stubbed in cart.js) with the product ID, and show a small message saying the item is in the cart. Done when the button appears and the message shows on click.' That is a task card. Because each card carries its own context, several people or agents can work on different cards at the same time without interfering with each other. And because each card is small, reviewing the result takes a few minutes, not a whole day. Task cards turn a big vague job into a list of small, checkable jobs.


## An analogy

Think of a wedding planner. The bride gives her a thick binder: colors, venue, guest list, menu, timeline. The planner cannot 'plan the wedding' in one go; she must break it into dozens of small tasks: book the caterer, order the flowers, send invitations, confirm the band, arrange seating. For each task, the planner writes an index card: what to do (call three florists and get quotes, then book one within budget), what information is needed (guest count, color scheme, budget), and what 'done' means (a signed contract with a florist). She can hand a card to an assistant or a vendor, and they can execute it without asking her for more details. The cards are self-contained: the florist does not need to know the entire wedding plan to arrange flowers. They can work in parallel: while the florist handles flowers, the caterer handles food, and the planner reviews each card when it comes back. The analogy breaks down where a task card is more precise than a wedding index card. In software, 'done' is testable, not just agreed upon. The card must specify acceptance criteria — conditions that can be checked automatically or manually to know the card is complete. Also, a wedding card might leave room for taste; a software card should leave as little as possible, because an AI agent has no taste and needs explicit instructions. A true task card is not a broad goal like 'improve the user experience' but a narrow, verifiable action like 'add a tooltip to the submit button that appears on hover, with text: This will send your request'.


## Definition

A task card is a small, self-contained work item derived from a specification, carrying enough context (what to do, what inputs are available, what 'done' means) for an agent or person to execute it independently, and sized so that its output is a reviewable unit of change.


## How it connects

You have not learned any other concepts yet, so this page stands alone. But your library will soon hold notes on Acceptance Criteria, Engineering Intent Documents, Product Requirements Documents, Requirements Traceability, Review Gates, Spec Drift, and the Spec-to-Code Pipeline. Task cards sit right in the middle of all of those. Each card should be derived from a requirement (from a product requirements document), should carry acceptance criteria (from the acceptance criteria notes), and should be reviewed at a gate (from the review gates notes). When the code drifts from the specification, the problem often shows up as a task card that was badly written or missing. When you build a spec-to-code pipeline, the task cards are what you feed to the AI agent. So every concept you learn later will assume you know what a task card is.


## The mathematics

This concept uses no mathematics beyond arithmetic — and barely that. But there is one mathematical idea hiding inside it: the idea of a decomposition. When you break a whole into pieces, you are doing something mathematicians call 'partitioning': dividing a set into non-overlapping parts that together cover the whole. For task cards, you are partitioning a specification into tasks. The only arithmetic involved is counting: how many tasks, how many are done, what fraction is complete. You do not need algebra, calculus, or probability. But the mental operation — carving a large specification into small, independent chunks — is a mathematical habit of mind: you want each card to be a subset of the spec, such that no two cards overlap in the code they touch (if they did, they could not run in parallel), and the union of all cards equals the whole spec (so nothing is left out). This is the same logic as an arithmetic puzzle: if you have 12 items to distribute into 3 boxes, each box can hold 4; but if you put 5 in the first, you have only 7 left for the other two. Similarly, if one task card is too large (covers too much of the spec), the rest become unbalanced, and the parallel execution stalls. The arithmetic of task cards is simply the arithmetic of balance: keep each card small, and the total progress adds up correctly.

Let T_total be the total time to finish all cards. Let T1, T2, ..., Tn be the time each agent spends (if cards are assigned to agents). When cards are independent and run in parallel, T_total = max(T1, T2, ..., Tn). When cards run one after another, T_total = T1 + T2 + ... + Tn. All symbols are just names for numbers you can count or measure; max means 'the largest of these numbers'.


## A worked example

```
You have a small specification with three requirements: R1 (add a product to cart), R2 (remove a product from cart), R3 (show the cart total). You decide to make one task card per requirement. You have two AI agents. Agent A takes 2 hours per card, Agent B takes 3 hours per card. You want to track progress and decide how to assign the cards so that the work finishes as early as possible.

Step 1: Number of cards = 3   # Each requirement becomes one card.
Step 2: Fraction of cards done after 1 card is complete = 1 ÷ 3 = 0.33 = 33%   # Simple division to express progress.
Step 3: If Agent A does R1 and R3 (2+2 = 4 hours) and Agent B does R2 (3 hours), the total time is max(4, 3) = 4 hours   # When work is done in parallel, the total time is the longest agent's time, not the sum of all times.
Step 4: If one agent did all three cards one after another, total time = 2 + 2 + 2 = 6 hours   # Serial execution is slower than parallel execution when cards are independent.

Result: Task cards enable parallel work, reducing the project time from 6 hours (serial) to 4 hours (parallel) in this example. The key arithmetic operation is max: the total time is the largest of the individual durations, not the sum.
```


## From scratch, in Python

```python
# A task card is just a structured piece of data. In Python we can use a dictionary.
# A dictionary is a way to store information by a name (a key) instead of by position.
# For example, {"fruit": "apple", "count": 3} stores the value "apple" under the key "fruit".

# Let's make one task card as a dictionary.
card1 = {
    "id": "C1",
    "title": "Add product to cart",
    "description": "Add an 'Add to cart' button to the product page. When clicked, call addToCart(product_id) and show a confirmation message.",
    "acceptance_criteria": [
        "Button appears on the product page",
        "Clicking the button calls addToCart with the correct product id",
        "A confirmation message appears after the click"
    ],
    "depends_on": [],  # empty list: this card has no dependencies
    "status": "pending"
}

# Now let's make two more cards for other parts of the spec.
card2 = {
    "id": "C2",
    "title": "Remove product from cart",
    "description": "Add a 'Remove' button next to each item in the cart. Clicking it removes the item and updates the total.",
    "acceptance_criteria": [
        "A remove button appears for each cart item",
        "Clicking it removes the item from the cart",
        "The cart total updates"
    ],
    "depends_on": ["C1"],  # this needs the cart to exist first
    "status": "pending"
}

card3 = {
    "id": "C3",
    "title": "Show cart total",
    "description": "Display the total cost of all items in the cart at the bottom of the cart page.",
    "acceptance_criteria": [
        "The total is shown on the cart page",
        "The total updates when items are added or removed"
    ],
    "depends_on": ["C1", "C2"],
    "status": "pending"
}

# A list is an ordered collection of things. Put all cards in one list.
all_cards = [card1, card2, card3]

# We can write a function (a reusable block of code) to check if a card is ready to start.
# A card is ready if all the cards it depends on are done.
def is_ready(card, all_cards):
    # Loop through the dependencies of this card.
    for dep_id in card["depends_on"]:
        # Find the card with that id in all_cards.
        for other in all_cards:
            if other["id"] == dep_id:
                if other["status"] != "done":
                    return False  # not ready yet
    return True

# We can also write a function to mark a card as done.
def mark_done(card):
    card["status"] = "done"

# And a function to calculate progress as a percentage.
def progress(cards):
    done_count = 0
    for card in cards:
        if card["status"] == "done":
            done_count = done_count + 1
    return (done_count / len(cards)) * 100  # multiply by 100 to get a percentage

# Let's see it in action.
print("Is C1 ready?", is_ready(card1, all_cards))  # True, no dependencies
print("Is C2 ready?", is_ready(card2, all_cards))  # False, depends on C1 which is not done
mark_done(card1)
print("Is C2 ready now?", is_ready(card2, all_cards))  # True, because C1 is done
print("Progress after C1 done:", progress(all_cards), "%")  # 33.333...%

# The output shows how task cards let you track work and decide when to start each piece.
```


## The same thing, with a framework

```python
In real project management, you would not use raw Python dictionaries. You would use a tool like Jira, Linear, or a simple Kanban board. Those tools store exactly the same information: an ID, a title, a description, acceptance criteria, dependencies, and a status. When you use an AI coding agent like GitHub Copilot Workspace or Claude Code, you feed it a task card as a prompt. There is no special machine-learning library for task cards because they are a project-management pattern, not a mathematical algorithm. What matters is the structure: a card must carry enough context for the agent or human to act without asking for more.
```


## What the code does

The code builds three task cards as dictionaries — Python's way of storing named values. The dictionary keys are id, title, description, acceptance_criteria, depends_on, and status. The acceptance_criteria is a list of strings; a list is an ordered collection. The depends_on is also a list, showing which cards must be done first. The is_ready function uses a nested loop: it loops over the card's dependencies, and for each one it searches the all_cards list to find that card and check its status. If any dependency is not done, the function returns False. The mark_done function simply changes the status. The progress function counts done cards using a loop and a counter, then divides by the total number of cards and multiplies by 100 to get a percentage. The example at the end shows how to check readiness, mark a card done, and print progress.


## Common misconceptions

**A task card is a one-line to-do item** — A task card is like a sticky note that says 'add to cart' and that is enough.

A one-line to-do lacks context: which file, which function, what 'done' looks like. An AI agent or a new developer cannot execute it without asking questions, which defeats the point of self-contained work. In fact: A task card carries enough context — description, acceptance criteria, dependencies, and references — for someone to execute it without referring back to the spec or asking for clarification.

**Task cards are only for AI agents** — I don't use AI agents, so task cards are not for me.

Task cards are a human project-management technique that predates AI. They are used in Kanban, agile, and any project with parallel work. AI agents simply make the benefit more obvious because they cannot fill in gaps. In fact: Task cards work for humans and agents alike; the self-containment principle applies to both.

**The smaller the card, the better** — A task card must be as small as physically possible.

If a card is too small, you spend more time creating and reviewing cards than doing the work. The sweet spot is a unit that is small enough to review in one pass but large enough to be meaningful. In fact: Size each card to match a reviewable unit of change: a focused change that can be reviewed and, if necessary, reverted without affecting unrelated work.

**Cards can overlap as long as they are written clearly** — It is fine if two cards touch the same file, as long as their descriptions are clear.

Overlap causes merge conflicts and breaks parallel execution. If two agents edit the same function, they cannot work independently. In fact: Design cards so they are independent in the code they touch — that is what allows parallel execution.

**A card's title is enough to communicate the work** — If I write 'Fix login bug', any developer knows what to do.

A title like that is ambiguous: which login bug? What is the expected behaviour? What code is involved? Without context, the executor must guess or investigate, which wastes time and leads to wrong implementations. In fact: The card must include a description and acceptance criteria that remove ambiguity.


## In short

A task card is the smallest unit of delegated work in spec-driven development. It is self-contained (carries full context), sized for review, and independent of other cards so that work can proceed in parallel. Each card should have a clear description and acceptance criteria, and should link back to a requirement for traceability. Training your AI agent to execute task cards, and reviewing each one, is how you turn a specification into code without losing control.


## Where this is used

Task cards are the backbone of any agentic AI workflow that plans and executes steps. In large language models (LLMs), task cards appear when a model is used as a coding agent: the agent breaks a user's request into a sequence of cards, then executes them one by one, checking each against its acceptance criteria. For example, GitHub Copilot Workspace or Claude Code takes a specification, generates a plan — and that plan is literally a list of task cards. In small language models running on a phone or laptop, task cards are less common because those models are usually single-shot; but even a lightweight agent might use a single card at a time. In retrieval-augmented generation (RAG), task cards are used to structure the retrieval plan: one card per question to answer, each with its own retrieval query and expected answer format. In agentic systems that call tools, task cards are the decomposition of a high-level goal into tool calls: 'card 1: search for flights', 'card 2: book the cheapest', and so on. In ordinary applied machine learning, task cards are used in MLOps: each data-cleaning step, model-training job, or evaluation is a card with clear inputs and outputs. A developer writing software with task cards reaches for a tool like Linear or a simple Kanban board, and writes a card with the fields shown in the code. When done badly — when cards are too large, or lack acceptance criteria, or overlap in the code they touch — parallel agents collide, reviews become impossible, and the project stalls. The card's size must match a reviewable unit of change: too big and the review is a guessing game; too small and the overhead of creating and reviewing cards outweighs the benefit.


---

Read this on the web: https://basavapurushottam.com/learn-ai/task-cards
