# Tasks

Tasks are the building blocks of missions. Each task has an objective and can depend on other tasks.

## Basic Task

```hcl
task "analyze" {
  objective = "Analyze the data and identify trends"
}
```

## Task with Dependencies

```hcl
task "summarize" {
  objective  = "Summarize the analysis results"
  depends_on = [tasks.analyze]
}
```

## Attributes

| Attribute | Type | Description |
|-----------|------|-------------|
| `objective` | string | What the task should accomplish |
| `depends_on` | list | Tasks that must complete first |
| `agents` | list | Agents available to this task's commander. Optional — when omitted, the task inherits the mission's `agents` list. When set, it fully replaces the mission list for this task. |
| `output` | block | Structured output schema (optional) |
| `router` | block | Conditional routing — LLM picks a branch after task completes (optional) |
| `send_to` | list | Unconditional routing — activate target tasks on completion (optional) |

## Dependencies

Tasks can depend on multiple tasks:

```hcl
task "combine" {
  objective  = "Combine results from both sources"
  depends_on = [tasks.fetch_source_a, tasks.fetch_source_b]
}
```

Dependencies are specified using `tasks.<task_name>`.

## Task-Level Agents

Every agent listed on the mission's `agents = [...]` is automatically available to every task in that mission — you do **not** need to repeat them on each `task` block.

Only set `agents` on a task when you want to **restrict** that task to a subset of the mission's agents (for example, to keep a code-review task away from the general-purpose agent):

```hcl
mission "pipeline" {
  agents = [agents.general, agents.coder]

  task "draft" {
    objective = "Draft the change description"
    # No agents attribute — task can use both `general` and `coder`.
  }

  task "code_review" {
    objective = "Review the code changes"
    agents    = [agents.coder]  # Restrict this task to the coder agent only.
  }
}
```

A task-level `agents` list fully replaces the mission's list for that task — pick exactly the agents you want available to the task's commander.

## Dynamic Objectives

Use variables and inputs in objectives:

```hcl
mission "report" {
  input "topic" {
    type = "string"
  }

  task "research" {
    objective = "Research the topic: ${inputs.topic}"
  }
}
```

## Commander Behavior

Each task gets a commander that:

1. Receives the objective
2. Breaks the task into subtasks using `set_subtasks`
3. Works through each subtask, delegating to agents using `call_agent`
4. Calls `submit_output` if the task has an output schema
5. Calls `task_complete` when all work is done

## Context from Dependencies

When a task completes, the commander provides a `summary` in `task_complete`. This summary is automatically passed as context to all dependent tasks — no extra LLM calls needed.

Commanders can also query structured data from dependencies using `query_task_output`, and ask follow-up questions to previous commanders using `ask_commander` if the summary doesn't have enough detail.

```hcl
task "step_2" {
  objective  = "Continue based on step 1 results"
  depends_on = [tasks.step_1]
}
```

The step_2 commander can query step_1's structured output and ask its commander clarifying questions.

## Structured Output

Tasks can define a structured output schema. When defined, the commander must call `submit_output` with data matching the schema:

```hcl
task "analyze_sales" {
  objective  = "Analyze Q4 sales data"
  depends_on = [tasks.fetch_sales]

  output {
    field "total_revenue" {
      type        = "number"
      description = "Total revenue in USD"
      required    = true
    }
    field "top_product" {
      type        = "string"
      description = "Best-selling product name"
      required    = true
    }
    field "growth_rate" {
      type = "number"
    }
  }
}
```

### Field Types

| Type | Description |
|------|-------------|
| `string` | Text value |
| `number` | Numeric value (float) |
| `integer` | Whole number |
| `boolean` | True/false |
| `list` | Array of values — element type specified via `list(type)` |
| `map` | Key-value pairs — keys are always strings, value type specified via `map(type)` |
| `object` | Structured data with named fields — properties specified via `object({...})` |

### Shorthand Schema Syntax

Instead of `field` blocks you can use a single `output = { ... }` attribute with schema helper functions:

```hcl
task "analyze_sales" {
  objective  = "Analyze Q4 sales data"
  depends_on = [tasks.fetch_sales]

  output = {
    total_revenue = number("Total revenue in USD", true)
    top_product   = string("Best-selling product name", true)
    growth_rate   = number("Growth rate as decimal")
    categories    = list(string, "Product categories found")
    metadata      = map(string, "Additional key-value data")
    breakdown     = object({
      online  = number("Online revenue", true)
      instore = number("In-store revenue", true)
    }, "Revenue breakdown by channel", true)
  }
}
```

Nested types are fully supported — lists can contain objects, objects can contain lists, etc. The commander's system prompt will display the full nested schema so the LLM knows the exact structure expected.

See [Functions](/config/functions) for the complete reference on all helper functions and type references.

Structured output is automatically captured and stored. Downstream tasks can query it using the `query_task_output` tool (see [Internal Tools](/missions/internal-tools)).

## Routing

Tasks can route to other tasks (or missions) after they complete. See [Routing](/missions/routing) for full details, including [when to use `depends_on` vs `router` vs `send_to`](/missions/routing#choosing-between-depends_on-router-and-send_to).

> **Rule of thumb:** prefer `depends_on` and build a static DAG. Reach for `router` only when the LLM must choose a branch, and `send_to` only for fan-out or conditional fan-in to a shared task.

### Conditional Routing

A `router` block lets the LLM choose which branch to activate:

```hcl
task "classify" {
  objective = "Classify the request"
  router {
    route {
      target    = tasks.handle_billing
      condition = "The request is about billing"
    }
    route {
      target    = tasks.handle_support
      condition = "The request is technical support"
    }
  }
}
```

### Unconditional Routing

`send_to` activates target tasks immediately — no LLM decision:

```hcl
task "fetch" {
  objective = "Fetch data"
  send_to   = [tasks.process_a, tasks.process_b]
}
```

> **Note:** `router` and `send_to` are mutually exclusive on a task. Dynamic targets (tasks reachable via `router` or `send_to`) cannot have `depends_on`.

## See Also

- [Routing](/missions/routing) - Conditional and unconditional routing
- [Missions Overview](/missions/overview) - Mission structure
- [Internal Tools](/missions/internal-tools) - Commander and agent tools
