# Tasks

> For the complete documentation index, see [llms.txt](https://docs.lertha.com/llms.txt).
> Any documentation page is available as raw Markdown by appending `.md` to its URL.

> A task is one unit of work with a side effect. The orchestrator retries it, times it out and de-duplicates it by id.

A **task** is one unit of work: send the SMS, call the model, query the bank. It is a
`suspend fun`, it may do anything, and the orchestrator takes care of retrying it, timing it out
and refusing to run it twice under one id.

```kotlin
data class GreetingInput(val greeting: String, val name: String)
data class Greeting(val text: String)

object GreetingTask : TaskHandler<GreetingInput, Greeting> {
    override val type = taskType<GreetingInput, Greeting>("ComposeGreeting")

    override suspend fun handle(input: GreetingInput, ctx: TaskContext): Greeting =
        Greeting("${input.greeting}, ${input.name}!")
}
```

A task is started from application code, not only from inside a flow:

```kotlin
val greeting = orchestrator.run(GreetingTask.type, GreetingInput("Hello", "Ada"), options)
```

## Contract: idempotent

Every engine retries. A retry means "run this again", not "run this once more if it didn't run".
A handler that cannot be idempotent says so by throwing `NonRetryableTaskError` on the second
attempt; `ctx.attempt` tells it which attempt it is on.

## Heartbeats

`ctx.heartbeat()` tells the engine the task is alive. Two things ride on it:

- **Cancellation** is delivered at the next heartbeat. A handler that never heartbeats cannot be
  cancelled, only timed out.
- **A dead worker** is detected by a missed `heartbeatTimeout`, which turns a stuck attempt into a
  retried one.

Short tasks need neither. Anything that runs for more than a few seconds should heartbeat.

## Type names

The name in `taskType<I, O>("ComposeGreeting")` is the wire identity: what the orchestrator
stores, what the UI and CLI show, and what a worker registers. Inputs and outputs are plain data
classes; the adapter owns serialisation.

**Remember:** a task is the only place side effects live.
