# Tasks Commands

> See [Tasks module docs](../../modules/workflows) for permissions and data model.

# Tasks Commands

See [Tasks module docs](../../modules/workflows) for permissions and data model.

### `soat list-tasks`

List tasks

- Method: `GET`
- Path: `/api/v1/tasks`

#### Usage

```bash
soat list-tasks
```

#### Options

##### `--project-id`

—

- Source: `query`
- Required: no
- Type: `string`

##### `--workflow-id`

—

- Source: `query`
- Required: no
- Type: `string`

##### `--state`

—

- Source: `query`
- Required: no
- Type: `string`

##### `--status`

—

- Source: `query`
- Required: no
- Type: `enum("open", "closed")`

##### `--automation-status`

Filter by the current state's dispatch status. Repeat the parameter to OR values. `none` selects the tasks whose `automation_status` is `null` — the ones that never entered a state with an automation. It is a value a task really holds, so it is a value of the filter too; the parameter's own absence already means "every task".  A value outside the enum, empty string included, is a `400`.

- Source: `query`
- Required: no
- Type: `array<enum("running", "completed", "failed", "unrouted", "paused", "none")>`
- Example: `["running"]`

##### `--assignee`

—

- Source: `query`
- Required: no
- Type: `string`

##### `--limit`

Maximum number of results to return

- Source: `query`
- Required: no
- Type: `integer`
- Default: `50`

##### `--offset`

Number of results to skip

- Source: `query`
- Required: no
- Type: `integer`
- Default: `0`

### `soat create-task`

Create a task

- Method: `POST`
- Path: `/api/v1/tasks`

#### Usage

```bash
soat create-task --workflow-id <string> --title <string>
```

#### Options

##### `--project-id`

—

- Source: `body`
- Required: no
- Type: `string`

##### `--workflow-id`

—

- Source: `body`
- Required: yes
- Type: `string`

##### `--title`

—

- Source: `body`
- Required: yes
- Type: `string`

##### `--payload`

—

- Source: `body`
- Required: no
- Type: `object`

##### `--assignee`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--state`

Name of a declared workflow state to create the task in directly, instead of the workflow's `initial` state. Must name a state declared on the workflow, or the request is rejected with `TASK_STATE_NOT_FOUND` (400). Defaults to the `initial` state.

- Source: `body`
- Required: no
- Type: `string`

##### `--tool-context`

Key-value pairs forwarded as `X-Soat-Context-<key>` headers on every `http`, `mcp` and `builtin` tool call made by this task's automation dispatches — the agent generations a state's `on_enter` starts, and the agent nodes of any orchestration run it starts. The header name is `X-Soat-Context-` plus the key verbatim; no character is re-cased. Creation is the task's first move, so this is the bag the entry state's `on_enter` runs with. Each transition may replace it (see `TransitionTaskRequest.tool_context`). The reserved identity keys (`session_id`, `actor_id`, `actor_external_id`) are stripped in any casing and re-derived server-side, so a task-dispatched generation cannot forge them. A key outside the HTTP header-name grammar is rejected with `INVALID_TOOL_CONTEXT_KEY` (400). Write-only: the stored bag is never returned by any task read, and it is cleared when the task reaches a terminal state.

- Source: `body`
- Required: no
- Type: `object<string, string>`

##### `--metadata`

Caller-supplied key/value metadata attached to the task record for attribution — which of your own tenants the task belongs to, the ticket that raised it, the import batch that created it. Round-trips verbatim on every read of the task, the list included, and survives every transition (a transition supplies no metadata of its own).  The bag is caller-owned and no key is reserved: everything the engine decides about a task (`state`, `status`, `workflow_version`, `last_result`, `active_dispatch`, the automation fields) is a field of its own and cannot be written from here.  Prefer this over `payload` for anything that is not task data: `payload` is read by every guard as `task.payload` and may be written by the workflow's declared `payload_writes`, so a label parked there is neither invisible to the state machine nor safe from it. A non-object is rejected with `400 VALIDATION_FAILED` and no task is created.

- Source: `body`
- Required: no
- Type: `object<string, unknown>`
- Example: `\{"tenant_account_id":"42","source":"zendesk"\}`

### `soat get-task`

Get a task

- Method: `GET`
- Path: `/api/v1/tasks/{task_id}`

#### Usage

```bash
soat get-task --task-id <string>
```

#### Options

##### `--task-id`

—

- Source: `path`
- Required: yes
- Type: `string`

### `soat update-task`

Update a task

- Method: `PATCH`
- Path: `/api/v1/tasks/{task_id}`

#### Usage

```bash
soat update-task --task-id <string>
```

#### Options

##### `--task-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--title`

—

- Source: `body`
- Required: no
- Type: `string`

##### `--payload`

Partial payload, shallow-merged over the existing payload. Omitted keys are preserved; provided keys overwrite. The merged result must satisfy the workflow's payload_schema.

- Source: `body`
- Required: no
- Type: `object`

##### `--assignee`

—

- Source: `body`
- Required: no
- Type: `string \| null`

### `soat delete-task`

Delete a task

- Method: `DELETE`
- Path: `/api/v1/tasks/{task_id}`

#### Usage

```bash
soat delete-task --task-id <string>
```

#### Options

##### `--task-id`

—

- Source: `path`
- Required: yes
- Type: `string`

### `soat transition-task`

Transition a task

- Method: `POST`
- Path: `/api/v1/tasks/{task_id}/transitions`

#### Usage

```bash
soat transition-task --task-id <string> --transition <string>
```

#### Options

##### `--task-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--transition`

—

- Source: `body`
- Required: yes
- Type: `string`

##### `--note`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--tool-context`

Caller context for the automation dispatches the task makes from here on, forwarded as `X-Soat-Context-<key>` headers on their tool calls. Supplying it **replaces** the task's stored bag wholesale; omitting it keeps the current one, so the context follows whoever last moved the task and survives every move that does not speak about it — including an approval gate, a retry, and an automation hop. Send an empty object to clear it without closing the task. The reserved identity keys (`session_id`, `actor_id`, `actor_external_id`) are stripped in any casing and re-derived server-side. A key outside the HTTP header-name grammar is rejected with `INVALID_TOOL_CONTEXT_KEY` (400). Write-only: never returned by a task read, and cleared when the transition closes the task.

- Source: `body`
- Required: no
- Type: `object<string, string>`

### `soat pause-task`

Pause a task

- Method: `POST`
- Path: `/api/v1/tasks/{task_id}/pause`

#### Usage

```bash
soat pause-task --task-id <string>
```

#### Options

##### `--task-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--reason`

Why the task is being paused, surfaced on `pause_reason`.

- Source: `body`
- Required: no
- Type: `string`

### `soat resume-task`

Resume a task

- Method: `POST`
- Path: `/api/v1/tasks/{task_id}/resume`

#### Usage

```bash
soat resume-task --task-id <string>
```

#### Options

##### `--task-id`

—

- Source: `path`
- Required: yes
- Type: `string`

### `soat get-task-history`

Get task history

- Method: `GET`
- Path: `/api/v1/tasks/{task_id}/history`

#### Usage

```bash
soat get-task-history --task-id <string>
```

#### Options

##### `--task-id`

—

- Source: `path`
- Required: yes
- Type: `string`
