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
const task = await nextmail.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 nextmail.tasks.run(task.id) let run = await nextmail.tasks.getRun(started.id)while (run.status === 'queued' || run.status === 'running') { await new Promise((resolve) => setTimeout(resolve, 5000)) run = await nextmail.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 nextmail.tasks.approve(approval.id) else await nextmail.tasks.deny(approval.id)} for await (const waiting of nextmail.tasks.iterateApprovals()) { console.log(waiting.taskName, waiting.summary, waiting.expiresAt)} const once = await nextmail.tasks.startRun({ instruction: 'Find every invoice that arrived this month and label it Invoices.', autonomy: 'organize', maxSteps: 30,}) await nextmail.tasks.update(task.id, { autonomy: 'reply' })await nextmail.tasks.pause(task.id)await nextmail.tasks.resume(task.id)await nextmail.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. Reading a run or one of its approval requests also needs the read scopes of every toolkit the run used. Without them, a list shows such a run without its report and its requests without their arguments. Approving counts the toolkits the run started with, plus the scopes of the tool the request would call.
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. A connector read that names a web address waits for approval too.