> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpioneer.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Tasks API

> Creating tasks, scheduling work, managing subagents, reading task trees, waiting for results, and tracking deliveries.

Tasks are the gateway's durable automation layer. A task can run immediately, wait for a schedule, repeat on an interval or cron expression, depend on another task, or be triggered manually or externally. With the `agent` executor, it can create a subagent thread with its own prompt, model, context policy, tool policy, result contract, and review policy.

Clients use the Tasks API for two different experiences: user-facing automation UI and internal agent orchestration. In both cases the gateway owns task state, run state, retries, write locks, delivery state, and the lineage between parent work and subagent threads.

Collaborative Composer submissions are also represented by the task runtime. They are not a third client method: the normal turn submission creates detached task work with a frozen `TaskComposerWork` launch record, a child conversation, and a delivery back to the originating thread. Use the explicit Tasks API when you need to create or inspect a durable task contract; use the Threads and Turns APIs to render the conversation and the task card created by a Composer request.

## Methods

| Method            | Params                 | Result                   | Purpose                                                                               |
| ----------------- | ---------------------- | ------------------------ | ------------------------------------------------------------------------------------- |
| `task/create`     | `TaskCreateParams`     | `TaskCreateResponse`     | Create a task and its first trigger.                                                  |
| `task/get`        | `TaskGetParams`        | `TaskGetResponse`        | Load one task plus triggers, runs, specs, dependencies, and locks.                    |
| `task/list`       | `TaskListParams`       | `TaskListResponse`       | List tasks in a workspace with optional filters.                                      |
| `task/tree`       | `TaskTreeParams`       | `TaskTreeResponse`       | Load a root task with nested child tasks.                                             |
| `task/events`     | `TaskEventsParams`     | `TaskEventsResponse`     | Read durable task event history.                                                      |
| `task/wait`       | `TaskWaitParams`       | `TaskWaitResponse`       | Wait for tasks or runs to reach terminal state.                                       |
| `task/accept`     | `TaskAcceptParams`     | `TaskAcceptResponse`     | Accept a pending result candidate and finalize the run.                               |
| `task/revise`     | `TaskReviseParams`     | `TaskReviseResponse`     | Reject a pending result candidate and start a revision turn in the same child thread. |
| `task/cancel`     | `TaskCancelParams`     | `TaskCancelResponse`     | Cancel a task and optionally its subtree.                                             |
| `task/reschedule` | `TaskRescheduleParams` | `TaskRescheduleResponse` | Replace a task trigger.                                                               |
| `task/detach`     | `TaskDetachParams`     | `TaskDetachResponse`     | Detach a child task from parent lifecycle.                                            |
| `task/pause`      | `TaskPauseParams`      | `TaskPauseResponse`      | Pause active triggers.                                                                |
| `task/resume`     | `TaskResumeParams`     | `TaskResumeResponse`     | Resume paused triggers.                                                               |
| `task/agenda`     | `TaskAgendaParams`     | `TaskAgendaResponse`     | Query upcoming/recent task schedule view.                                             |
| `task/deliveries` | `TaskDeliveriesParams` | `TaskDeliveriesResponse` | Query task result delivery records and attempts.                                      |

`crates/protocol` also defines `TaskUpdateParams`, `TaskUpdateResponse`, and a `task/update` method constant for task-service update contracts. The current gateway JSON-RPC dispatcher does not expose `task/update` as a client-callable method. Task updates can still happen through the model-facing `task_update` tool and task service, and clients observe them through `task/updated` plus `task/tree/changed`.

## Creating an agent task

`task/create` uses mostly `camelCase` payload fields. The gateway creates the task, stores the trigger, and may also create a run immediately depending on the trigger.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "aaaaaaaaaaaaaaaaaaaaa",
  "method": "task/create",
  "params": {
    "workspaceId": "ws_000000000000000001",
    "ownerKind": "thread",
    "ownerId": "thr_000000000000000001",
    "createdByThreadId": "thr_000000000000000001",
    "createdByTurnId": "trn_000000000000000001",
    "executorKind": "agent",
    "title": "Review the protocol docs",
    "goal": "Check the protocol reference for missing methods and incorrect examples.",
    "priority": 0,
    "trigger": {
      "spec": {
        "kind": "immediate"
      }
    },
    "agentSpec": {
      "agentRole": "Reviewer",
      "agentNickname": "Protocol reviewer",
      "model": "gpt-5.1",
      "modelProvider": "openai",
      "prompt": {
        "goal": "Review the Protocol Reference section.",
        "instructions": [
          "Compare the docs with pioneer-protocol types.",
          "Report incorrect method names, payload casing, or missing lifecycle notes."
        ],
        "outputInstructions": "Return a concise Markdown review."
      },
      "contextPolicy": {
        "mode": "inherit_parent",
        "includeParentSummary": true,
        "includeArtifacts": true
      },
      "toolPolicy": {
        "allowedTools": ["grep_files", "read_file"],
        "deniedTools": [],
        "writeMode": "read_only",
        "allowedPaths": ["/Users/alexander/Code/pioneer"],
        "networkAccess": false
      },
      "resultContract": {
        "format": "markdown",
        "required": true
      },
      "depth": 1,
      "maxDepth": 2
    }
  }
}
```

Important create fields:

| Field                                               | Meaning                                                    |
| --------------------------------------------------- | ---------------------------------------------------------- |
| `workspaceId`                                       | Gateway workspace that owns the task.                      |
| `ownerKind`, `ownerId`                              | Logical owner: `user`, `thread`, `workspace`, or `system`. |
| `createdByThreadId`, `createdByTurnId`              | Optional lineage back to the turn that created the task.   |
| `parentTaskId`                                      | Optional parent for task trees and subagent orchestration. |
| `executorKind`                                      | `agent`, `tool`, `workflow`, `webhook`, or `system`.       |
| `title`, `goal`                                     | Human-facing title and durable goal.                       |
| `priority`                                          | Higher-level scheduling hint. Defaults to `0`.             |
| `trigger`                                           | When and how the task should run.                          |
| `agentSpec`                                         | Required for agent-style subagent work.                    |
| `lifecyclePolicy`                                   | Parent/child attachment and completion behavior.           |
| `deliveryPolicy`                                    | Where the result should be delivered.                      |
| `retryPolicy`, `timeoutPolicy`, `concurrencyPolicy` | Execution controls.                                        |
| `metadata`                                          | Labels and structured custom data.                         |

Response:

```json theme={null}
{
  "task": {
    "id": "tsk_000000000000000001",
    "workspaceId": "ws_000000000000000001",
    "ownerKind": "thread",
    "ownerId": "thr_000000000000000001",
    "executorKind": "agent",
    "status": "queued",
    "title": "Review the protocol docs",
    "goal": "Check the protocol reference for missing methods and incorrect examples.",
    "priority": 0,
    "revision": 1,
    "createdAt": 1777900000,
    "updatedAt": 1777900000
  },
  "trigger": {
    "id": "trg_000000000000000001",
    "taskId": "tsk_000000000000000001",
    "status": "active",
    "spec": {
      "kind": "immediate"
    },
    "createdAt": 1777900000,
    "updatedAt": 1777900000
  },
  "run": {
    "id": "run_000000000000000001",
    "taskId": "tsk_000000000000000001",
    "runGroupId": "grp_000000000000000001",
    "attemptNumber": 1,
    "runNumber": 1,
    "status": "queued",
    "executorKind": "agent",
    "createdAt": 1777900000,
    "updatedAt": 1777900000
  },
  "agentSpec": {
    "id": "ags_000000000000000001",
    "taskId": "tsk_000000000000000001",
    "agentRole": "Reviewer",
    "agentNickname": "Protocol reviewer",
    "prompt": {
      "goal": "Review the Protocol Reference section.",
      "instructions": [],
      "outputInstructions": "Return a concise Markdown review."
    },
    "depth": 1,
    "maxDepth": 2,
    "createdAt": 1777900000,
    "updatedAt": 1777900000
  }
}
```

`TaskStatus` values serialize as `snake_case`: `draft`, `scheduled`, `queued`, `running`, `waiting`, `completed`, `failed`, `cancelled`. Many task payloads use `camelCase` field names while enum values use `snake_case`, so clients should follow the generated schema rather than guessing casing.

## Trigger specs

The `trigger.spec` object is tagged by `kind`.

| Kind           | Extra fields                                       | Meaning                                            |
| -------------- | -------------------------------------------------- | -------------------------------------------------- |
| `immediate`    | none                                               | Queue as soon as the task is created.              |
| `scheduled_at` | `scheduled_at`, optional `timezone`                | Run once at a Unix timestamp.                      |
| `interval`     | `interval_seconds`, optional `interval_anchor_at`  | Run repeatedly on an interval.                     |
| `cron`         | `cron_expr`, `timezone`                            | Run repeatedly from a cron expression.             |
| `manual`       | optional `allowed_actor`                           | Create task but wait for manual/external start.    |
| `external`     | `source`, optional `event_type`, optional `filter` | Run from an external event source.                 |
| `dependency`   | `policy`                                           | Run after other tasks satisfy a dependency policy. |

Example cron trigger:

```json theme={null}
{
  "spec": {
    "kind": "cron",
    "cron_expr": "0 9 * * 1-5",
    "timezone": "Europe/Moscow"
  }
}
```

Dependency trigger policy uses `mode` values `all_succeeded`, `any_succeeded`, or `all_terminal` and a `dependsOnTaskIds` list.

## Subagents

`agentSpec` tells the gateway to create a child thread and run it with bounded context and tools. The UI is only one way to request this work.

| Field                        | Meaning                                                                       |
| ---------------------------- | ----------------------------------------------------------------------------- |
| `agentRole`, `agentNickname` | Human-readable identity for history and task trees.                           |
| `model`, `modelProvider`     | Optional model override for this subagent.                                    |
| `prompt.goal`                | Main objective.                                                               |
| `prompt.instructions`        | Additional instructions.                                                      |
| `prompt.input`               | Optional structured variables, attachments, and references.                   |
| `prompt.outputInstructions`  | How the result should be returned.                                            |
| `contextPolicy`              | What parent context the subagent receives.                                    |
| `toolPolicy`                 | What tools, paths, writes, and network access are allowed.                    |
| `resultContract`             | Expected result format and optional schema.                                   |
| `reviewPolicy`               | How the subagent result candidate should be reviewed before it becomes final. |
| `depth`, `maxDepth`          | Nesting controls for subagent trees.                                          |

Context policy modes are `inherit_parent`, `last_n_turns`, `summary_only`, `empty`, and `custom`. Write modes are `read_only`, `workspace_write`, `scoped_write`, and `full_access`. Result formats are `text`, `markdown`, `json`, and `artifact`.

Callers usually omit `reviewPolicy`. The gateway applies the default parent-agent review policy to immediate attached agent tasks. Direct `reviewPolicy` overrides in `task/create` require `gateway.tasks.review.allow_task_create_review_policy = true`.

When a task creates a child thread, task events include child thread lineage. The child thread is hidden from the normal sidebar, but clients can show the subagent's work in the parent task tree and can load the child conversation through [Threads API](/protocol/threads) and [Turns API](/protocol/turns).

## Result review

Agent tasks can require review before a child result becomes the final run result. For attached subagent work, the default review mode is parent-agent review with explicit acceptance and five revision rounds.

Review policy fields:

| Field                       | Meaning                                                                                                            |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `mode`                      | `none`, `parent_agent`, `parent_agent_with_reviewers`, or `user_approval`.                                         |
| `maxRevisionRounds`         | Maximum number of revision turns after the initial child turn.                                                     |
| `requireExplicitAcceptance` | Whether a candidate must be accepted before the run succeeds.                                                      |
| `reviewers`                 | Optional reviewer specs for future review-agent or user-review flows.                                              |
| `resolutionStrategy`        | How multiple review decisions resolve, for example `parent_final` or `require_all_required_reviewers_then_parent`. |

When a child turn finishes, the gateway creates a `TaskResultCandidate`. If review is required, the candidate status is `pending_review`, the run/execution waits for review, and `task/wait` can return it under `reviewRequired`.

The parent accepts a candidate with `task/accept`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "review_accept_00000001",
  "method": "task/accept",
  "params": {
    "taskId": "tsk_000000000000000001",
    "runId": "run_000000000000000001",
    "candidateId": "trc_000000000000000001",
    "reason": "The subagent included the required file:line references and answered the task."
  }
}
```

Accepting creates a `TaskResultReviewEvent` with `decision = accept`, marks the candidate accepted, stores the accepted result on the run, and completes the task when its lifecycle policy allows it.

The parent requests changes with `task/revise`:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "review_revise_00000001",
  "method": "task/revise",
  "params": {
    "taskId": "tsk_000000000000000001",
    "runId": "run_000000000000000001",
    "candidateId": "trc_000000000000000001",
    "feedback": "Add a Revision verification section with three exact file:line references.",
    "additionalInstructions": [
      "Keep the original structure.",
      "Do not redo unrelated research."
    ]
  }
}
```

Revising creates a review event with `decision = request_changes`, marks the current candidate rejected, creates a new `TaskRunTurn` with `kind = revision`, and dispatches the same child thread again with the feedback. The next child turn produces a new candidate.

`TaskResultReviewEvent` is an audit log rather than a snapshot of the latest state. It records reviewer kind (`parent_agent`, `review_agent`, `user`, `runtime_auto`, or `system`), event kind (`advisory`, `decision`, `override`, or `system_auto`), decision, feedback, optional reviewer thread/turn/user/agent ids, and the next revision turn when one is created.

## Policies

Lifecycle policy controls what happens to child tasks when parent work ends:

```json theme={null}
{
  "attachment": "attached",
  "onParentCancel": "cancel",
  "onParentFailure": "detach",
  "completion": "complete_on_terminal_run"
}
```

Delivery policy controls where task results go:

```json theme={null}
{
  "mode": "owner_thread",
  "includeResult": true,
  "format": "summary"
}
```

Retry, timeout, and concurrency policies are optional, but they are what turn tasks from "run this once" into reliable automation:

```json theme={null}
{
  "retryPolicy": {
    "maxAttempts": 3,
    "backoff": "exponential",
    "initialDelaySeconds": 30,
    "maxDelaySeconds": 600,
    "retryOn": ["provider", "tool", "timeout"]
  },
  "timeoutPolicy": {
    "queueTimeoutSeconds": 300,
    "runTimeoutSeconds": 1800,
    "heartbeatTimeoutSeconds": 120
  },
  "concurrencyPolicy": {
    "key": "docs-protocol-reference",
    "maxParallelRuns": 1,
    "onConflict": "queue"
  }
}
```

Write locks are produced by the task runtime when a task needs exclusive write access to a workspace or path. Clients normally display them in diagnostics rather than creating them directly.

## Reading tasks

Use `task/get` for a detail view:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "bbbbbbbbbbbbbbbbbbbbb",
  "method": "task/get",
  "params": {
    "taskId": "tsk_000000000000000001"
  }
}
```

Use `task/list` for a workspace list:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "ccccccccccccccccccccc",
  "method": "task/list",
  "params": {
    "workspaceId": "ws_000000000000000001",
    "ownerKind": "thread",
    "ownerId": "thr_000000000000000001",
    "status": "running",
    "limit": 50
  }
}
```

`task/tree` returns a root `TaskTree` with nested children. Use it when showing a delegated workflow, because a parent task can fan out into child tasks and each child can have its own run, agent spec, dependencies, write locks, and child thread lineage.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "ddddddddddddddddddddd",
  "method": "task/tree",
  "params": {
    "taskId": "tsk_000000000000000001"
  }
}
```

## Events

`task/events` returns durable task events with monotonically increasing `sequence`.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "eeeeeeeeeeeeeeeeeeeee",
  "method": "task/events",
  "params": {
    "taskId": "tsk_000000000000000001",
    "afterSequence": 42
  }
}
```

Each event has `eventType`, `payload`, `createdAt`, optional `runId`, optional `threadId`, and optional `turnId`. The payload is tagged by `kind`, with variants for task creation, trigger creation, task updates, run start/completion/failure, retries, cancellation, delivery, child thread linking, depth limits, and write-lock state.

Use `afterSequence` for incremental polling after reconnect. Live clients should also listen to task notifications.

## Waiting

`task/wait` is useful for automation clients and for a parent agent waiting on delegated work.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "fffffffffffffffffffff",
  "method": "task/wait",
  "params": {
    "taskIds": ["tsk_000000000000000001"],
    "runIds": [],
    "timeoutMs": 30000,
    "mode": "all_terminal",
    "returnCompleted": true,
    "returnPending": true
  }
}
```

Response groups terminal and pending work:

```json theme={null}
{
  "completed": [],
  "failed": [],
  "cancelled": [],
  "reviewRequired": [],
  "pending": [],
  "timedOut": false,
  "totalCount": 1,
  "terminalCount": 1,
  "pendingCount": 0,
  "reviewRequiredCount": 0,
  "mode": "all_terminal"
}
```

Wait modes are `all_terminal`, `any_terminal`, `all_terminal_or_review_required`, and `any_terminal_or_review_required`. A timed-out wait does not cancel the task; it only returns control to the caller.

Parent-agent orchestration normally uses a review-aware wait mode. When a candidate needs a decision, `reviewRequired` contains the task/run item, the candidate, the review policy, revision limits, and allowed actions:

```json theme={null}
{
  "reviewRequired": [
    {
      "item": {
        "task": { "id": "tsk_000000000000000001", "status": "waiting" },
        "run": { "id": "run_000000000000000001", "status": "waiting_review" },
        "childThreadId": "thr_child_0000000001",
        "childTurnId": "trn_child_0000000001"
      },
      "candidate": {
        "id": "trc_000000000000000001",
        "status": "pending_review",
        "round": 0,
        "summary": "Found the relevant TaskService implementation."
      },
      "maxRevisionRounds": 5,
      "remainingRevisionRounds": 5,
      "allowedActions": ["task_accept", "task_revise", "task_cancel"]
    }
  ],
  "reviewRequiredCount": 1,
  "mode": "all_terminal_or_review_required"
}
```

If `remainingRevisionRounds` is `0`, `allowedActions` omits `task_revise` and `revisionBlockedReason` explains why. The parent should then accept, cancel, or create a separate follow-up task.

## Cancelling and lifecycle changes

Cancel scope controls how far cancellation propagates:

| Scope              | Meaning                                                      |
| ------------------ | ------------------------------------------------------------ |
| `task_only`        | Cancel only this task.                                       |
| `attached_subtree` | Cancel this task and attached children. This is the default. |
| `full_subtree`     | Cancel this task and all descendants.                        |

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "ggggggggggggggggggggg",
  "method": "task/cancel",
  "params": {
    "taskId": "tsk_000000000000000001",
    "reason": "User cancelled from UI",
    "scope": "attached_subtree"
  }
}
```

Use `task/pause` and `task/resume` for scheduled or recurring tasks. Use `task/reschedule` to replace the trigger. Use `task/detach` when a child task should keep running independently of its parent.

## Agenda

`task/agenda` is optimized for "what is coming up" and "what recently ran" screens.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "hhhhhhhhhhhhhhhhhhhhh",
  "method": "task/agenda",
  "params": {
    "workspaceId": "ws_000000000000000001",
    "from": 1777900000,
    "to": 1778504800,
    "triggerKinds": ["cron", "interval", "scheduled_at"],
    "includePaused": true,
    "includeCompleted": false,
    "limit": 100
  }
}
```

Agenda items include the task, trigger, latest run, latest delivery, goal preview, next/last fire timestamps, recurring flag, delivery mode, and result/error previews.

## Deliveries

Delivery records track result handoff after a run: owner thread posts, target thread posts, user notifications, and webhook attempts.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "iiiiiiiiiiiiiiiiiiiii",
  "method": "task/deliveries",
  "params": {
    "workspaceId": "ws_000000000000000001",
    "taskId": "tsk_000000000000000001",
    "statuses": ["pending", "failed"],
    "limit": 50
  }
}
```

The response contains `deliveries` and `attempts`. Use it for a delivery/debug panel and for retry/error visibility in scheduled automation.

## Notifications

Task notifications use the same event names as durable task events:

| Event                                                                                                                                    | Meaning                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `task/created`, `task/scheduled`, `task/queued`                                                                                          | Task lifecycle entered created/scheduled/queued state.                               |
| `task/run/created`, `task/run/started`, `task/progress`                                                                                  | Run lifecycle and progress updates.                                                  |
| `task/run/completed`, `task/run/failed`, `task/run/blocked`, `task/run/cancelled`                                                        | Run terminal or recoverable blocked updates.                                         |
| `task/run/retry_scheduled`, `task/run/retry_exhausted`                                                                                   | Retry lifecycle updates.                                                             |
| `task/run/thread_binding/created`                                                                                                        | A task run was linked to its executor, reviewer, or recovery thread.                 |
| `task/run/turn/started`, `task/run/turn/completed`, `task/run/turn/failed`, `task/run/turn/blocked`                                      | Initial, revision, recovery, and review turn lifecycle.                              |
| `task/run/entered_review`                                                                                                                | A run has a pending result candidate and is waiting for review.                      |
| `task/result_candidate/created`, `task/result_candidate/accepted`, `task/result_candidate/rejected`, `task/result_candidate/cancelled`   | Candidate lifecycle for child outputs.                                               |
| `task/result_review_event/recorded`                                                                                                      | Parent-agent, user, review-agent, runtime-auto, or system review event was recorded. |
| `task/revision/requested`                                                                                                                | A review decision requested another child-thread revision turn.                      |
| `task/completed`, `task/failed`, `task/blocked`, `task/cancelled`                                                                        | Task terminal or recoverable blocked updates.                                        |
| `task/detached`, `task/updated`, `task/rescheduled`, `task/paused`, `task/resumed`                                                       | Manual lifecycle and editable task contract changes.                                 |
| `task/tree/changed`                                                                                                                      | Parent/child structure, dependencies, or child thread linkage changed.               |
| `task/recovered`                                                                                                                         | Runtime recovered task state.                                                        |
| `task/delivery/queued`, `task/delivery/started`, `task/delivery/delivered`, `task/delivery/failed`, `task/delivery/cancelled`            | Result delivery lifecycle.                                                           |
| `task/write_lock/acquired`, `task/write_lock/extended`, `task/write_lock/released`, `task/write_lock/blocked`, `task/write_lock/expired` | Write-lock lifecycle.                                                                |

Notification params include a `context` object with `workspaceId`, `taskId`, optional `runId`, optional parent/root ids, optional thread/turn ids, `eventId`, and `sequence`. Treat notifications as streaming state changes and use read methods to rebuild exact state when needed.

## How tasks relate to turns

Agent turns can create tasks, tasks can create child threads, and child turns can report results back to parent tasks. For rendering a conversation that includes delegated work, combine [Threads API](/protocol/threads) `thread/timeline/page`, [Turns API](/protocol/turns) `turn/work/page`, `task/tree`, and `task/events`.

For a task automation screen, use `task/agenda`, `task/list`, `task/get`, and `task/deliveries`. For an agent orchestration screen, use `task/tree`, `task/events`, and child thread links.
