---
title: "Tasks"
description: "`tasks.list`, `listAll`, `iterate`, `get`, `create`, `update`, `delete`, `pause`, `resume` and `run`, with `listRuns`, `listAllRuns`, `iterateRuns`, `getRun`, `startRun` and `cancelRun` for runs, and `listApprovals`, `listAllApprovals`, `iterateApprovals`, `getApproval`, `approve` and `deny` for what runs ask."
url: "https://openemail.uk/docs/sdk/tasks"
area: "TypeScript"
category: "Mailbox"
---

# Tasks

`tasks.list`, `listAll`, `iterate`, `get`, `create`, `update`, `delete`, `pause`, `resume` and `run`, with `listRuns`, `listAllRuns`, `iterateRuns`, `getRun`, `startRun` and `cancelRun` for runs, and `listApprovals`, `listAllApprovals`, `iterateApprovals`, `getApproval`, `approve` and `deny` for what runs ask.

## Every method

**tasks.ts**

```
const task = await openemail.tasks.create({
  name: 'Morning summary',
  instruction: 'Go through the mail that arrived since yesterday. Tell me which conversations need a reply from me, most urgent first, and draft a short reply for each.',
  trigger: {
    kind: 'schedule',
    schedule: { cadence: 'daily', hour: 8, minute: 0, weekdays: [1, 2, 3, 4, 5], timezone: 'Europe/London' },
  },
  autonomy: 'organize',
})

const started = await openemail.tasks.run(task.id)

let run = await openemail.tasks.getRun(started.id)
while (run.status === 'queued' || run.status === 'running') {
  await new Promise((resolve) => setTimeout(resolve, 5000))
  run = await openemail.tasks.getRun(run.id)
}

for (const approval of run.approvals) {
  if (approval.status !== 'pending') continue
  console.log(approval.tool, approval.summary, approval.args)
  if (approval.tool === 'replyToEmail') await openemail.tasks.approve(approval.id)
  else await openemail.tasks.deny(approval.id)
}

for await (const waiting of openemail.tasks.iterateApprovals()) {
  console.log(waiting.taskName, waiting.summary, waiting.expiresAt)
}

const once = await openemail.tasks.startRun({
  instruction: 'Find every invoice that arrived this month and label it Invoices.',
  autonomy: 'organize',
  maxSteps: 30,
})

await openemail.tasks.update(task.id, { autonomy: 'reply' })
await openemail.tasks.pause(task.id)
await openemail.tasks.resume(task.id)
await openemail.tasks.cancelRun(once.id)

console.log(run.status, run.result, run.transcript.length)
```

A task is an instruction with a `trigger`: a `schedule`, new `mail`, or `manual` for one that only runs when you call `run`. `autonomy` says how much a run may change without asking: `ask` nothing, `organize` labels, archive, drafts, notes and contacts, and `reply` also answers to the people already on a conversation. Everything else waits as an approval request, and the run picks up again once every request is answered.

`run` and `startRun` return at once with the run `queued`. `getRun` returns its `transcript`, every step with the tools it called, and its `approvals`. A run is `waiting` while a request is open, and `approve` takes `subject` and `body` to replace the words of a send or a reply.

Reading needs `tasks:read` with `threads:read` and `emails:read`. `create`, `update`, `resume`, `run`, `startRun` and `approve` need `tasks:write` with `threads:read`, `threads:write`, `emails:read`, `emails:send` and `labels:write`, and the scopes of every toolkit the task names. `pause`, `delete`, `cancelRun` and `deny` need only `tasks:write`. A key or a token limited to some addresses is refused, because a task works across the whole workspace.

A task whose `toolkits` hold `connectors` may use the apps connected for the workspace, never a connector that belongs to one person, and it then also needs `connectors:read` and `connectors:use`. Such a run reads through a connector alone, every change in an app waits as an approval request whatever the `autonomy`, and with `reply` every answer to an email waits for approval as well.
