Tasks
The definition of a repeatable job: its goal, its limits, the tools it may use, and what happens next. A task never runs; a run does.
A task is a definition
A task is a repeatable job description: what the job is for, how to do it, what it may touch, and what happens after it. Creating one does no work. Work happens in a run, and a run starts from a person, a schedule, a webhook, or the task before it in a handoff.
Create one on Tasks → Create task, or over the API. Create a task when a capability is missing, not for one piece of work: "triage an issue" is a task, and "fix issue 42" is a run of one.
Anatomy
Most of a task lives in its version, which is fixed once saved:
| Part | What it is |
|---|---|
| Goal | One sentence of what the task is for. The model reads it on every run, and self-improvement aims at it. |
| Success metric | How you would know it is working, one line per metric. Free text today. |
| Guardrails | Rules the model must not break, one per line: "never email a customer", "escalate if unsure". They are instructions to the model. What actually stops a call is a tool scope or a gate. |
| Skill | The SKILL.md: how to do the job, step by step, in plain language. |
| Tools | Every tool a run may call, and nothing else. A tool can be narrowed to some values of its fields. See Gates and tool scopes. |
| Inputs | The fields a run starts with: each has a key, a label, a type (string or number), and optionally a default and whether it is required. |
| Gates | The tool calls that wait for your approval before they happen. |
| Spend | A budget per run, and which model runs it: an exact model, or a highest model tier. See Spend and models. |
| Workspace | For a task that works in a repository: the branch it works on and which files it may write. See Workspaces. |
| Successors | The tasks that run after it, and on which outcome. See Handoffs. |
Some things belong to the task itself rather than to a version, so the version history does not record them:
| Part | What it is |
|---|---|
| Name and slug | The slug is unique in your enterprise. Successors, webhooks and the API find the task by it, so choose it deliberately. |
| Team | The team the task belongs to. |
| Who runs it | A role. Each run goes to a member who holds that role on the task's team and is free, the one who has waited longest first. A role with no team is enterprise-wide. A task cannot be given to one member. See Roles. |
| Runs at once | Its lanes, if it declares any. See Runs at once. |
| Status | active, or deprecated: a deprecated task starts no new runs. Start, the API and its webhook refuse it, its schedule stops firing, and runs waiting to start are closed. Runs already under way finish. |
| Schedule | Its cadence, if it has one. Changing it publishes no new version. See Schedules and webhooks. |
A task's page in the portal also shows its runs, its triggers, and any self-improvement recommendations waiting on it.
What a task can call
A run can call only the tools its task lists, by exact name, and nothing else. They come in two kinds:
- Built-in tools, which the OS answers itself:
os.*,workspace.*,memory.*,web.*, and the actions of a browser. The built-in tools reference is the exact list, with what each takes, whether it writes, and which can wait at a gate. - Vendor tools, from the systems your enterprise connects: GitHub, Slack and the rest. The Tools directory lists each system, and how to connect it.
How to narrow a tool to some values, and which calls wait for you, is in Gates and tool scopes.
Runs at once
A task runs one run at a time unless it says how its work splits. Declare the input keys that split it, its
lanes, with serializeOn (Tasks API): a task that works one issue of one repository at a
time might declare ["repo", "issue"]. Then runs on different issues run at once, and two runs on the same issue
never do: the second waits, or is skipped, as it would for a task with one lane.
- A lane is the values of those inputs, trimmed and in lower case, so
Acme/Webandacme/webare the same lane. - A member still does one run at a time. Lanes run side by side only when enough members hold the task's role.
- Keys are yours to choose: a repository, a campaign, a region. The OS never reads meaning into them.
Versions
Every save publishes a new version, numbered from 1. A version is never changed after it is saved.
- A run keeps the version it started on. Saving a new version while a run is under way changes nothing for that
run; the next run uses the new one. A run waiting as
pendingtakes whichever version is current when it starts. - Version history on the task shows every version as it was, read-only, and the runs that used it.
- Going back to an earlier definition means opening that version and saving its content as a new version. There is no one-click restore.
Editing safely
Edit on a task opens its current version; Save as new version publishes your changes as the next one.
If someone (a person, or a self-improvement change you approved) published a newer version while you were editing,
your save is refused rather than putting the older definition back over theirs. Copy what you want to keep, then
Cancel edit to load the newer version and make your change on top of it. Over the API, the same protection is
baseVersionId: send the version you read, and a save made after someone else's is refused with a 409.
Checks when you save
A version that could never run is refused, and one with a likely mistake is saved with a warning:
| Code | Refused or warned | Why |
|---|---|---|
gate_required_for_tool |
Refused | The task can merge a pull request or send a new mail but declares no gate on it, or it can write a plan (a team, role, member, task or spend change) but declares no CEO gate on asking the CEO. |
gate_summary_tool_required |
Refused | The task can merge but cannot write the summary the merge gate needs. |
deterministic_with_tools |
Refused | A task that runs no model (deterministic) lists tools it could never call. |
successor_when_unknown |
Refused | A successor's when is not one the OS knows. |
successor_cap_invalid |
Refused | A successor's loop cap is not a whole number of at least 1. |
successor_delay_invalid |
Refused | A successor's delay is not more than 0 and at most 1440 minutes. |
unconditional_loop |
Refused | Successors on terminal loop back to the task, so it would never stop. |
successor_unknown_slug |
Warned | A successor names a task your enterprise does not have. |
successor_on_unknown |
Warned | A successor waits on an outcome the OS does not know, usually a typo. |
Warnings show on the task, and on Blockers under Task definitions, until they are fixed.
Inputs
A task's inputs are what a run starts with. Start a run on the task's page shows them as a form, filled with their defaults, and will not start while a required one is empty. The same keys are what a schedule, a webhook body, or the task before it provide.
However a run starts, an input it leaves out or blank takes its default, and a required input with no value and no
default refuses the start with input_required naming it: a schedule's firing, a webhook, the API and chat alike. The
one exception is a run the task before it starts: its input is whatever that run handed on. Keys the task does not
declare pass through to the run as sent.
Clone and copy
Community → Catalog lists the tasks you can take into your enterprise, in two ways:
| Clone | Copy | |
|---|---|---|
| What you get | Your own installation of the original, linked to it | A new, independent task |
| Who owns the definition | The original's owner | You |
| Can you edit it | No: Edit is disabled, and self-improvement does not run on it | Yes |
| Starts on | The original's current version | Version 1, with the original's definition |
| Later versions | A newer version of the original is offered on the clone's page; Update takes it, and nothing moves your clone until you do | None: it is yours from here |
| You choose | Its team | Its name, slug, team and role |
A clone keeps the original's role, and a copy keeps it unless you choose another. Either runs only once someone on its team holds that role.
Either way, you can run it, schedule it and delete it. Neither brings a schedule, run history, credentials or memory: you connect your own tools, and a clone may not write memory above its own task. Successors that pointed at the original point at your copy; other successors look for tasks with the same slugs in your enterprise.
Copy also works on your own tasks, from the task's page, to start a variant without touching the original.
The OS's own tasks are part of the product, not of the catalog: the same in every enterprise, and changed only with a release of the OS. They cannot be cloned or copied, and nobody can edit, reschedule or delete one. You can still start them. See Enterprise.
Deleting a task
Delete on a task removes its definition and every version of it. Runs that already happened are kept.
Over the API
With an API token scoped tasks:read (and tasks:write to change them):
| Call | What it does |
|---|---|
POST /v1/tasks |
Create a task, with its first version. |
GET /v1/tasks/{id} |
The task, its current version and skill, its version list, and its definition warnings. |
POST /v1/tasks/{id}/versions |
Save a new version. Send baseVersionId. |
POST /v1/tasks/{id}/copy |
Copy it, with a new name, slug and team, and optionally a new role. |
PUT /v1/tasks/{id}/schedule |
Set its schedule. |
POST /v1/tasks/{id}/runs |
Start a run. |
See Tasks over the API for the full shape of a task.